From 0bc30c34fb6f7aefa75b10caf23ff548239bda6a Mon Sep 17 00:00:00 2001 From: Micha Date: Mon, 6 Apr 2026 07:36:05 +0000 Subject: [PATCH] feat: update network-health renderer for new scrutiny/adguard UI --- .../assets/js/renderers/network-health.js | 131 +++++++++--------- 1 file changed, 65 insertions(+), 66 deletions(-) diff --git a/apps/dashboard/assets/js/renderers/network-health.js b/apps/dashboard/assets/js/renderers/network-health.js index 2a31963..c69bd7c 100644 --- a/apps/dashboard/assets/js/renderers/network-health.js +++ b/apps/dashboard/assets/js/renderers/network-health.js @@ -1,85 +1,84 @@ -function statusTone(status) { - if (status === "failed" || status === "offline") return "offline"; - if (status === "unknown") return "warning"; - return "online"; -} - -function deviceStatusIcon(status) { - if (status === "passed") return "online"; - if (status === "failed") return "offline"; - return "warning"; -} - -function fmtNumber(n) { - if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; - if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`; - return String(n); -} - export function renderNetworkHealth(state) { - renderAdGuard(state.data.adguard); - renderScrutiny(state.data.scrutiny); + _renderAdGuard(state.adguard || {}); + _renderScrutiny(state.scrutiny || {}); } -function renderAdGuard(adguard) { +function _renderAdGuard(d) { + const online = d.source_status === "online"; + const pill = document.getElementById("adguard-pill"); - const totalEl = document.getElementById("adguard-total"); - const blockedEl = document.getElementById("adguard-blocked"); - const blockedPctEl = document.getElementById("adguard-blocked-pct"); - const latencyEl = document.getElementById("adguard-latency"); - const barFill = document.getElementById("adguard-bar-fill"); + if (pill) { + pill.textContent = online ? "ONLINE" : "OFFLINE"; + pill.className = "status-pill " + (online ? "pill-online" : "pill-offline"); + } - if (!pill) return; + const set = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; }; - const online = adguard.source_status === "online"; - pill.className = `status-pill ${online ? "online" : "offline"}`; - pill.textContent = online ? "Online" : "Offline"; + if (online) { + set("adguard-total", fmtK(d.total_queries)); + set("adguard-blocked", fmtK(d.blocked_queries)); + set("adguard-blocked-pct", `${d.blocked_percent ?? 0}%`); + set("adguard-latency", `${d.avg_processing_ms ?? 0}ms`); - totalEl.textContent = fmtNumber(adguard.total_queries); - blockedEl.textContent = fmtNumber(adguard.blocked_queries); - blockedPctEl.textContent = `${adguard.blocked_percent ?? 0}%`; - - const pct = adguard.blocked_percent ?? 0; - blockedPctEl.className = pct > 30 ? "metric-accent warning" : "metric-accent online"; - - latencyEl.textContent = online ? `${adguard.avg_processing_ms ?? 0} MS` : "N/A"; - latencyEl.className = online ? "online" : "offline"; - - const barPct = Math.min(pct, 100); - barFill.style.width = `${barPct}%`; - const bar = barFill.closest(".metric-bar"); - if (bar) bar.className = pct > 40 ? "metric-bar warning" : "metric-bar"; + const bar = document.getElementById("adguard-bar-fill"); + if (bar) bar.style.width = `${Math.min(d.blocked_percent ?? 0, 100)}%`; + } else { + ["adguard-total", "adguard-blocked", "adguard-blocked-pct", "adguard-latency"].forEach(id => set(id, "—")); + const bar = document.getElementById("adguard-bar-fill"); + if (bar) bar.style.width = "0%"; + } } -function renderScrutiny(scrutiny) { +function _renderScrutiny(d) { + const online = d.source_status === "online"; + const pill = document.getElementById("scrutiny-pill"); - const listEl = document.getElementById("scrutiny-list"); + if (pill) { + pill.textContent = online ? "ONLINE" : "OFFLINE"; + pill.className = "status-pill " + (online ? "pill-online" : "pill-offline"); + } - if (!pill || !listEl) return; + // stat blocks + const set = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; }; + if (online) { + set("scrutiny-total", d.total_count ?? 0); + set("scrutiny-failed", d.failed_count ?? 0); + const passedEl = document.getElementById("scrutiny-passed"); + if (passedEl) { + passedEl.textContent = (d.total_count ?? 0) - (d.failed_count ?? 0); + } + } else { + set("scrutiny-total", "—"); + set("scrutiny-failed", "—"); + set("scrutiny-passed", "—"); + } - const online = scrutiny.source_status === "online"; - const hasFailed = scrutiny.failed_count > 0; - pill.className = `status-pill ${hasFailed ? "offline" : online ? "online" : "offline"}`; - pill.textContent = hasFailed ? "Failed" : online ? "All Passed" : "Offline"; + // disk list + const list = document.getElementById("scrutiny-list"); + if (!list) return; - if (!online || scrutiny.devices.length === 0) { - listEl.innerHTML = `
No data
`; + if (!online || !d.devices || d.devices.length === 0) { + list.innerHTML = `
— ${online ? "no devices" : "offline"}
`; return; } - listEl.innerHTML = scrutiny.devices.map((device) => { - const tone = deviceStatusIcon(device.status); - const shortName = device.name.replace(/^sd/, "sd").toUpperCase(); - const shortModel = device.model.length > 22 ? device.model.slice(0, 22) + "…" : device.model; + list.innerHTML = d.devices.map(dev => { + const ok = dev.status === "passed"; + const icon = ok ? "✓" : dev.status === "failed" ? "✗" : "?"; + const cls = ok ? "disk-ok" : dev.status === "failed" ? "disk-fail" : "disk-unk"; + const temp = dev.temperature != null ? `${dev.temperature}°C` : ""; return ` -
- ${shortName} - ${shortModel} -
- -
- ${device.status.toUpperCase()} -
- `; +
+ ${icon} + ${dev.name} + ${dev.model} + ${temp} +
`; }).join(""); } + +function fmtK(n) { + if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + "M"; + if (n >= 1_000) return (n / 1_000).toFixed(0) + "K"; + return String(n ?? 0); +}