// Auto-refresh: re-fetch the current page's content block every few seconds // and swap it in. Rendering stays server-side; this keeps the UI live without // duplicating templates in JS. (function () { var page = document.body.dataset.page; var interval = { dashboard: 5000, zfs: 15000, alerts: 15000, disk: 30000 }[page]; if (!interval) return; var main = document.getElementById('content'); var dot = document.getElementById('refresh-state'); var timer = null; // A refresh replaces the whole content block, which would wipe a form the // user is typing into: hold off while a form is focused or has been edited. main.addEventListener('input', function (e) { var f = e.target.closest('form'); if (f) f.classList.add('dirty'); }); // The ✕ / "show again" forms are single buttons, not something being typed // into, so they never hold a refresh back. function editing() { if (main.querySelector('form.dirty:not(.x-form)')) return true; var a = document.activeElement; return !!(a && a.closest && a.closest('#content form:not(.x-form)')); } function tick() { if (document.hidden || editing()) { dot.className = 'refresh paused'; return; } var open = [].slice.call(main.querySelectorAll('details[open]')).map(function (d) { return d.className; }); var url = new URL(location.href); url.searchParams.set('partial', '1'); url.searchParams.delete('msg'); var n = null; fetch(url, { cache: 'no-store' }).then(function (r) { if (!r.ok) throw new Error(r.status); n = r.headers.get('X-Alerts-Open'); return r.text(); }).then(function (html) { main.innerHTML = html; open.forEach(function (cls) { var d = main.querySelector('details.' + cls.split(' ').join('.')); if (d) d.open = true; }); var nav = document.querySelector('nav a[href="/alerts"]'); if (nav && n !== null) nav.innerHTML = 'Alerts' + (n !== '0' ? ' ' + n + '' : ''); dot.className = 'refresh'; }).catch(function () { dot.className = 'refresh stale'; }); } // ✕ / "show again" forms: post in place and refresh the content block document.addEventListener('submit', function (ev) { var f = ev.target; if (!f.classList.contains('x-form')) return; ev.preventDefault(); if (document.activeElement && document.activeElement.blur) document.activeElement.blur(); fetch(f.action, { method: 'POST', headers: { 'X-Requested-With': 'fetch' } }) .then(function (r) { if (!r.ok) throw new Error(r.status); tick(); }) .catch(function () { f.submit(); }); }); function start() { if (!timer) timer = setInterval(tick, interval); } document.addEventListener('visibilitychange', function () { if (!document.hidden) tick(); }); start(); })();