From 1e95149456450c93b054d274364a86a322314c33 Mon Sep 17 00:00:00 2001 From: M1 Date: Mon, 16 Mar 2026 16:10:04 +0400 Subject: [PATCH] feat: live-updating timestamps via data-ts attribute --- apps/web/src/dashboard/app.js | 22 ++++++++++++++++++---- apps/web/src/views/detail.ejs | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/web/src/dashboard/app.js b/apps/web/src/dashboard/app.js index 5e392b6..d944cfc 100644 --- a/apps/web/src/dashboard/app.js +++ b/apps/web/src/dashboard/app.js @@ -44,14 +44,28 @@ async function api(path, opts = {}) { } // Format relative time -function timeAgo(date) { - const s = Math.floor((Date.now() - new Date(date).getTime()) / 1000); - if (s < 60) return `${s}s ago`; +function formatAgo(ms) { + const s = Math.floor(ms / 1000); + if (s < 60) return `${s}s ago`; if (s < 3600) return `${Math.floor(s / 60)}m ago`; - if (s < 86400) return `${Math.floor(s / 3600)}h ago`; + if (s < 86400)return `${Math.floor(s / 3600)}h ago`; return `${Math.floor(s / 86400)}d ago`; } +function timeAgo(date) { + const ts = new Date(date).getTime(); + const elapsed = Date.now() - ts; + return `${formatAgo(elapsed)}`; +} + +// Tick all live timestamps every second +setInterval(() => { + document.querySelectorAll('.timestamp[data-ts]').forEach(el => { + const elapsed = Date.now() - Number(el.dataset.ts); + el.textContent = formatAgo(elapsed); + }); +}, 1000); + // Render a tiny sparkline SVG from latency values function sparkline(values, width = 120, height = 32) { if (!values.length) return ''; diff --git a/apps/web/src/views/detail.ejs b/apps/web/src/views/detail.ejs index 4837076..d5d58bf 100644 --- a/apps/web/src/views/detail.ejs +++ b/apps/web/src/views/detail.ejs @@ -164,7 +164,7 @@ : ''; document.getElementById('stat-latency').textContent = avgLatency != null ? `${avgLatency}ms` : '—'; document.getElementById('stat-uptime').textContent = uptime != null ? `${uptime}%` : '—'; - document.getElementById('stat-last').textContent = lastPing ? timeAgo(lastPing.checked_at) : '—'; + document.getElementById('stat-last').innerHTML = lastPing ? timeAgo(lastPing.checked_at) : '—'; // Latency chart renderLatencyChart(results.slice().reverse());