fix(tauri): cascade delete must handle the full subtree, not just direct children
delete_task only collected direct children when a parent was deleted, so grandchildren (and deeper descendants — the data model allows any depth even though the UI is two-level today) would be left with a parent_id pointing at a deleted task. Walk the parent-child graph to collect the full descendant set and delete children before the parent so a mid-cascade failure can't strand descendants.
This commit is contained in:
parent
df66e7bc98
commit
f276233be5
|
|
@ -420,14 +420,23 @@ fn delete_task(
|
||||||
let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?;
|
let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?;
|
||||||
let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?;
|
let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?;
|
||||||
let repo = repo_mut(&mut s)?;
|
let repo = repo_mut(&mut s)?;
|
||||||
// Cascade-delete subtasks first
|
// Cascade-delete the full descendant subtree (not just direct children)
|
||||||
|
// so deleting a parent can't leave grandchildren orphaned with a
|
||||||
|
// parent_id pointing at a deleted task.
|
||||||
let all_tasks = repo.list_tasks(lid).map_err(|e| e.to_string())?;
|
let all_tasks = repo.list_tasks(lid).map_err(|e| e.to_string())?;
|
||||||
let child_ids: Vec<Uuid> = all_tasks
|
let mut to_delete: Vec<Uuid> = Vec::new();
|
||||||
.iter()
|
let mut frontier: Vec<Uuid> = vec![tid];
|
||||||
.filter(|t| t.parent_id == Some(tid))
|
while let Some(parent) = frontier.pop() {
|
||||||
.map(|t| t.id)
|
for t in &all_tasks {
|
||||||
.collect();
|
if t.parent_id == Some(parent) && !to_delete.contains(&t.id) {
|
||||||
for child_id in child_ids {
|
to_delete.push(t.id);
|
||||||
|
frontier.push(t.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete children before the parent so a mid-cascade failure doesn't
|
||||||
|
// leave the parent removed but descendants stranded.
|
||||||
|
for child_id in to_delete {
|
||||||
repo.delete_task(lid, child_id).map_err(|e| format!("Failed to delete subtask {}: {}", child_id, e))?;
|
repo.delete_task(lid, child_id).map_err(|e| format!("Failed to delete subtask {}: {}", child_id, e))?;
|
||||||
}
|
}
|
||||||
repo.delete_task(lid, tid)
|
repo.delete_task(lid, tid)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue