From 221de2204db6a77cc575dc02158b8cb2713b9c05 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 5 Jun 2026 12:35:22 +0200 Subject: [PATCH] fix(dashboard): preserve spawn-form input across approval_added/resolved re-renders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit renderApprovals() called root.replaceChildren() on every approval_added / approval_resolved SSE event, wiping the spawn form's name input if the operator had started typing a new agent name. Save the current input value before the wipe and restore it into the freshly-built input element. The form itself is still rebuilt (no keyed-cache needed here — approval cards have no user inputs), so all other behaviour is unchanged. --- frontend/packages/dashboard/src/tabs.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index e0f7d2c2..5d6c8e01 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -2092,21 +2092,29 @@ window.marked = marked; // no-op elsewhere — `approval_added` / `approval_resolved` SSE // events route through here on every page that loads the bundle. if (!root) return; + // Save spawn form input + focus state before the DOM wipe so a live + // approval_added/resolved event doesn't erase a partially-typed name + // or steal focus from the operator. + const savedSpawnName = root.querySelector('.spawnform input[name="name"]')?.value ?? ''; + const spawnHadFocus = document.activeElement === root.querySelector('.spawnform input[name="name"]'); root.replaceChildren(); // Spawn request form: submitting it queues a Spawn approval that // lands in this same list, so the form belongs here rather than on // the containers list (the agent doesn't exist yet). + const spawnNameInput = el('input', { + name: 'name', + placeholder: 'new agent name (≤9 chars)', + maxlength: '9', required: '', autocomplete: 'off', + }); + if (savedSpawnName) spawnNameInput.value = savedSpawnName; + if (spawnHadFocus) spawnNameInput.focus(); const spawn = el('form', { method: 'POST', action: '/request-spawn', class: 'spawnform', 'data-async': '', 'data-no-refresh': '', }); spawn.append( - el('input', { - name: 'name', - placeholder: 'new agent name (≤9 chars)', - maxlength: '9', required: '', autocomplete: 'off', - }), + spawnNameInput, el('button', { type: 'submit', class: 'btn btn-spawn' }, '◆ R3QU3ST SP4WN'), ); root.append(spawn);