feat: collapse subtasks from parent rows
ci / docker (push) Successful in 4m16s

This commit is contained in:
2026-09-08 10:31:31 +08:00
parent 3528e880f6
commit c8abb75cf4
4 changed files with 31 additions and 4 deletions
+7
View File
@@ -8,6 +8,7 @@ type SearchTask = {
parent_id?: string | null
completed?: boolean
list_name?: string
subtasks?: SearchTask[]
}
const tasks: SearchTask[] = [
@@ -26,6 +27,12 @@ describe('task utilities', () => {
expect(groupTaskTree(tasks)).toEqual([{ task: tasks[0], subtasks: [tasks[1]] }, { task: tasks[2], subtasks: [] }])
})
it('preserves subtasks already nested by the task API', () => {
const child: SearchTask = { id: 'nested-child', title: 'Nested child', parent_id: 'nested-parent' }
const parent: SearchTask = { id: 'nested-parent', title: 'Nested parent', parent_id: null, subtasks: [child] }
expect(groupTaskTree([parent])).toEqual([{ task: parent, subtasks: [child] }])
})
it('moves an item before or after another item without changing other scopes', () => {
const rows = [
{ id: 'a', parent_id: null },
+5 -1
View File
@@ -5,6 +5,7 @@ export type MinimalTask = {
parent_id?: string | null
completed?: boolean
list_name?: string
subtasks?: MinimalTask[]
}
const escapeHtml = (value: string) =>
@@ -85,7 +86,10 @@ export function groupTaskTree<T extends MinimalTask>(tasks: T[]) {
if (!task.parent_id) continue
children.set(task.parent_id, [...(children.get(task.parent_id) ?? []), task])
}
return tasks.filter((task) => !task.parent_id).map((task) => ({ task, subtasks: children.get(task.id) ?? [] }))
return tasks.filter((task) => !task.parent_id).map((task) => ({
task,
subtasks: children.get(task.id) ?? (task.subtasks as T[] | undefined) ?? [],
}))
}
export function moveItemWithinScope<T extends { id: string; parent_id?: string | null }>(items: T[], sourceId: string, targetId: string, placement: 'before' | 'after') {