Files
vacuum-wall/webui/static/pages/dashboard.js
T
mteehan 633505e7dc refactor: modernize frontend with hoover framework components and docs
- Add quick modal, table, service status, and confirmation dialog components
- Refactor all pages (certs, dhcp, proxy, etc.) to use new component patterns
- Introduce refactor load utility and render guard for consistent UX
- Add hoover documentation and update AGENTS.md, architecture, overview
2026-06-21 04:29:27 +00:00

73 lines
2.8 KiB
JavaScript

import { h, PageHeader, apiFetch, definePage, renderGuard, refactorLoad, ServiceStatus, StatCard } from '/static/hoover/index.js?v=6';
export default definePage({
init() {
return { data: null };
},
subscribe: ['firewall', 'dnsmasq', 'wireguard', 'acme', 'networkd'],
async load(state, abortController, entry) {
await refactorLoad(state,
s => s.data,
async (s, sig, isAborted) => {
const res = await apiFetch('/api/status/all', { signal: sig });
if (isAborted()) return;
if (res.ok) s.data = res.data;
else s.error = res.error;
},
{ entry, abortController },
);
},
render(state) {
const guard = renderGuard(state, 'Dashboard', 'System overview', state.data);
if (guard) return guard;
const d = state.data;
const fwZones = (d.firewall?.zones) || {};
const net = d.net || {};
const nCount = Object.keys(net).length;
const upI = Object.values(net).filter(i => i.state === 'up');
const upC = upI.length;
const certs = d.certs || [];
const certW = certs.filter(c => c.expired || c.days_remaining <= 30);
const dmsk = d.dnsmasq?.status || {};
const wP = (d.wg || {}).peers || [];
return [
PageHeader({ title: 'Dashboard', subtitle: 'System overview' }),
h('div', { class: 'grid grid-4' },
StatCard({
label: 'Active Zones',
value: Object.keys(fwZones).length,
meta: Object.keys(fwZones).join(', ') || 'None',
}),
StatCard({
label: 'Interfaces Up',
value: upC + '/' + nCount,
meta: upI.map(i => i.name).join(', ') || 'None up',
}),
StatCard({
label: 'WireGuard',
value: String(d.wg?.state || 'unknown'),
meta: wP.length + ' peers',
}),
StatCard({
label: 'Certificates',
value: certs.length,
meta: certW.length + ' expiring/expired',
}),
),
h('div', { class: 'grid grid-2' },
h('div', { class: 'card' },
h('div', { class: 'card-header' }, 'Services'),
h('div', { class: 'card-body' },
h('ul', { class: 'service-list' },
h('li', null, ServiceStatus({ state: dmsk.state || 'down', label: 'Dnsmasq' })),
h('li', null, ServiceStatus({ state: d.wg?.state || 'down', label: 'WireGuard' })),
),
),
),
),
];
},
});