feat: add properties to models

This commit is contained in:
Dominik Pschenitschni 2022-06-23 03:22:21 +02:00
parent 74ad6e65e8
commit 797de0c543
Signed by: dpschen
GPG Key ID: B257AC0149F43A77
33 changed files with 367 additions and 186 deletions

View File

@ -3,22 +3,25 @@ import UserModel from './user'
import FileModel from './file'
export default class AttachmentModel extends AbstractModel {
id: number
taskId: number
createdBy: UserModel
file: FileModel
created: Date
constructor(data) {
super(data)
this.createdBy = new UserModel(this.createdBy)
this.file = new FileModel(this.file)
this.created = new Date(this.created)
/** @type {number} */
this.id
}
defaults() {
return {
id: 0,
taskId: 0,
file: FileModel,
createdBy: UserModel,
file: FileModel,
created: null,
}
}

View File

@ -1,6 +1,10 @@
import AbstractModel from './abstractModel'
export type AVATAR_PROVIDERS = 'default' | 'initials' | 'gravatar' | 'marble' | 'upload'
export default class AvatarModel extends AbstractModel {
avatarProvider: AVATAR_PROVIDERS
defaults() {
return {
avatarProvider: '',

View File

@ -1,6 +1,15 @@
import AbstractModel from './abstractModel'
export default class BackgroundImageModel extends AbstractModel {
id: number
url: string
thumb: string
info: {
author: string
authorName: string
}
blurHash: string
defaults() {
return {
id: 0,

View File

@ -3,6 +3,18 @@ import UserModel from './user'
import TaskModel from './task'
export default class BucketModel extends AbstractModel {
id: number
title: string
listId: number
limit: number
tasks: TaskModel[]
isDoneBucket: boolean
position: number
createdBy: UserModel
created: Date
updated: Date
constructor(bucket) {
super(bucket)

View File

@ -1,14 +1,15 @@
import AbstractModel from './abstractModel'
export default class CaldavTokenModel extends AbstractModel {
id: number
created: Date
constructor(data? : Object) {
super(data)
/** @type {number} */
this.id
if (this.created) {
/** @type {Date} */
this.created = new Date(this.created)
}
}

View File

@ -1,6 +1,9 @@
import AbstractModel from './abstractModel'
export default class EmailUpdateModel extends AbstractModel {
newEmail: string
password: string
defaults() {
return {
newEmail: '',

View File

@ -1,6 +1,12 @@
import AbstractModel from './abstractModel'
export default class FileModel extends AbstractModel {
id: number
mime: string
name: string
size: number
created: Date
constructor(data) {
super(data)
this.created = new Date(this.created)

View File

@ -4,6 +4,17 @@ import {colorIsDark} from '@/helpers/color/colorIsDark'
const DEFAULT_LABEL_BACKGROUND_COLOR = 'e8e8e8'
export default class LabelModel extends AbstractModel {
id: number
title: string
hexColor: string
description: string
createdBy: UserModel
listId: number
textColor: string
created: Date
updated: Date
constructor(data) {
super(data)
// FIXME: this should be empty and be definied in the client.

View File

@ -1,6 +1,10 @@
import AbstractModel from './abstractModel'
export default class LabelTask extends AbstractModel {
id: number
taskId: number
labelId: number
defaults() {
return {
id: 0,

View File

@ -2,6 +2,16 @@ import AbstractModel from './abstractModel'
import UserModel from './user'
export default class LinkShareModel extends AbstractModel {
id: number
hash: string
right: Right
sharedBy: UserModel
sharingType: number // FIXME: use correct numbers
listId: number
name: string
password: string
created: Date
updated: Date
constructor(data) {
// The constructor of AbstractModel handles all the default parsing.

View File

@ -1,72 +1,48 @@
import AbstractModel from './abstractModel'
import TaskModel from './task'
import UserModel from './user'
import type NamespaceModel from './namespace'
import {getSavedFilterIdFromListId} from '@/helpers/savedFilter'
import SubscriptionModel from '@/models/subscription'
export default class ListModel extends AbstractModel {
id: number
title: string
description: string
owner: UserModel
tasks: TaskModel[]
namespaceId: NamespaceModel['id']
isArchived: boolean
hexColor: string
identifier: string
backgroundInformation: any
isFavorite: boolean
subscription: SubscriptionModel
position: number
backgroundBlurHash: string
created: Date
updated: Date
constructor(data) {
super(data)
this.owner = new UserModel(this.owner)
/** @type {number} */
this.id
/** @type {string} */
this.title
/** @type {string} */
this.description
/** @type {UserModel} */
this.owner
/** @type {TaskModel[]} */
this.tasks
// Make all tasks to task models
this.tasks = this.tasks.map(t => {
return new TaskModel(t)
})
/** @type {number} */
this.namespaceId
/** @type {boolean} */
this.isArchived
/** @type {string} */
this.hexColor
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
this.hexColor = '#' + this.hexColor
}
/** @type {string} */
this.identifier
/** @type */
this.backgroundInformation
/** @type {boolean} */
this.isFavorite
/** @type */
this.subscription
if (typeof this.subscription !== 'undefined' && this.subscription !== null) {
this.subscription = new SubscriptionModel(this.subscription)
}
/** @type {number} */
this.position
/** @type {Date} */
this.created = new Date(this.created)
/** @type {Date} */
this.updated = new Date(this.updated)
}

View File

@ -1,7 +1,12 @@
import AbstractModel from './abstractModel'
import ListModel from './list'
import NamespaceModel from './namespace'
export default class ListDuplicateModel extends AbstractModel {
listId: number
namespaceId: NamespaceModel['id']
list: ListModel
constructor(data) {
super(data)
this.list = new ListModel(this.list)

View File

@ -4,6 +4,18 @@ import UserModel from './user'
import SubscriptionModel from '@/models/subscription'
export default class NamespaceModel extends AbstractModel {
id: number
title: string
description: string
owner: UserModel
lists: ListModel[]
isArchived: boolean
hexColor: string
subscription: SubscriptionModel
created: Date
updated: Date
constructor(data) {
super(data)
@ -11,7 +23,6 @@ export default class NamespaceModel extends AbstractModel {
this.hexColor = '#' + this.hexColor
}
/** @type {ListModel[]} */
this.lists = this.lists.map(l => {
return new ListModel(l)
})
@ -22,15 +33,6 @@ export default class NamespaceModel extends AbstractModel {
this.subscription = new SubscriptionModel(this.subscription)
}
/** @type {number} */
this.id
/** @type {string} */
this.title
/** @type {boolean} */
this.isArchived
this.created = new Date(this.created)
this.updated = new Date(this.updated)
}

View File

@ -5,35 +5,86 @@ import TaskModel from '@/models/task'
import TaskCommentModel from '@/models/taskComment'
import ListModel from '@/models/list'
import TeamModel from '@/models/team'
import names from './constants/notificationNames.json'
export const NOTIFICATION_NAMES = {
'TASK_COMMENT': 'task.comment',
'TASK_ASSIGNED': 'task.assigned',
'TASK_DELETED': 'task.deleted',
'LIST_CREATED': 'list.created',
'TEAM_MEMBER_ADDED': 'team.member.added',
} as const
interface Notification {
doer: UserModel
}
interface NotificationTask extends Notification {
task: TaskModel
comment: TaskCommentModel
}
interface NotificationAssigned extends Notification {
task: TaskModel
assignee: UserModel
}
interface NotificationDeleted extends Notification {
task: TaskModel
}
interface NotificationCreated extends Notification {
task: TaskModel
}
interface NotificationMemberAdded extends Notification {
member: UserModel
team: TeamModel
}
export default class NotificationModel extends AbstractModel {
id: number
name: string
notification: NotificationTask | NotificationAssigned | NotificationDeleted | NotificationCreated | NotificationMemberAdded
read: boolean
readAt: Date | null
created: Date
constructor(data) {
super(data)
switch (this.name) {
case names.TASK_COMMENT:
this.notification.doer = new UserModel(this.notification.doer)
this.notification.task = new TaskModel(this.notification.task)
this.notification.comment = new TaskCommentModel(this.notification.comment)
case NOTIFICATION_NAMES.TASK_COMMENT:
this.notification = {
doer: new UserModel(this.notification.doer),
task: new TaskModel(this.notification.task),
comment: new TaskCommentModel(this.notification.comment),
}
break
case names.TASK_ASSIGNED:
this.notification.doer = new UserModel(this.notification.doer)
this.notification.task = new TaskModel(this.notification.task)
this.notification.assignee = new UserModel(this.notification.assignee)
case NOTIFICATION_NAMES.TASK_ASSIGNED:
this.notification = {
doer: new UserModel(this.notification.doer),
task: new TaskModel(this.notification.task),
assignee: new UserModel(this.notification.assignee),
}
break
case names.TASK_DELETED:
this.notification.doer = new UserModel(this.notification.doer)
this.notification.task = new TaskModel(this.notification.task)
case NOTIFICATION_NAMES.TASK_DELETED:
this.notification = {
doer: new UserModel(this.notification.doer),
task: new TaskModel(this.notification.task),
}
break
case names.LIST_CREATED:
this.notification.doer = new UserModel(this.notification.doer)
this.notification.list = new ListModel(this.notification.list)
case NOTIFICATION_NAMES.LIST_CREATED:
this.notification = {
doer: new UserModel(this.notification.doer),
list: new ListModel(this.notification.list),
}
break
case names.TEAM_MEMBER_ADDED:
this.notification.doer = new UserModel(this.notification.doer)
this.notification.member = new UserModel(this.notification.member)
this.notification.team = new TeamModel(this.notification.team)
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
this.notification = {
doer: new UserModel(this.notification.doer),
member: new UserModel(this.notification.member),
team: new TeamModel(this.notification.team),
}
break
}
@ -55,9 +106,9 @@ export default class NotificationModel extends AbstractModel {
let who = ''
switch (this.name) {
case names.TASK_COMMENT:
case NOTIFICATION_NAMES.TASK_COMMENT:
return `commented on ${this.notification.task.getTextIdentifier()}`
case names.TASK_ASSIGNED:
case NOTIFICATION_NAMES.TASK_ASSIGNED:
who = `${this.notification.assignee.getDisplayName()}`
if (user !== null && user.id === this.notification.assignee.id) {
@ -65,11 +116,11 @@ export default class NotificationModel extends AbstractModel {
}
return `assigned ${who} to ${this.notification.task.getTextIdentifier()}`
case names.TASK_DELETED:
case NOTIFICATION_NAMES.TASK_DELETED:
return `deleted ${this.notification.task.getTextIdentifier()}`
case names.LIST_CREATED:
case NOTIFICATION_NAMES.LIST_CREATED:
return `created ${this.notification.list.title}`
case names.TEAM_MEMBER_ADDED:
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
who = `${this.notification.member.getDisplayName()}`
if (user !== null && user.id === this.notification.member.id) {

View File

@ -1,6 +1,10 @@
import AbstractModel from './abstractModel'
export default class PasswordResetModel extends AbstractModel {
token: string
newPassword: string
email: string
constructor(data) {
super(data)

View File

@ -1,6 +1,9 @@
import AbstractModel from './abstractModel'
export default class PasswordUpdateModel extends AbstractModel {
newPassword: string
oldPassword: string
defaults() {
return {
newPassword: '',

View File

@ -2,6 +2,23 @@ import AbstractModel from '@/models/abstractModel'
import UserModel from '@/models/user'
export default class SavedFilterModel extends AbstractModel {
id: 0
title: string
description: string
filters: {
sortBy: ('done' | 'id')[]
orderBy: ('asc' | 'desc')[]
filterBy: 'done'[]
filterValue: 'false'[]
filterComparator: 'equals'[]
filterConcat: 'and'
filterIncludeNulls: boolean
}
owner: any
created: Date
updated: Date
constructor(data) {
super(data)

View File

@ -2,22 +2,17 @@ import AbstractModel from '@/models/abstractModel'
import UserModel from '@/models/user'
export default class SubscriptionModel extends AbstractModel {
id: number
entity: string // FIXME: correct type?
entityId: number // FIXME: correct type?
user: UserModel
created: Date
constructor(data) {
super(data)
/** @type {number} */
this.id
/** @type {string} */
this.entity
/** @type {number} */
this.entityId
/** @type {Date} */
this.created = new Date(this.created)
/** @type {UserModel} */
this.user = new UserModel(this.user)
}

View File

@ -2,69 +2,86 @@ import AbstractModel from './abstractModel'
import UserModel from './user'
import LabelModel from './label'
import AttachmentModel from './attachment'
import {REPEAT_MODE_DEFAULT} from './constants/taskRepeatModes'
import SubscriptionModel from '@/models/subscription'
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import type ListModel from './list'
const SUPPORTS_TRIGGERED_NOTIFICATION = 'Notification' in window && 'showTrigger' in Notification.prototype
export const TASK_DEFAULT_COLOR = '#1973ff'
export const TASK_REPEAT_MODES = {
'REPEAT_MODE_DEFAULT': 0,
'REPEAT_MODE_MONTH': 1,
'REPEAT_MODE_FROM_CURRENT_DATE': 2,
} as const
export type TaskRepeatMode = typeof TASK_REPEAT_MODES[keyof typeof TASK_REPEAT_MODES]
export interface RepeatAfter {
type: 'hours' | 'weeks' | 'months' | 'years' | 'days'
amount: number
}
export default class TaskModel extends AbstractModel {
constructor(data) {
id: number
title: string
description: string
done: boolean
doneAt: Date | null
priority: 0
labels: LabelModel[]
assignees: UserModel[]
dueDate: Date | null
startDate: Date | null
endDate: Date | null
repeatAfter: number | RepeatAfter
repeatFromCurrentDate: boolean
repeatMode: TaskRepeatMode
reminderDates: Date[]
parentTaskId: TaskModel['id']
hexColor: string
percentDone: number
relatedTasks: { [relationKind: string]: TaskModel } // FIXME: use relationKinds
attachments: AttachmentModel[]
identifier: string
index: number
isFavorite: boolean
subscription: SubscriptionModel
position: number
kanbanPosition: number
createdBy: UserModel
created: Date
updated: Date
listId: ListModel['id'] // Meta, only used when creating a new task
constructor(data: Partial<TaskModel>) {
super(data)
/** @type {number} */
this.id = Number(this.id)
/** @type {string} */
this.title = this.title?.trim()
/** @type {string} */
this.description
/** @type {boolean} */
this.done
/** @type */
this.doneAt = parseDateOrNull(this.doneAt)
/** @type {number} */
this.priority
/** @type {LabelModel[]} */
this.labels = this.labels
.map(l => new LabelModel(l))
.sort((f, s) => f.title > s.title ? 1 : -1)
/** @type {UserModel[]} */
// Parse the assignees into user models
this.assignees = this.assignees.map(a => {
return new UserModel(a)
})
/** @type {Date} */
this.dueDate = parseDateOrNull(this.dueDate)
/** @type {Date} */
this.startDate = parseDateOrNull(this.startDate)
/** @type {Date} */
this.endDate = parseDateOrNull(this.endDate)
/** @type */
this.repeatAfter
// Parse the repeat after into something usable
this.parseRepeatAfter()
/** @type {boolean} */
this.repeatFromCurrentDate
/** @type {TaskRepeatMode: 0 | 1 | 2} */
this.repeatMode
/** @type {Date[]} */
this.reminderDates = this.reminderDates.map(d => new Date(d))
// Cancel all scheduled notifications for this task to be sure to only have available notifications
@ -73,22 +90,10 @@ export default class TaskModel extends AbstractModel {
this.reminderDates.forEach(d => this.scheduleNotification(d))
})
/** @type {number} */
this.parentTaskId
/** @type {string} */
this.hexColor
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
this.hexColor = '#' + this.hexColor
}
/** @type {number} */
this.percentDone
/** @type {{ [relationKind: string]: TaskModel }} */
this.relatedTasks
// Make all subtasks to task models
Object.keys(this.relatedTasks).forEach(relationKind => {
this.relatedTasks[relationKind] = this.relatedTasks[relationKind].map(t => {
@ -97,46 +102,21 @@ export default class TaskModel extends AbstractModel {
})
// Make all attachments to attachment models
/** @type {AttachmentModel[]} */
this.attachments = this.attachments.map(a => new AttachmentModel(a))
/** @type {string} */
this.identifier
// Set the task identifier to empty if the list does not have one
if (this.identifier === `-${this.index}`) {
this.identifier = ''
}
/** @type {number} */
this.index
/** @type {boolean} */
this.isFavorite
/** @type {SubscriptionModel} */
this.subscription
if (typeof this.subscription !== 'undefined' && this.subscription !== null) {
this.subscription = new SubscriptionModel(this.subscription)
}
/** @type {number} */
this.position
/** @type {number} */
this.kanbanPosition
/** @type {UserModel} */
this.createdBy = new UserModel(this.createdBy)
/** @type {Date} */
this.created = new Date(this.created)
/** @type {Date} */
this.updated = new Date(this.updated)
/** @type {number} */
this.listId = Number(this.listId)
}
@ -156,7 +136,7 @@ export default class TaskModel extends AbstractModel {
endDate: 0,
repeatAfter: 0,
repeatFromCurrentDate: false,
repeatMode: REPEAT_MODE_DEFAULT,
repeatMode: TASK_REPEAT_MODES.REPEAT_MODE_DEFAULT,
reminderDates: [],
parentTaskId: 0,
hexColor: '',
@ -204,7 +184,7 @@ export default class TaskModel extends AbstractModel {
* This function should only be called from the constructor.
*/
parseRepeatAfter() {
const repeatAfterHours = (this.repeatAfter / 60) / 60
const repeatAfterHours = (this.repeatAfter as number / 60) / 60
this.repeatAfter = {type: 'hours', amount: repeatAfterHours}
// if its dividable by 24, its something with days, otherwise hours

View File

@ -1,6 +1,12 @@
import AbstractModel from './abstractModel'
import type UserModel from './user'
import type TaskModel from './task'
export default class TaskAssigneeModel extends AbstractModel {
created: Date
userId: UserModel['id']
taskId: TaskModel['id']
constructor(data) {
super(data)
this.created = new Date(this.created)

View File

@ -1,7 +1,16 @@
import AbstractModel from './abstractModel'
import UserModel from './user'
import type TaskModel from './task'
export default class TaskCommentModel extends AbstractModel {
id: number
taskId: TaskModel['id']
comment: string
author: UserModel
created: Date
updated: Date
constructor(data) {
super(data)
this.author = new UserModel(this.author)
@ -16,7 +25,7 @@ export default class TaskCommentModel extends AbstractModel {
comment: '',
author: UserModel,
created: null,
update: null,
updated: null,
}
}
}

View File

@ -1,7 +1,31 @@
import AbstractModel from './abstractModel'
import UserModel from './user'
import type TaskModel from './task'
export const RELATION_KINDS = [
'subtask',
'parenttask',
'related',
'duplicates',
'blocking',
'blocked',
'precedes',
'follows',
'copiedfrom',
'copiedto',
] as const
export type RelationKind = typeof RELATION_KINDS[number]
export default class TaskRelationModel extends AbstractModel {
id: number
otherTaskId: TaskModel['id']
taskId: TaskModel['id']
relationKind: RelationKind
createdBy: UserModel
created: Date
constructor(data) {
super(data)
this.createdBy = new UserModel(this.createdBy)

View File

@ -3,6 +3,16 @@ import UserModel from './user'
import TeamMemberModel from './teamMember'
export default class TeamModel extends AbstractModel {
id: 0
name: string
description: string
members: TeamMemberModel[]
right: Right
createdBy: UserModel
created: Date
updated: Date
constructor(data) {
super(data)

View File

@ -1,6 +1,9 @@
import TeamShareBaseModel from './teamShareBase'
import type ListModel from './list'
export default class TeamListModel extends TeamShareBaseModel {
listId: ListModel['id']
defaults() {
return {
...super.defaults(),

View File

@ -1,6 +1,10 @@
import UserModel from './user'
import type ListModel from './list'
export default class TeamMemberModel extends UserModel {
admin: boolean
teamId: ListModel['id']
defaults() {
return {
...super.defaults(),

View File

@ -1,6 +1,9 @@
import TeamShareBaseModel from './teamShareBase'
import type NamespaceModel from './namespace'
export default class TeamNamespaceModel extends TeamShareBaseModel {
namespaceId: NamespaceModel['id']
defaults() {
return {
...super.defaults(),

View File

@ -1,10 +1,18 @@
import AbstractModel from './abstractModel'
import type TeamModel from './team'
import type {Right} from '@/models/constants/rights'
/**
* This class is a base class for common team sharing model.
* It is extended in a way so it can be used for namespaces as well for lists.
*/
export default class TeamShareBaseModel extends AbstractModel {
teamId: TeamModel['id']
right: Right
created: Date
updated: Date
constructor(data) {
super(data)
this.created = new Date(this.created)

View File

@ -1,6 +1,10 @@
import AbstractModel from './abstractModel'
export default class TotpModel extends AbstractModel {
secret: string
enabled: boolean
url: string
defaults() {
return {
secret: '',

View File

@ -2,30 +2,21 @@ import AbstractModel from './abstractModel'
import UserSettingsModel from '@/models/userSettings'
export default class UserModel extends AbstractModel {
id: number
email: string
username: string
name: string
created: Date
updated: Date
settings: UserSettingsModel
constructor(data) {
super(data)
/** @type {number} */
this.id
/** @type {string} */
this.email
/** @type {string} */
this.username
/** @type {string} */
this.name
/** @type {Date} */
this.created = new Date(this.created)
/** @type {Date} */
this.updated = new Date(this.updated)
/** @type {UserSettingsModel} */
this.settings
if (this.settings !== null) {
this.settings = new UserSettingsModel(this.settings)
}

View File

@ -1,7 +1,9 @@
import UserShareBaseModel from './userShareBase'
import type ListModel from './list'
// This class extends the user share model with a 'rights' parameter which is used in sharing
export default class UserListModel extends UserShareBaseModel {
listId: ListModel['id']
defaults() {
return {
...super.defaults(),

View File

@ -1,7 +1,10 @@
import UserShareBaseModel from './userShareBase'
import type NamespaceModel from './namespace'
// This class extends the user share model with a 'rights' parameter which is used in sharing
export default class UserNamespaceModel extends UserShareBaseModel {
namespaceId: NamespaceModel['id']
defaults() {
return {
...super.defaults(),

View File

@ -1,7 +1,17 @@
import AbstractModel from './abstractModel'
import type ListModel from './list'
export default class UserSettingsModel extends AbstractModel {
name: string
emailRemindersEnabled: boolean
discoverableByName: boolean
discoverableByEmail: boolean
overdueTasksRemindersEnabled: boolean
defaultListId: undefined | ListModel['id']
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6
timezone: string
defaults() {
return {
name: '',

View File

@ -1,6 +1,14 @@
import AbstractModel from './abstractModel'
import type UserModel from './user'
import type {Right} from '@/models/constants/rights'
export default class UserShareBaseModel extends AbstractModel {
userId: UserModel['id']
right: Right
created: Date
updated: Date
constructor(data) {
super(data)
this.created = new Date(this.created)