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:
@@ -268,8 +268,11 @@ export function formAction(fn) {
|
||||
* @param {string} [opts.method] - HTTP method (default: 'POST')
|
||||
* @param {function} [opts.body] - () => object, body builder
|
||||
* @param {function} [opts.validate] - (body) => string|null, validation function
|
||||
* @param {function} [opts.confirm] - (body) => string|null; if a message is
|
||||
* returned, a native confirm() dialog gates
|
||||
* the submit; on approval the body gains
|
||||
* force=true (server-side guard override)
|
||||
* @param {string} [opts.successMsg] - Success toast message
|
||||
* @param {string|string[]} [opts.refresh] - Model name(s) to refresh via modelFetch
|
||||
* @param {string} [opts.submitText] - Submit button text (default: 'Submit')
|
||||
* @returns {object[]} Array of action descriptors
|
||||
*/
|
||||
@@ -279,8 +282,8 @@ export function apiSubmit(opts) {
|
||||
method = 'POST',
|
||||
body,
|
||||
validate,
|
||||
confirm,
|
||||
successMsg = 'Saved',
|
||||
refresh,
|
||||
submitText = 'Submit',
|
||||
closeModal,
|
||||
} = opts;
|
||||
@@ -300,6 +303,13 @@ export function apiSubmit(opts) {
|
||||
const err = validate(b);
|
||||
if (err) { toast(err, 'error'); return; }
|
||||
}
|
||||
if (confirm) {
|
||||
const msg = confirm(b);
|
||||
if (msg) {
|
||||
if (!window.confirm(msg)) return;
|
||||
b.force = true;
|
||||
}
|
||||
}
|
||||
refreshModals();
|
||||
const res = await apiFetch(url, { method, body: b });
|
||||
if (res.ok) {
|
||||
@@ -307,14 +317,10 @@ export function apiSubmit(opts) {
|
||||
let msg = successMsg;
|
||||
if (synced && synced.length) {
|
||||
msg += ' (auto-synced: ' + synced.join(', ') + ')';
|
||||
synced.forEach(s => modelFetch(s));
|
||||
}
|
||||
toast(msg, 'success');
|
||||
if (closeModal) closeModal();
|
||||
if (refresh) {
|
||||
const models = Array.isArray(refresh) ? refresh : [refresh];
|
||||
await Promise.all(models.map(m => modelFetch(m)));
|
||||
}
|
||||
// No modelFetch — WS delta updates all affected subsystems.
|
||||
} else {
|
||||
toast(res.error || 'Failed', 'error');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user