From 9e8f45b1f8baf1fe19b0caeda8a395dfd7c75a08 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 13 Mar 2026 11:44:29 +0100 Subject: [PATCH] feat(tasks): show deadlines in scheduled list page and planner task --- .../planner-task/planner-task.component.html | 11 +++++ .../planner-task/planner-task.component.scss | 19 ++++++++ .../features/tasks/store/task.selectors.ts | 20 ++++++++ .../scheduled-list-page.component.html | 46 +++++++++++++++++++ .../scheduled-list-page.component.ts | 13 ++++++ src/app/t.const.ts | 2 + src/assets/i18n/en.json | 4 +- 7 files changed, 114 insertions(+), 1 deletion(-) diff --git a/src/app/features/planner/planner-task/planner-task.component.html b/src/app/features/planner/planner-task/planner-task.component.html index 55e194bba7..0497f284f5 100644 --- a/src/app/features/planner/planner-task/planner-task.component.html +++ b/src/app/features/planner/planner-task/planner-task.component.html @@ -44,6 +44,17 @@
{{ task.title }}
+ @if (task.deadlineDay || task.deadlineWithTime) { +
+ event_busy + @if (task.deadlineWithTime) { + {{ task.deadlineWithTime | shortDate2 }} + } @else if (task.deadlineDay) { + {{ task.deadlineDay | shortDate2 }} + } +
+ } + { + return tasks + .filter( + (task) => + task && + !task.isDone && + (task.deadlineDay || typeof task.deadlineWithTime === 'number'), + ) + .sort((a, b) => { + const aTime = + a.deadlineWithTime || new Date(a.deadlineDay + 'T23:59:59').getTime(); + const bTime = + b.deadlineWithTime || new Date(b.deadlineDay + 'T23:59:59').getTime(); + return aTime - bTime; + }); + }, +); + export const selectUndoneTasksWithDueDayNoReminder = createSelector( selectAllTasks, (tasks: Task[]): Task[] => { diff --git a/src/app/pages/scheduled-list-page/scheduled-list-page.component.html b/src/app/pages/scheduled-list-page/scheduled-list-page.component.html index 4632297cee..1be119c2bd 100644 --- a/src/app/pages/scheduled-list-page/scheduled-list-page.component.html +++ b/src/app/pages/scheduled-list-page/scheduled-list-page.component.html @@ -133,4 +133,50 @@ } @else { } + @if (tasksWithDeadlines$ | async; as tasksWithDeadlines) { +
+

{{ T.SCHEDULE.TASKS_WITH_DEADLINES | translate }}

+ @if (!tasksWithDeadlines?.length) { +

{{ T.SCHEDULE.NO_DEADLINES | translate }}

+ } +
+ @for (task of tasksWithDeadlines; track task.id) { + +
+
+ @if (task.deadlineWithTime) { +
+ {{ task.deadlineWithTime | localeDate: 'EE, d MMM, ' }} + {{ task.deadlineWithTime | shortTime }} +
+
+ {{ task.deadlineWithTime | localeDate: 'd MMM, ' }}, + {{ task.deadlineWithTime | shortTime }} +
+
+ ({{ task.deadlineWithTime | humanizeTimestamp }}) +
+ } @else if (task.deadlineDay) { +
{{ task.deadlineDay | localeDate: 'EE, d MMM' }}
+ } +
+ event_busy +
+
+ } +
+
+ } @else { + + } diff --git a/src/app/pages/scheduled-list-page/scheduled-list-page.component.ts b/src/app/pages/scheduled-list-page/scheduled-list-page.component.ts index a8e110a236..b0dea4dfc7 100644 --- a/src/app/pages/scheduled-list-page/scheduled-list-page.component.ts +++ b/src/app/pages/scheduled-list-page/scheduled-list-page.component.ts @@ -12,6 +12,7 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { DialogEditTaskRepeatCfgComponent } from '../../features/task-repeat-cfg/dialog-edit-task-repeat-cfg/dialog-edit-task-repeat-cfg.component'; import { TaskRepeatCfgService } from '../../features/task-repeat-cfg/task-repeat-cfg.service'; import { DialogScheduleTaskComponent } from '../../features/planner/dialog-schedule-task/dialog-schedule-task.component'; +import { DialogDeadlineComponent } from '../../features/tasks/dialog-deadline/dialog-deadline.component'; import { DateTimeFormatService } from '../../core/date-time-format/date-time-format.service'; import { MatCard, MatCardContent } from '@angular/material/card'; import { TaskTitleComponent } from '../../ui/task-title/task-title.component'; @@ -26,6 +27,7 @@ import { PlannerTaskComponent } from '../../features/planner/planner-task/planne import { selectAllTasksWithDueTimeSorted, selectAllUndoneTasksWithDueDay, + selectAllUndoneTasksWithDeadlineSorted, } from '../../features/tasks/store/task.selectors'; import { selectTaskRepeatCfgsSortedByTitleAndProject } from '../../features/task-repeat-cfg/store/task-repeat-cfg.selectors'; import { getNextRepeatOccurrence } from '../../features/task-repeat-cfg/store/get-next-repeat-occurrence.util'; @@ -69,6 +71,7 @@ export class ScheduledListPageComponent { taskRepeatCfgs$ = this._store.select(selectTaskRepeatCfgsSortedByTitleAndProject); tasksPlannedForDays$ = this._store.select(selectAllUndoneTasksWithDueDay); tasksPlannedWithTime$ = this._store.select(selectAllTasksWithDueTimeSorted); + tasksWithDeadlines$ = this._store.select(selectAllUndoneTasksWithDeadlineSorted); editReminder(task: TaskCopy, ev: MouseEvent): void { ev.preventDefault(); @@ -79,6 +82,16 @@ export class ScheduledListPageComponent { }); } + editDeadline(task: TaskCopy, ev: MouseEvent): void { + ev.preventDefault(); + ev.stopPropagation(); + this._matDialog.open(DialogDeadlineComponent, { + autoFocus: false, + restoreFocus: true, + data: { task }, + }); + } + editTaskRepeatCfg(repeatCfg: TaskRepeatCfg): void { this._matDialog.open(DialogEditTaskRepeatCfgComponent, { restoreFocus: false, diff --git a/src/app/t.const.ts b/src/app/t.const.ts index 335220bfca..33796aaf00 100644 --- a/src/app/t.const.ts +++ b/src/app/t.const.ts @@ -2579,6 +2579,8 @@ const T = { SCHEDULED_TASKS: 'SCHEDULE.SCHEDULED_TASKS', SCHEDULED_TASKS_WITH_TIME: 'SCHEDULE.SCHEDULED_TASKS_WITH_TIME', START_TASK: 'SCHEDULE.START_TASK', + TASKS_WITH_DEADLINES: 'SCHEDULE.TASKS_WITH_DEADLINES', + NO_DEADLINES: 'SCHEDULE.NO_DEADLINES', }, 'Share Chart': 'Share Chart', 'Share Heatmap': 'Share Heatmap', diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index a07ad70a2f..fe7dfa02a6 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -2523,7 +2523,9 @@ "REPEATED_TASKS": "Recurring Tasks", "SCHEDULED_TASKS": "Scheduled Tasks", "SCHEDULED_TASKS_WITH_TIME": "Scheduled Tasks with Start Time", - "START_TASK": "Start task and remove reminder" + "START_TASK": "Start task and remove reminder", + "TASKS_WITH_DEADLINES": "Tasks with Deadlines", + "NO_DEADLINES": "There are currently no tasks with deadlines. You can set a deadline via the task's context menu or detail panel." }, "Share Chart": "", "Share Heatmap": "",