diff --git a/src/main.js b/src/main.js index 45c41f9..988646f 100644 --- a/src/main.js +++ b/src/main.js @@ -193,6 +193,7 @@ class AppState { this.wan = WAN_HOSTS.map((h) => new HostState(h)); this.local = localHosts.map((h) => new HostState(h)); this.paused = false; + this.tickCount = 0; } get allHosts() { @@ -592,6 +593,41 @@ function updateHealthBox(state) { }`; } +// --- Sorting ----------------------------------------------------------------- + +// Sort WAN hosts by last latency (ascending), with datavi.be pinned at top +// and unreachable hosts sorted to the bottom. Rebuilds the WAN DOM rows. +function sortAndRebuildWAN(state) { + const pinned = state.wan.filter((h) => h.name === "datavi.be"); + const rest = state.wan.filter((h) => h.name !== "datavi.be"); + rest.sort((a, b) => { + if (a.lastLatency === null && b.lastLatency === null) return 0; + if (a.lastLatency === null) return 1; + if (b.lastLatency === null) return -1; + return a.lastLatency - b.lastLatency; + }); + state.wan = [...pinned, ...rest]; + + const container = document.getElementById("wan-hosts"); + container.innerHTML = state.wan.map((h, i) => hostRowHTML(h, i)).join(""); + + // Re-index local hosts after WAN + const localContainer = document.getElementById("local-hosts"); + localContainer.innerHTML = state.local + .map((h, i) => hostRowHTML(h, state.wan.length + i)) + .join(""); + + // Resize canvases and redraw + requestAnimationFrame(() => { + document.querySelectorAll(".sparkline-canvas").forEach((canvas) => { + SparklineRenderer.sizeCanvas(canvas); + }); + state.allHosts.forEach((host, i) => { + updateHostRow(host, i); + }); + }); +} + // --- Main Loop --------------------------------------------------------------- async function tick(state) { @@ -621,6 +657,12 @@ async function tick(state) { updateHostRow(host, i); }); + state.tickCount++; + // Sort after the first check, then every 5 checks thereafter + if (state.tickCount === 1 || state.tickCount % 5 === 1) { + sortAndRebuildWAN(state); + } + updateSummary(state); updateHealthBox(state); }