From f747d5b2fcadb7459c389372dca4507b75cdd4fa Mon Sep 17 00:00:00 2001 From: ce72 Date: Sat, 11 Mar 2023 19:20:07 +0100 Subject: [PATCH] feat: Use new Reminders API instead of reminder_dates --- src/components/tasks/partials/reminders.vue | 33 +++++++-------------- src/modelTypes/ITask.ts | 3 +- src/modelTypes/ITaskReminder.ts | 8 +++++ src/models/task.ts | 7 +++-- src/models/taskReminder.ts | 17 +++++++++++ src/services/task.ts | 14 ++++----- src/types/IReminderPeriodRelativeTo.ts | 8 +++++ src/views/tasks/TaskDetailView.vue | 4 +-- 8 files changed, 60 insertions(+), 34 deletions(-) create mode 100644 src/modelTypes/ITaskReminder.ts create mode 100644 src/models/taskReminder.ts create mode 100644 src/types/IReminderPeriodRelativeTo.ts diff --git a/src/components/tasks/partials/reminders.vue b/src/components/tasks/partials/reminders.vue index 47c842954..a0af652cd 100644 --- a/src/components/tasks/partials/reminders.vue +++ b/src/components/tasks/partials/reminders.vue @@ -3,11 +3,11 @@
@@ -30,30 +30,19 @@ import {type PropType, ref, onMounted, watch} from 'vue' import BaseButton from '@/components/base/BaseButton.vue' import Datepicker from '@/components/input/datepicker.vue' - -type Reminder = Date | string - - +import TaskReminderModel from '@/models/taskReminder' +import type { ITaskReminder } from '@/modelTypes/ITaskReminder' const props = defineProps({ modelValue: { - type: Array as PropType, + type: Array as PropType, default: () => [], validator(prop) { - // This allows arrays of Dates and strings + // This allows arrays if (!(prop instanceof Array)) { return false } - const isDate = (e: unknown) => e instanceof Date - const isString = (e: unknown) => typeof e === 'string' - - for (const e of prop) { - if (!isDate(e) && !isString(e)) { - return false - } - } - return true }, }, @@ -65,7 +54,7 @@ const props = defineProps({ const emit = defineEmits(['update:modelValue']) -const reminders = ref([]) +const reminders = ref([]) onMounted(() => { reminders.value = [...props.modelValue] @@ -75,8 +64,8 @@ watch( () => props.modelValue, (newVal) => { for (const i in newVal) { - if (typeof newVal[i] === 'string') { - newVal[i] = new Date(newVal[i]) + if (typeof newVal[i].reminder === 'string') { + newVal[i].reminder = new Date(newVal[i].reminder) } } reminders.value = newVal @@ -95,9 +84,9 @@ function addReminderDate(index : number | null = null) { if (newReminder.value === null) { return } - reminders.value.push(new Date(newReminder.value)) + reminders.value.push(new TaskReminderModel({reminder: new Date(newReminder.value)})) newReminder.value = null - } else if(reminders.value[index] === null) { + } else if(reminders.value[index].reminder === null) { return } diff --git a/src/modelTypes/ITask.ts b/src/modelTypes/ITask.ts index e66d447ef..b4cfc4582 100644 --- a/src/modelTypes/ITask.ts +++ b/src/modelTypes/ITask.ts @@ -13,6 +13,7 @@ import type {IRepeatAfter} from '@/types/IRepeatAfter' import type {IRepeatMode} from '@/types/IRepeatMode' import type {PartialWithId} from '@/types/PartialWithId' +import type {ITaskReminder} from '@/modelTypes/ITaskReminder' export interface ITask extends IAbstract { id: number @@ -30,7 +31,7 @@ export interface ITask extends IAbstract { repeatAfter: number | IRepeatAfter repeatFromCurrentDate: boolean repeatMode: IRepeatMode - reminderDates: Date[] + reminders: ITaskReminder[] parentTaskId: ITask['id'] hexColor: string percentDone: number diff --git a/src/modelTypes/ITaskReminder.ts b/src/modelTypes/ITaskReminder.ts new file mode 100644 index 000000000..25aa493f2 --- /dev/null +++ b/src/modelTypes/ITaskReminder.ts @@ -0,0 +1,8 @@ +import type { IAbstract } from './IAbstract' +import type { IReminderPeriodRelativeTo } from '@/types/IReminderPeriodRelativeTo' + +export interface ITaskReminder extends IAbstract { + reminder: Date + relativePeriod: number + relativeTo: IReminderPeriodRelativeTo +} \ No newline at end of file diff --git a/src/models/task.ts b/src/models/task.ts index 9974f41b9..7a35d9214 100644 --- a/src/models/task.ts +++ b/src/models/task.ts @@ -20,6 +20,8 @@ import LabelModel from './label' import UserModel from './user' import AttachmentModel from './attachment' import SubscriptionModel from './subscription' +import type {ITaskReminder} from '@/modelTypes/ITaskReminder' +import TaskReminderModel from '@/models/taskReminder' export const TASK_DEFAULT_COLOR = '#1973ff' @@ -68,7 +70,8 @@ export default class TaskModel extends AbstractModel implements ITask { repeatAfter: number | IRepeatAfter = 0 repeatFromCurrentDate = false repeatMode: IRepeatMode = TASK_REPEAT_MODES.REPEAT_MODE_DEFAULT - reminderDates: Date[] = [] + reminderDates = null + reminders: ITaskReminder[] = [] parentTaskId: ITask['id'] = 0 hexColor = '' percentDone = 0 @@ -115,7 +118,7 @@ export default class TaskModel extends AbstractModel implements ITask { // Parse the repeat after into something usable this.repeatAfter = parseRepeatAfter(this.repeatAfter as number) - this.reminderDates = this.reminderDates.map(d => new Date(d)) + this.reminders = this.reminders.map(r => new TaskReminderModel(r)) if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') { this.hexColor = '#' + this.hexColor diff --git a/src/models/taskReminder.ts b/src/models/taskReminder.ts new file mode 100644 index 000000000..b0a52b519 --- /dev/null +++ b/src/models/taskReminder.ts @@ -0,0 +1,17 @@ +import AbstractModel from './abstractModel' +import type {ITaskReminder} from '@/modelTypes/ITaskReminder' +import {parseDateOrNull} from '@/helpers/parseDateOrNull' +import type {IReminderPeriodRelativeTo} from '@/types/IReminderPeriodRelativeTo' + +export default class TaskReminderModel extends AbstractModel implements ITaskReminder { + reminder: Date | null + relativePeriod: number = 0 + relativeTo: IReminderPeriodRelativeTo | null = null + + constructor(data: Partial = {}) { + super() + this.assignData(data) + this.reminder = parseDateOrNull(data.reminder) + } + +} \ No newline at end of file diff --git a/src/services/task.ts b/src/services/task.ts index f40642b0c..a05bdacaf 100644 --- a/src/services/task.ts +++ b/src/services/task.ts @@ -54,17 +54,17 @@ export default class TaskService extends AbstractService { model.created = new Date(model.created).toISOString() model.updated = new Date(model.updated).toISOString() + model.reminderDates = null // remove all nulls, these would create empty reminders - for (const index in model.reminderDates) { - if (model.reminderDates[index] === null) { - model.reminderDates.splice(index, 1) + for (const index in model.reminders) { + if (model.reminders[index] === null) { + model.reminders.splice(index, 1) } } - // Make normal timestamps from js dates - if (model.reminderDates.length > 0) { - model.reminderDates = model.reminderDates.map(r => { - return new Date(r).toISOString() + if (model.reminders.length > 0) { + model.reminders.forEach(r => { + r.reminder = new Date(r.reminder).toISOString() }) } diff --git a/src/types/IReminderPeriodRelativeTo.ts b/src/types/IReminderPeriodRelativeTo.ts new file mode 100644 index 000000000..4254ebf7b --- /dev/null +++ b/src/types/IReminderPeriodRelativeTo.ts @@ -0,0 +1,8 @@ +export const REMINDER_PERIOD_RELATIVE_TO_TYPES = { + DUEDATE: 'due_date', + STARTDATE: 'start_date', + ENDDATE: 'end_date', +} as const + +export type IReminderPeriodRelativeTo = typeof REMINDER_PERIOD_RELATIVE_TO_TYPES[keyof typeof REMINDER_PERIOD_RELATIVE_TO_TYPES] + diff --git a/src/views/tasks/TaskDetailView.vue b/src/views/tasks/TaskDetailView.vue index e891869d9..7bb41375e 100644 --- a/src/views/tasks/TaskDetailView.vue +++ b/src/views/tasks/TaskDetailView.vue @@ -160,7 +160,7 @@
@@ -639,7 +639,7 @@ function setActiveFields() { activeFields.percentDone = task.percentDone > 0 activeFields.priority = task.priority !== PRIORITIES.UNSET activeFields.relatedTasks = Object.keys(task.relatedTasks).length > 0 - activeFields.reminders = task.reminderDates.length > 0 + activeFields.reminders = task.reminders.length > 0 activeFields.repeatAfter = task.repeatAfter.amount > 0 activeFields.startDate = task.startDate !== null }