-
+
-
{groupCount}
+
+ {groupCompletedCount} / {groupCount}
+
+
-
- {groupTasks.map(renderTask)}
-
+ {!isCollapsed && (
+
+ {groupTasks.map(renderTask).filter(Boolean)}
+
+ )}
);
}
diff --git a/website/src/features/toolboxes/storage/toolboxStorage.js b/website/src/features/toolboxes/storage/toolboxStorage.js
index aee0bbc..4a9ade7 100644
--- a/website/src/features/toolboxes/storage/toolboxStorage.js
+++ b/website/src/features/toolboxes/storage/toolboxStorage.js
@@ -384,12 +384,17 @@ export function normalizeTaskPlannerData(data) {
return normalized;
});
const taskIds = new Set(tasks.map((task) => task.id));
+ const categoryOrder = normalizeTaskPlannerCategoryOrder(data?.categoryOrder, tasks);
return {
sortMode: TASK_SORT_MODES.has(data?.sortMode) ? data.sortMode : "manual",
weeklyResetDay: normalizeWeekDay(data?.weeklyResetDay),
resetTime: isClockTimeString(data?.resetTime) ? data.resetTime : DEFAULT_TASK_PLANNER_RESET_TIME,
lastResetAt: normalizeTimestamp(data?.lastResetAt),
- categoryOrder: normalizeTaskPlannerCategoryOrder(data?.categoryOrder, tasks),
+ hideCompleted: data?.hideCompleted === true,
+ collapsedCategories: (Array.isArray(data?.collapsedCategories) ? data.collapsedCategories : [])
+ .map((category) => String(category || "").trim())
+ .filter((category, index, categories) => category && categoryOrder.includes(category) && categories.indexOf(category) === index),
+ categoryOrder,
tasks,
relations: relations.filter((relation) => taskIds.has(relation.fromTaskId) && taskIds.has(relation.toTaskId))
};
@@ -535,6 +540,8 @@ export function compactModuleDataForStorage(type, value) {
if (normalized.weeklyResetDay !== DEFAULT_TASK_PLANNER_WEEKLY_RESET_DAY) compact.weeklyResetDay = normalized.weeklyResetDay;
if (normalized.resetTime !== DEFAULT_TASK_PLANNER_RESET_TIME) compact.resetTime = normalized.resetTime;
if (normalized.lastResetAt) compact.lastResetAt = normalized.lastResetAt;
+ if (normalized.hideCompleted) compact.hideCompleted = true;
+ if (normalized.collapsedCategories.length) compact.collapsedCategories = normalized.collapsedCategories;
if (normalized.tasks.length) {
compact.tasks = normalized.tasks.map((task) => {
const compactTask = {
diff --git a/website/src/styles/_toolboxes.scss b/website/src/styles/_toolboxes.scss
index 6e5b4f6..c35c2ae 100644
--- a/website/src/styles/_toolboxes.scss
+++ b/website/src/styles/_toolboxes.scss
@@ -1235,10 +1235,26 @@ textarea:focus {
height: 16px;
}
+.task-planner-clear-completed-button {
+ display: inline-flex;
+ min-height: 38px;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 0 12px;
+ white-space: nowrap;
+}
+
+.task-planner-clear-completed-button .ui-icon {
+ width: 15px;
+ height: 15px;
+}
+
.task-planner-settings {
display: grid;
grid-template-columns: minmax(130px, 1fr) minmax(110px, 0.72fr);
gap: 10px;
+ align-items: end;
padding: 12px;
border: 1px solid rgba(165, 180, 252, 0.12);
border-radius: var(--radius-md);
@@ -1247,6 +1263,12 @@ textarea:focus {
rgba(7, 10, 24, 0.34);
}
+.task-planner-settings-actions {
+ display: flex;
+ grid-column: 1 / -1;
+ justify-content: flex-end;
+}
+
.task-planner-settings label,
.task-planner-weekly-override {
display: grid;
@@ -1318,7 +1340,18 @@ textarea:focus {
position: relative;
}
-.task-planner-child-list > .task-planner-item::before {
+.task-planner-hidden-parent-children {
+ position: relative;
+ display: grid;
+ min-width: 0;
+}
+
+.task-planner-hidden-parent-children > .task-planner-child-list {
+ margin-top: 0;
+}
+
+.task-planner-child-list > .task-planner-item::before,
+.task-planner-child-list > .task-planner-hidden-parent-children::before {
content: "";
position: absolute;
top: 25px;
@@ -1351,7 +1384,7 @@ textarea:focus {
padding: 0 2px;
}
-.task-planner-category-header > div {
+.task-planner-category-title {
display: inline-flex;
flex: 1 1 auto;
min-width: 0;
@@ -1359,6 +1392,13 @@ textarea:focus {
gap: 8px;
}
+.task-planner-category-actions {
+ display: inline-flex;
+ flex: 0 0 auto;
+ align-items: center;
+ gap: 8px;
+}
+
.task-planner-category-header h3 {
min-width: 0;
margin: 0;
@@ -1369,7 +1409,7 @@ textarea:focus {
white-space: nowrap;
}
-.task-planner-category-header > span {
+.task-planner-category-actions > span {
flex: 0 0 auto;
padding: 3px 9px;
border: 1px solid rgba(246, 196, 83, 0.22);
@@ -1380,6 +1420,11 @@ textarea:focus {
font-weight: 800;
}
+.task-planner-category-section.is-complete .task-planner-category-header h3 {
+ color: var(--color-text-muted);
+ text-decoration: line-through;
+}
+
.task-planner-category-section.is-dragging {
cursor: grabbing;
opacity: 0.58;
@@ -2426,6 +2471,7 @@ textarea:focus {
.tool-split-entry > button.danger,
.counter-actions button.danger,
.link-item button.danger,
+.task-planner-clear-completed-button.danger,
.task-planner-delete-button.danger {
border-color: rgba(251, 113, 133, 0.2);
background: rgba(21, 26, 48, 0.88);
@@ -2436,6 +2482,7 @@ textarea:focus {
.tool-split-entry > button.danger:hover,
.counter-actions button.danger:hover,
.link-item button.danger:hover,
+.task-planner-clear-completed-button.danger:hover:not(:disabled),
.task-planner-delete-button.danger:hover {
border-color: rgba(251, 113, 133, 0.56);
background:
@@ -2451,6 +2498,7 @@ textarea:focus {
.tool-split-entry > button.danger:hover .ui-icon,
.counter-actions button.danger:hover .ui-icon,
.link-item button.danger:hover .ui-icon,
+.task-planner-clear-completed-button.danger:hover .ui-icon,
.task-planner-delete-button.danger:hover .ui-icon {
background-color: #fff;
filter: drop-shadow(0 0 6px rgba(251, 113, 133, 0.26));