feat(tasks): apply default reminders to quick-add tasks with due date
When a user has configured default reminders in their frontend settings, those are cloned onto every task created via quick-add magic that has a parsed due date. Tasks without a due date are silently skipped. The buildDefaultRemindersForQuickAdd helper is exported as a pure function so it can be unit-tested without stubbing the Pinia store.
This commit is contained in:
parent
338d4d8b76
commit
5afd066a13
|
|
@ -0,0 +1,44 @@
|
|||
import {describe, expect, it} from 'vitest'
|
||||
import {buildDefaultRemindersForQuickAdd} from './tasks'
|
||||
import {REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
||||
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
||||
|
||||
const aDefault: ITaskReminder = {
|
||||
reminder: null,
|
||||
relativePeriod: -3600,
|
||||
relativeTo: REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE,
|
||||
} as ITaskReminder
|
||||
|
||||
describe('buildDefaultRemindersForQuickAdd', () => {
|
||||
it('returns empty array when due date is null', () => {
|
||||
expect(buildDefaultRemindersForQuickAdd([aDefault], null)).toEqual([])
|
||||
})
|
||||
|
||||
it('returns empty array when defaults are undefined', () => {
|
||||
expect(buildDefaultRemindersForQuickAdd(undefined, '2026-05-01T00:00:00.000Z')).toEqual([])
|
||||
})
|
||||
|
||||
it('returns empty array when defaults are empty', () => {
|
||||
expect(buildDefaultRemindersForQuickAdd([], '2026-05-01T00:00:00.000Z')).toEqual([])
|
||||
})
|
||||
|
||||
it('clones defaults with relativeTo locked to due_date', () => {
|
||||
const result = buildDefaultRemindersForQuickAdd([aDefault], '2026-05-01T00:00:00.000Z')
|
||||
expect(result).toHaveLength(1)
|
||||
expect(result[0].relativePeriod).toBe(-3600)
|
||||
expect(result[0].relativeTo).toBe(REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE)
|
||||
expect(result[0].reminder).toBeNull()
|
||||
})
|
||||
|
||||
it('does not share references with the input array', () => {
|
||||
const defaults = [aDefault]
|
||||
const result = buildDefaultRemindersForQuickAdd(defaults, '2026-05-01T00:00:00.000Z')
|
||||
expect(result[0]).not.toBe(defaults[0])
|
||||
})
|
||||
|
||||
it('forces relativeTo to due_date even if a default somehow had another value', () => {
|
||||
const weird = {...aDefault, relativeTo: REMINDER_PERIOD_RELATIVE_TO_TYPES.STARTDATE} as ITaskReminder
|
||||
const result = buildDefaultRemindersForQuickAdd([weird], '2026-05-01T00:00:00.000Z')
|
||||
expect(result[0].relativeTo).toBe(REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE)
|
||||
})
|
||||
})
|
||||
|
|
@ -15,13 +15,17 @@ import LabelTaskModel from '@/models/labelTask'
|
|||
import LabelTask from '@/models/labelTask'
|
||||
import TaskModel from '@/models/task'
|
||||
import LabelModel from '@/models/label'
|
||||
import TaskReminderModel from '@/models/taskReminder'
|
||||
|
||||
import type {ILabel} from '@/modelTypes/ILabel'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
import {REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
||||
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
|
|
@ -38,6 +42,23 @@ interface MatchedAssignee extends IUser {
|
|||
match: string,
|
||||
}
|
||||
|
||||
export function buildDefaultRemindersForQuickAdd(
|
||||
defaults: readonly ITaskReminder[] | undefined,
|
||||
dueDate: string | null,
|
||||
): ITaskReminder[] {
|
||||
if (!dueDate) {
|
||||
return []
|
||||
}
|
||||
if (!defaults || defaults.length === 0) {
|
||||
return []
|
||||
}
|
||||
return defaults.map(d => new TaskReminderModel({
|
||||
reminder: null,
|
||||
relativePeriod: d.relativePeriod,
|
||||
relativeTo: REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE,
|
||||
}))
|
||||
}
|
||||
|
||||
// IDEA: maybe use a small fuzzy search here to prevent errors
|
||||
function findPropertyByValue(object, key, value, fuzzy = false) {
|
||||
return Object.values(object).find(l => {
|
||||
|
|
@ -483,6 +504,10 @@ export const useTaskStore = defineStore('task', () => {
|
|||
index,
|
||||
})
|
||||
task.repeatAfter = parsedTask.repeats
|
||||
task.reminders = buildDefaultRemindersForQuickAdd(
|
||||
authStore.settings.frontendSettings.quickAddDefaultReminders,
|
||||
dueDate,
|
||||
)
|
||||
|
||||
if (parsedTask.repeats?.type === REPEAT_TYPES.Months && parsedTask.repeats?.amount === 1) {
|
||||
task.repeatMode = TASK_REPEAT_MODES.REPEAT_MODE_MONTH
|
||||
|
|
|
|||
Loading…
Reference in New Issue