commit 9a5d6e972d2d5fa79226bfa6e2b5c29a4fc70fc3
parent 2726d06bd227ebb53e72bcaef6180facb037c1fb
Author: Hunter
Date: Mon, 5 Aug 2024 16:47:11 -0400
propagate status up and down the tree
Diffstat:
| M | index.html | | | 132 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
1 file changed, 80 insertions(+), 52 deletions(-)
diff --git a/index.html b/index.html
@@ -412,35 +412,95 @@
}
function toggleTaskState(task) {
- if (task.state === 1) {
- if (task.subtasks.length === 0 || !task.subtasks.every(t => t.state === 1)) {
- task.state = 0;
- updateSubtasksState(task, 0);
+ if (task.state === 1) {
+ // Only allow unchecking if not all direct children are checked
+ if (task.subtasks.length === 0 || !task.subtasks.every(t => t.state === 1)) {
+ task.state = 0;
+ updateSubtasksState(task, 0);
+
+ const parent = findParentTask(task);
+ if (parent) {
+ updateTaskAndAncestors(parent);
}
- } else {
- task.state = 1;
- updateSubtasksState(task, 1);
+
+ renderCurrentView();
+ selectAndFocusTask(task);
+ scheduleSave();
+ }
+ // If all direct children are checked, do nothing
+ } else {
+ task.state = 1;
+ updateSubtasksState(task, 1);
+
+ const parent = findParentTask(task);
+ if (parent) {
+ updateTaskAndAncestors(parent);
}
- updateParentTaskState(task);
+
renderCurrentView();
selectAndFocusTask(task);
scheduleSave();
}
+ }
- function updateParentTaskState(task) {
- const parent = findParentTask(task);
- if (parent) {
- const allChecked = parent.subtasks.every(t => t.state === 1);
- const anyUnchecked = parent.subtasks.some(t => t.state === 0);
+ //recalculates the state of a task based on its subtasks
+ function recalculateTaskState(task) {
+ if (task.subtasks.length === 0) {
+ return task.state; // If no subtasks, keep current state
+ }
+ const allChecked = task.subtasks.every(t => t.state === 1);
+ const anyUnchecked = task.subtasks.some(t => t.state === 0);
+ if (allChecked) {
+ return 1; // Checked
+ } else if (anyUnchecked) {
+ return 0; // Unchecked
+ }
+ }
- if (allChecked) {
- parent.state = 1;
- } else if (anyUnchecked) {
- parent.state = 0;
+ function updateTaskAndAncestors(task) {
+ const newState = recalculateTaskState(task);
+ if (task.state !== newState) {
+ const oldState = task.state;
+ task.state = newState;
+
+ // If the task changed from checked to unchecked, update its descendants
+ if (oldState === 1 && newState === 0) {
+ updateSubtasksState(task, 0);
+ }
+
+ const parent = findParentTask(task);
+ if (parent) {
+ updateTaskAndAncestors(parent);
}
+ }
+ }
+
+ function deleteSubtask(subtask) {
+ const parentTask = taskPath[taskPath.length - 1];
+ const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
- updateParentTaskState(parent);
+ if (parentTask.id === 'root' && parentTask.subtasks.length === 1) {
+ return;
}
+
+ // Delete the subtask
+ parentTask.subtasks = parentTask.subtasks.filter(t => t.id !== subtask.id);
+
+ // Recalculate parent state and propagate changes
+ updateTaskAndAncestors(parentTask);
+
+ if (parentTask.subtasks.length === 0 && taskPath.length > 1) {
+ navigateToParentTask();
+ } else {
+ renderCurrentView();
+ if (parentTask.subtasks.length > 0) {
+ const targetIndex = Math.max(0, index - 1);
+ selectAndFocusTask(parentTask.subtasks[targetIndex]);
+ } else {
+ selectAndFocusTask(parentTask);
+ }
+ }
+ scheduleSave();
}
function updateSubtasksState(task, state) {
@@ -532,12 +592,7 @@
parentTask.subtasks.push(newSubtask);
}
- parentTask.state = 0;
- parentTask.subtasks.forEach(subtask => {
- if (subtask.state === 2) {
- subtask.state = 0;
- }
- });
+ updateTaskAndAncestors(parentTask);
renderCurrentView();
selectAndFocusTask(newSubtask);
@@ -557,31 +612,6 @@
taskInput.setSelectionRange(0, 0);
}
- function deleteSubtask(subtask) {
- const parentTask = taskPath[taskPath.length - 1];
- const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
-
- if (parentTask.id === 'root' && parentTask.subtasks.length === 1) {
- return;
- }
-
- parentTask.subtasks = parentTask.subtasks.filter(t => t.id !== subtask.id);
- updateParentTaskState(parentTask);
-
- if (parentTask.subtasks.length === 0 && taskPath.length > 1) {
- navigateToParentTask();
- } else {
- renderCurrentView();
- if (parentTask.subtasks.length > 0) {
- const targetIndex = Math.max(0, index - 1);
- selectAndFocusTask(parentTask.subtasks[targetIndex]);
- } else {
- selectAndFocusTask(parentTask);
- }
- }
- scheduleSave();
- }
-
function deleteCurrentParentTask() {
if (taskPath.length <= 1) return; // Don't delete root task
@@ -596,7 +626,7 @@
const index = grandparentTask.subtasks.findIndex(t => t.id === currentParentTask.id);
grandparentTask.subtasks = grandparentTask.subtasks.filter(t => t.id !== currentParentTask.id);
- updateParentTaskState(grandparentTask);
+ updateTaskAndAncestors(grandparentTask);
taskPath.pop(); // Remove the deleted task from the path
currentTask = grandparentTask;
@@ -663,7 +693,6 @@
const currentTaskId = currentTask.id;
taskPath.pop();
currentTask = taskPath[taskPath.length - 1];
- updateParentTaskState(currentTask);
updateBreadcrumbs(currentTask);
renderCurrentView();
const selectedSubtask = currentTask.subtasks.find(t => t.id === currentTaskId);
@@ -760,7 +789,6 @@
const task = currentTask.id === taskId ? currentTask : currentTask.subtasks.find(t => t.id === taskId);
if (task) {
task.text = activeTaskInput.value;
- updateParentTaskState(task);
scheduleSave();
}
}