Initial import: nasmon health monitor, split out of home_nas
Go service (nasmon/) plus nfpm packaging (packaging/), carried over from the home_nas monorepo. Adds rpm packaging alongside the existing deb build (Fedora/RHEL/Rocky dependency names via nfpm overrides, per-format systemd unit path, dpkg+rpm-compatible maintainer scripts) and a Gitea Actions workflow that builds both formats on every push. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// 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' ? ' <span class="badge crit">' + n + '</span>' : '');
|
||||
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();
|
||||
})();
|
||||
Reference in New Issue
Block a user