/* OME Cockpit — Reports / export / compliance drawer */ (function () { const $ = (sel, root = document) => root.querySelector(sel); const $$ = (sel, root = document) => [...root.querySelectorAll(sel)]; const state = { tab: "analytics", fleet: null, compliance: null, warranties: null, reportDefs: null, jobs: null, catalogs: null, brief: null, outdatedOnly: true, search: "", hwDeviceId: null, filters: { model: "", connected: "all", // all | yes | no severity: "all", // all | critical | warning component: "all", // all | BIOS | iDRAC | ... warranty: "all", // all | expired | d30 | d90 | ok category: "", }, }; const TAB_HELP = { analytics: "Live KPIs for fleet health, Dell catalog compliance and warranty. Click a KPI to jump to a filtered view.", hardware: "Current physical inventory (OME) vs separate Dell max-expansion recommendations. RDP IPs resolved from OS hostname when available.", fleet: "Full inventory matrix with Service Tags. Filter by model and connection, then export CSV/JSON.", firmware: "Current vs Dell catalog versions (BIOS/iDRAC/…). Filter by component and severity; open Dell driver links.", warranty: "OME warranty records. Filter expired / expiring soon for customer attention.", ome: "Native OME ReportDefs, catalogs, baselines and recent jobs. Run a report or fetch results.", brief: "Printable customer one-pager with Service Tag appendix. Use Print → PDF for handoff.", }; function escapeHtml(s) { return String(s ?? "") .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function escapeAttr(s) { return escapeHtml(s).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", "#network-drawer", "#console-drawer", "#team-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 === "analytics") { const [fleet, compliance, warranties, brief] = await Promise.all([ apiGet("/api/reports/fleet"), apiGet("/api/compliance"), apiGet("/api/warranties"), apiGet("/api/reports/brief"), ]); state.fleet = fleet; state.compliance = compliance; state.warranties = warranties; state.brief = brief; renderAnalytics(mount); } else if (tab === "hardware") { if (!state.fleet) state.fleet = await apiGet("/api/reports/fleet"); renderHardware(mount); } else 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 uniqueModels(rows) { return [...new Set((rows || []).map((r) => r.model).filter(Boolean))].sort((a, b) => a.localeCompare(b)); } function applyBaseFilters(rows, opts = {}) { const f = state.filters; return (rows || []).filter((r) => { if (f.model && r.model !== f.model) return false; if (f.connected === "yes" && !r.connected) return false; if (f.connected === "no" && r.connected) return false; if (opts.searchFields && !matchSearch(r, opts.searchFields)) return false; return true; }); } function filterBar(opts = {}) { const models = opts.models || []; const showConnected = opts.connected !== false; const showSeverity = !!opts.severity; const showComponent = !!opts.componentOptions; const showWarranty = !!opts.warranty; const showDeviceSelect = !!opts.deviceSelect; const devices = opts.deviceSelect || []; const help = TAB_HELP[state.tab] || ""; return `
${escapeHtml(help)}
${opts.exports || ""}
${ showDeviceSelect ? `` : "" } ${ showConnected ? `` : "" } ${ showSeverity ? `` : "" } ${ showComponent ? `` : "" } ${ showWarranty ? `` : "" } ${ opts.outdatedToggle ? `` : "" }
${(opts.quick || []) .map( (q) => `` ) .join("")}
`; } function wireFilters(mount, rerender) { const sync = () => { state.search = $("#rpt-search")?.value || ""; state.filters.model = $("#flt-model")?.value || ""; state.filters.connected = $("#flt-connected")?.value || "all"; state.filters.severity = $("#flt-severity")?.value || "all"; state.filters.component = $("#flt-component")?.value || "all"; state.filters.warranty = $("#flt-warranty")?.value || "all"; const od = $("#rpt-outdated-only"); if (od) state.outdatedOnly = od.checked; rerender(); }; $("#rpt-search")?.addEventListener("input", sync); ["flt-model", "flt-connected", "flt-severity", "flt-component", "flt-warranty", "rpt-outdated-only"].forEach((id) => { $(`#${id}`)?.addEventListener("change", sync); }); $("#flt-device")?.addEventListener("change", (e) => { const id = Number(e.target.value); if (!id) return; state.hwDeviceId = id; rerender(); }); $("#rpt-clear-filters")?.addEventListener("click", () => { state.search = ""; state.filters = { model: "", connected: "all", severity: "all", component: "all", warranty: "all", category: "" }; state.outdatedOnly = state.tab === "firmware"; rerender(); }); $("#rpt-print")?.addEventListener("click", () => window.print()); $("#rpt-quick")?.addEventListener("click", (e) => { const btn = e.target.closest("[data-quick]"); if (!btn) return; const id = btn.dataset.quick; if (id && id.startsWith("cat:")) { state.filters.category = id.slice(4); rerender(); return; } if (id === "connected") state.filters.connected = "yes"; if (id === "offline") state.filters.connected = "no"; if (id === "outdated") { state.outdatedOnly = true; state.filters.severity = "critical"; if (state.tab !== "firmware") loadTab("firmware"); else rerender(); return; } if (id === "warranty-risk") { state.filters.warranty = "expired"; if (state.tab !== "warranty") loadTab("warranty"); else rerender(); return; } if (id === "all") { state.filters.connected = "all"; state.filters.severity = "all"; state.filters.warranty = "all"; state.filters.model = ""; state.filters.category = ""; state.filters.component = "all"; state.search = ""; } if (id === "bios") state.filters.component = "BIOS"; if (id === "idrac") state.filters.component = "iDRAC"; rerender(); }); } function toolbar(exports) { return filterBar({ exports, models: uniqueModels(state.fleet?.rows || state.compliance?.devices || []) }); } 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 countBy(items, keyFn) { const map = new Map(); for (const item of items) { const k = keyFn(item) || "Unknown"; map.set(k, (map.get(k) || 0) + 1); } return [...map.entries()].sort((a, b) => b[1] - a[1]); } function barRows(entries, maxN, fillClass, kind) { const top = entries.slice(0, maxN); const max = Math.max(1, ...top.map(([, n]) => n)); return top .map( ([label, n]) => `` ) .join(""); } function donut(slices, chartId) { const total = slices.reduce((s, x) => s + x.value, 0) || 1; let acc = 0; const parts = []; const meta = []; slices.forEach((s) => { const start = (acc / total) * 100; acc += s.value; const end = (acc / total) * 100; parts.push(`${s.color} ${start}% ${end}%`); meta.push({ key: s.key || s.label, label: s.label, value: s.value, color: s.color, startPct: start, endPct: end, }); }); const legend = meta .map( (s) => `
  • ` ) .join(""); return `
    `; } function closeAnContext() { const modal = $("#an-context-modal"); if (!modal) return; modal.classList.add("hidden"); modal.setAttribute("aria-hidden", "true"); const scrim = $("#scrim"); if (scrim?.dataset.mode === "an-context") { // keep reports drawer open underneath if ($("#reports-drawer")?.classList.contains("open")) { scrim.dataset.mode = "reports-drawer"; scrim.classList.add("open"); } else { scrim.classList.remove("open"); delete scrim.dataset.mode; } } } function openAnContext({ title, sub, pills, rows, actions }) { const modal = $("#an-context-modal"); if (!modal) return; $("#an-ctx-title").textContent = title || "Context"; $("#an-ctx-sub").textContent = sub || ""; $("#an-ctx-pills").innerHTML = (pills || []) .map((p) => `${escapeHtml(p)}`) .join(""); const list = $("#an-ctx-list"); if (!rows?.length) { list.innerHTML = `

    No matching records in the current OME snapshot.

    `; } else { list.innerHTML = ` ${(rows[0].cols || []).map((c) => ``).join("")} ${rows .map((r) => { const cells = (r.cells || []).map((c) => ``).join(""); const attr = r.jumpHw ? ` class="an-row-click" data-jump-hw="${r.jumpHw}"` : ""; return `${cells}`; }) .join("")}
    ${escapeHtml(c)}
    ${c}
    ${rows.length >= 80 ? `

    Showing first ${rows.length} rows.

    ` : ""}`; } $("#an-ctx-actions").innerHTML = (actions || []) .map( (a) => `` ) .join(""); modal.classList.remove("hidden"); modal.setAttribute("aria-hidden", "false"); const scrim = $("#scrim"); if (scrim) { scrim.classList.add("open"); scrim.dataset.mode = "an-context"; } $("#an-ctx-close")?.addEventListener("click", closeAnContext, { once: true }); $("#an-ctx-actions")?.querySelectorAll("[data-an-action]").forEach((btn) => { btn.addEventListener("click", () => { const id = btn.dataset.anAction; const act = (actions || []).find((x) => x.id === id); if (act?.run) act.run(); closeAnContext(); }); }); list.querySelectorAll("[data-jump-hw]").forEach((el) => { el.addEventListener("click", () => { const id = Number(el.dataset.jumpHw); if (!id) return; closeAnContext(); state.hwDeviceId = id; loadTab("hardware"); }); }); } function sliceFromDonutClick(btn, evt) { const wrap = btn.closest(".an-donut-wrap"); let meta = []; try { meta = JSON.parse(decodeURIComponent(wrap?.dataset.anMeta || "%5B%5D")); } catch (_) { meta = []; } if (!meta.length) return null; const rect = btn.getBoundingClientRect(); const cx = rect.left + rect.width / 2; const cy = rect.top + rect.height / 2; const dx = evt.clientX - cx; const dy = evt.clientY - cy; let deg = (Math.atan2(dx, -dy) * 180) / Math.PI; if (deg < 0) deg += 360; const pct = (deg / 360) * 100; return meta.find((s) => pct >= s.startPct && pct < s.endPct) || meta[meta.length - 1]; } function renderAnalytics(mount) { const fleet = state.fleet?.rows || []; const sum = state.fleet?.summary || state.brief?.summary || {}; const cs = state.compliance?.summary || {}; const comps = state.compliance?.components || []; const devices = state.compliance?.devices || []; const warranties = state.warranties?.items || []; const connected = fleet.filter((d) => d.connected).length; const offline = Math.max(0, fleet.length - connected); const outdatedDevs = cs.outdated_devices ?? devices.filter((d) => String(d.compliance_status || "").toUpperCase() === "CRITICAL").length; const critComps = comps.filter((c) => String(c.compliance_status || "").toUpperCase() === "CRITICAL").length; const warnComps = comps.filter((c) => String(c.compliance_status || "").toUpperCase() === "WARNING").length; const upgradeComps = comps.filter((c) => String(c.update_action || "").toUpperCase() === "UPGRADE").length; const expired = warranties.filter((w) => intOr(w.days_remaining) <= 0).length; const d30 = warranties.filter((w) => { const d = intOr(w.days_remaining); return d > 0 && d <= 30; }).length; const d90 = warranties.filter((w) => { const d = intOr(w.days_remaining); return d > 30 && d <= 90; }).length; const okW = warranties.filter((w) => intOr(w.days_remaining) > 90).length; const byComponent = countBy( comps.filter((c) => String(c.update_action || "").toUpperCase() === "UPGRADE"), (c) => shortComponent(c.component) ); const byModel = countBy( devices.filter( (d) => String(d.compliance_status || "").toUpperCase() === "CRITICAL" || String(d.firmware_status || "").toLowerCase().includes("non-compliant") ), (d) => d.model || "Unknown" ); const byStatus = countBy(comps, (c) => String(c.compliance_status || "UNKNOWN").toUpperCase()); const topOutdated = devices .filter( (d) => String(d.compliance_status || "").toUpperCase() === "CRITICAL" || String(d.firmware_status || "").toLowerCase().includes("non-compliant") ) .slice(0, 8); mount.innerHTML = ` ${filterBar({ models: uniqueModels(fleet), connected: true, exports: ` Firmware CSV Fleet CSV `, quick: [ { id: "all", label: "All", title: "Clear connection focus" }, { id: "connected", label: "Connected", title: "Jump to fleet · connected only", active: state.filters.connected === "yes" }, { id: "offline", label: "Offline", title: "Jump to fleet · offline only", active: state.filters.connected === "no" }, { id: "outdated", label: "Outdated firmware", title: "Open Firmware tab filtered to critical upgrades" }, { id: "warranty-risk", label: "Warranty risk", title: "Open Warranty tab · expired" }, ], })}
    Live OME analytics · baseline ${escapeHtml(cs.baseline_name || "—")} · last run ${escapeHtml(fmtDate(cs.last_run))}

    Compliance mix

    ${donut( [ { key: "CRITICAL", label: "Critical", value: critComps || Number(byStatus.find(([k]) => k === "CRITICAL")?.[1] || 0), color: "#ff5c5c" }, { key: "WARNING", label: "Warning", value: warnComps || Number(byStatus.find(([k]) => k === "WARNING")?.[1] || 0), color: "#ffb84d" }, { key: "OK", label: "Other / OK", value: Math.max(0, comps.length - critComps - warnComps), color: "#3dffa0", }, ], "compliance" )}

    ${upgradeComps} components marked UPGRADE against Dell catalog — click for list

    Outdated by component

    ${barRows(byComponent, 8, "crit", "component") || '

    No upgrade components

    '}

    Outdated by model

    ${barRows(byModel, 8, "warn", "model") || '

    No outdated models

    '}

    Connection state

    ${donut( [ { key: "connected", label: "Connected", value: connected, color: "#3dffa0" }, { key: "offline", label: "Offline", value: offline, color: "#e53935" }, ], "connection" )}

    ${escapeHtml(String(sum.total_watts != null ? Math.round(sum.total_watts) + " W sampled" : "Power samples from live poll"))}

    Warranty health

    ${donut( [ { key: "expired", label: "Expired", value: expired, color: "#ff5c5c" }, { key: "d30", label: "≤ 30 days", value: d30, color: "#ffb84d" }, { key: "d90", label: "31–90 days", value: d90, color: "#ff9a3c" }, { key: "ok", label: "> 90 days", value: okW, color: "#3dffa0" }, ], "warranty" )}

    ${warranties.length} warranty records from OME

    Top outdated systems

    ${ topOutdated .map( (d) => `` ) .join("") || `` }
    Service TagDeviceStatus
    ${escapeHtml(d.service_tag || "—")} ${escapeHtml(d.name || "—")}
    ${escapeHtml(d.model || "")}
    ${badge(d.compliance_status || d.firmware_status)}
    No outdated devices in baseline

    `; wireFilters(mount, () => { if (state.filters.connected !== "all") { loadTab("fleet"); return; } renderAnalytics(mount); }); $("#an-refresh")?.addEventListener("click", () => loadTab("analytics")); $("#an-goto-firmware")?.addEventListener("click", () => { state.outdatedOnly = true; state.filters.severity = "critical"; loadTab("firmware"); }); function ctxRowsFromComps(list) { return list.slice(0, 80).map((c) => ({ cols: ["ST", "Device", "Component", "Current → Catalog", "Status"], cells: [ `${escapeHtml(c.service_tag || "—")}`, escapeHtml(c.device_name || "—"), escapeHtml(shortComponent(c.component)), `${escapeHtml(c.current_version || "?")} → ${escapeHtml(c.catalog_version || "?")}`, badge(c.compliance_status || c.update_action), ], jumpHw: c.device_id || null, })); } function ctxRowsFromDevices(list) { return list.slice(0, 80).map((d) => ({ cols: ["ST", "Name", "Model", "Status"], cells: [ `${escapeHtml(d.service_tag || "—")}`, escapeHtml(d.name || d.device_name || "—"), escapeHtml(d.model || "—"), badge(d.compliance_status || d.firmware_status || (d.connected ? "connected" : "offline")), ], jumpHw: d.device_id || d.id || null, })); } function ctxRowsFromFleet(list) { return list.slice(0, 80).map((d) => ({ cols: ["ST", "Name", "Model", "iDRAC", "State"], cells: [ `${escapeHtml(d.service_tag || "—")}`, escapeHtml(d.name || "—"), escapeHtml(d.model || "—"), `${escapeHtml(d.idrac_ip || d.ip || "—")}`, d.connected ? `online` : `offline`, ], jumpHw: d.id || d.device_id || null, })); } function ctxRowsFromWarranty(list) { return list.slice(0, 80).map((w) => ({ cols: ["ST", "Device", "Level", "Ends", "Days left"], cells: [ `${escapeHtml(w.service_tag || "—")}`, escapeHtml(w.device_name || "—"), escapeHtml(w.service_level || "—"), escapeHtml(w.end_date || "—"), String(intOr(w.days_remaining)), ], jumpHw: w.device_id || null, })); } function handleAnContext(kind, key, count, evt) { let title = key; let sub = ""; let pills = [`${count ?? "?"} items`]; let rows = []; let actions = []; if (kind === "compliance") { if (key === "UPGRADE") { const list = comps.filter((c) => String(c.update_action || "").toUpperCase() === "UPGRADE"); title = "UPGRADE components"; sub = "Dell Online Baseline · update_action = UPGRADE"; rows = ctxRowsFromComps(list); pills = [`${list.length} components`, `baseline ${cs.baseline_name || "—"}`]; actions = [ { id: "fw", label: "Open Firmware / BIOS", primary: true, run: () => { state.outdatedOnly = true; loadTab("firmware"); }, }, ]; } else { const list = key === "OK" ? comps.filter((c) => { const s = String(c.compliance_status || "").toUpperCase(); return s !== "CRITICAL" && s !== "WARNING"; }) : comps.filter((c) => String(c.compliance_status || "").toUpperCase() === key); title = `Compliance · ${key}`; sub = "Component compliance from Dell catalog baseline"; rows = ctxRowsFromComps(list); pills = [`${list.length} components`, key]; actions = [ { id: "fw", label: "Open Firmware tab", primary: true, run: () => { state.outdatedOnly = key !== "OK"; state.filters.severity = key === "CRITICAL" ? "critical" : key === "WARNING" ? "warning" : "all"; loadTab("firmware"); }, }, ]; } } else if (kind === "component") { const list = comps.filter( (c) => String(c.update_action || "").toUpperCase() === "UPGRADE" && shortComponent(c.component) === key ); title = `Outdated · ${key}`; sub = "Components marked UPGRADE in this firmware family"; rows = ctxRowsFromComps(list); pills = [`${list.length} components`, key]; actions = [ { id: "fw", label: "Open Firmware filtered", primary: true, run: () => { state.outdatedOnly = true; state.filters.component = key; loadTab("firmware"); }, }, ]; } else if (kind === "model") { const list = devices.filter( (d) => (d.model || "Unknown") === key && (String(d.compliance_status || "").toUpperCase() === "CRITICAL" || String(d.firmware_status || "").toLowerCase().includes("non-compliant")) ); title = `Outdated · ${key}`; sub = "Non-compliant systems for this model"; rows = ctxRowsFromDevices(list); pills = [`${list.length} systems`, key]; actions = [ { id: "fw", label: "Open Firmware / BIOS", primary: true, run: () => { state.outdatedOnly = true; state.filters.model = key; loadTab("firmware"); }, }, ]; } else if (kind === "connection") { const list = fleet.filter((d) => (key === "connected" ? d.connected : !d.connected)); title = key === "connected" ? "Connected systems" : "Offline systems"; sub = "OME ConnectionState from live fleet snapshot"; rows = ctxRowsFromFleet(list); pills = [`${list.length} devices`, key === "connected" ? "online" : "offline"]; actions = [ { id: "fleet", label: "Open Fleet inventory", primary: true, run: () => { state.filters.connected = key === "connected" ? "yes" : "no"; loadTab("fleet"); }, }, ]; } else if (kind === "warranty") { const list = warranties.filter((w) => { const d = intOr(w.days_remaining); if (key === "expired") return d <= 0; if (key === "d30") return d > 0 && d <= 30; if (key === "d90") return d > 30 && d <= 90; return d > 90; }); const labels = { expired: "Expired", d30: "≤ 30 days", d90: "31–90 days", ok: "> 90 days" }; title = `Warranty · ${labels[key] || key}`; sub = "OME WarrantyService days_remaining buckets"; rows = ctxRowsFromWarranty(list); pills = [`${list.length} records`, labels[key] || key]; actions = [ { id: "war", label: "Open Warranty tab", primary: true, run: () => { state.filters.warranty = key === "expired" ? "expired" : key === "d30" ? "d30" : key === "d90" ? "d90" : "ok"; loadTab("warranty"); }, }, ]; } else if (kind === "kpi") { // handled separately return; } else { title = `${kind} · ${key}`; sub = "Analytics selection"; } openAnContext({ title, sub, pills, rows, actions }); } mount.querySelectorAll("[data-an-kind]").forEach((el) => { el.addEventListener("click", (evt) => { evt.preventDefault(); evt.stopPropagation(); let kind = el.dataset.anKind; let key = el.dataset.anKey; let count = el.dataset.anCount; if (el.dataset.anDonut === "1") { const hit = sliceFromDonutClick(el, evt); if (!hit) return; key = hit.key; count = hit.value; } if (!key) return; handleAnContext(kind, key, count, evt); }); }); mount.querySelectorAll("[data-jump]").forEach((el) => { el.addEventListener("click", (evt) => { evt.preventDefault(); const jump = el.dataset.jump; // KPI → context popup first if (el.classList.contains("an-kpi")) { let kind = "connection"; let key = "connected"; if (el.dataset.conn === "all") { openAnContext({ title: "Fleet devices", sub: "Full OME fleet snapshot", pills: [`${fleet.length} devices`, `${connected} online`, `${offline} offline`], rows: ctxRowsFromFleet(fleet), actions: [ { id: "fleet", label: "Open Fleet inventory", primary: true, run: () => { state.filters.connected = "all"; loadTab("fleet"); }, }, ], }); return; } if (el.dataset.conn === "yes") { handleAnContext("connection", "connected", connected); return; } if (el.dataset.conn === "no") { handleAnContext("connection", "offline", offline); return; } if (el.dataset.sev === "critical") { const label = (el.querySelector("span")?.textContent || "").toLowerCase(); if (label.includes("component")) { handleAnContext("compliance", "CRITICAL", critComps); } else { const list = devices.filter( (d) => String(d.compliance_status || "").toUpperCase() === "CRITICAL" || String(d.firmware_status || "").toLowerCase().includes("non-compliant") ); openAnContext({ title: "Outdated vs Dell", sub: "Systems non-compliant against Dell Online Baseline", pills: [`${list.length} systems`, `baseline ${cs.baseline_name || "—"}`], rows: ctxRowsFromDevices(list), actions: [ { id: "fw", label: "Open Firmware / BIOS", primary: true, run: () => { state.outdatedOnly = true; state.filters.severity = "critical"; loadTab("firmware"); }, }, ], }); } return; } if (el.dataset.war) { const list = warranties.filter((w) => { const d = intOr(w.days_remaining); return d <= 30; }); openAnContext({ title: "Warranty risk (≤30d / expired)", sub: "OME warranty records needing attention", pills: [`${list.length} records`, `${expired} expired`, `${d30} ≤30d`], rows: ctxRowsFromWarranty(list), actions: [ { id: "war", label: "Open Warranty tab", primary: true, run: () => { state.filters.warranty = "expired"; loadTab("warranty"); }, }, ], }); return; } } if (el.dataset.conn) state.filters.connected = el.dataset.conn; if (el.dataset.sev) { state.filters.severity = el.dataset.sev; state.outdatedOnly = true; } if (el.dataset.war) state.filters.warranty = el.dataset.war; loadTab(jump); }); }); mount.querySelectorAll("[data-jump-hw]").forEach((el) => { el.addEventListener("click", () => { const id = Number(el.dataset.jumpHw); if (!id) return; state.hwDeviceId = id; loadTab("hardware"); }); }); } function intOr(v) { const n = Number(v); return Number.isFinite(n) ? n : 0; } function shortComponent(name) { const s = String(name || "component"); if (/bios/i.test(s)) return "BIOS"; if (/idrac/i.test(s)) return "iDRAC"; if (/boss/i.test(s)) return "BOSS"; if (/cpld/i.test(s)) return "CPLD"; if (/nic|network|broadcom|mellanox|intel/i.test(s)) return "NIC / Network"; if (/perc|raid|storage/i.test(s)) return "RAID / Storage"; if (/openmanage|ome/i.test(s)) return "OME / Modular"; return s.length > 28 ? s.slice(0, 26) + "…" : s; } function renderHardware(mount) { const all = (state.fleet?.rows || []).filter( (r) => r.is_server || String(r.model || "").toLowerCase().includes("poweredge") ); const rows = applyBaseFilters(all, { searchFields: ["name", "service_tag", "ip", "model"] }); const selectedId = state.hwDeviceId || rows[0]?.id || all[0]?.id; if (selectedId) state.hwDeviceId = selectedId; mount.innerHTML = ` ${filterBar({ models: uniqueModels(all), connected: true, deviceSelect: rows.length ? rows : all, searchPlaceholder: "Filter server list…", exports: ``, quick: [ { id: "all", label: "All servers", title: "Clear filters" }, { id: "connected", label: "Connected", title: "Only connected", active: state.filters.connected === "yes" }, { id: "offline", label: "Offline", title: "Only offline", active: state.filters.connected === "no" }, ], })}

    Select a server above or use the Server dropdown…

    `; wireFilters(mount, () => renderHardware(mount)); $("#hw-reload")?.addEventListener("click", () => { if (state.hwDeviceId) loadHardwareDetail(state.hwDeviceId, true); }); mount.querySelectorAll("[data-hw-id]").forEach((btn) => { btn.addEventListener("click", () => { state.hwDeviceId = Number(btn.dataset.hwId); mount.querySelectorAll(".hw-item").forEach((el) => el.classList.toggle("active", Number(el.dataset.hwId) === state.hwDeviceId)); const sel = $("#flt-device"); if (sel) sel.value = String(state.hwDeviceId); loadHardwareDetail(state.hwDeviceId); }); }); if (selectedId) loadHardwareDetail(selectedId); } async function loadHardwareDetail(deviceId, force) { const el = $("#hw-detail"); if (!el) return; const liveHint = (state.fleet?.rows || []).find((r) => Number(r.id) === Number(deviceId)); const label = liveHint ? `${liveHint.service_tag || "—"} · ${liveHint.name || ""}` : `OME #${deviceId}`; const steps = [ "Connecting to OpenManage Enterprise…", "Reading processors & memory map…", "Reading disks, RAID & adapters…", "Reading OS / network inventory…", "Building current state vs Dell catalog…", ]; let stepIdx = 0; const t0 = performance.now(); let timer = null; let stepTimer = null; function paintLoading() { const sec = Math.max(0, Math.floor((performance.now() - t0) / 1000)); el.innerHTML = `

    Fetching hardware from OME

    ${escapeHtml(label)}

    ${escapeHtml(steps[stepIdx])}

    Waiting ${sec}s — full inventory can take up to a minute

    `; } paintLoading(); timer = setInterval(() => { const secEl = el.querySelector("#hw-wait-sec"); if (secEl) secEl.textContent = String(Math.max(0, Math.floor((performance.now() - t0) / 1000))); }, 250); stepTimer = setInterval(() => { stepIdx = Math.min(steps.length - 1, stepIdx + 1); const stepEl = el.querySelector("#hw-wait-step"); if (stepEl) stepEl.textContent = steps[stepIdx]; el.querySelectorAll(".hw-wait-checklist li").forEach((li, i) => { li.classList.toggle("on", i <= stepIdx); }); }, 4500); try { const data = await apiGet(`/api/devices/${deviceId}/expansion${force ? "?force=true" : ""}`); // Prefer live fleet node (has DNS-resolved RDP IPs) over detail snapshot const live = (state.fleet?.rows || []).find((r) => Number(r.id) === Number(deviceId)); if (live && data.device) { data.device = { ...data.device, rdp_host: live.rdp_host || data.device.rdp_host, rdp_ips: live.rdp_ips || data.device.rdp_ips || [], os_hostname: live.os_hostname || data.device.os_hostname, idrac_ip: live.idrac_ip || data.device.idrac_ip || data.device.ip, is_windows: live.is_windows || data.device.is_windows, }; } el.innerHTML = renderExpansionHtml(data); el.querySelector("#hw-rdp-btn")?.addEventListener("click", () => { const host = el.querySelector("#hw-rdp-btn")?.dataset?.rdpHost; window.cockpitRdp?.open({ ...(data.device || {}), ip: host || data.device?.rdp_host || data.device?.ip, host: host || data.device?.rdp_host || data.device?.ip, }); }); } catch (err) { el.innerHTML = ` `; el.querySelector("#hw-wait-retry")?.addEventListener("click", () => loadHardwareDetail(deviceId, true)); } finally { clearInterval(timer); clearInterval(stepTimer); } } function renderExpansionHtml(data) { const d = data.device || {}; const x = data.expansion || {}; const cur = x.current || {}; const exp = x.expansion || {}; const findings = x.findings || []; const memNow = cur.memory || {}; const cpuNow = cur.cpu || {}; const diskNow = cur.disks || {}; const memExp = exp.memory || {}; const cpuExp = exp.cpu || {}; const diskExp = exp.disks || {}; const pcieExp = exp.pcie || {}; const modules = memNow.modules || []; const processors = cpuNow.processors || []; const disks = diskNow.items || []; const adapters = cur.adapters || []; const osRows = cur.os || []; const slotMap = memExp.slot_map || []; const banks = [...new Set(slotMap.map((s) => s.cpu_bank).filter(Boolean))]; const rdpHost = d.rdp_host || (d.rdp_ips && d.rdp_ips[0]) || ""; const rdpIps = d.rdp_ips || []; const idracIp = d.idrac_ip || d.ip || ""; const bankHtml = banks .map((bank) => { const bankSlots = slotMap.filter((s) => s.cpu_bank === bank).sort((a, b) => (a.slot_num || 0) - (b.slot_num || 0)); const filled = bankSlots.filter((s) => s.populated).length; return `

    CPU ${escapeHtml(bank)} · ${filled}/${bankSlots.length} populated (catalog map)

    ${bankSlots .map((s) => { const title = s.populated ? `${s.slot}: ${s.size_gb || "?"} GB @ ${s.operating_mts || s.rated_mts || "?"} MT/s · ${s.part_number || ""}` : `${s.slot}: EMPTY (catalog)`; return `
    ${escapeHtml(s.slot)} ${s.populated ? escapeHtml(String(s.size_gb ?? "?")) + "G" : "—"} ${s.populated ? escapeHtml(String(s.operating_mts || s.rated_mts || "")) : "empty"}
    `; }) .join("")}
    `; }) .join(""); const dash = (v) => (v == null || v === "" ? "—" : v); const catalogBadge = exp.catalog_known ? `Catalog: ${escapeHtml(exp.catalog_model || "")}` : `No catalog max for this model`; return `

    ${escapeHtml(d.name || "Device")}

    ${escapeHtml(d.service_tag || "—")} · ${escapeHtml(d.model || "—")}

    iDRAC ${escapeHtml(idracIp || "—")} ${d.os_hostname ? `OS host ${escapeHtml(d.os_hostname)}` : ""} ${rdpIps.length ? `RDP IP(s) ${escapeHtml(rdpIps.join(", "))}` : `RDP IP not resolved`} ${rdpHost ? `` : ""}

    ${osRows .map( (o) => `

    ${escapeHtml([o.os_name, o.os_version, o.hostname].filter(Boolean).join(" · ") || "OS inventory empty")}

    ` ) .join("")}
    ${catalogBadge}

    Current state · physical (OME live)

    Only what OME reports as installed — not Dell maximums.

    ${dash(memNow.installed_gb)} GBRAM installed
    ${dash(memNow.dimm_count)}DIMM modules
    ${dash(cpuNow.sockets_populated)}CPU sockets filled
    ${dash(cpuNow.cores_total)}Cores total
    ${dash(diskNow.count)}Disks installed
    ${dash(diskNow.capacity_gb)} GBDisk capacity sum

    Memory modules (installed)

    Rated MT/s: ${escapeHtml((memNow.rated_mts || []).join(", ") || "—")} · Operating MT/s: ${escapeHtml((memNow.operating_mts || []).join(", ") || "—")}

    ${modules .map( (s) => `` ) .join("") || ""}
    SlotSizeRatedOperatingTypePartSerial
    ${escapeHtml(s.slot)} ${s.size_gb ?? "—"} GB ${escapeHtml(String(s.rated_mts ?? "—"))} ${escapeHtml(String(s.operating_mts ?? "—"))} ${escapeHtml(s.type || "—")} ${escapeHtml(s.part_number || "—")} ${escapeHtml(s.serial || "—")}
    No DIMMs in OME inventory

    Processors (installed)

    Disks (installed)

    ${disks .map( (disk) => `` ) .join("") || ""}
    BayModelMediaSize (GB)BusStatusSerial
    ${escapeHtml(String(disk.bay ?? "—"))} ${escapeHtml(disk.model || "—")} ${escapeHtml(disk.media || "—")} ${escapeHtml(String(disk.size_gb ?? "—"))} ${escapeHtml(disk.bus || "—")} ${escapeHtml(String(disk.status || "—"))} ${escapeHtml(disk.serial || "—")}
    No disks in inventory

    Adapters seen by OME

    ${adapters .slice(0, 40) .map( (c) => `` ) .join("") || ""}
    SlotDescriptionType
    ${escapeHtml(c.slot || "—")} ${escapeHtml(c.description || "—")} ${escapeHtml(c.slot_type || "—")}
    No adapters

    Max expansion · recommendations (Dell catalog)

    ${escapeHtml(exp.source || "")} — separate from live inventory. Confirm against Tech Specs for this Service Tag BOM.

    ${memExp.max_capacity_tb != null ? memExp.max_capacity_tb + " TB" : "—"}Max memory
    ${memExp.headroom_gb != null ? memExp.headroom_gb + " GB" : "—"}Headroom vs installed
    ${memExp.dimms_installed ?? "—"}/${memExp.dimm_slots_max ?? "—"}DIMMs used / max slots
    ${cpuExp.sockets_populated ?? "—"}/${cpuExp.sockets_max ?? "—"}CPU sockets used / max
    ${diskExp.drives_installed ?? "—"}/${diskExp.bays_max ?? "—"}Disks / max bays
    ${pcieExp.slots_max ?? "—"}Max PCIe (catalog)

    Memory: ${escapeHtml(memExp.note || "—")}

    CPU: ${escapeHtml(cpuExp.note || "—")}

    Disks: ${escapeHtml(diskExp.note || "—")}

    PCIe: ${escapeHtml(pcieExp.note || "—")}

    Supported memory: ${escapeHtml((memExp.supported_types || []).join(", ") || "—")} · catalog max rated ${dash(memExp.max_rated_mts)} MT/s

    Dell docs ${(exp.docs || []) .map((doc) => { const kind = doc.kind || (String(doc.title || "").toLowerCase().includes("spec") ? "spec" : "doc"); return `${escapeHtml(doc.title)}`; }) .join("")} Support · ST ${escapeHtml(d.service_tag || "—")}
    ${ exp.catalog_known ? `

    Catalog DIMM map (empty = expansion candidate)

    ${bankHtml || "

    No slot map

    "}` : `

    No Cockpit catalog for ${escapeHtml(d.model || "this model")} — maxima above are blank on purpose (not guessed).

    ` }
    ${findings .map((f) => `
    ${escapeHtml(f.text)}
    `) .join("") || `
    No population warnings from live inventory vs catalog rules.
    `}

    Dell guidance (not current inventory)

    Installation / population

      ${(exp.best_practices || []).map((t) => `
    • ${escapeHtml(t)}
    • `).join("") || "
    • "}

    Performance

      ${(exp.performance_notes || []).map((t) => `
    • ${escapeHtml(t)}
    • `).join("") || "
    • "}
    `; } function renderFleet(mount) { const all = state.fleet?.rows || []; const rows = applyBaseFilters(all, { searchFields: ["name", "service_tag", "ip", "model", "subnet"] }); mount.innerHTML = filterBar({ models: uniqueModels(all), connected: true, exports: ` CSV JSON `, quick: [ { id: "all", label: "All", title: "Clear filters" }, { id: "connected", label: "Connected", active: state.filters.connected === "yes" }, { id: "offline", label: "Offline", active: state.filters.connected === "no" }, ], }) + `
    ${rows.length} / ${all.length} devices shown · Service Tags + warranty joined
    ${rows .map( (r) => `` ) .join("")}
    NameService TagModelIPConnectedPowerWarranty endDays left
    ${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 ?? "—"}
    `; wireFilters(mount, () => renderFleet(mount)); mount.querySelectorAll("[data-open-hw]").forEach((tr) => { tr.addEventListener("click", () => { state.hwDeviceId = Number(tr.dataset.openHw); loadTab("hardware"); }); }); } function renderFirmware(mount) { const sum = state.compliance?.summary || {}; let comps = state.compliance?.components || []; const compOpts = [...new Set(comps.map((c) => shortComponent(c.component)))].sort(); 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" ); } if (state.filters.severity === "critical") { comps = comps.filter((c) => String(c.compliance_status || "").toUpperCase() === "CRITICAL"); } else if (state.filters.severity === "warning") { comps = comps.filter((c) => String(c.compliance_status || "").toUpperCase() === "WARNING"); } if (state.filters.component && state.filters.component !== "all") { comps = comps.filter((c) => shortComponent(c.component) === state.filters.component); } if (state.filters.model) { comps = comps.filter((c) => c.model === state.filters.model); } comps = comps.filter((c) => matchSearch(c, ["device_name", "service_tag", "model", "component", "ip"])); mount.innerHTML = filterBar({ models: uniqueModels(state.compliance?.devices || []), connected: false, severity: true, componentOptions: compOpts, outdatedToggle: true, exports: ` CSV JSON `, quick: [ { id: "all", label: "All", title: "Clear severity/component filters" }, { id: "bios", label: "BIOS", title: "Only PowerEdge BIOS rows", active: state.filters.component === "BIOS" }, { id: "idrac", label: "iDRAC", title: "Only iDRAC / Lifecycle Controller", active: state.filters.component === "iDRAC" }, { id: "outdated", label: "Critical", title: "Critical only", active: state.filters.severity === "critical" }, ], }) + `
    Baseline ${escapeHtml(sum.baseline_name || "—")} · showing ${comps.length} rows · outdated devices ${sum.outdated_devices ?? "—"}
    ${comps .map( (c) => `` ) .join("")}
    Service TagDeviceComponentCurrentDell catalogActionStatusDell.com
    ${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` : "—"}
    `; wireFilters(mount, () => renderFirmware(mount)); } function renderWarranty(mount) { let items = state.warranties?.items || []; if (state.filters.warranty === "expired") items = items.filter((w) => intOr(w.days_remaining) <= 0); else if (state.filters.warranty === "d30") items = items.filter((w) => { const d = intOr(w.days_remaining); return d > 0 && d <= 30; }); else if (state.filters.warranty === "d90") items = items.filter((w) => { const d = intOr(w.days_remaining); return d > 30 && d <= 90; }); else if (state.filters.warranty === "ok") items = items.filter((w) => intOr(w.days_remaining) > 90); if (state.filters.model) items = items.filter((w) => w.model === state.filters.model); items = items.filter((w) => matchSearch(w, ["device_name", "service_tag", "model", "service_level"])); mount.innerHTML = filterBar({ models: uniqueModels(state.warranties?.items || []), connected: false, warranty: true, exports: ` CSV JSON `, quick: [ { id: "all", label: "All", title: "Clear warranty filter" }, { id: "warranty-risk", label: "Expired", title: "Expired only", active: state.filters.warranty === "expired" }, ], }) + `
    ${items.length} warranty records shown
    ${items .map( (w) => `` ) .join("")}
    Service TagDeviceModelService levelStartEndDays left
    ${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 ?? "—"}
    `; wireFilters(mount, () => renderWarranty(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"])); const categories = [...new Set(defs.map((d) => d.category).filter(Boolean))].sort(); const shown = state.filters.category ? filtered.filter((d) => d.category === state.filters.category) : filtered; mount.innerHTML = ` ${filterBar({ models: [], connected: false, searchPlaceholder: "Filter OME report definitions…", exports: ``, quick: categories.slice(0, 8).map((c) => ({ id: `cat:${c}`, label: c, title: `Show ReportDefs in category ${c}`, active: state.filters.category === c, })), })}

    Dell catalogs

    Baselines

    Recent OME jobs

    OME ReportDefs (${shown.length})

    ${shown .map( (d) => `` ) .join("")}
    NameCategoryColumnsLast run
    ${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))}
    `; wireFilters(mount, () => renderOme(mount, baselines)); $("#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 (err) { alert("Run failed: " + err.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 (err) { if (out) out.textContent = String(err.message || err); } }); }); } function renderBrief(mount) { const b = state.brief || {}; const sum = b.summary || {}; const cs = b.compliance_summary || {}; const ome = b.ome || {}; mount.innerHTML = `
    JSON brief Fleet CSV Firmware CSV Warranty CSV
    Dell

    Customer fleet brief

    ${escapeHtml(ome.name || "OM Enterprise")} ${escapeHtml(ome.version || "")} · ${escapeHtml(ome.fqdn || "")}

    Generated ${escapeHtml(new Date((b.generated_at || 0) * 1000).toLocaleString())}

    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

    Systems out of date (Dell catalog)

    Warranty attention (≤ 90 days)

    Device appendix (Service Tags)

    ${(b.fleet || []) .map( (r) => `` ) .join("")}
    Service TagNameModelIPConnected
    ${escapeHtml(r.service_tag || "—")} ${escapeHtml(r.name || "—")} ${escapeHtml(r.model || "—")} ${escapeHtml(r.ip || "—")} ${r.connected ? "Yes" : "No"}
    `; wireCommon(mount); } function wireCommon(mount) { // legacy no-op kept for brief; prefer wireFilters $("#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", () => { const mode = $("#scrim")?.dataset.mode; if (mode === "an-context") closeAnContext(); else if (mode === "reports-drawer") closeReports(); }); // Extend ops closeDrawers awareness via custom event window.addEventListener("cockpit-close-drawers", closeReports); } window.cockpitReports = { open: openReports, close: closeReports, loadTab, closeAnContext }; if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init); else init(); })();