Add state management, WebSocket polling, html.js templating, and refactor pages
- lib/state.py: per-subsystem collectors with versioned state store - daemon/server.py: state refresh on request, batch routing updates - webui/static/hoover/html.js: new html tag template helper via htm.js - webui/static/hoover/websocket.js: real-time state change notifications - webui/static/hoover/vdom.js: VDOM improvements for keyed diff - All frontend pages refactored to use html templates - Add tests for state management and polling - Update docs and AGENTS.md
This commit is contained in:
+17
-19
@@ -1,4 +1,4 @@
|
||||
import { h, PageHeader, Badge, Empty, Table, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, modelFetch, ActionButton, ActionCell, certStatusBadge, ActionGroup, QuickModal } from '/static/hoover/index.js?v=7';
|
||||
import { html, PageHeader, Badge, Empty, Table, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, modelFetch, ActionButton, ActionCell, certStatusBadge, ActionGroup, QuickModal } from '/static/hoover/index.js?v=7';
|
||||
|
||||
const addDomain = QuickModal({
|
||||
title: 'Add Proxy Domain',
|
||||
@@ -66,26 +66,24 @@ export default definePage({
|
||||
expired: d.cert_status === 'expired',
|
||||
});
|
||||
|
||||
return h('tr', { key: d.domain },
|
||||
h('td', null, h('strong', null, esc(d.domain))),
|
||||
h('td', null, esc(d.backend_host || '-')),
|
||||
h('td', null, d.backend_port || '-'),
|
||||
h('td', null, Badge({ text: d.backend_proto || d.protocol || 'http', variant: 'info' })),
|
||||
h('td', null, certBadge),
|
||||
ActionCell({
|
||||
editLabel: 'Edit',
|
||||
editClick: () => editDomain(d),
|
||||
removeUrl: '/api/proxy/domains/' + enc(d.domain),
|
||||
removeMessage: 'Remove proxy for ' + d.domain + '?',
|
||||
removeSuccess: 'Domain removed',
|
||||
removeRefresh: ['nginx', 'acme'],
|
||||
removeLabel: 'Delete',
|
||||
}),
|
||||
);
|
||||
return html`<tr key=${d.domain}>
|
||||
<td><strong>${esc(d.domain)}</strong></td>
|
||||
<td>${esc(d.backend_host || '-')}</td>
|
||||
<td>${d.backend_port || '-'}</td>
|
||||
<td><${Badge} text=${d.backend_proto || d.protocol || 'http'} variant="info" /></td>
|
||||
<td>${certBadge}</td>
|
||||
<${ActionCell}
|
||||
editLabel="Edit" editClick=${() => editDomain(d)}
|
||||
removeUrl=${'/api/proxy/domains/' + enc(d.domain)}
|
||||
removeMessage=${'Remove proxy for ' + d.domain + '?'}
|
||||
removeSuccess="Domain removed"
|
||||
removeRefresh={['nginx', 'acme']}
|
||||
removeLabel="Delete" />
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
const actions = ActionGroup(
|
||||
h('button', { class: 'btn btn-primary', 'on:click': () => addDomain(state) }, 'Add Domain'),
|
||||
html`<button class="btn btn-primary" onClick=${() => addDomain(state)}>Add Domain</button>`,
|
||||
ActionButton({
|
||||
url: '/api/proxy/apply',
|
||||
successMsg: 'Nginx applied & reloaded',
|
||||
@@ -104,4 +102,4 @@ export default definePage({
|
||||
: Empty({ text: 'No proxy domains configured. Add a domain to start terminating SSL.' }),
|
||||
];
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user