ws: migrate push stream to data streaming
- daemon: send full snapshot on connect; versions/tick now carry the full state of one subsystem (subsystem + data); no legacy updated/subsystems payloads; refresh_state and POST /status/refresh broadcast per-subsystem versions with data - client: modelSet() patches models in place; onMessage/topic refresh retired; 3s initial-load fallback via new POST /api/status/refresh - schema: lib/schema.py TypedDicts + hoover/schema.js defaults + docs/state-model.md as single source of truth for state shapes - system: poll at 1s, volatile metrics registered, dashboard uses a dedicated system model (status model removed) - firewall: refuse to strip both https and ssh from the default zone (409, force override via UI confirm); set_zone_services persists services to the declarative config; collector exposes default_zone - UI: pages migrate to flat state shapes; post-mutation modelFetch refreshes removed (WS delta covers it) - tests: ws snapshot/delta/broadcast, refresh-state, schema types, model-set/js ws handler and reconnect fallback
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { html, h, PageHeader, ConfirmDelete, Tabs, Table, ServiceStatus, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, modelFetch, ActionButton, ActionGroup, QuickModal, ApplyConfirm } from '/static/hoover/index.js';
|
||||
import { html, h, PageHeader, ConfirmDelete, Tabs, Table, ServiceStatus, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, ActionButton, ActionGroup, QuickModal, ApplyConfirm } from '/static/hoover/index.js';
|
||||
|
||||
function makeAddRange(activeZones, interfaces) {
|
||||
const opts = [
|
||||
@@ -70,7 +70,6 @@ function makeAddRange(activeZones, interfaces) {
|
||||
validate: (b) => !b.start || !b.end ? 'Start and end are required' : null,
|
||||
successMsg: 'Range added',
|
||||
},
|
||||
refresh: 'dnsmasq',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,7 +90,6 @@ const addLease = QuickModal({
|
||||
validate: (b) => !b.mac || !b.ip ? 'MAC and IP are required' : null,
|
||||
successMsg: 'Lease added',
|
||||
},
|
||||
refresh: 'dnsmasq',
|
||||
});
|
||||
|
||||
const addDns = QuickModal({
|
||||
@@ -106,7 +104,6 @@ const addDns = QuickModal({
|
||||
validate: (b) => !b.name || !b.address ? 'Name and address are required' : null,
|
||||
successMsg: 'DNS record added',
|
||||
},
|
||||
refresh: 'dnsmasq',
|
||||
});
|
||||
|
||||
export default definePage({
|
||||
@@ -140,8 +137,7 @@ export default definePage({
|
||||
deleteKey=${(r.interface || '_g') + '-' + r.start + '-' + r.end}
|
||||
message=${'Remove range ' + r.start + ' - ' + r.end + '?'}
|
||||
body=${{ interface: r.interface || '', start: r.start, end: r.end }}
|
||||
success="Range removed"
|
||||
refresh="dnsmasq" />
|
||||
success="Range removed" />
|
||||
</td>
|
||||
</tr>`);
|
||||
|
||||
@@ -154,8 +150,7 @@ export default definePage({
|
||||
url=${'/api/dhcp/static-lease/' + enc(l.mac)}
|
||||
deleteKey=${l.mac}
|
||||
message=${'Remove lease ' + l.mac + '?'}
|
||||
success="Lease removed"
|
||||
refresh="dnsmasq" />
|
||||
success="Lease removed" />
|
||||
</td>
|
||||
</tr>`);
|
||||
|
||||
@@ -167,8 +162,7 @@ export default definePage({
|
||||
url=${'/api/dhcp/dns-record/' + enc(rec.name || '')}
|
||||
deleteKey=${rec.name || 'unnamed'}
|
||||
message=${'Remove DNS record ' + (rec.name || 'unnamed') + '?'}
|
||||
success="Record removed"
|
||||
refresh="dnsmasq" />
|
||||
success="Record removed" />
|
||||
</td>
|
||||
</tr>`);
|
||||
|
||||
@@ -179,7 +173,7 @@ export default definePage({
|
||||
});
|
||||
if (res.ok) {
|
||||
toast('DNS domain updated', 'success');
|
||||
modelFetch('dnsmasq');
|
||||
// No modelFetch — WS delta updates the dnsmasq model.
|
||||
} else {
|
||||
toast(res.error || 'Failed to update', 'error');
|
||||
}
|
||||
@@ -198,7 +192,7 @@ export default definePage({
|
||||
|
||||
const tabNames = ['ranges', 'leases', 'dns', 'active'];
|
||||
const actions = ActionGroup(
|
||||
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.zones?.active, state.firewall.data?.interfaces)(state)}>Add Range</button>`,
|
||||
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.active_zones, state.firewall.data?.interfaces)(state)}>Add Range</button>`,
|
||||
html`<button class="btn btn-outline" onClick=${() => addLease(state)}>Static Lease</button>`,
|
||||
html`<button class="btn btn-outline" onClick=${() => addDns(state)}>DNS Record</button>`,
|
||||
(() => {
|
||||
@@ -213,10 +207,9 @@ export default definePage({
|
||||
let msg = 'dnsmasq applied';
|
||||
if (synced && synced.length) {
|
||||
msg += ' (auto-synced: ' + synced.join(', ') + ')';
|
||||
synced.forEach(s => modelFetch(s));
|
||||
}
|
||||
toast(msg, 'success');
|
||||
modelFetch('dnsmasq');
|
||||
// No modelFetch — WS delta updates the dnsmasq model.
|
||||
} else {
|
||||
toast(res.error || 'Apply failed', 'error');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user