From 6c57b2b4e0d5a31b38c6313035282aae37be2524 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 5 Jun 2026 13:35:04 +0200 Subject: [PATCH] fix(dashboard): preserve checked meta-input checkboxes across MetaInputsChanged re-renders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit renderMetaInputs snapshots the set of checked data-meta-input values before calling root.replaceChildren(), then restores them after rebuilding the list. Without this, a MetaInputsChanged SSE event (e.g. fired when a concurrent meta-update completes) would silently wipe any checkboxes the operator had ticked but not yet submitted — forcing them to re-select their inputs. --- frontend/packages/dashboard/src/tabs.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 54325005..1c965e07 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -2364,6 +2364,14 @@ window.marked = marked; function renderMetaInputs(s) { const root = $('meta-inputs-section'); if (!root) return; + // Snapshot which checkboxes the operator has ticked before wiping the + // DOM. A MetaInputsChanged event (e.g. triggered by a concurrent + // meta-update completing) would otherwise silently clear pending + // selections mid-flight. We restore them after rebuilding the list. + const checkedInputs = new Set( + Array.from(root.querySelectorAll('input[type="checkbox"][data-meta-input]:checked')) + .map((cb) => cb.dataset.metaInput), + ); root.replaceChildren(); const inputs = s.meta_inputs || []; if (!inputs.length) { @@ -2410,6 +2418,7 @@ window.marked = marked; value: inp.name, 'data-meta-input': inp.name, }); + if (checkedInputs.has(inp.name)) cb.checked = true; const label = el('label', { for: id, title: inp.name }); label.append(cb); if (depth > 0) label.append(el('span', { class: 'meta-input-twig' }, '└ '));