// intelligence → knowledge table // filter/sort/pagination persisted via url query params // depends on: app.js, intel-shared.js let knowledgeOffset = 0; function syncUrl() { const companyId = document.getElementById("i-company").value; const type = document.getElementById("i-type").value; const sort = document.getElementById("i-sort").value; queryWrite({ company_id: companyId, type: type, sort: sort && sort !== "id" ? sort : "", offset: knowledgeOffset > 0 ? knowledgeOffset : "", }); } async function loadKnowledge() { // fall back to url params when the company dropdown hasn't populated // yet — lets init fire all api calls in parallel const companyId = document.getElementById("i-company").value || queryGet("company_id"); const type = document.getElementById("i-type").value; const sort = document.getElementById("i-sort").value; const params = new URLSearchParams({ limit: PAGE, offset: knowledgeOffset }); if (companyId) params.set("company_id", companyId); if (type) params.set("type", type); if (sort) params.set("sort", sort); const data = await api(`/admin/api/intelligence/knowledge?${params}`); intelRows = data.rows; document.getElementById("intel-thead").innerHTML = ` IDCompanyEventTypeDataEvent date`; document.getElementById("intel-tbody").innerHTML = data.rows.map(r => { let parsed = {}; try { parsed = JSON.parse(r.data); } catch (_) {} const summary = Object.values(parsed).filter(v => typeof v === "string").join(" · ").slice(0, 120); return ` ${r.id} ${escapeHtml(r.company_name)} ${r.event_id} ${escapeHtml(r.type)} ${escapeHtml(summary)} ${r.event_date ? r.event_date.slice(0,10) : "—"} `; }).join(""); const total = data.total; document.getElementById("iPageInfo").textContent = `${knowledgeOffset + 1}–${Math.min(knowledgeOffset + PAGE, total)} of ${total.toLocaleString()}`; document.getElementById("iPrevBtn").disabled = knowledgeOffset === 0; document.getElementById("iNextBtn").disabled = knowledgeOffset + PAGE >= total; } document.addEventListener("DOMContentLoaded", async () => { document.getElementById("iPrevBtn").onclick = () => { knowledgeOffset = Math.max(0, knowledgeOffset - PAGE); syncUrl(); loadKnowledge(); }; document.getElementById("iNextBtn").onclick = () => { knowledgeOffset += PAGE; syncUrl(); loadKnowledge(); }; document.getElementById("i-filter-btn").onclick = () => { knowledgeOffset = 0; syncUrl(); loadKnowledge(); }; // restore non-async inputs from url up-front (company_id is handled // inside loadIntelCompanies once the dropdown has options) queryApplyToInputs({ "i-type": "type", "i-sort": "sort", }); knowledgeOffset = parseInt(queryGet("offset"), 10) || 0; // fire all three calls concurrently — loadKnowledge reads company_id // from the url when the select isn't populated yet await Promise.all([ loadIntelStatsRow(), loadIntelCompanies(), loadKnowledge(), ]); });