fix(ui): preserve other pending answers on needs-input submit - #641
fix(ui): preserve other pending answers on needs-input submit#641emrahzunicaplab wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes the UI behavior where submitting one question in a pending_questions batch causes the action panel to fully re-render and lose unsubmitted selections/free-text drafts on sibling questions. This stays entirely client-side by persisting per-question drafts in module state and re-applying them on re-render.
Changes:
- Added an in-memory draft store for task-level batch questions (
taskQuestionDrafts) keyed by task/question id. - Updated
renderTaskQuestionsItemto restore option selection and free-text from the draft store on every paint. - Updated action handlers to record draft state on option selection / free-text input, and clear it once a question is successfully submitted.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| ${questions.map((q, idx) => { | ||
| // Restore any un-submitted selection for this question so a | ||
| // re-render (e.g. after a sibling question is submitted) | ||
| // does not wipe it — see taskQuestionDrafts (issue #622). | ||
| const draft = (taskQuestionDrafts[taskId] || {})[q.id] || {}; |
There was a problem hiding this comment.
🟡 Not ready to approve
The new free-text input handler can clear the stored draft on whitespace-only input while leaving an option selected, which can still cause selections to be lost after a subsequent re-render.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (1)
src/ui/static/modules/actions.js:993
- The free-text input handler clears the stored draft whenever
textarea.value.trim()is empty, but it does not account for the case where the user types only whitespace while an option is still selected. In that case, the option remains selected in the DOM, but the stored draft is removed, so a subsequent panel re-render will lose the selection again.
textarea.addEventListener('input', () => {
const questionBlock = textarea.closest('.task-question-block');
if (questionBlock?.classList.contains('answered')) return;
if (textarea.value.trim()) {
questionBlock?.querySelectorAll('.answer-option').forEach(opt => opt.classList.remove('selected'));
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
carlospedreira
left a comment
There was a problem hiding this comment.
The draft is still lost in one reproducible path: choose an option, then enter only whitespace in the custom-answer textarea. The option remains visually selected, but the input handler sees an empty trimmed value and clears taskQuestionDrafts; the next panel re-render then drops the selection. Preserve the option draft when a selected option exists (or clear the selection consistently) before this can be merged.
There was a problem hiding this comment.
🟢 Ready to approve
The changes are scoped to client-side UI state management, include pruning/cleanup to avoid stale restoration, and align with the existing per-question submit contract without introducing backend/API changes.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
🟡 Not ready to approve
The behavior change isn’t covered by the existing automated UI tests, so a Playwright E2E regression test for “submit Q1 preserves Q2/Q3 drafts” should be added to prevent future regressions.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (1)
src/ui/static/modules/actions.js:15
- The new client-side draft store for task batch questions fixes a subtle UI regression, but there’s no automated coverage for the cross-submit persistence scenario (select answers on Q2/Q3, submit Q1, verify Q2/Q3 drafts persist after the panel re-renders). The existing Playwright E2E suite doesn’t appear to exercise the action-required slideout / task-questions flow, so this could regress without being caught.
// Un-submitted selections for task-level batch questions (the "task-questions"
// action item). Keyed { taskId: { questionId: { key, customText } } }. Selections
// for a batch of pending_questions otherwise live only in the DOM's `.selected`
// class, so submitting one question — which triggers a full panel re-render —
// wipes the choices lined up on the sibling questions (issue #622). This store
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Linked issue
Closes #622
Summary of changes
renderActionItemsfully rebuilds the action-required panel's DOM after anyquestion submit (
container.innerHTML = ...), so submitting one question ina
pending_questionsbatch wiped the.selectedstate and free-text draftson sibling, un-submitted questions — the only place that state lived.
Added a small client-side draft store (
taskQuestionDrafts) insrc/ui/static/modules/actions.jsthat records each un-submittedselection/free-text as the user makes it, and re-applies it whenever
renderTaskQuestionsItemrepaints. The draft for a question is cleared oncethe server confirms it's answered. No API or backend changes — this keeps
the existing per-question submit/resume contract documented in
PRD-029 (
pending_questions[]: "mark answered per question; move when alldone"), rather than moving to a single "Submit all" action.
Screenshots / recordings
Before/after recording: on main, submitting one question in the 4-question batch wipes the in-progress selections on the other pending questions; on this branch, sibling selections/drafts are preserved across submits until each question is answered.
Before.mp4
After.mp4
Testing notes
Repro'd with a seeded
needs-inputtask carrying 4pending_questions(
extensions.runner.pending_questions) against a localdotbot serveinstance:
previously they were wiped.
"No pending actions" once the last question is answered.
Checklist