From bbb07b65ca779d484e09b8717e1fac146093b7a3 Mon Sep 17 00:00:00 2001 From: "Valentin V. Bartenev" Date: Sat, 9 May 2026 21:23:40 +0300 Subject: [PATCH] Web: stale stats indicator in Stats header Add a blinking "refreshed >Xm ago" label aligned to the right of the Stats page h2 header. The label is hidden until stats are more than 1 minute old, then appears with a CSS color-pulse animation (red to --text-muted) to draw attention. It hides immediately when a refresh is initiated and reappears only after the next successful fetch. - Add @keyframes blink-stale (color pulse red <-> --text-muted) and .stats-stale CSS class (13px, normal weight, 1.5s animation) - Add statsLastUpdated span inside the Stats h2 (flex, right-aligned, initially hidden) - statsLastFetchedAt: null until first successful fetch, reset to null at the start of each loadStatsPage call, set to Date.now() on success - updateStatsLastUpdated() hides span when null or secs < 60, shows minutes/hours elapsed otherwise - setInterval(updateStatsLastUpdated, 10000) runs only on /stats page --- src/helpers/web/WebPanelServer.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/helpers/web/WebPanelServer.cpp b/src/helpers/web/WebPanelServer.cpp index d222c56f..e14c67f6 100644 --- a/src/helpers/web/WebPanelServer.cpp +++ b/src/helpers/web/WebPanelServer.cpp @@ -481,6 +481,8 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( .stats-shell { display:grid; gap:12px; } .stats-empty, .stats-error { background:var(--surface2); border:1px dashed var(--border); border-radius:12px; padding:16px; color:var(--text-muted); } .stats-error { color:var(--status-red); } + @keyframes blink-stale { 0%, 100% { color: #e05050; } 50% { color: var(--text-muted); } } + .stats-stale { color: #e05050; font-size: 13px; font-weight: 400; animation: blink-stale 1.5s ease-in-out infinite; } .trend-section-copy { display:grid; gap:6px; } .trend-section-copy p { margin:0; color:var(--text-muted); } .trend-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; } @@ -983,7 +985,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(