// Operator status strip mounted at the top of every .main pane.
(function () {
function esc(s) {
if (!s) return '';
return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');
}
function mount() {
const main = document.querySelector('.main');
if (!main || main.querySelector('.topbar-strip')) return;
const strip = document.createElement('div');
strip.className = 'topbar-strip';
strip.innerHTML =
'' +
'Z-AMPP' +
'00:00:00' +
'' +
'Page' +
'' + esc(pageName()) + '' +
'' +
'API' +
'--';
main.insertBefore(strip, main.firstChild);
tick(); setInterval(tick, 1000);
ping(); setInterval(ping, 10000);
}
function pageName() {
const p = location.pathname.replace(/\.html$/, '').replace(/^\//, '');
if (!p || p === 'index') return 'Library';
return p.charAt(0).toUpperCase() + p.slice(1);
}
function tick() {
const n = new Date();
const hh = String(n.getHours()).padStart(2, '0');
const mm = String(n.getMinutes()).padStart(2, '0');
const ss = String(n.getSeconds()).padStart(2, '0');
const el = document.getElementById('tsNow');
if (el) el.textContent = hh + ':' + mm + ':' + ss;
}
async function ping() {
const dot = document.getElementById('tsDot');
const apiEl = document.getElementById('tsApi');
const t0 = performance.now();
try {
const r = await fetch('/api/v1/projects', { credentials: 'include', signal: AbortSignal.timeout(4000) });
const ms = Math.round(performance.now() - t0);
if (r.ok) {
if (dot) { dot.style.background = 'var(--signal-good)'; dot.style.boxShadow = '0 0 8px var(--signal-good)'; }
if (apiEl) apiEl.textContent = ms + ' ms';
} else {
if (dot) { dot.style.background = 'var(--signal-warn)'; dot.style.boxShadow = '0 0 8px var(--signal-warn)'; }
if (apiEl) apiEl.textContent = 'HTTP ' + r.status;
}
} catch (e) {
if (dot) { dot.style.background = 'var(--signal-bad)'; dot.style.boxShadow = '0 0 8px var(--signal-bad)'; }
if (apiEl) apiEl.textContent = 'offline';
}
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mount);
else mount();
})();