Merge branch 'fix/issue-4931'

* fix/issue-4931:
  refactor(task-repeat-cfg): deprecate order field and remove from config UI
  feat(task-repeat-cfg): add skipOverdue option to recurring tasks
This commit is contained in:
Johannes Millan 2026-03-06 12:40:12 +01:00
commit f35bd621ec
6 changed files with 40 additions and 14 deletions

View file

@ -249,15 +249,6 @@ export const TASK_REPEAT_CFG_FORM_CFG_BEFORE_TAGS: FormlyFieldConfig[] = [
updateOn: 'blur',
},
},
{
key: 'order',
type: 'input',
templateOptions: {
label: T.F.TASK_REPEAT.F.ORDER,
type: 'number',
description: T.F.TASK_REPEAT.F.ORDER_DESCRIPTION,
},
},
];
export const TASK_REPEAT_CFG_ADVANCED_FORM_CFG: FormlyFieldConfig[] = [
@ -290,4 +281,13 @@ export const TASK_REPEAT_CFG_ADVANCED_FORM_CFG: FormlyFieldConfig[] = [
},
className: 'sp-formly-child-option',
},
{
key: 'skipOverdue',
type: 'checkbox',
defaultValue: false,
templateOptions: {
label: T.F.TASK_REPEAT.F.SKIP_OVERDUE,
description: T.F.TASK_REPEAT.F.SKIP_OVERDUE_DESCRIPTION,
},
},
];

View file

@ -54,7 +54,6 @@ const SCHEDULE_AFFECTING_FIELDS: (keyof TaskRepeatCfgCopy)[] = [
'friday',
'saturday',
'sunday',
'order', // controls top/bottom placement of created tasks, which affects rescheduling behavior
'isPaused',
];

View file

@ -29,6 +29,10 @@ export interface TaskRepeatCfgCopy {
lastTaskCreationDay?: string;
title: string | null;
tagIds: string[];
/**
* @deprecated No longer configurable via UI. Kept for backwards compatibility.
* order<=0 task inserted at top; order>0 task inserted at bottom.
*/
order: number;
defaultEstimate?: number;
startTime?: string;
@ -65,6 +69,8 @@ export interface TaskRepeatCfgCopy {
}[];
// Exception list for deleted instances (ISO date strings YYYY-MM-DD)
deletedInstanceDates?: string[];
// When true, missed/overdue instances are silently skipped instead of being created
skipOverdue?: boolean;
}
export type TaskRepeatCfg = Readonly<TaskRepeatCfgCopy>;
@ -101,4 +107,5 @@ export const DEFAULT_TASK_REPEAT_CFG: Omit<TaskRepeatCfgCopy, 'id'> = {
notes: undefined,
shouldInheritSubtasks: false,
disableAutoUpdateSubtasks: false,
skipOverdue: false,
};

View file

@ -228,6 +228,26 @@ export class TaskRepeatCfgService {
if (taskRepeatCfg.deletedInstanceDates?.includes(targetDateStr)) {
return [];
}
// If skipOverdue is enabled, silently skip instances that are in the past (before today).
// We still dispatch updateTaskRepeatCfg to advance lastTaskCreationDay so that the same
// overdue date is not re-evaluated on every subsequent app open (which would stall progress
// permanently for non-daily or every-N-day schedules where today may not be a scheduled day).
if (
taskRepeatCfg.skipOverdue &&
targetDateStr < getDbDateStr(new Date(targetDayDate))
) {
return [
updateTaskRepeatCfg({
taskRepeatCfg: {
id: taskRepeatCfg.id,
changes: {
lastTaskCreation: targetCreated.getTime(),
lastTaskCreationDay: targetDateStr,
},
},
}),
];
}
const { task, isAddToBottom } = this._getTaskRepeatTemplate(
taskRepeatCfg,

View file

@ -1682,8 +1682,6 @@ const T = {
INHERIT_SUBTASKS_DESCRIPTION: 'F.TASK_REPEAT.F.INHERIT_SUBTASKS_DESCRIPTION',
MONDAY: 'F.TASK_REPEAT.F.MONDAY',
NOTES: 'F.TASK_REPEAT.F.NOTES',
ORDER: 'F.TASK_REPEAT.F.ORDER',
ORDER_DESCRIPTION: 'F.TASK_REPEAT.F.ORDER_DESCRIPTION',
QUICK_SETTING: 'F.TASK_REPEAT.F.QUICK_SETTING',
Q_CUSTOM: 'F.TASK_REPEAT.F.Q_CUSTOM',
Q_DAILY: 'F.TASK_REPEAT.F.Q_DAILY',
@ -1699,6 +1697,8 @@ const T = {
REPEAT_EVERY: 'F.TASK_REPEAT.F.REPEAT_EVERY',
SATURDAY: 'F.TASK_REPEAT.F.SATURDAY',
SCHEDULE_TYPE_LABEL: 'F.TASK_REPEAT.F.SCHEDULE_TYPE_LABEL',
SKIP_OVERDUE: 'F.TASK_REPEAT.F.SKIP_OVERDUE',
SKIP_OVERDUE_DESCRIPTION: 'F.TASK_REPEAT.F.SKIP_OVERDUE_DESCRIPTION',
START_DATE: 'F.TASK_REPEAT.F.START_DATE',
START_TIME: 'F.TASK_REPEAT.F.START_TIME',
START_TIME_DESCRIPTION: 'F.TASK_REPEAT.F.START_TIME_DESCRIPTION',

View file

@ -1635,8 +1635,6 @@
"INHERIT_SUBTASKS_DESCRIPTION": "When enabled, subtasks from the most recent task instance will be recreated with the recurring task",
"MONDAY": "Monday",
"NOTES": "Default notes",
"ORDER": "Order",
"ORDER_DESCRIPTION": "Creation order of recurring tasks. Only affects recurring tasks created at the same time. A lower value means a task will be created higher up the list; a higher number means it will be further down. A value greater than 0 means tasks are created below normal tasks.",
"QUICK_SETTING": "Recurring Config",
"Q_CUSTOM": "Custom recurring config",
"Q_DAILY": "Every day",
@ -1652,6 +1650,8 @@
"REPEAT_EVERY": "Recur every",
"SATURDAY": "Saturday",
"SCHEDULE_TYPE_LABEL": "Schedule type",
"SKIP_OVERDUE": "Skip overdue instances",
"SKIP_OVERDUE_DESCRIPTION": "When enabled, if the app is opened after missing a scheduled occurrence (e.g. a weekly task where today is not a scheduled day), the missed instance will be silently skipped instead of being created as an overdue task",
"START_DATE": "Start date",
"START_TIME": "Scheduled start time",
"START_TIME_DESCRIPTION": "E.g. 15:00. Leave blank for an all day task",