From 75aa6fb8853b7ce0a35b7465b0f6ea1c1fd304f2 Mon Sep 17 00:00:00 2001 From: Mike Teehan Date: Tue, 23 Jun 2026 00:08:40 +0000 Subject: [PATCH] fix: wrap model data in named objects and fix renderGuardMulti empty check --- webui/static/app.js | 4 ++-- webui/static/hoover/components/layout.js | 10 ++++++++-- webui/static/pages/certs.js | 2 +- webui/static/pages/proxy.js | 2 +- webui/static/pages/wireguard.js | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/webui/static/app.js b/webui/static/app.js index ab35b51..8181a9e 100644 --- a/webui/static/app.js +++ b/webui/static/app.js @@ -93,7 +93,7 @@ modelRegister('nginx', { fetch: async () => { const r = await apiFetch('/api/proxy/domains'); if (!r.ok) throw new Error(r.error); - return r.data || []; + return { domains: r.data || [] }; }, }); @@ -102,7 +102,7 @@ modelRegister('acme', { fetch: async () => { const r = await apiFetch('/api/certs/list'); if (!r.ok) throw new Error(r.error); - return r.data || []; + return { certs: r.data || [] }; }, }); diff --git a/webui/static/hoover/components/layout.js b/webui/static/hoover/components/layout.js index 189e213..490f074 100644 --- a/webui/static/hoover/components/layout.js +++ b/webui/static/hoover/components/layout.js @@ -80,7 +80,7 @@ export function renderGuard(state, title, subtitle, data) { */ export function renderGuardMulti(title, subtitle, ...models) { const combined = collectLoadingModels(...models); - return renderGuard(combined, title, subtitle); + return renderGuard(combined, title, subtitle, models.map(m => m.data)); } /** @@ -90,7 +90,13 @@ export function renderGuardMulti(title, subtitle, ...models) { */ function isEmpty(data) { if (data === null || data === undefined || data === '') return true; - if (Array.isArray(data)) return data.length === 0; + if (Array.isArray(data)) { + // Array of model data values (from renderGuardMulti) — empty only if all models have no data + if (data.length === 0) return true; + return data.every(d => d === null || d === undefined || + (Array.isArray(d) && d.length === 0) || + (typeof d === 'object' && Object.keys(d).length === 0)); + } if (typeof data === 'object') return Object.keys(data).length === 0; if (typeof data === 'number') return false; return !data; diff --git a/webui/static/pages/certs.js b/webui/static/pages/certs.js index 8bc3f44..f328767 100644 --- a/webui/static/pages/certs.js +++ b/webui/static/pages/certs.js @@ -58,7 +58,7 @@ export default definePage({ const guard = renderGuard(state.acme, 'Certificates', 'ACME certificate management', state.acme.data); if (guard) return guard; - const rows = (state.acme.data || []).map(c => { + const rows = (state.acme.data?.certs || []).map(c => { const badge = certStatusBadge({ expired: c.expired, daysRemaining: c.days_remaining }); return h('tr', { key: c.domain }, diff --git a/webui/static/pages/proxy.js b/webui/static/pages/proxy.js index 5fe425a..2ee291b 100644 --- a/webui/static/pages/proxy.js +++ b/webui/static/pages/proxy.js @@ -58,7 +58,7 @@ export default definePage({ const guard = renderGuardMulti('Proxy', 'Nginx reverse proxy', state.nginx, state.acme); if (guard) return guard; - const domains = state.nginx.data || []; + const domains = state.nginx.data.domains || []; const rows = domains.map(d => { const certBadge = certStatusBadge({ certStatus: d.cert_status, diff --git a/webui/static/pages/wireguard.js b/webui/static/pages/wireguard.js index c9d558b..8c85887 100644 --- a/webui/static/pages/wireguard.js +++ b/webui/static/pages/wireguard.js @@ -57,7 +57,7 @@ export default definePage({ }; }, render(state) { - const guard = renderGuard(state.wireguard, 'WireGuard', null, state.wireguard.data?.peers); + const guard = renderGuard(state.wireguard, 'WireGuard', 'Tunnel & peer management', state.wireguard.data); if (guard) return guard; const st = state.wireguard.data?.status || {};