feat: add auto metric refresh

This commit is contained in:
2026-06-08 15:54:17 +01:00
parent 458b7897dd
commit 027ac59bc7
2 changed files with 15 additions and 1 deletions
+14 -1
View File
@@ -162,6 +162,7 @@
<script src="https://cdn.datatables.net/2.3.8/js/dataTables.min.js"></script> <script src="https://cdn.datatables.net/2.3.8/js/dataTables.min.js"></script>
<script> <script>
let logTable = null; let logTable = null;
let _lastDataKey = '';
function esc(str) { function esc(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
@@ -190,7 +191,7 @@
}); });
} }
async function loadLog() { async function loadLog(isRefresh = false) {
const tbody = document.getElementById('logBody'); const tbody = document.getElementById('logBody');
try { try {
@@ -202,6 +203,14 @@
document.getElementById('stat-failed').textContent = stats.total_failed ?? '—'; document.getElementById('stat-failed').textContent = stats.total_failed ?? '—';
document.getElementById('stat-rate').textContent = stats.success_rate != null ? stats.success_rate + '%' : '—'; document.getElementById('stat-rate').textContent = stats.success_rate != null ? stats.success_rate + '%' : '—';
// Skip expensive DOM rebuild if nothing has changed
const dataKey = `${entries.length}:${stats.total_sent}:${stats.total_failed}`;
if (isRefresh && dataKey === _lastDataKey) return;
_lastDataKey = dataKey;
// Preserve current page position before destroying the table
const prevPage = logTable ? logTable.page() : 0;
// Destroy existing DataTable before rewriting DOM // Destroy existing DataTable before rewriting DOM
if (logTable) { logTable.destroy(); logTable = null; } if (logTable) { logTable.destroy(); logTable = null; }
@@ -237,12 +246,16 @@
}); });
}, },
}); });
if (isRefresh && prevPage > 0 && prevPage < logTable.page.info().pages) {
logTable.page(prevPage).draw(false);
}
} catch { } catch {
tbody.innerHTML = `<tr><td colspan="5" class="text-danger text-center py-4">Could not load delivery log.</td></tr>`; tbody.innerHTML = `<tr><td colspan="5" class="text-danger text-center py-4">Could not load delivery log.</td></tr>`;
} }
} }
loadLog(); loadLog();
setInterval(() => loadLog(true), 10_000);
</script> </script>
<script> <script>
async function checkAuth() { async function checkAuth() {
+1
View File
@@ -334,6 +334,7 @@
} catch { /* DB unavailable — stats stay as dashes */ } } catch { /* DB unavailable — stats stay as dashes */ }
} }
loadStats(); loadStats();
setInterval(() => loadStats(), 10_000);
</script> </script>
<script> <script>
async function checkAuth() { async function checkAuth() {