chore: move frontend files
This commit is contained in:
23
frontend/src/models/abstractModel.ts
Normal file
23
frontend/src/models/abstractModel.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {objectToCamelCase} from '@/helpers/case'
|
||||
import {omitBy, isNil} from '@/helpers/utils'
|
||||
import type {Right} from '@/constants/rights'
|
||||
import type {IAbstract} from '@/modelTypes/IAbstract'
|
||||
|
||||
export default abstract class AbstractModel<Model extends IAbstract = IAbstract> implements IAbstract {
|
||||
|
||||
|
||||
/**
|
||||
* The max right the user has on this object, as returned by the x-max-right header from the api.
|
||||
*/
|
||||
maxRight: Right | null = null
|
||||
|
||||
/**
|
||||
* Takes an object and merges its data with the default data of this model.
|
||||
*/
|
||||
assignData(data: Partial<Model>) {
|
||||
data = objectToCamelCase(data)
|
||||
|
||||
// Put all data in our model while overriding those with a value of null or undefined with their defaults
|
||||
Object.assign(this, omitBy(data, isNil))
|
||||
}
|
||||
}
|
21
frontend/src/models/apiTokenModel.ts
Normal file
21
frontend/src/models/apiTokenModel.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import AbstractModel from '@/models/abstractModel'
|
||||
import type {IApiToken} from '@/modelTypes/IApiToken'
|
||||
|
||||
export default class ApiTokenModel extends AbstractModel<IApiToken> {
|
||||
id = 0
|
||||
title = ''
|
||||
token = ''
|
||||
permissions = null
|
||||
expiresAt: Date = null
|
||||
created: Date = null
|
||||
|
||||
constructor(data: Partial<IApiToken> = {}) {
|
||||
super()
|
||||
|
||||
this.assignData(data)
|
||||
|
||||
this.expiresAt = new Date(this.expiresAt)
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
25
frontend/src/models/attachment.ts
Normal file
25
frontend/src/models/attachment.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
import FileModel from './file'
|
||||
import type { IUser } from '@/modelTypes/IUser'
|
||||
import type { IFile } from '@/modelTypes/IFile'
|
||||
import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||
|
||||
export const SUPPORTED_IMAGE_SUFFIX = ['.jpg', '.png', '.bmp', '.gif']
|
||||
|
||||
export default class AttachmentModel extends AbstractModel<IAttachment> implements IAttachment {
|
||||
id = 0
|
||||
taskId = 0
|
||||
createdBy: IUser = UserModel
|
||||
file: IFile = FileModel
|
||||
created: Date = null
|
||||
|
||||
constructor(data: Partial<IAttachment>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
this.file = new FileModel(this.file)
|
||||
this.created = new Date(this.created)
|
||||
}
|
||||
}
|
11
frontend/src/models/avatar.ts
Normal file
11
frontend/src/models/avatar.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import type { IAvatar } from '@/modelTypes/IAvatar'
|
||||
|
||||
export default class AvatarModel extends AbstractModel<IAvatar> implements IAvatar {
|
||||
avatarProvider: IAvatar['avatarProvider'] = 'default'
|
||||
|
||||
constructor(data: Partial<IAvatar>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
18
frontend/src/models/backgroundImage.ts
Normal file
18
frontend/src/models/backgroundImage.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import type {IBackgroundImage} from '@/modelTypes/IBackgroundImage'
|
||||
|
||||
export default class BackgroundImageModel extends AbstractModel<IBackgroundImage> implements IBackgroundImage {
|
||||
id = 0
|
||||
url = ''
|
||||
thumb = ''
|
||||
info: {
|
||||
author: string
|
||||
authorName: string
|
||||
} = {}
|
||||
blurHash = ''
|
||||
|
||||
constructor(data: Partial<IBackgroundImage>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
32
frontend/src/models/bucket.ts
Normal file
32
frontend/src/models/bucket.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
import TaskModel from './task'
|
||||
|
||||
import type {IBucket} from '@/modelTypes/IBucket'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class BucketModel extends AbstractModel<IBucket> implements IBucket {
|
||||
id = 0
|
||||
title = ''
|
||||
projectId = ''
|
||||
limit = 0
|
||||
tasks: ITask[] = []
|
||||
position = 0
|
||||
count = 0
|
||||
|
||||
createdBy: IUser = null
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<IBucket>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.tasks = this.tasks.map(t => new TaskModel(t))
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
17
frontend/src/models/caldavToken.ts
Normal file
17
frontend/src/models/caldavToken.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {ICaldavToken} from '@/modelTypes/ICaldavToken'
|
||||
|
||||
export default class CaldavTokenModel extends AbstractModel<ICaldavToken> implements ICaldavToken {
|
||||
id: number
|
||||
created: Date
|
||||
|
||||
constructor(data: Partial<CaldavTokenModel>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
if (this.created) {
|
||||
this.created = new Date(this.created)
|
||||
}
|
||||
}
|
||||
}
|
13
frontend/src/models/emailUpdate.ts
Normal file
13
frontend/src/models/emailUpdate.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {IEmailUpdate} from '@/modelTypes/IEmailUpdate'
|
||||
|
||||
export default class EmailUpdateModel extends AbstractModel<IEmailUpdate> implements IEmailUpdate {
|
||||
newEmail = ''
|
||||
password = ''
|
||||
|
||||
constructor(data : Partial<IEmailUpdate> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
17
frontend/src/models/file.ts
Normal file
17
frontend/src/models/file.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import type {IFile} from '@/modelTypes/IFile'
|
||||
|
||||
export default class FileModel extends AbstractModel<IFile> implements IFile {
|
||||
id = 0
|
||||
mime = ''
|
||||
name = ''
|
||||
size = 0
|
||||
created: Date = null
|
||||
|
||||
constructor(data: Partial<IFile>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
}
|
||||
}
|
46
frontend/src/models/label.ts
Normal file
46
frontend/src/models/label.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
|
||||
import type {ILabel} from '@/modelTypes/ILabel'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||
|
||||
export default class LabelModel extends AbstractModel<ILabel> implements ILabel {
|
||||
id = 0
|
||||
title = ''
|
||||
// FIXME: this should be empty and be definied in the client.
|
||||
// that way it get's never send to the server db and is easier to change in future versions.
|
||||
hexColor = ''
|
||||
description = ''
|
||||
createdBy: IUser
|
||||
projectId = 0
|
||||
textColor = ''
|
||||
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ILabel> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
if (this.hexColor !== '' && !this.hexColor.startsWith('#') && !this.hexColor.startsWith('var(')) {
|
||||
this.hexColor = '#' + this.hexColor
|
||||
}
|
||||
|
||||
if (this.hexColor === '') {
|
||||
this.hexColor = 'var(--grey-200)'
|
||||
this.textColor = 'var(--grey-800)'
|
||||
} else {
|
||||
this.textColor = colorIsDark(this.hexColor)
|
||||
// Fixed colors to avoid flipping in dark mode
|
||||
? 'hsl(215, 27.9%, 16.9%)' // grey-800
|
||||
: 'hsl(220, 13%, 91%)' // grey-200
|
||||
}
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
14
frontend/src/models/labelTask.ts
Normal file
14
frontend/src/models/labelTask.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type { ILabelTask } from '@/modelTypes/ILabelTask'
|
||||
|
||||
export default class LabelTask extends AbstractModel<ILabelTask> implements ILabelTask {
|
||||
id = 0
|
||||
taskId = 0
|
||||
labelId = 0
|
||||
|
||||
constructor(data: Partial<ILabelTask>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
29
frontend/src/models/linkShare.ts
Normal file
29
frontend/src/models/linkShare.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
|
||||
import {RIGHTS, type Right} from '@/constants/rights'
|
||||
import type {ILinkShare} from '@/modelTypes/ILinkShare'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class LinkShareModel extends AbstractModel<ILinkShare> implements ILinkShare {
|
||||
id = 0
|
||||
hash = ''
|
||||
right: Right = RIGHTS.READ
|
||||
sharedBy: IUser = UserModel
|
||||
sharingType = 0 // FIXME: use correct numbers
|
||||
projectId = 0
|
||||
name: ''
|
||||
password: ''
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ILinkShare>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.sharedBy = new UserModel(this.sharedBy)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
103
frontend/src/models/notification.ts
Normal file
103
frontend/src/models/notification.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
||||
import UserModel, {getDisplayName} from '@/models/user'
|
||||
import TaskModel from '@/models/task'
|
||||
import TaskCommentModel from '@/models/taskComment'
|
||||
import ProjectModel from '@/models/project'
|
||||
import TeamModel from '@/models/team'
|
||||
|
||||
import {NOTIFICATION_NAMES, type INotification} from '@/modelTypes/INotification'
|
||||
import type { IUser } from '@/modelTypes/IUser'
|
||||
|
||||
export default class NotificationModel extends AbstractModel<INotification> implements INotification {
|
||||
id = 0
|
||||
name = ''
|
||||
notification: INotification['notification'] = null
|
||||
read = false
|
||||
readAt: Date | null = null
|
||||
|
||||
created: Date
|
||||
|
||||
constructor(data: Partial<INotification>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
switch (this.name) {
|
||||
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 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 NOTIFICATION_NAMES.TASK_DELETED:
|
||||
this.notification = {
|
||||
doer: new UserModel(this.notification.doer),
|
||||
task: new TaskModel(this.notification.task),
|
||||
}
|
||||
break
|
||||
case NOTIFICATION_NAMES.PROJECT_CREATED:
|
||||
this.notification = {
|
||||
doer: new UserModel(this.notification.doer),
|
||||
project: new ProjectModel(this.notification.project),
|
||||
}
|
||||
break
|
||||
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
|
||||
case NOTIFICATION_NAMES.TASK_REMINDER:
|
||||
this.notification = {
|
||||
task: new TaskModel(this.notification.task),
|
||||
project: new ProjectModel(this.notification.project),
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.readAt = parseDateOrNull(this.readAt)
|
||||
}
|
||||
|
||||
toText(user: IUser | null = null) {
|
||||
let who = ''
|
||||
|
||||
switch (this.name) {
|
||||
case NOTIFICATION_NAMES.TASK_COMMENT:
|
||||
return `commented on ${this.notification.task.getTextIdentifier()}`
|
||||
case NOTIFICATION_NAMES.TASK_ASSIGNED:
|
||||
who = `${getDisplayName(this.notification.assignee)}`
|
||||
|
||||
if (user !== null && user.id === this.notification.assignee.id) {
|
||||
who = 'you'
|
||||
}
|
||||
|
||||
return `assigned ${who} to ${this.notification.task.getTextIdentifier()}`
|
||||
case NOTIFICATION_NAMES.TASK_DELETED:
|
||||
return `deleted ${this.notification.task.getTextIdentifier()}`
|
||||
case NOTIFICATION_NAMES.PROJECT_CREATED:
|
||||
return `created ${this.notification.project.title}`
|
||||
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
|
||||
who = `${getDisplayName(this.notification.member)}`
|
||||
|
||||
if (user !== null && user.id === this.notification.member.id) {
|
||||
who = 'you'
|
||||
}
|
||||
|
||||
return `added ${who} to the ${this.notification.team.name} team`
|
||||
case NOTIFICATION_NAMES.TASK_REMINDER:
|
||||
return `Reminder for ${this.notification.task.getTextIdentifier()} ${this.notification.task.title} (${this.notification.project.title})`
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
}
|
16
frontend/src/models/passwordReset.ts
Normal file
16
frontend/src/models/passwordReset.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {IPasswordReset} from '@/modelTypes/IPasswordReset'
|
||||
|
||||
export default class PasswordResetModel extends AbstractModel<IPasswordReset> implements IPasswordReset {
|
||||
token = ''
|
||||
newPassword = ''
|
||||
email = ''
|
||||
|
||||
constructor(data: Partial<IPasswordReset>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.token = localStorage.getItem('passwordResetToken')
|
||||
}
|
||||
}
|
13
frontend/src/models/passwordUpdate.ts
Normal file
13
frontend/src/models/passwordUpdate.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {IPasswordUpdate} from '@/modelTypes/IPasswordUpdate'
|
||||
|
||||
export default class PasswordUpdateModel extends AbstractModel<IPasswordUpdate> implements IPasswordUpdate {
|
||||
newPassword = ''
|
||||
oldPassword = ''
|
||||
|
||||
constructor(data: Partial<IPasswordUpdate> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
54
frontend/src/models/project.ts
Normal file
54
frontend/src/models/project.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import TaskModel from '@/models/task'
|
||||
import UserModel from '@/models/user'
|
||||
import SubscriptionModel from '@/models/subscription'
|
||||
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||
|
||||
export default class ProjectModel extends AbstractModel<IProject> implements IProject {
|
||||
id = 0
|
||||
title = ''
|
||||
description = ''
|
||||
owner: IUser = UserModel
|
||||
tasks: ITask[] = []
|
||||
isArchived = false
|
||||
hexColor = ''
|
||||
identifier = ''
|
||||
backgroundInformation: unknown | null = null
|
||||
isFavorite = false
|
||||
subscription: ISubscription = null
|
||||
position = 0
|
||||
backgroundBlurHash = ''
|
||||
parentProjectId = 0
|
||||
doneBucketId = 0
|
||||
defaultBucketId = 0
|
||||
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<IProject> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.owner = new UserModel(this.owner)
|
||||
|
||||
// Make all tasks to task models
|
||||
this.tasks = this.tasks.map(t => {
|
||||
return new TaskModel(t)
|
||||
})
|
||||
|
||||
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
|
||||
this.hexColor = '#' + this.hexColor
|
||||
}
|
||||
|
||||
if (typeof this.subscription !== 'undefined' && this.subscription !== null) {
|
||||
this.subscription = new SubscriptionModel(this.subscription)
|
||||
}
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
18
frontend/src/models/projectDuplicateModel.ts
Normal file
18
frontend/src/models/projectDuplicateModel.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import ProjectModel from './project'
|
||||
|
||||
import type {IProjectDuplicate} from '@/modelTypes/IProjectDuplicate'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
export default class ProjectDuplicateModel extends AbstractModel<IProjectDuplicate> implements IProjectDuplicate {
|
||||
projectId = 0
|
||||
duplicatedProject: IProject | null = null
|
||||
parentProjectId = 0
|
||||
|
||||
constructor(data : Partial<IProjectDuplicate>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.duplicatedProject = this.duplicatedProject ? new ProjectModel(this.duplicatedProject) : null
|
||||
}
|
||||
}
|
34
frontend/src/models/savedFilter.ts
Normal file
34
frontend/src/models/savedFilter.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from '@/models/user'
|
||||
|
||||
import type {ISavedFilter} from '@/modelTypes/ISavedFilter'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class SavedFilterModel extends AbstractModel<ISavedFilter> implements ISavedFilter {
|
||||
id = 0
|
||||
title = ''
|
||||
description = ''
|
||||
filters: ISavedFilter['filters'] = {
|
||||
sortBy: ['done', 'id'],
|
||||
orderBy: ['asc', 'desc'],
|
||||
filterBy: ['done'],
|
||||
filterValue: ['false'],
|
||||
filterComparator: ['equals'],
|
||||
filterConcat: 'and',
|
||||
filterIncludeNulls: true,
|
||||
}
|
||||
|
||||
owner: IUser = {}
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ISavedFilter> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.owner = new UserModel(this.owner)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
22
frontend/src/models/subscription.ts
Normal file
22
frontend/src/models/subscription.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from '@/models/user'
|
||||
|
||||
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class SubscriptionModel extends AbstractModel<ISubscription> implements ISubscription {
|
||||
id = 0
|
||||
entity = ''
|
||||
entityId = 0
|
||||
user: IUser = {}
|
||||
|
||||
created: Date = null
|
||||
|
||||
constructor(data : Partial<ISubscription>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.user = new UserModel(this.user)
|
||||
}
|
||||
}
|
161
frontend/src/models/task.ts
Normal file
161
frontend/src/models/task.ts
Normal file
@ -0,0 +1,161 @@
|
||||
import {PRIORITIES, type Priority} from '@/constants/priorities'
|
||||
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {ILabel} from '@/modelTypes/ILabel'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||
import type {IBucket} from '@/modelTypes/IBucket'
|
||||
|
||||
import type {IRepeatAfter} from '@/types/IRepeatAfter'
|
||||
import type {IRelationKind} from '@/types/IRelationKind'
|
||||
import {TASK_REPEAT_MODES, type IRepeatMode} from '@/types/IRepeatMode'
|
||||
|
||||
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
||||
|
||||
import AbstractModel from './abstractModel'
|
||||
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'
|
||||
import {secondsToPeriod} from '@/helpers/time/period'
|
||||
|
||||
export function getHexColor(hexColor: string): string | undefined {
|
||||
if (hexColor === '' || hexColor === '#') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return hexColor
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses `repeatAfterSeconds` into a usable js object.
|
||||
*/
|
||||
export function parseRepeatAfter(repeatAfterSeconds: number): IRepeatAfter {
|
||||
|
||||
const period = secondsToPeriod(repeatAfterSeconds)
|
||||
|
||||
return {
|
||||
type: period.unit,
|
||||
amount: period.amount,
|
||||
}
|
||||
}
|
||||
|
||||
export function getTaskIdentifier(task: ITask | null | undefined): string {
|
||||
if (task === null || typeof task === 'undefined') {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (task.identifier === '') {
|
||||
return `#${task.index}`
|
||||
}
|
||||
|
||||
return task.identifier
|
||||
}
|
||||
|
||||
export default class TaskModel extends AbstractModel<ITask> implements ITask {
|
||||
id = 0
|
||||
title = ''
|
||||
description = ''
|
||||
done = false
|
||||
doneAt: Date | null = null
|
||||
priority: Priority = PRIORITIES.UNSET
|
||||
labels: ILabel[] = []
|
||||
assignees: IUser[] = []
|
||||
|
||||
dueDate: Date | null = 0
|
||||
startDate: Date | null = 0
|
||||
endDate: Date | null = 0
|
||||
repeatAfter: number | IRepeatAfter = 0
|
||||
repeatFromCurrentDate = false
|
||||
repeatMode: IRepeatMode = TASK_REPEAT_MODES.REPEAT_MODE_DEFAULT
|
||||
reminders: ITaskReminder[] = []
|
||||
parentTaskId: ITask['id'] = 0
|
||||
hexColor = ''
|
||||
percentDone = 0
|
||||
relatedTasks: Partial<Record<IRelationKind, ITask[]>> = {}
|
||||
attachments: IAttachment[] = []
|
||||
coverImageAttachmentId: IAttachment['id'] = null
|
||||
identifier = ''
|
||||
index = 0
|
||||
isFavorite = false
|
||||
subscription: ISubscription = null
|
||||
|
||||
position = 0
|
||||
kanbanPosition = 0
|
||||
|
||||
createdBy: IUser = UserModel
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
projectId: IProject['id'] = 0
|
||||
bucketId: IBucket['id'] = 0
|
||||
|
||||
constructor(data: Partial<ITask> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.id = Number(this.id)
|
||||
this.title = this.title?.trim()
|
||||
this.doneAt = parseDateOrNull(this.doneAt)
|
||||
|
||||
this.labels = this.labels
|
||||
.map(l => new LabelModel(l))
|
||||
.sort((f, s) => f.title > s.title ? 1 : -1)
|
||||
|
||||
// Parse the assignees into user models
|
||||
this.assignees = this.assignees.map(a => {
|
||||
return new UserModel(a)
|
||||
})
|
||||
|
||||
this.dueDate = parseDateOrNull(this.dueDate)
|
||||
this.startDate = parseDateOrNull(this.startDate)
|
||||
this.endDate = parseDateOrNull(this.endDate)
|
||||
|
||||
// Parse the repeat after into something usable
|
||||
this.repeatAfter = parseRepeatAfter(this.repeatAfter as number)
|
||||
|
||||
this.reminders = this.reminders.map(r => new TaskReminderModel(r))
|
||||
|
||||
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
|
||||
this.hexColor = '#' + this.hexColor
|
||||
}
|
||||
|
||||
// Convert all subtasks to task models
|
||||
Object.keys(this.relatedTasks).forEach(relationKind => {
|
||||
this.relatedTasks[relationKind] = this.relatedTasks[relationKind].map(t => {
|
||||
return new TaskModel(t)
|
||||
})
|
||||
})
|
||||
|
||||
// Make all attachments to attachment models
|
||||
this.attachments = this.attachments.map(a => new AttachmentModel(a))
|
||||
|
||||
// Set the task identifier to empty if the project does not have one
|
||||
if (this.identifier === `-${this.index}`) {
|
||||
this.identifier = ''
|
||||
}
|
||||
|
||||
if (typeof this.subscription !== 'undefined' && this.subscription !== null) {
|
||||
this.subscription = new SubscriptionModel(this.subscription)
|
||||
}
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
|
||||
this.projectId = Number(this.projectId)
|
||||
}
|
||||
|
||||
getTextIdentifier() {
|
||||
return getTaskIdentifier(this)
|
||||
}
|
||||
|
||||
getHexColor() {
|
||||
return getHexColor(this.hexColor)
|
||||
}
|
||||
}
|
||||
|
17
frontend/src/models/taskAssignee.ts
Normal file
17
frontend/src/models/taskAssignee.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {ITaskAssignee} from '@/modelTypes/ITaskAssignee'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
|
||||
export default class TaskAssigneeModel extends AbstractModel<ITaskAssignee> implements ITaskAssignee {
|
||||
created: Date = null
|
||||
userId: IUser['id'] = 0
|
||||
taskId: ITask['id'] = 0
|
||||
|
||||
constructor(data: Partial<ITaskAssignee>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
this.created = new Date(this.created)
|
||||
}
|
||||
}
|
25
frontend/src/models/taskComment.ts
Normal file
25
frontend/src/models/taskComment.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
|
||||
import type {ITaskComment} from '@/modelTypes/ITaskComment'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class TaskCommentModel extends AbstractModel<ITaskComment> implements ITaskComment {
|
||||
id = 0
|
||||
taskId: ITask['id'] = 0
|
||||
comment = ''
|
||||
author: IUser = UserModel
|
||||
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ITaskComment> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.author = new UserModel(this.author)
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
25
frontend/src/models/taskRelation.ts
Normal file
25
frontend/src/models/taskRelation.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
|
||||
import type {ITaskRelation} from '@/modelTypes/ITaskRelation'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
import {RELATION_KIND, type IRelationKind} from '@/types/IRelationKind'
|
||||
export default class TaskRelationModel extends AbstractModel<ITaskRelation> implements ITaskRelation {
|
||||
id = 0
|
||||
otherTaskId: ITask['id'] = 0
|
||||
taskId: ITask['id'] = 0
|
||||
relationKind: IRelationKind = RELATION_KIND.RELATED
|
||||
|
||||
createdBy: IUser = new UserModel()
|
||||
created: Date = new Date
|
||||
|
||||
constructor(data: Partial<ITaskRelation>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
this.created = new Date(this.created)
|
||||
}
|
||||
}
|
20
frontend/src/models/taskReminder.ts
Normal file
20
frontend/src/models/taskReminder.ts
Normal file
@ -0,0 +1,20 @@
|
||||
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<ITaskReminder> implements ITaskReminder {
|
||||
reminder: Date | null
|
||||
relativePeriod = 0
|
||||
relativeTo: IReminderPeriodRelativeTo | null = null
|
||||
|
||||
constructor(data: Partial<ITaskReminder> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
this.reminder = parseDateOrNull(data.reminder)
|
||||
if (this.relativeTo === '') {
|
||||
this.relativeTo = null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
34
frontend/src/models/team.ts
Normal file
34
frontend/src/models/team.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
import TeamMemberModel from './teamMember'
|
||||
|
||||
import {RIGHTS, type Right} from '@/constants/rights'
|
||||
import type {ITeam} from '@/modelTypes/ITeam'
|
||||
import type {ITeamMember} from '@/modelTypes/ITeamMember'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class TeamModel extends AbstractModel<ITeam> implements ITeam {
|
||||
id = 0
|
||||
name = ''
|
||||
description = ''
|
||||
members: ITeamMember[] = []
|
||||
right: Right = RIGHTS.READ
|
||||
|
||||
createdBy: IUser = {} // FIXME: seems wrong
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ITeam> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
// Make the members to usermodels
|
||||
this.members = this.members.map(m => {
|
||||
return new TeamMemberModel(m)
|
||||
})
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
14
frontend/src/models/teamMember.ts
Normal file
14
frontend/src/models/teamMember.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import UserModel from './user'
|
||||
|
||||
import type {ITeamMember} from '@/modelTypes/ITeamMember'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
export default class TeamMemberModel extends UserModel implements ITeamMember {
|
||||
admin = false
|
||||
teamId: IProject['id'] = 0
|
||||
|
||||
constructor(data: Partial<ITeamMember>) {
|
||||
super(data)
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
13
frontend/src/models/teamProject.ts
Normal file
13
frontend/src/models/teamProject.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import TeamShareBaseModel from './teamShareBase'
|
||||
|
||||
import type {ITeamProject} from '@/modelTypes/ITeamProject'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
export default class TeamProjectModel extends TeamShareBaseModel implements ITeamProject {
|
||||
projectId: IProject['id'] = 0
|
||||
|
||||
constructor(data: Partial<ITeamProject>) {
|
||||
super(data)
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
25
frontend/src/models/teamShareBase.ts
Normal file
25
frontend/src/models/teamShareBase.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import {RIGHTS, type Right} from '@/constants/rights'
|
||||
import type {ITeamShareBase} from '@/modelTypes/ITeamShareBase'
|
||||
import type {ITeam} from '@/modelTypes/ITeam'
|
||||
|
||||
/**
|
||||
* This class is a base class for common team sharing model.
|
||||
* It is extended in a way, so it can be used for projects.
|
||||
*/
|
||||
export default class TeamShareBaseModel extends AbstractModel<ITeamShareBase> implements ITeamShareBase {
|
||||
teamId: ITeam['id'] = 0
|
||||
right: Right = RIGHTS.READ
|
||||
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<ITeamShareBase>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
14
frontend/src/models/totp.ts
Normal file
14
frontend/src/models/totp.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {ITotp} from '@/modelTypes/ITotp'
|
||||
|
||||
export default class TotpModel extends AbstractModel<ITotp> implements ITotp {
|
||||
secret = ''
|
||||
enabled = false
|
||||
url = ''
|
||||
|
||||
constructor(data: Partial<ITotp> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
43
frontend/src/models/user.ts
Normal file
43
frontend/src/models/user.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserSettingsModel from '@/models/userSettings'
|
||||
|
||||
import { AUTH_TYPES, type IUser, type AuthType } from '@/modelTypes/IUser'
|
||||
import type { IUserSettings } from '@/modelTypes/IUserSettings'
|
||||
|
||||
export function getAvatarUrl(user: IUser, size = 50) {
|
||||
return `${window.API_URL}/avatar/${user.username}?size=${size}`
|
||||
}
|
||||
|
||||
export function getDisplayName(user: IUser) {
|
||||
if (user.name !== '') {
|
||||
return user.name
|
||||
}
|
||||
|
||||
return user.username
|
||||
}
|
||||
|
||||
export default class UserModel extends AbstractModel<IUser> implements IUser {
|
||||
id = 0
|
||||
email = ''
|
||||
username = ''
|
||||
name = ''
|
||||
exp = 0
|
||||
type: AuthType = AUTH_TYPES.UNKNOWN
|
||||
|
||||
created: Date
|
||||
updated: Date
|
||||
settings: IUserSettings
|
||||
|
||||
isLocalUser: boolean
|
||||
deletionScheduledAt: null
|
||||
|
||||
constructor(data: Partial<IUser> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
|
||||
this.settings = new UserSettingsModel(this.settings || {})
|
||||
}
|
||||
}
|
14
frontend/src/models/userProject.ts
Normal file
14
frontend/src/models/userProject.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import UserShareBaseModel from './userShareBase'
|
||||
|
||||
import type {IUserProject} from '@/modelTypes/IUserProject'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||
export default class UserProjectModel extends UserShareBaseModel implements IUserProject {
|
||||
projectId: IProject['id'] = 0
|
||||
|
||||
constructor(data: Partial<IUserProject>) {
|
||||
super(data)
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
28
frontend/src/models/userSettings.ts
Normal file
28
frontend/src/models/userSettings.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import type {IFrontendSettings, IUserSettings} from '@/modelTypes/IUserSettings'
|
||||
import {getBrowserLanguage} from '@/i18n'
|
||||
import {PrefixMode} from '@/modules/parseTaskText'
|
||||
|
||||
export default class UserSettingsModel extends AbstractModel<IUserSettings> implements IUserSettings {
|
||||
name = ''
|
||||
emailRemindersEnabled = true
|
||||
discoverableByName = false
|
||||
discoverableByEmail = false
|
||||
overdueTasksRemindersEnabled = true
|
||||
overdueTasksRemindersTime = undefined
|
||||
defaultProjectId = undefined
|
||||
weekStart = 0 as IUserSettings['weekStart']
|
||||
timezone = ''
|
||||
language = getBrowserLanguage()
|
||||
frontendSettings: IFrontendSettings = {
|
||||
playSoundWhenDone: true,
|
||||
quickAddMagicMode: PrefixMode.Default,
|
||||
colorSchema: 'auto',
|
||||
}
|
||||
|
||||
constructor(data: Partial<IUserSettings> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
}
|
||||
}
|
21
frontend/src/models/userShareBase.ts
Normal file
21
frontend/src/models/userShareBase.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
import {RIGHTS, type Right} from '@/constants/rights'
|
||||
import type {IUserShareBase} from '@/modelTypes/IUserShareBase'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
|
||||
export default class UserShareBaseModel extends AbstractModel<IUserShareBase> implements IUserShareBase {
|
||||
userId: IUser['id'] = ''
|
||||
right: Right = RIGHTS.READ
|
||||
|
||||
created: Date = null
|
||||
updated: Date = null
|
||||
|
||||
constructor(data: Partial<IUserShareBase>) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
25
frontend/src/models/webhook.ts
Normal file
25
frontend/src/models/webhook.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import AbstractModel from '@/models/abstractModel'
|
||||
import type {IWebhook} from '@/modelTypes/IWebhook'
|
||||
import UserModel from '@/models/user'
|
||||
|
||||
export default class WebhookModel extends AbstractModel<IWebhook> implements IWebhook {
|
||||
id = 0
|
||||
projectId = 0
|
||||
secret = ''
|
||||
targetUrl = ''
|
||||
events = []
|
||||
createdBy = null
|
||||
|
||||
created: Date
|
||||
updated: Date
|
||||
|
||||
constructor(data: Partial<IWebhook> = {}) {
|
||||
super()
|
||||
this.assignData(data)
|
||||
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user