const BASE_URL = "/api"; const { fetch: originalFetch } = window; window.fetch = async (...args) => { try { const response = await originalFetch(...args); // Check for HTTP errors (e.g., 4xx or 5xx status codes) // if (!response.ok) { // const errorDetails = { // url: response.url, // status: response.status, // statusText: response.statusText, // // You might also want to parse the response body for more details // // const errorData = await response.json(); // // errorData: errorData // }; // console.error('Global Fetch Error (HTTP):', errorDetails); // // Re-throw the error to be caught by individual catch blocks if needed // throw new Error(`HTTP error! Status: ${response.status}`); // } if( response.status == 401){ removeToken(); } return response; } catch (error) { // Handle network errors or other errors thrown before the response is received console.error('Global Fetch Error (Network/Other):', error); // Re-throw the error to be caught by individual catch blocks if needed throw error; } }; function getToken(silently = false){ let token = localStorage.getItem("token"); if(!silently && !token){ window.location.href = "/login"; }; return token; } function removeToken(){ localStorage.removeItem("token"); getToken(); } function setToken(token){ localStorage.setItem("token", token); } function login(username, password) { const formdata = new FormData(); formdata.append("username", username); formdata.append("password", password); fetch(BASE_URL + "/auth/login", { method: "POST", body: formdata, redirect: "follow" }) .then(res => res.json()) .then(data => { if (data.access_token) { setToken(data.access_token); window.location.href = "policies"; } else { alert("Login failed!"); } }); } function refreshToken() { fetch(BASE_URL + "/auth/refresh", { method: "POST", headers: {"Authorization": "Bearer " + getToken()}, redirect: "follow" }) .then(res => res.json()) .then(data => { if (data.access_token) { document.getElementById("token").innerHTML = data.access_token; } else { alert("Refesh Token failed!"); } }); } function register(email, password) { fetch(BASE_URL + "/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }) }) .then(res => res.json()) .then(data => { if (data.success) { alert("Registered successfully!"); window.location.href = "login"; } else { alert("Registration failed!"); } }); } function snakeCaseToTitleCase(snakeCaseString) { if (!snakeCaseString) { return ""; } // Split the string by underscore const words = snakeCaseString.split('_'); // Capitalize the first letter of each word and convert the rest to lowercase const titleCaseWords = words.map(word => { if (word.length === 0) { return ""; } return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }); // Join the words with a space return titleCaseWords.join(' '); } async function loadPolicies() { let response = await fetch(BASE_URL + "/policies", { headers: { "Authorization": "Bearer " + getToken() } }) let data = await response.json(); let mapping = {}; const modules = ['regex', 'bert_similarity', 'openai_compliance', 'prompt']; data = data.map((row, i) =>{ modules.forEach(m => { row[m] = 'No'; }); mapping[row.slug] = i; return row; }); for(let i = 0; i < modules.length; i++){ let response = await fetch(`${BASE_URL}/${modules[i]}/available-policies`, { headers: { "Authorization": "Bearer " + getToken() } }); response = await response.json(); response.forEach(slug => { data[mapping[slug]][modules[i]] = "Yes"; }); } let columns = [ { data: 'slug', title: 'Slug', columnControl: ['order', ['orderAsc', 'orderDesc', 'orderRemove', 'orderClear', 'orderAddAsc', 'orderAddDesc']] }, { data: 'name', title: 'Name' }, { data: 'description', title: 'Description'}, { data: 'priority_score', title: 'Score' }, { data: 'priority', title: 'Priority' }, { data: 'is_active', title: 'Active', render: function(data, type, row, meta){ if(type != 'display') return data; return data ? `Yes` : `No` } }, ]; modules.forEach(m => { columns.push({ data: m, title: snakeCaseToTitleCase(m), visible: true, className: 'dt-body-center', render: function(data, type, row, meta){ if(type != 'display') return data; return data == "Yes" ? `Yes` : `No` } }); }) columns.push({ data: 'slug', title: 'Action', searchable: false, orderable: false, className: 'dt-body-center', render: function(data, type, row, meta){ return `Edit` }, columnControl: [{target: 0, content: []}, {target: 1, content: []}] }); let table = $("#table").DataTable({ data, columns: columns, fixedHeader: { headerOffset: $('nav').outerHeight() }, fixedColumns: { start: 1, end: 1 }, scrollX: true, colReorder: { columns: ':not(:first-child, :last-child)' }, columnControl: [ { target: 0, content: ['order', ['orderAsc', 'orderDesc', 'orderRemove', 'orderClear', 'orderAddAsc', 'orderAddDesc'], 'reorder'] }, { target: 1, content: ['search'] } ], ordering: { indicators: false, handler: false }, layout: { // top1Start: 'search', top1Start: { buttons: [ { extend: 'searchPanes', className: 'btn btn-sm bg-secondary text-white my-auto border-0 rounded', config: { cascadePanes: true } }, { extend: 'colvis', className: 'btn btn-sm bg-secondary text-white my-auto border-0 rounded', } ] }, top1End: { buttons: [ { text: 'New', className: 'btn btn-sm bg-primary text-white my-auto border-0 rounded', action: function ( e, dt, node, config ) { window.location.href = "/create-policy"; } } ] } // top2: 'searchBuilder' } }); } function loadPolicyDetail() { const params = new URLSearchParams(window.location.search); const id = params.get("id"); fetch(BASE_URL + "/policies/" + id, { headers: { "Authorization": "Bearer " + getToken() } }) .then(res => res.json()) .then(data => { document.getElementById("slug").value = data.slug ?? ""; document.getElementById("name").value = data.name ?? ""; document.getElementById("priority_score").value = data.priority_score ?? ""; document.getElementById("priority").value = data.priority ?? ""; document.getElementById("description").value = data.description ?? ""; document.getElementById("is_active").value = data.is_active ? "true" : "false"; }); } function createPolicyDetail() { fetch(BASE_URL + "/policies/", { method: "POST", headers: { "Authorization": "Bearer " + getToken(), "Content-Type": "application/json" }, body: JSON.stringify({ slug: document.getElementById("slug").value, name: document.getElementById("name").value, description: document.getElementById("description").value }) }) .then(res => res.json()) .then(data => { if(data.slug){ alert("Details Saved Successfully"); window.location.href = "/policy-detail?id=" + data.slug } else{ alert(data.detail?.length && data.detail[0]?.msg ? `${data.detail[0].input} : ${data.detail[0].msg}` : "Something went wrong"); } }); } function deletePolicyDetail() { fetch(BASE_URL + "/policies/" + document.getElementById("slug").value, { method: "DELETE", headers: { "Authorization": "Bearer " + getToken(), "Content-Type": "application/json" }, }) .then(data => { alert("Policy Deleted Successfully"); window.location.href = "/policies" }).catch(err => { alert("Something went wrong") }); } function savePolicyDetail() { const params = new URLSearchParams(window.location.search); const id = params.get("id"); fetch(BASE_URL + "/policies/" + id, { method: "PATCH", headers: { "Authorization": "Bearer " + getToken(), "Content-Type": "application/json" }, body: JSON.stringify({ slug: document.getElementById("slug").value, name: document.getElementById("name").value, is_active: document.getElementById("is_active").value == "true", priority_score: document.getElementById("priority_score").value, priority: document.getElementById("priority").value, description: document.getElementById("description").value }) }) .then(res => res.json()) .then(data => { alert("Details Saved Successfully"); }); } function loadPolicyDetailFor(key) { const params = new URLSearchParams(window.location.search); const id = params.get("id"); fetch(`${BASE_URL}/${key}/${id}`, { headers: { "Authorization": "Bearer " + getToken() } }) .then(res => res.json()) .then(data => { document.getElementById(key).value = data && data.length ? data.join("\n") : ""; }); } function savePolicyDetailFor(key) { const params = new URLSearchParams(window.location.search); const id = params.get("id"); fetch(`${BASE_URL}/${key}/${id}`, { method: "POST", headers: { "Authorization": "Bearer " + getToken(), "Content-Type": "application/json" }, body: JSON.stringify(document.getElementById(key).value.split("\n").map(l => l.trim()).filter(l => l != "")) }) .then(res => res.json()) .then(data => { alert(`${key} Saved Successfully`); }); } function validateAd() { document.getElementById("result").textContent = "Validating..."; fetch(BASE_URL + "/ads/validate", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") }, body: JSON.stringify({ url: document.getElementById("url").value, headlines: document.getElementById("headlines").value.split("\n").map((l) => l.trim()).filter((l) => l != ""), descriptions: document.getElementById("descriptions").value.split("\n").map((l) => l.trim()).filter((l) => l != ""), module: document.getElementById("module").value, config:{ article: "separator:none", open_ai_key: document.getElementById("open_ai_key").value.trim() != "" ? document.getElementById("open_ai_key").value.trim() : undefined } }) }) .then(res => res.json()) .then(data => { document.getElementById("result").textContent = JSON.stringify(data, null, 2); }); } function validateContent() { document.getElementById("result").textContent = "Validating..."; fetch(BASE_URL + "/ads/validate-content", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") }, body: JSON.stringify({ content: document.getElementById("content").value, module: document.getElementById("module").value, config: { content: "separator:none", open_ai_key: document.getElementById("open_ai_key").value.trim() != "" ? document.getElementById("open_ai_key").value.trim() : undefined } }) }) .then(res => res.json()) .then(data => { document.getElementById("result").textContent = JSON.stringify(data, null, 2); }); } function articleExtract() { document.getElementById("result").textContent = "Extracting..."; fetch(BASE_URL + "/article-extractor", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") }, body: JSON.stringify({ url: document.getElementById("url").value, open_ai_key: document.getElementById("open_ai_key").value.trim() != "" ? document.getElementById("open_ai_key").value.trim() : undefined }) }) .then(res => res.json()) .then(data => { document.getElementById("result").textContent = JSON.stringify(data, null, 2); document.getElementById("article").innerHTML = data.html ?? ""; }); } function validateData(data) { document.getElementById("result").textContent = "Validating..."; fetch(BASE_URL + "/ads/validate", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") }, body: JSON.stringify(data) }) .then(res => res.json()) .then(data => { document.getElementById("result").textContent = JSON.stringify(data, null, 2); }); }