/* OME Cockpit — Reports / export / compliance drawer */
(function () {
const $ = (sel, root = document) => root.querySelector(sel);
const $$ = (sel, root = document) => [...root.querySelectorAll(sel)];
const state = {
tab: "fleet",
fleet: null,
compliance: null,
warranties: null,
reportDefs: null,
jobs: null,
catalogs: null,
brief: null,
outdatedOnly: true,
search: "",
};
function escapeHtml(s) {
return String(s ?? "")
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """);
}
function fmtDate(v) {
if (!v) return "—";
return String(v).replace(/\.\d+$/, "").slice(0, 19);
}
function badge(status) {
const s = String(status || "").toLowerCase();
let cls = "unk";
if (s.includes("critical") || s === "outdated" || s.includes("non-compliant")) cls = "bad";
else if (s.includes("warning")) cls = "warn";
else if (s.includes("normal") || s === "current" || s.includes("compliant") || s === "ok") cls = "ok";
return `${escapeHtml(status || "—")}`;
}
function downloadUrl(kind, fmt) {
const q = new URLSearchParams({ fmt });
if (state.outdatedOnly && kind === "firmware") q.set("force", "0");
return `/api/export/${kind}?${q.toString()}`;
}
async function apiGet(url) {
const r = await fetch(url);
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
return r.json();
}
function openReports() {
const drawer = $("#reports-drawer");
const scrim = $("#scrim");
if (!drawer) return;
["#chat-drawer", "#ops-drawer", "#ai-drawer"].forEach((id) => {
const el = $(id);
if (el) {
el.classList.remove("open");
el.setAttribute("aria-hidden", "true");
}
});
drawer.classList.add("open");
drawer.setAttribute("aria-hidden", "false");
if (scrim) {
scrim.classList.add("open");
scrim.dataset.mode = "reports-drawer";
}
loadTab(state.tab);
}
function closeReports() {
const drawer = $("#reports-drawer");
const scrim = $("#scrim");
drawer?.classList.remove("open");
drawer?.setAttribute("aria-hidden", "true");
if (scrim?.dataset.mode === "reports-drawer") {
scrim.classList.remove("open");
delete scrim.dataset.mode;
}
}
async function loadTab(tab) {
state.tab = tab;
$$("#reports-tabs .chip").forEach((c) => c.classList.toggle("active", c.dataset.tab === tab));
const mount = $("#reports-mount");
if (!mount) return;
mount.innerHTML = `
Loading ${escapeHtml(tab)}…
`;
try {
if (tab === "fleet") {
state.fleet = await apiGet("/api/reports/fleet");
renderFleet(mount);
} else if (tab === "firmware") {
state.compliance = await apiGet("/api/compliance");
renderFirmware(mount);
} else if (tab === "warranty") {
state.warranties = await apiGet("/api/warranties");
renderWarranty(mount);
} else if (tab === "ome") {
const [defs, jobs, catalogs, baselines] = await Promise.all([
apiGet("/api/ome/report-defs"),
apiGet("/api/ome/jobs"),
apiGet("/api/catalogs"),
apiGet("/api/baselines"),
]);
state.reportDefs = defs;
state.jobs = jobs;
state.catalogs = catalogs;
renderOme(mount, baselines);
} else if (tab === "brief") {
state.brief = await apiGet("/api/reports/brief");
renderBrief(mount);
}
} catch (err) {
mount.innerHTML = `Failed: ${escapeHtml(err.message)}
`;
}
}
function toolbar(exports) {
return `
`;
}
function matchSearch(row, fields) {
const q = state.search.trim().toLowerCase();
if (!q) return true;
return fields.some((f) => String(row[f] ?? "").toLowerCase().includes(q));
}
function renderFleet(mount) {
const rows = (state.fleet?.rows || []).filter((r) =>
matchSearch(r, ["name", "service_tag", "ip", "model", "subnet"])
);
mount.innerHTML =
toolbar(`
CSV
JSON
`) +
`${rows.length} devices · Service Tags + warranty joined
| Name | Service Tag | Model | IP | Connected | Power | Warranty end | Days left |
${rows
.map(
(r) => `
| ${escapeHtml(r.name)} |
${escapeHtml(r.service_tag || "—")} |
${escapeHtml(r.model || "—")} |
${escapeHtml(r.ip || "—")} |
${r.connected ? badge("CONNECTED") : badge("OFFLINE")} |
${r.watts != null ? Math.round(r.watts) + " W" : "—"} |
${escapeHtml(fmtDate(r.warranty_end))} |
${r.warranty_days_remaining ?? "—"} |
`
)
.join("")}
`;
wireCommon(mount);
}
function renderFirmware(mount) {
const sum = state.compliance?.summary || {};
let comps = state.compliance?.components || [];
if (state.outdatedOnly) {
comps = comps.filter(
(c) =>
String(c.update_action || "").toUpperCase() === "UPGRADE" ||
String(c.compliance_status || "").toUpperCase() === "CRITICAL" ||
String(c.compliance_status || "").toUpperCase() === "WARNING"
);
}
comps = comps.filter((c) =>
matchSearch(c, ["device_name", "service_tag", "model", "component", "ip"])
);
mount.innerHTML =
toolbar(`
CSV
JSON
`) +
`
Baseline ${escapeHtml(sum.baseline_name || "—")}
· Dell catalog compare · outdated devices ${sum.outdated_devices ?? "—"}
· components ${comps.length}
| Service Tag | Device | Component | Current | Dell catalog | Action | Status | Dell.com |
${comps
.map(
(c) => `
${escapeHtml(c.service_tag || "—")} |
${escapeHtml(c.device_name || "—")} ${escapeHtml(c.model || "")} |
${escapeHtml(c.component || "—")} |
${escapeHtml(c.current_version || "—")} |
${escapeHtml(c.catalog_version || "—")} |
${escapeHtml(c.update_action || "—")} |
${badge(c.compliance_status || c.status_badge)} |
${c.dell_uri ? `Driver` : "—"} |
`
)
.join("")}
`;
wireCommon(mount);
$("#rpt-outdated-only")?.addEventListener("change", (e) => {
state.outdatedOnly = e.target.checked;
renderFirmware(mount);
});
}
function renderWarranty(mount) {
const items = (state.warranties?.items || []).filter((w) =>
matchSearch(w, ["device_name", "service_tag", "model", "service_level"])
);
mount.innerHTML =
toolbar(`
CSV
JSON
`) +
`${items.length} warranty records from OME WarrantyService
| Service Tag | Device | Model | Service level | Start | End | Days left |
${items
.map(
(w) => `
${escapeHtml(w.service_tag || "—")} |
${escapeHtml(w.device_name || "—")} |
${escapeHtml(w.model || "—")} |
${escapeHtml(w.service_level || "—")} |
${escapeHtml(fmtDate(w.start_date))} |
${escapeHtml(fmtDate(w.end_date))} |
${w.days_remaining ?? "—"} |
`
)
.join("")}
`;
wireCommon(mount);
}
function renderOme(mount, baselines) {
const defs = state.reportDefs?.items || [];
const jobs = state.jobs?.items || [];
const cats = state.catalogs?.items || [];
const filtered = defs.filter((d) => matchSearch(d, ["name", "description", "category"]));
mount.innerHTML = `
Dell catalogs
${cats
.map(
(c) =>
`- ${escapeHtml(c.repository_name || c.filename || "#" + c.id)}
${escapeHtml(c.repository_type || "")} · ${escapeHtml(fmtDate(c.last_updated))}
`
)
.join("") || "- No catalogs
"}
Baselines
${(baselines?.items || [])
.map(
(b) =>
`- ${escapeHtml(b.name)} ${badge(b.compliance_status)}
critical ${b.critical ?? 0} · last ${escapeHtml(fmtDate(b.last_run))}
`
)
.join("")}
Recent OME jobs
${jobs
.slice(0, 20)
.map(
(j) =>
`- ${escapeHtml(j.name || "#" + j.id)} ${badge(j.status)}
${escapeHtml(j.job_type || "")}
`
)
.join("") || "- No jobs returned
"}
OME ReportDefs (${filtered.length})
| Name | Category | Columns | Last run | |
${filtered
.map(
(d) => `
| ${escapeHtml(d.name)} ${escapeHtml(d.description || "")} |
${escapeHtml(d.category || "—")} |
${escapeHtml((d.columns || []).slice(0, 4).join(", "))}${(d.columns || []).length > 4 ? "…" : ""} |
${escapeHtml(fmtDate(d.last_run))} |
|
`
)
.join("")}
`;
wireCommon(mount);
$("#rpt-refresh-ome")?.addEventListener("click", () => loadTab("ome"));
mount.querySelectorAll("[data-run-report]").forEach((btn) => {
btn.addEventListener("click", async () => {
const id = Number(btn.dataset.runReport);
btn.disabled = true;
try {
const res = await fetch("/api/ome/reports/run", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ report_def_id: id }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail || res.statusText);
alert(`OME report job started: ${data.job_id}`);
} catch (e) {
alert("Run failed: " + e.message);
} finally {
btn.disabled = false;
}
});
});
mount.querySelectorAll("[data-fetch-report]").forEach((btn) => {
btn.addEventListener("click", async () => {
const id = Number(btn.dataset.fetchReport);
const out = $("#rpt-ome-results");
out?.classList.remove("hidden");
if (out) out.textContent = "Loading…";
try {
const data = await apiGet(`/api/ome/reports/${id}/results`);
if (out) out.textContent = JSON.stringify(data, null, 2);
} catch (e) {
if (out) out.textContent = String(e.message || e);
}
});
});
}
function renderBrief(mount) {
const b = state.brief || {};
const sum = b.summary || {};
const cs = b.compliance_summary || {};
const ome = b.ome || {};
mount.innerHTML = `
Executive summary
${sum.total ?? "—"}Devices
${sum.connected ?? "—"}Connected
${cs.outdated_devices ?? "—"}Outdated vs Dell catalog
${sum.alerts_critical ?? "—"}Critical alerts
Baseline: ${escapeHtml(cs.baseline_name || "—")}
(${escapeHtml(cs.compliance_status || "—")}) · last run ${escapeHtml(fmtDate(cs.last_run))}
Critical alerts
${(b.critical_alerts || [])
.map(
(a) =>
`- ${escapeHtml(a.device || "—")} ${escapeHtml(a.ip || "")} — ${escapeHtml((a.message || "").slice(0, 160))}
`
)
.join("") || "- None in snapshot
"}
Systems out of date (Dell catalog)
${(b.outdated_devices || [])
.map(
(d) =>
`${escapeHtml(d.service_tag || "—")} ${escapeHtml(d.name || "")} · ${escapeHtml(d.model || "")} · ${escapeHtml(d.compliance_status || d.firmware_status || "")} `
)
.join("") || "- No outdated devices in baseline report
"}
Warranty attention (≤ 90 days)
${(b.warranty_expiring || [])
.map(
(w) =>
`${escapeHtml(w.service_tag || "—")} ${escapeHtml(w.device_name || "")} · ends ${escapeHtml(fmtDate(w.end_date))} · ${w.days_remaining} days `
)
.join("") || "- No warranties expiring within 90 days
"}
Device appendix (Service Tags)
| Service Tag | Name | Model | IP | Connected |
${(b.fleet || [])
.map(
(r) => `
${escapeHtml(r.service_tag || "—")} |
${escapeHtml(r.name || "—")} |
${escapeHtml(r.model || "—")} |
${escapeHtml(r.ip || "—")} |
${r.connected ? "Yes" : "No"} |
`
)
.join("")}
`;
wireCommon(mount);
}
function wireCommon(mount) {
$("#rpt-search")?.addEventListener("input", (e) => {
state.search = e.target.value;
// re-render current tab with filter
if (state.tab === "fleet" && state.fleet) renderFleet(mount);
else if (state.tab === "firmware" && state.compliance) renderFirmware(mount);
else if (state.tab === "warranty" && state.warranties) renderWarranty(mount);
else if (state.tab === "ome" && state.reportDefs) loadTab("ome");
});
$("#rpt-print")?.addEventListener("click", () => window.print());
}
function init() {
$("#btn-reports")?.addEventListener("click", openReports);
$("#btn-reports-close")?.addEventListener("click", closeReports);
$("#reports-tabs")?.addEventListener("click", (e) => {
const chip = e.target.closest("[data-tab]");
if (!chip) return;
state.search = "";
loadTab(chip.dataset.tab);
});
$("#scrim")?.addEventListener("click", () => {
if ($("#scrim")?.dataset.mode === "reports-drawer") closeReports();
});
// Extend ops closeDrawers awareness via custom event
window.addEventListener("cockpit-close-drawers", closeReports);
}
window.cockpitReports = { open: openReports, close: closeReports, loadTab };
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init);
else init();
})();