Build and push server image / build-and-push (push) Successful in 39s
Moved out of the Stats tab's side column into a new horizontal bar shared by every frame page (Photos/Configuration/Stats), sitting between the page title and the tabs so it's on screen regardless of which tab is active. _device_status_bar.html is a new partial included via a device_status block in app_base.html; device_status_bar.js is the fetch/render/poll logic extracted from frame_stats.js and adapted to a wrapping row of label/value pairs instead of a stacked list. frame_stats.html's Device card and now-single-card .side-col are gone -- Battery history and Lifetime stats just stack directly.
52 lines
1.7 KiB
JavaScript
52 lines
1.7 KiB
JavaScript
// Stats tab: lifetime counters + battery history chart (chart logic in
|
|
// battery_chart.js). Device status now lives in the always-visible bar
|
|
// (device_status_bar.js), not here. window.FRAME_API set by template.
|
|
|
|
function renderStats(stats) {
|
|
const el = document.getElementById('stats-box');
|
|
el.innerHTML = '';
|
|
const now = Date.now() / 1000;
|
|
const rows = [
|
|
['Running since', stats.first_seen ? formatDuration(Math.max(0, now - stats.first_seen)) + ' ago' : 'never checked in'],
|
|
['Wake cycles', stats.device_wakes],
|
|
['Photos displayed', stats.photos_displayed],
|
|
['Photos removed from rotation', stats.photos_removed],
|
|
['Battery reports received', stats.battery_reports],
|
|
['Battery recharge cycles', stats.recharge_cycles],
|
|
['OTA updates applied', stats.ota_updates_applied],
|
|
['Settings saved', stats.config_saves],
|
|
];
|
|
for (const [label, value] of rows) {
|
|
const p = document.createElement('p');
|
|
p.className = 'sub';
|
|
p.textContent = `${label}: ${value}`;
|
|
el.appendChild(p);
|
|
}
|
|
}
|
|
|
|
async function loadStats() {
|
|
const el = document.getElementById('stats-box');
|
|
try {
|
|
const resp = await fetch(`${window.FRAME_API}/stats`);
|
|
if (!resp.ok) {
|
|
el.innerHTML = '<p class="sub">Could not load.</p>';
|
|
return;
|
|
}
|
|
renderStats(await resp.json());
|
|
} catch (e) {
|
|
el.innerHTML = '<p class="sub">Could not load.</p>';
|
|
}
|
|
}
|
|
|
|
loadStats();
|
|
loadBatteryLog();
|
|
|
|
// Redraw the canvas chart with the new theme's colors as soon as the
|
|
// toggle is used -- canvas pixels don't repaint themselves the way CSS
|
|
// does.
|
|
document.addEventListener('themechange', () => {
|
|
if (lastBatteryLog) {
|
|
drawBatteryChart(lastBatteryLog);
|
|
}
|
|
});
|