// 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(); })();