feat: add network-health renderer

This commit is contained in:
2026-04-05 21:09:37 +00:00
parent ad8859f22c
commit 685bc1dd77
@@ -0,0 +1,85 @@
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);
}
function renderAdGuard(adguard) {
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) return;
const online = adguard.source_status === "online";
pill.className = `status-pill ${online ? "online" : "offline"}`;
pill.textContent = online ? "Online" : "Offline";
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";
}
function renderScrutiny(scrutiny) {
const pill = document.getElementById("scrutiny-pill");
const listEl = document.getElementById("scrutiny-list");
if (!pill || !listEl) return;
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";
if (!online || scrutiny.devices.length === 0) {
listEl.innerHTML = `<div class="storage-row"><strong style="color:var(--text-dim)">No data</strong><span>—</span><span></span><span></span></div>`;
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;
return `
<div class="storage-row">
<strong>${shortName}</strong>
<span>${shortModel}</span>
<div class="metric-bar ${tone === "offline" ? "danger" : ""}">
<span style="width:${tone === "online" ? "100" : "0"}%"></span>
</div>
<span class="status-pill ${tone}">${device.status.toUpperCase()}</span>
</div>
`;
}).join("");
}