add categories to task planner
All checks were successful
Deploy Sokko G / deploy (push) Successful in 6s

This commit is contained in:
Shinuwa 2026-07-28 09:32:14 +02:00
parent e306bfc5d6
commit 3cd350c7b8
10 changed files with 459 additions and 120 deletions

View file

@ -154,8 +154,8 @@ export function normalizeChecklistData(data) {
const sections = Array.isArray(data?.sections)
? data.sections.map((section) => normalizeChecklistSection(section)).filter((section) => section.items.length || section.title)
: [];
const legacyItems = (data?.items || []).map(normalizeChecklistItem).filter((item) => item.label);
if (!sections.length && legacyItems.length) return { hideCompletedSections, hideCompletedSectionsFully, sections: [{ id: uid("section"), title: "", items: legacyItems }], items: legacyItems };
const simpleItems = (data?.items || []).map(normalizeChecklistItem).filter((item) => item.label);
if (!sections.length && simpleItems.length) return { hideCompletedSections, hideCompletedSectionsFully, sections: [{ id: uid("section"), title: "", items: simpleItems }], items: simpleItems };
const items = sections.flatMap((section) => section.items);
return { hideCompletedSections, hideCompletedSectionsFully, sections, items };
}
@ -267,7 +267,6 @@ export function normalizeCalculatorData(data) {
export function normalizeTimerData(data) {
const stopwatch = data?.stopwatch || {};
const legacyAlertMode = TIMER_ALERT_MODES.has(data?.alertMode) ? data.alertMode : "off";
const laps = (Array.isArray(stopwatch.laps) ? stopwatch.laps : [])
.map((lap) => ({
id: lap?.id || uid("timer"),
@ -282,7 +281,7 @@ export function normalizeTimerData(data) {
id: countdown?.id || uid("timer"),
label: String(countdown?.label || "Timer").trim() || "Timer",
type,
alertMode: TIMER_ALERT_MODES.has(countdown?.alertMode) ? countdown.alertMode : legacyAlertMode
alertMode: TIMER_ALERT_MODES.has(countdown?.alertMode) ? countdown.alertMode : "off"
};
if (type === "duration") {
const durationMs = Math.max(0, Number(countdown?.durationMs) || 0);
@ -299,8 +298,7 @@ export function normalizeTimerData(data) {
return isTimeString(pattern, true) ? { ...normalized, pattern } : null;
}
if (type === "interval") {
const legacyIntervalMs = (Number.parseInt(countdown?.intervalMinutes, 10) || 0) * 60000;
const intervalMs = Math.max(0, Number(countdown?.intervalMs) || legacyIntervalMs);
const intervalMs = Math.max(0, Number(countdown?.intervalMs) || 0);
const anchorAt = Math.max(0, Number(countdown?.anchorAt) || 0);
return intervalMs > 0 ? { ...normalized, intervalMs, anchorAt } : null;
}
@ -324,6 +322,7 @@ export function normalizeTimerData(data) {
function normalizeTaskPlannerTask(task) {
const title = String(task?.title || "").trim() || "Tâche";
const type = TASK_TYPES.has(task?.type) ? task.type : "unique";
const category = String(task?.category || "").trim();
const normalized = {
id: task?.id || uid("task"),
title,
@ -332,23 +331,29 @@ function normalizeTaskPlannerTask(task) {
checked: task?.checked === true,
checkedAt: normalizeTimestamp(task?.checkedAt)
};
if (category) normalized.category = category;
if (type === "weekly" && task?.weeklyResetDay !== undefined) normalized.weeklyResetDay = normalizeWeekDay(task.weeklyResetDay);
if (!normalized.checked) normalized.checkedAt = 0;
return normalized;
}
function normalizeTaskPlannerCategoryOrder(value, tasks) {
const categories = new Set(tasks.map((task) => task.category).filter(Boolean));
const ordered = [];
(Array.isArray(value) ? value : []).forEach((category) => {
const normalized = String(category || "").trim();
if (normalized && categories.has(normalized) && !ordered.includes(normalized)) ordered.push(normalized);
});
tasks.forEach((task) => {
if (task.category && !ordered.includes(task.category)) ordered.push(task.category);
});
return ordered;
}
function normalizeTaskPlannerRelations(data, taskIds) {
const seen = new Set();
const seenChildren = new Set();
const legacyDependencies = new Set((Array.isArray(data?.dependencies) ? data.dependencies : [])
.map((relation) => `${relation?.fromTaskId || ""}:${relation?.toTaskId || ""}`));
const sourceRelations = Array.isArray(data?.relations)
? data.relations
: [
...(Array.isArray(data?.links) ? data.links : []),
...(Array.isArray(data?.dependencies) ? data.dependencies : []).map((relation) => ({ ...relation, dependency: true }))
];
return sourceRelations
return (Array.isArray(data?.relations) ? data.relations : [])
.map((relation) => {
const fromTaskId = String(relation?.fromTaskId || "");
const toTaskId = String(relation?.toTaskId || "");
@ -361,22 +366,32 @@ function normalizeTaskPlannerRelations(data, taskIds) {
id: relation?.id || uid("relation"),
fromTaskId,
toTaskId,
dependency: relation?.dependency === true || legacyDependencies.has(key)
prerequisite: relation?.prerequisite === true
};
})
.filter(Boolean);
}
export function normalizeTaskPlannerData(data) {
const tasks = (Array.isArray(data?.tasks) ? data.tasks : []).map(normalizeTaskPlannerTask).filter(Boolean);
const rawTasks = (Array.isArray(data?.tasks) ? data.tasks : []).map(normalizeTaskPlannerTask).filter(Boolean);
const rawTaskIds = new Set(rawTasks.map((task) => task.id));
const relations = normalizeTaskPlannerRelations(data, rawTaskIds);
const childTaskIds = new Set(relations.map((relation) => relation.fromTaskId));
const tasks = rawTasks.map((task) => {
if (!childTaskIds.has(task.id) || !task.category) return task;
const normalized = { ...task };
delete normalized.category;
return normalized;
});
const taskIds = new Set(tasks.map((task) => task.id));
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),
tasks,
relations: normalizeTaskPlannerRelations(data, taskIds)
relations: relations.filter((relation) => taskIds.has(relation.fromTaskId) && taskIds.has(relation.toTaskId))
};
}
@ -387,7 +402,7 @@ function clampPercent(value) {
}
export function normalizeImageAnnotationData(data) {
const image = String(data?.image || data?.dataUrl || "");
const image = String(data?.image || "");
const markers = (data?.markers || [])
.map((marker) => ({
id: marker?.id || uid("marker"),
@ -528,12 +543,14 @@ export function compactModuleDataForStorage(type, value) {
type: task.type
};
if (task.description) compactTask.description = task.description;
if (task.category) compactTask.category = task.category;
if (task.checked) compactTask.checked = true;
if (task.checked && task.checkedAt) compactTask.checkedAt = task.checkedAt;
if (task.type === "weekly" && task.weeklyResetDay !== undefined) compactTask.weeklyResetDay = task.weeklyResetDay;
return compactTask;
});
}
if (normalized.categoryOrder.length) compact.categoryOrder = normalized.categoryOrder;
if (normalized.relations.length) {
compact.relations = normalized.relations.map((relation) => {
const compactRelation = {
@ -541,7 +558,7 @@ export function compactModuleDataForStorage(type, value) {
fromTaskId: relation.fromTaskId,
toTaskId: relation.toTaskId
};
if (relation.dependency) compactRelation.dependency = true;
if (relation.prerequisite) compactRelation.prerequisite = true;
return compactRelation;
});
}