9.1 KiB
9.1 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/tasks/sidebar-task-edit.md | 2026-08-03 | complete |
Implementation Plan: Sidebar Task Editing
Overview
Extend the shared sidebar TaskSwitcher single-task menu with an Edit callback, then route both the desktop sidebar and phone/tablet task switcher through one small edit controller and the existing TaskCreateDialog in edit mode. The implementation reuses current task snapshots and workflow-step data, leaves Rename intact, and relies on the existing PATCH /api/v1/tasks/:taskId plus task.updated reconciliation. No backend, schema, or public API changes are required.
Frontend
Shared single-task menu contract
- Update
apps/web/components/task/task-switcher.tsxsoTaskSwitcher,TaskRow, andTaskItemWithContextMenucan receiveonEditTask(task)for the exactTaskSwitcherItemwhose menu was opened. - Update
apps/web/components/task/task-switcher-context-menu.tsxto render a localized Edit item next to Rename for one live task. Keep it out of the existing multi-selection menu and omit it for archived or workflow-less synthetic rows; use the existing processing state to disable it while deletion is in progress. - Add
common:edittoapps/web/src/locales/en/common.jsonand resolve it at render time withuseTranslation(). - Regenerate
apps/web/src/locales/pseudo/common.jsonas the checked-in locale synchronization artifact.
Shared edit controller and dialog
- Add
apps/web/components/task/task-session-sidebar-edit.tsxcontaining:- a pure target builder that combines the selected
TaskSwitcherItem's workflow identity with the authoritative task fromfindTaskInSnapshots(); useSidebarTaskEdit(), which resolves the clicked task fromkanbanMulti.snapshotswith the activekanban.tasksfallback and owns the open edit target;SidebarTaskEditDialog, which renders the existingTaskCreateDialogwithmode="edit", the target workflow and step list, and matchingeditingTask/initialValuesfields.
- a pure target builder that combines the selected
- Do not navigate or change
tasks.activeTaskIdwhen opening or saving. Let the existing edit submit path andtask.updatedhandler update both active Kanban state and multi-workflow snapshots. - If the target cannot be resolved or lacks workflow/step metadata, do not open the dialog.
Desktop sidebar wiring
- Update
apps/web/components/task/task-session-sidebar.tsxto composeuseSidebarTaskEdit()intouseSidebarActions(). - Update
apps/web/components/task/task-session-sidebar-switcher-props.tsto passhandleEditTaskinto the shared switcher. - Update
apps/web/components/task/task-session-sidebar-dialogs.tsxto hostSidebarTaskEditDialogwith the active workspace andstepsByWorkflowId; closing it clears only the edit target.
Phone and tablet wiring
- Update
apps/web/components/task/mobile/session-task-switcher-sheet.tsxto use the same edit controller, pass Edit throughMobileTaskList, and render the shared edit dialog withuseSheetData().stepsByWorkflowId. - Wrap the edit callback with the existing
surfaceAction()policy: the phoneDrawercloses before the editor opens, while the tabletSheetstays mounted behind it.
Mobile design contract
- Desktop outcome / mobile entry: desktop uses right-click on a sidebar row; phone and tablet use the row's visible Task actions control.
- Nearest shipped exemplar:
apps/web/components/task/mobile/session-task-switcher-sheet.tsxsupplies the existing inset bottomDrawer, widerSheet, action handoff, safe-area padding, and single internal scroll owner.apps/web/components/task/task-switcher-context-menu.tsxsupplies the shared responsive menu primitive. - Hierarchy and primary action: selecting a task remains the row's primary action. Edit stays a secondary action in the explicit overflow menu and opens the established focused task editor.
- Presentation rationale: editing is a focused, potentially multi-field operation, so it uses the existing modal editor. The temporary phone task navigator closes first to avoid stacked bottom surfaces; the roomier tablet sheet retains context behind the modal.
- Geometry: keep the drawer's
88dvhbound, safe-area padding, and internal task-list scroll. The existing mobile menu treatment owns viewport containment and at least 44px action rows; no document-level horizontal scrolling is added. - Shared logic: target resolution, form values, validation, submission, and task state are shared. Only the phone/tablet surface-dismissal behavior remains presentation-specific.
Tests
- What: one eligible task exposes Edit and invokes the callback with the exact clicked task, while multi-selection and archived rows do not expose it.
- File:
apps/web/components/task/task-switcher.test.tsx - How: render the shared switcher, open the Radix context menu, invoke Edit, and assert callback/visibility rules.
- File:
- What: the sidebar edit target uses the clicked task's workflow and authoritative snapshot fields, refuses incomplete targets, and supplies the existing dialog with correct edit props and workflow-specific steps.
- File:
apps/web/components/task/task-session-sidebar-edit.test.tsx - How: unit-test the pure target builder and render the dialog with a mocked
TaskCreateDialog.
- File:
- What: the touch task list forwards Edit through the same shared menu contract.
- File:
apps/web/components/task/mobile/session-task-switcher-sheet.test.tsx - How: open the visible task-actions button, select Edit, and assert the target task is passed.
- File:
- Existing
TaskCreateDialogunit tests remain the authority for edit validation and started-task field locks; this feature does not duplicate that form logic.
E2E Tests
- Scenario: GIVEN a non-active desktop sidebar task, WHEN Edit is opened, saved, and the editor closes, THEN the route stays on the original task while the target's persisted title and sidebar row update.
- File:
apps/web/e2e/tests/task/sidebar-layout.spec.ts - What to verify: Edit is present alongside Rename; target values are prefilled; save persists; route and active task are unchanged.
- File:
- Scenario: GIVEN a started task in the phone task drawer, WHEN Edit is selected, THEN the drawer closes, the title stays editable, the prompt stays locked, and saving is visible after reopening the drawer.
- File:
apps/web/e2e/tests/task/mobile-sidebar-task-actions.spec.ts - What to verify: visible task-actions entry, responsive menu row, no stacked drawer, lifecycle locks, persistence, and updated sidebar copy.
- File:
- Scenario: GIVEN the tablet task-switcher sheet, WHEN Edit is opened and canceled, THEN the sheet remains visible with the unchanged task row.
- File:
apps/web/e2e/tests/task/mobile-sidebar-task-actions.spec.ts - What to verify: tablet sheet retention and cancel behavior.
- File:
- Extend the existing mobile action-menu geometry assertion in
mobile-sidebar-task-actions.spec.tsto include Edit, retaining viewport containment, internal scrolling, and 44px row coverage after the menu grows.
Verification Results
- Focused unit tests followed Red-Green-Refactor: the pre-implementation run reported 2 expected Edit-menu failures with 16 passing tests; the final run passed 24 tests across the three focused files, including unresolved-source, missing-workflow, and selection-clear guards added during PR review.
cd apps/web && pnpm run typecheckpassed.cd apps/web && pnpm run i18n:checkandpnpm run i18n:ratchetpassed after regenerating the pseudo locale.- Targeted ESLint for all changed frontend files passed with no warnings;
git diff --checkpassed. cd apps/web && pnpm run buildpassed.- Managed Playwright passed 9 Chromium sidebar tests and 10 mobile-chrome sidebar/action tests. The final capture runs also passed 2 Chromium and 2 mobile-chrome tests and produced four validated, compressed screenshots under the ignored
.pr-assets/directory.
Implementation Waves And Parallel Candidates
Wave 1:
Wave 2:
- Task 02: Prove desktop and mobile edit parity — depends on Task 01.
The tasks are sequential because Task 02 exercises the UI and selectors introduced by Task 01. No subagent use is implied by this plan.
Risks
- Sidebar rows aggregate tasks across workflows; using the globally active workflow would initialize the wrong step list. The edit target must retain the clicked row's workflow identity.
- The synthetic archived row is not backed by a complete editable task snapshot. It must not expose Edit.
- Phone action selection must close the task drawer before opening the dialog, while tablet behavior intentionally differs; reusing
surfaceAction()preserves that breakpoint contract. - The menu already has substantial mobile height. Adding Edit must preserve bottom-sheet containment, internal scrolling, and access to destructive actions.
- Task updates arrive through the existing WebSocket reconciliation path; tests should assert eventual sidebar state and must not add a second competing cache-update implementation.