3.6 KiB
3.6 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 02-frontend-nest-drop-infrastructure | Frontend nest-drop infrastructure | done | 2 |
|
plan.md | ../../specs/tasks/requirements/subtask-reparenting-drag-drop.md |
Task 02: Frontend nest-drop infrastructure
Acceptance
- A single
DndContextper sidebar group section replaces the per-level contexts, so a drag can target rows outside its own sibling level; sibling reorder behavior is unchanged. resolveSidebarDrop(pure) andcomputeNestTargets(pure) exist with unit tests;NestDropZonerenders on candidate rows withdata-testid="nest-drop-zone"anddata-task-id.- Existing
TaskSwitcher/SortableTaskLeveltests pass (no behavior regression when no group-level context or reorder is configured).
Verification
cd apps/web && pnpm test -- components/task/task-switcher-subtask-dnd.test.ts components/task/task-switcher.test.tsx lib/sidebar/nest-candidates.test.ts
cd apps/web && pnpm run typecheck
Files likely touched
apps/web/components/task/task-switcher-subtask-dnd.tsx— hoistDndContextout ofSortableTaskLevel(newexternalDragContextmode), addNestDropZone,resolveSidebarDrop,computeNestTargets, custom collision (pointerWithin→nest:ids, elseclosestCenter), sensors, group-levelonDragStart/onDragEnd.apps/web/components/task/task-switcher.tsx—GroupSectionrenders the hoistedDndContext;TaskTreeContextcarries candidate ids +onReparentTask;TaskTreeNoderendersNestDropZoneon candidate rows; new optionalonReparentTaskprop onTaskSwitcher(unwired for now).apps/web/components/task/task-switcher-subtask-dnd.test.ts(new) —resolveSidebarDropunit tests: nest id mapping, group-root reorder, subtask-level reorder, cross-level drop → null, no-over → null.
Dependencies
Task 01 (semantics only — infra works against the existing updateTask path regardless).
Inputs
- Spec sections: What (gesture, targets, reorder preservation), Scenarios.
- Existing code:
useLevelDnd/SortableTaskLevel/DraggableSortableTaskNodeintask-switcher-subtask-dnd.tsx;TaskTreeLevel/GroupSection/TaskTreeContextintask-switcher.tsx;computeNestCandidatesinapps/web/lib/sidebar/nest-candidates.ts; activation constraints constants. - Reorder callbacks keep their signatures:
onReorderGroup(orderedTaskIds),onReorderSubtasks(parentTaskId, orderedTaskIds).
Output contract
Report the component/helper changes, exact commands and results, files changed, blockers, residual risks; update this task and plan.md when acceptance passes.
Results
cd apps/web && pnpm test -- components/task/task-switcher-subtask-dnd.test.ts components/task/task-switcher.test.tsx components/task/task-switcher-direct-subtasks.test.tsx— 31 passed (new helper tests + switcher regression suites).pnpm run typecheckclean;pnpm run lintclean (0 warnings);pnpm run i18n:ratchetclean.- Hoisted per-level
DndContextintoTaskTreeDndGroup(one per group section; custom collision:pointerWithin→nest:ids win, elseclosestCenter);SortableTaskLevelgainedexternalDragContext; addedNestDropZone+ pureresolveSidebarDrop/computeNestTargets(unit-tested);GroupSectionslimmed via props-object + newtask-switcher-tree-context.ts(flattenGroupTasks/buildTaskTreeContext) to stay under lint line limits. - Files changed:
components/task/task-switcher-subtask-dnd.tsx,task-switcher-subtask-dnd.test.ts,task-switcher.tsx,task-switcher-tree-context.ts(new),src/locales/en/sidebar.json(sidebar:nestUnder).