fix(dashboard): wire data-async form submit handler on the C0R3 page
Clicking "update & rebuild" (and cancel / respawn / purge) on /core.html navigated to the bare `ok` response page instead of submitting async. The C0R3 page (split out of the dashboard) carries `data-async` forms but its bundle never had the global submit interceptor — that handler lived inline in tabs.js, so only the dashboard bundle had it. The forms POSTed natively and the browser followed the response. Fix: lift the `data-async` submit handler out of tabs.js into a shared `bindAsyncForms(onSuccess)` in common.js (which already owns the `form` helper that builds these forms), and call it from both pages: - tabs.js: `bindAsyncForms(() => refreshState())` — behaviour-preserving (same handler, now imported). - core.js: add a `refreshState()` (re-fetch /api/state + re-render) used for the cold load and as the post-submit refresh, and call `bindAsyncForms(() => refreshState())` at boot. Forms with `data-no-refresh` (e.g. meta-update, which gets its update via the meta SSE events) skip the refresh, same as before.
This commit is contained in:
parent
48347a01c9
commit
878f95205b
3 changed files with 87 additions and 69 deletions
|
|
@ -11,7 +11,7 @@
|
|||
// dashboard SYST3M tab); the dashboard keeps its own copies for now —
|
||||
// de-duplication + removing the SYST3M tab is a deliberate follow-up.
|
||||
|
||||
import { $, el, form, openStream, initServerWarnings } from './common.js';
|
||||
import { $, el, form, openStream, initServerWarnings, bindAsyncForms } from './common.js';
|
||||
import { fmtAgo, fmtElapsed, truncate } from './util.js';
|
||||
import { createTabStrip } from '@hive/shared/tabs.js';
|
||||
|
||||
|
|
@ -503,9 +503,28 @@ const SSE_HANDLERS = {
|
|||
};
|
||||
|
||||
// ─── boot ─────────────────────────────────────────────────────────────────
|
||||
// Re-fetch /api/state, re-sync the derived state, re-render. Used for the
|
||||
// cold load and as the post-submit refresh for `data-async` forms whose
|
||||
// mutation doesn't arrive via an SSE event (e.g. the meta-update / spawn /
|
||||
// purge actions that opt out of `data-no-refresh`).
|
||||
async function refreshState() {
|
||||
try {
|
||||
const resp = await fetch('/api/state');
|
||||
if (resp.ok) syncFromSnapshot(await resp.json());
|
||||
} catch {
|
||||
// best-effort: the page keeps its last-rendered state
|
||||
}
|
||||
renderAll();
|
||||
}
|
||||
|
||||
async function init() {
|
||||
initServerWarnings();
|
||||
|
||||
// `data-async` form submit interceptor — without this the meta-update /
|
||||
// cancel / respawn / purge buttons POST natively and the browser navigates
|
||||
// to the bare `ok` response page.
|
||||
bindAsyncForms(() => refreshState());
|
||||
|
||||
// Hash-routed sub-tab strip; default Rebuild Queue. Container-load
|
||||
// polling runs only while the LOAD sub-tab is open (cpu is a short
|
||||
// two-sample read each refresh on the server).
|
||||
|
|
@ -517,15 +536,7 @@ async function init() {
|
|||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const resp = await fetch('/api/state');
|
||||
if (resp.ok) {
|
||||
syncFromSnapshot(await resp.json());
|
||||
}
|
||||
} catch {
|
||||
// best-effort: the page still renders its empty states
|
||||
}
|
||||
renderAll();
|
||||
await refreshState();
|
||||
|
||||
const es = openStream('/dashboard/stream');
|
||||
if (es) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue