feat: add modelTypes
This commit is contained in:
parent
8416b1f448
commit
7d4ba6249e
91 changed files with 751 additions and 513 deletions
|
@ -52,7 +52,7 @@ import {computed, onMounted, onUnmounted, ref} from 'vue'
|
||||||
import NotificationService from '@/services/notification'
|
import NotificationService from '@/services/notification'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import User from '@/components/misc/user.vue'
|
import User from '@/components/misc/user.vue'
|
||||||
import { NOTIFICATION_NAMES as names, type INotification} from '@/models/notification'
|
import { NOTIFICATION_NAMES as names, type INotification} from '@/modelTypes/INotification'
|
||||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||||
import {useStore} from '@/store'
|
import {useStore} from '@/store'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
/>
|
/>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<span>
|
<span>
|
||||||
{{ a.file.getHumanSize() }}
|
{{ getHumanSize(a.file.size) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="a.file.mime">
|
<span v-if="a.file.mime">
|
||||||
{{ a.file.mime }}
|
{{ a.file.mime }}
|
||||||
|
@ -157,6 +157,7 @@ import {formatDate, formatDateSince, formatDateLong} from '@/helpers/time/format
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton'
|
import BaseButton from '@/components/base/BaseButton'
|
||||||
import type { IFile } from '@/models/file'
|
import type { IFile } from '@/models/file'
|
||||||
|
import { getHumanSize } from '@/helpers/getHumanSize'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'attachments',
|
name: 'attachments',
|
||||||
|
@ -231,6 +232,7 @@ export default defineComponent({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getHumanSize,
|
||||||
formatDate,
|
formatDate,
|
||||||
formatDateSince,
|
formatDateSince,
|
||||||
formatDateLong,
|
formatDateLong,
|
||||||
|
|
|
@ -144,7 +144,8 @@ import {defineComponent} from 'vue'
|
||||||
import TaskService from '../../../services/task'
|
import TaskService from '../../../services/task'
|
||||||
import TaskModel from '../../../models/task'
|
import TaskModel from '../../../models/task'
|
||||||
import TaskRelationService from '../../../services/taskRelation'
|
import TaskRelationService from '../../../services/taskRelation'
|
||||||
import TaskRelationModel, {RELATION_KINDS} from '@/models/taskRelation'
|
import TaskRelationModel from '@/models/taskRelation'
|
||||||
|
import { RELATION_KIND, RELATION_KINDS } from '@/types/IRelationKind'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
|
@ -158,7 +159,7 @@ export default defineComponent({
|
||||||
foundTasks: [],
|
foundTasks: [],
|
||||||
relationKinds: RELATION_KINDS,
|
relationKinds: RELATION_KINDS,
|
||||||
newTaskRelationTask: new TaskModel(),
|
newTaskRelationTask: new TaskModel(),
|
||||||
newTaskRelationKind: 'related',
|
newTaskRelationKind: RELATION_KIND.RELATED,
|
||||||
taskRelationService: new TaskRelationService(),
|
taskRelationService: new TaskRelationService(),
|
||||||
showDeleteModal: false,
|
showDeleteModal: false,
|
||||||
relationToDelete: {},
|
relationToDelete: {},
|
||||||
|
|
|
@ -66,7 +66,10 @@ import {ref, reactive, watch, type PropType} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import {error} from '@/message'
|
import {error} from '@/message'
|
||||||
import {TASK_REPEAT_MODES, type ITask, type RepeatAfter} from '@/models/task'
|
|
||||||
|
import {TASK_REPEAT_MODES} from '@/types/IRepeatMode'
|
||||||
|
import type {IRepeatAfter} from '@/types/IRepeatAfter'
|
||||||
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -116,7 +119,7 @@ function updateData() {
|
||||||
emit('change')
|
emit('change')
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRepeatAfter(amount: number, type: RepeatAfter['type']) {
|
function setRepeatAfter(amount: number, type: IRepeatAfter['type']) {
|
||||||
Object.assign(repeatAfter, { amount, type})
|
Object.assign(repeatAfter, { amount, type})
|
||||||
updateData()
|
updateData()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export function colorIsDark(color) {
|
export function colorIsDark(color: string | undefined) {
|
||||||
if (typeof color === 'undefined') {
|
if (typeof color === 'undefined') {
|
||||||
return true // Defaults to dark
|
return true // Defaults to dark
|
||||||
}
|
}
|
||||||
|
|
18
src/helpers/getHumanSize.ts
Normal file
18
src/helpers/getHumanSize.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const SIZES = [
|
||||||
|
'B',
|
||||||
|
'KB',
|
||||||
|
'MB',
|
||||||
|
'GB',
|
||||||
|
'TB',
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function getHumanSize(inputSize: number) {
|
||||||
|
let iterator = 0
|
||||||
|
let size = inputSize
|
||||||
|
while (size > 1024) {
|
||||||
|
size /= 1024
|
||||||
|
iterator++
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number(Math.round(Number(size + 'e2')) + 'e-2') + ' ' + SIZES[iterator]
|
||||||
|
}
|
43
src/modelSchema/common/repeats.ts
Normal file
43
src/modelSchema/common/repeats.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { REPEAT_TYPES, type IRepeatAfter } from '@/types/IRepeatAfter'
|
||||||
|
import { nativeEnum, number, object, preprocess } from 'zod'
|
||||||
|
|
||||||
|
export const RepeatsSchema = preprocess(
|
||||||
|
(repeats: unknown) => {
|
||||||
|
// Parses the "repeat after x seconds" from the task into a usable js object inside the task.
|
||||||
|
|
||||||
|
if (typeof repeats !== 'number') {
|
||||||
|
return repeats
|
||||||
|
}
|
||||||
|
|
||||||
|
const repeatAfterHours = (repeats / 60) / 60
|
||||||
|
|
||||||
|
const repeatAfter : IRepeatAfter = {
|
||||||
|
type: 'hours',
|
||||||
|
amount: repeatAfterHours,
|
||||||
|
}
|
||||||
|
|
||||||
|
// if its dividable by 24, its something with days, otherwise hours
|
||||||
|
if (repeatAfterHours % 24 === 0) {
|
||||||
|
const repeatAfterDays = repeatAfterHours / 24
|
||||||
|
if (repeatAfterDays % 7 === 0) {
|
||||||
|
repeatAfter.type = 'weeks'
|
||||||
|
repeatAfter.amount = repeatAfterDays / 7
|
||||||
|
} else if (repeatAfterDays % 30 === 0) {
|
||||||
|
repeatAfter.type = 'months'
|
||||||
|
repeatAfter.amount = repeatAfterDays / 30
|
||||||
|
} else if (repeatAfterDays % 365 === 0) {
|
||||||
|
repeatAfter.type = 'years'
|
||||||
|
repeatAfter.amount = repeatAfterDays / 365
|
||||||
|
} else {
|
||||||
|
repeatAfter.type = 'days'
|
||||||
|
repeatAfter.amount = repeatAfterDays
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repeatAfter
|
||||||
|
},
|
||||||
|
object({
|
||||||
|
type: nativeEnum(REPEAT_TYPES),
|
||||||
|
amount: number().int(),
|
||||||
|
}),
|
||||||
|
)
|
5
src/modelTypes/IAbstract.ts
Normal file
5
src/modelTypes/IAbstract.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import type {Right} from '@/constants/rights'
|
||||||
|
|
||||||
|
export interface IAbstract {
|
||||||
|
maxRight: Right | null // FIXME: should this be readonly?
|
||||||
|
}
|
11
src/modelTypes/IAttachment.ts
Normal file
11
src/modelTypes/IAttachment.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IFile} from './IFile'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
|
||||||
|
export interface IAttachment extends IAbstract {
|
||||||
|
id: number
|
||||||
|
taskId: number
|
||||||
|
createdBy: IUser
|
||||||
|
file: IFile
|
||||||
|
created: Date
|
||||||
|
}
|
7
src/modelTypes/IAvatar.ts
Normal file
7
src/modelTypes/IAvatar.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export type AvatarProvider = 'default' | 'initials' | 'gravatar' | 'marble' | 'upload'
|
||||||
|
|
||||||
|
export interface IAvatar extends IAbstract {
|
||||||
|
avatarProvider: AvatarProvider
|
||||||
|
}
|
12
src/modelTypes/IBackgroundImage.ts
Normal file
12
src/modelTypes/IBackgroundImage.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface IBackgroundImage extends IAbstract {
|
||||||
|
id: number
|
||||||
|
url: string
|
||||||
|
thumb: string
|
||||||
|
info: {
|
||||||
|
author: string
|
||||||
|
authorName: string
|
||||||
|
}
|
||||||
|
blurHash: string
|
||||||
|
}
|
17
src/modelTypes/IBucket.ts
Normal file
17
src/modelTypes/IBucket.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
|
||||||
|
export interface IBucket extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
listId: number
|
||||||
|
limit: number
|
||||||
|
tasks: ITask[]
|
||||||
|
isDoneBucket: boolean
|
||||||
|
position: number
|
||||||
|
|
||||||
|
createdBy: IUser
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
7
src/modelTypes/ICaldavToken.ts
Normal file
7
src/modelTypes/ICaldavToken.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface ICaldavToken extends IAbstract {
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
created: Date;
|
||||||
|
}
|
6
src/modelTypes/IEmailUpdate.ts
Normal file
6
src/modelTypes/IEmailUpdate.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface IEmailUpdate extends IAbstract {
|
||||||
|
newEmail: string
|
||||||
|
password: string
|
||||||
|
}
|
10
src/modelTypes/IFile.ts
Normal file
10
src/modelTypes/IFile.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface IFile extends IAbstract {
|
||||||
|
id: number
|
||||||
|
mime: string
|
||||||
|
name: string
|
||||||
|
size: number
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
}
|
15
src/modelTypes/ILabel.ts
Normal file
15
src/modelTypes/ILabel.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
|
||||||
|
export interface ILabel extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
hexColor: string
|
||||||
|
description: string
|
||||||
|
createdBy: IUser
|
||||||
|
listId: number
|
||||||
|
textColor: string
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
7
src/modelTypes/ILabelTask.ts
Normal file
7
src/modelTypes/ILabelTask.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface ILabelTask extends IAbstract {
|
||||||
|
id: number
|
||||||
|
taskId: number
|
||||||
|
labelId: number
|
||||||
|
}
|
17
src/modelTypes/ILinkShare.ts
Normal file
17
src/modelTypes/ILinkShare.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type { Right } from '@/constants/rights'
|
||||||
|
|
||||||
|
export interface ILinkShare extends IAbstract {
|
||||||
|
id: number
|
||||||
|
hash: string
|
||||||
|
right: Right
|
||||||
|
sharedBy: IUser
|
||||||
|
sharingType: number // FIXME: use correct numbers
|
||||||
|
listId: number
|
||||||
|
name: string
|
||||||
|
password: string
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
26
src/modelTypes/IList.ts
Normal file
26
src/modelTypes/IList.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ISubscription} from './ISubscription'
|
||||||
|
import type {INamespace} from './INamespace'
|
||||||
|
|
||||||
|
|
||||||
|
export interface IList extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
owner: IUser
|
||||||
|
tasks: ITask[]
|
||||||
|
namespaceId: INamespace['id']
|
||||||
|
isArchived: boolean
|
||||||
|
hexColor: string
|
||||||
|
identifier: string
|
||||||
|
backgroundInformation: any // FIXME: improve type
|
||||||
|
isFavorite: boolean
|
||||||
|
subscription: ISubscription
|
||||||
|
position: number
|
||||||
|
backgroundBlurHash: string
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
9
src/modelTypes/IListDuplicate.ts
Normal file
9
src/modelTypes/IListDuplicate.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
import type {INamespace} from './INamespace'
|
||||||
|
|
||||||
|
export interface IListDuplicate extends IAbstract {
|
||||||
|
listId: number
|
||||||
|
namespaceId: INamespace['id']
|
||||||
|
list: IList
|
||||||
|
}
|
18
src/modelTypes/INamespace.ts
Normal file
18
src/modelTypes/INamespace.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ISubscription} from './ISubscription'
|
||||||
|
|
||||||
|
export interface INamespace extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
owner: IUser
|
||||||
|
lists: IList[]
|
||||||
|
isArchived: boolean
|
||||||
|
hexColor: string
|
||||||
|
subscription: ISubscription
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
51
src/modelTypes/INotification.ts
Normal file
51
src/modelTypes/INotification.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
import type {ITaskComment} from './ITaskComment'
|
||||||
|
import type {ITeam} from './ITeam'
|
||||||
|
import type { IList } from './IList'
|
||||||
|
|
||||||
|
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: IUser
|
||||||
|
}
|
||||||
|
interface NotificationTask extends Notification {
|
||||||
|
task: ITask
|
||||||
|
comment: ITaskComment
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NotificationAssigned extends Notification {
|
||||||
|
task: ITask
|
||||||
|
assignee: IUser
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NotificationDeleted extends Notification {
|
||||||
|
task: ITask
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NotificationCreated extends Notification {
|
||||||
|
task: ITask
|
||||||
|
list: IList
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NotificationMemberAdded extends Notification {
|
||||||
|
member: IUser
|
||||||
|
team: ITeam
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INotification extends IAbstract {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
notification: NotificationTask | NotificationAssigned | NotificationDeleted | NotificationCreated | NotificationMemberAdded
|
||||||
|
read: boolean
|
||||||
|
readAt: Date | null
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
}
|
7
src/modelTypes/IPasswordReset.ts
Normal file
7
src/modelTypes/IPasswordReset.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface IPasswordReset extends IAbstract {
|
||||||
|
token: string
|
||||||
|
newPassword: string
|
||||||
|
email: string
|
||||||
|
}
|
6
src/modelTypes/IPasswordUpdate.ts
Normal file
6
src/modelTypes/IPasswordUpdate.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface IPasswordUpdate extends IAbstract {
|
||||||
|
newPassword: string
|
||||||
|
oldPassword: string
|
||||||
|
}
|
14
src/modelTypes/ISavedFilter.ts
Normal file
14
src/modelTypes/ISavedFilter.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {IFilter} from '@/types/IFilter'
|
||||||
|
|
||||||
|
export interface ISavedFilter extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
filters: IFilter
|
||||||
|
|
||||||
|
owner: IUser
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
11
src/modelTypes/ISubscription.ts
Normal file
11
src/modelTypes/ISubscription.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
|
||||||
|
export interface ISubscription extends IAbstract {
|
||||||
|
id: number
|
||||||
|
entity: string // FIXME: correct type?
|
||||||
|
entityId: number // FIXME: correct type?
|
||||||
|
user: IUser
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
}
|
50
src/modelTypes/ITask.ts
Normal file
50
src/modelTypes/ITask.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import type { Priority } from '@/constants/priorities'
|
||||||
|
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ILabel} from './ILabel'
|
||||||
|
import type {IAttachment} from './IAttachment'
|
||||||
|
import type {ISubscription} from './ISubscription'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
import type {IBucket} from './IBucket'
|
||||||
|
|
||||||
|
import type {IRelationKind} from '@/types/IRelationKind'
|
||||||
|
import type {IRepeatAfter} from '@/types/IRepeatAfter'
|
||||||
|
import type {IRepeatMode} from '@/types/IRepeatMode'
|
||||||
|
export interface ITask extends IAbstract {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
done: boolean
|
||||||
|
doneAt: Date | null
|
||||||
|
priority: Priority
|
||||||
|
labels: ILabel[]
|
||||||
|
assignees: IUser[]
|
||||||
|
|
||||||
|
dueDate: Date | null
|
||||||
|
startDate: Date | null
|
||||||
|
endDate: Date | null
|
||||||
|
repeatAfter: number | IRepeatAfter
|
||||||
|
repeatFromCurrentDate: boolean
|
||||||
|
repeatMode: IRepeatMode
|
||||||
|
reminderDates: Date[]
|
||||||
|
parentTaskId: ITask['id']
|
||||||
|
hexColor: string
|
||||||
|
percentDone: number
|
||||||
|
relatedTasks: Partial<Record<IRelationKind, ITask>>,
|
||||||
|
attachments: IAttachment[]
|
||||||
|
identifier: string
|
||||||
|
index: number
|
||||||
|
isFavorite: boolean
|
||||||
|
subscription: ISubscription
|
||||||
|
|
||||||
|
position: number
|
||||||
|
kanbanPosition: number
|
||||||
|
|
||||||
|
createdBy: IUser
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
|
||||||
|
listId: IList['id'] // Meta, only used when creating a new task
|
||||||
|
bucketId: IBucket['id']
|
||||||
|
}
|
9
src/modelTypes/ITaskAssignee.ts
Normal file
9
src/modelTypes/ITaskAssignee.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
|
||||||
|
export interface ITaskAssignee extends IAbstract {
|
||||||
|
created: Date
|
||||||
|
userId: IUser['id']
|
||||||
|
taskId: ITask['id']
|
||||||
|
}
|
13
src/modelTypes/ITaskComment.ts
Normal file
13
src/modelTypes/ITaskComment.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
|
||||||
|
export interface ITaskComment extends IAbstract {
|
||||||
|
id: number
|
||||||
|
taskId: ITask['id']
|
||||||
|
comment: string
|
||||||
|
author: IUser
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
15
src/modelTypes/ITaskRelation.ts
Normal file
15
src/modelTypes/ITaskRelation.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ITask} from './ITask'
|
||||||
|
|
||||||
|
import type {IRelationKind} from '@/types/IRelationKind'
|
||||||
|
|
||||||
|
export interface ITaskRelation extends IAbstract {
|
||||||
|
id: number
|
||||||
|
otherTaskId: ITask['id']
|
||||||
|
taskId: ITask['id']
|
||||||
|
relationKind: IRelationKind
|
||||||
|
|
||||||
|
createdBy: IUser
|
||||||
|
created: Date
|
||||||
|
}
|
16
src/modelTypes/ITeam.ts
Normal file
16
src/modelTypes/ITeam.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {ITeamMember} from './ITeamMember'
|
||||||
|
import type {Right} from '@/constants/rights'
|
||||||
|
|
||||||
|
export interface ITeam extends IAbstract {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
members: ITeamMember[]
|
||||||
|
right: Right
|
||||||
|
|
||||||
|
createdBy: IUser
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
6
src/modelTypes/ITeamList.ts
Normal file
6
src/modelTypes/ITeamList.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {ITeamShareBase} from './ITeamShareBase'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
|
||||||
|
export interface ITeamList extends ITeamShareBase {
|
||||||
|
listId: IList['id']
|
||||||
|
}
|
7
src/modelTypes/ITeamMember.ts
Normal file
7
src/modelTypes/ITeamMember.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
|
||||||
|
export interface ITeamMember extends IUser {
|
||||||
|
admin: boolean
|
||||||
|
teamId: IList['id']
|
||||||
|
}
|
6
src/modelTypes/ITeamNamespace.ts
Normal file
6
src/modelTypes/ITeamNamespace.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {ITeamShareBase} from './ITeamShareBase'
|
||||||
|
import type {INamespace} from './INamespace'
|
||||||
|
|
||||||
|
export interface ITeamNamespace extends ITeamShareBase {
|
||||||
|
namespaceId: INamespace['id']
|
||||||
|
}
|
11
src/modelTypes/ITeamShareBase.ts
Normal file
11
src/modelTypes/ITeamShareBase.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {ITeam} from './ITeam'
|
||||||
|
import type {Right} from '@/constants/rights'
|
||||||
|
|
||||||
|
export interface ITeamShareBase extends IAbstract {
|
||||||
|
teamId: ITeam['id']
|
||||||
|
right: Right
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
7
src/modelTypes/ITotp.ts
Normal file
7
src/modelTypes/ITotp.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
|
||||||
|
export interface ITotp extends IAbstract {
|
||||||
|
secret: string
|
||||||
|
enabled: boolean
|
||||||
|
url: string
|
||||||
|
}
|
13
src/modelTypes/IUser.ts
Normal file
13
src/modelTypes/IUser.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUserSettings} from './IUserSettings'
|
||||||
|
|
||||||
|
export interface IUser extends IAbstract {
|
||||||
|
id: number
|
||||||
|
email: string
|
||||||
|
username: string
|
||||||
|
name: string
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
settings: IUserSettings
|
||||||
|
}
|
6
src/modelTypes/IUserList.ts
Normal file
6
src/modelTypes/IUserList.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {IUserShareBase} from './IUserShareBase'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
|
||||||
|
export interface IUserList extends IUserShareBase {
|
||||||
|
listId: IList['id']
|
||||||
|
}
|
6
src/modelTypes/IUserNamespace.ts
Normal file
6
src/modelTypes/IUserNamespace.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import type {IUserShareBase} from './IUserShareBase'
|
||||||
|
import type {INamespace} from './INamespace'
|
||||||
|
|
||||||
|
export interface IUserNamespace extends IUserShareBase {
|
||||||
|
namespaceId: INamespace['id']
|
||||||
|
}
|
14
src/modelTypes/IUserSettings.ts
Normal file
14
src/modelTypes/IUserSettings.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IList} from './IList'
|
||||||
|
|
||||||
|
export interface IUserSettings extends IAbstract {
|
||||||
|
name: string
|
||||||
|
emailRemindersEnabled: boolean
|
||||||
|
discoverableByName: boolean
|
||||||
|
discoverableByEmail: boolean
|
||||||
|
overdueTasksRemindersEnabled: boolean
|
||||||
|
defaultListId: undefined | IList['id']
|
||||||
|
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||||
|
timezone: string
|
||||||
|
}
|
11
src/modelTypes/IUserShareBase.ts
Normal file
11
src/modelTypes/IUserShareBase.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import type {IAbstract} from './IAbstract'
|
||||||
|
import type {IUser} from './IUser'
|
||||||
|
import type {Right} from '@/constants/rights'
|
||||||
|
|
||||||
|
export interface IUserShareBase extends IAbstract {
|
||||||
|
userId: IUser['id']
|
||||||
|
right: Right
|
||||||
|
|
||||||
|
created: Date
|
||||||
|
updated: Date
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
import {objectToCamelCase} from '@/helpers/case'
|
import {objectToCamelCase} from '@/helpers/case'
|
||||||
import {omitBy, isNil} from '@/helpers/utils'
|
import {omitBy, isNil} from '@/helpers/utils'
|
||||||
import type {Right} from '@/constants/rights'
|
import type {Right} from '@/constants/rights'
|
||||||
|
import type {IAbstract} from '@/modelTypes/IAbstract'
|
||||||
export interface IAbstract {
|
|
||||||
maxRight: Right | null // FIXME: should this be readonly?
|
|
||||||
}
|
|
||||||
|
|
||||||
export default abstract class AbstractModel<Model extends IAbstract = IAbstract> implements 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.
|
* The max right the user has on this object, as returned by the x-max-right header from the api.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, {type IUser} from './user'
|
import UserModel from './user'
|
||||||
import FileModel, {type IFile} from './file'
|
import FileModel from './file'
|
||||||
|
import type { IUser } from '@/modelTypes/IUser'
|
||||||
export interface IAttachment extends IAbstract {
|
import type { IFile } from '@/modelTypes/IFile'
|
||||||
id: number
|
import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||||
taskId: number
|
|
||||||
createdBy: IUser
|
|
||||||
file: IFile
|
|
||||||
created: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AttachmentModel extends AbstractModel implements IAttachment {
|
export default class AttachmentModel extends AbstractModel implements IAttachment {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
import type { IAvatar } from '@/modelTypes/IAvatar'
|
||||||
export type AvatarProvider = 'default' | 'initials' | 'gravatar' | 'marble' | 'upload'
|
|
||||||
|
|
||||||
export interface IAvatar extends IAbstract {
|
|
||||||
avatarProvider: AvatarProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AvatarModel extends AbstractModel implements IAvatar {
|
export default class AvatarModel extends AbstractModel implements IAvatar {
|
||||||
avatarProvider: AvatarProvider = 'default'
|
avatarProvider: IAvatar['avatarProvider'] = 'default'
|
||||||
|
|
||||||
constructor(data: Partial<IAvatar>) {
|
constructor(data: Partial<IAvatar>) {
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
import type {IBackgroundImage} from '@/modelTypes/IBackgroundImage'
|
||||||
export interface IBackgroundImage extends IAbstract {
|
|
||||||
id: number
|
|
||||||
url: string
|
|
||||||
thumb: string
|
|
||||||
info: {
|
|
||||||
author: string
|
|
||||||
authorName: string
|
|
||||||
}
|
|
||||||
blurHash: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class BackgroundImageModel extends AbstractModel implements IBackgroundImage {
|
export default class BackgroundImageModel extends AbstractModel implements IBackgroundImage {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import TaskModel, { type ITask } from './task'
|
import TaskModel from './task'
|
||||||
|
|
||||||
export interface IBucket extends IAbstract {
|
import type {IBucket} from '@/modelTypes/IBucket'
|
||||||
id: number
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
title: string
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
listId: number
|
|
||||||
limit: number
|
|
||||||
tasks: ITask[]
|
|
||||||
isDoneBucket: boolean
|
|
||||||
position: number
|
|
||||||
|
|
||||||
createdBy: IUser
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class BucketModel extends AbstractModel implements IBucket {
|
export default class BucketModel extends AbstractModel implements IBucket {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
export interface ICaldavToken extends IAbstract {
|
import type {ICaldavToken} from '@/modelTypes/ICaldavToken'
|
||||||
id: number;
|
|
||||||
created: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class CaldavTokenModel extends AbstractModel implements ICaldavToken {
|
export default class CaldavTokenModel extends AbstractModel implements ICaldavToken {
|
||||||
id: number
|
id: number
|
||||||
created: Date
|
created: Date
|
||||||
|
|
||||||
constructor(data? : Partial<CaldavTokenModel>) {
|
constructor(data: Partial<CaldavTokenModel>) {
|
||||||
super()
|
super()
|
||||||
this.assignData(data)
|
this.assignData(data)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
interface IEmailUpdate extends IAbstract {
|
import type {IEmailUpdate} from '@/modelTypes/IEmailUpdate'
|
||||||
newEmail: string
|
|
||||||
password: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class EmailUpdateModel extends AbstractModel implements IEmailUpdate {
|
export default class EmailUpdateModel extends AbstractModel implements IEmailUpdate {
|
||||||
newEmail = ''
|
newEmail = ''
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
import type {IFile} from '@/modelTypes/IFile'
|
||||||
export interface IFile extends IAbstract {
|
|
||||||
id: number
|
|
||||||
mime: string
|
|
||||||
name: string
|
|
||||||
size: number
|
|
||||||
created: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class FileModel extends AbstractModel implements IFile {
|
export default class FileModel extends AbstractModel implements IFile {
|
||||||
id = 0
|
id = 0
|
||||||
|
@ -21,23 +14,4 @@ export default class FileModel extends AbstractModel implements IFile {
|
||||||
|
|
||||||
this.created = new Date(this.created)
|
this.created = new Date(this.created)
|
||||||
}
|
}
|
||||||
|
|
||||||
getHumanSize() {
|
|
||||||
const sizes = {
|
|
||||||
0: 'B',
|
|
||||||
1: 'KB',
|
|
||||||
2: 'MB',
|
|
||||||
3: 'GB',
|
|
||||||
4: 'TB',
|
|
||||||
}
|
|
||||||
|
|
||||||
let it = 0
|
|
||||||
let size = this.size
|
|
||||||
while (size > 1024) {
|
|
||||||
size /= 1024
|
|
||||||
it++
|
|
||||||
}
|
|
||||||
|
|
||||||
return Number(Math.round(size + 'e2') + 'e-2') + ' ' + sizes[it]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,13 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
|
|
||||||
|
import type {ILabel} from '@/modelTypes/ILabel'
|
||||||
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
|
|
||||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||||
|
|
||||||
const DEFAULT_LABEL_BACKGROUND_COLOR = 'e8e8e8'
|
const DEFAULT_LABEL_BACKGROUND_COLOR = 'e8e8e8'
|
||||||
|
|
||||||
export interface ILabel extends IAbstract {
|
|
||||||
id: number
|
|
||||||
title: string
|
|
||||||
hexColor: string
|
|
||||||
description: string
|
|
||||||
createdBy: IUser
|
|
||||||
listId: number
|
|
||||||
textColor: string
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LabelModel extends AbstractModel implements ILabel {
|
export default class LabelModel extends AbstractModel implements ILabel {
|
||||||
id = 0
|
id = 0
|
||||||
title = ''
|
title = ''
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
export interface ILabelTask extends IAbstract {
|
import type { ILabelTask } from '@/modelTypes/ILabelTask'
|
||||||
id: number
|
|
||||||
taskId: number
|
|
||||||
labelId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LabelTask extends AbstractModel implements ILabelTask {
|
export default class LabelTask extends AbstractModel implements ILabelTask {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import {RIGHTS, type Right} from '@/constants/rights'
|
|
||||||
|
|
||||||
export interface ILinkShare extends IAbstract {
|
import {RIGHTS, type Right} from '@/constants/rights'
|
||||||
id: number
|
import type {ILinkShare} from '@/modelTypes/ILinkShare'
|
||||||
hash: string
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
right: Right
|
|
||||||
sharedBy: IUser
|
|
||||||
sharingType: number // FIXME: use correct numbers
|
|
||||||
listId: number
|
|
||||||
name: string
|
|
||||||
password: string
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LinkShareModel extends AbstractModel implements ILinkShare {
|
export default class LinkShareModel extends AbstractModel implements ILinkShare {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,31 +1,16 @@
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import TaskModel, { type ITask } from '@/models/task'
|
import TaskModel from '@/models/task'
|
||||||
import UserModel, { type IUser } from '@/models/user'
|
import UserModel from '@/models/user'
|
||||||
import SubscriptionModel, { type ISubscription } from '@/models/subscription'
|
import SubscriptionModel from '@/models/subscription'
|
||||||
import type { INamespace } from '@/models/namespace'
|
|
||||||
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
|
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||||
|
|
||||||
import {getSavedFilterIdFromListId} from '@/helpers/savedFilter'
|
import {getSavedFilterIdFromListId} from '@/helpers/savedFilter'
|
||||||
|
|
||||||
export interface IList extends IAbstract {
|
|
||||||
id: number
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
owner: IUser
|
|
||||||
tasks: ITask[]
|
|
||||||
namespaceId: INamespace['id']
|
|
||||||
isArchived: boolean
|
|
||||||
hexColor: string
|
|
||||||
identifier: string
|
|
||||||
backgroundInformation: any // FIXME: improve type
|
|
||||||
isFavorite: boolean
|
|
||||||
subscription: ISubscription
|
|
||||||
position: number
|
|
||||||
backgroundBlurHash: string
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ListModel extends AbstractModel implements IList {
|
export default class ListModel extends AbstractModel implements IList {
|
||||||
id = 0
|
id = 0
|
||||||
title = ''
|
title = ''
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import ListModel, { type IList } from './list'
|
import ListModel from './list'
|
||||||
import type { INamespace } from './namespace'
|
|
||||||
|
|
||||||
export interface IListDuplicate extends IAbstract {
|
import type {IListDuplicate} from '@/modelTypes/IListDuplicate'
|
||||||
listId: number
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
namespaceId: INamespace['id']
|
import type {IList} from '@/modelTypes/IList'
|
||||||
list: IList
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ListDuplicateModel extends AbstractModel implements IListDuplicate {
|
export default class ListDuplicateModel extends AbstractModel implements IListDuplicate {
|
||||||
listId = 0
|
listId = 0
|
||||||
|
|
|
@ -1,21 +1,12 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import ListModel, { type IList } from './list'
|
import ListModel from './list'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import SubscriptionModel, { type ISubscription } from '@/models/subscription'
|
import SubscriptionModel from '@/models/subscription'
|
||||||
|
|
||||||
export interface INamespace extends IAbstract {
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
id: number
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
title: string
|
import type {IList} from '@/modelTypes/IList'
|
||||||
description: string
|
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||||
owner: IUser
|
|
||||||
lists: IList[]
|
|
||||||
isArchived: boolean
|
|
||||||
hexColor: string
|
|
||||||
subscription: ISubscription
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class NamespaceModel extends AbstractModel implements INamespace {
|
export default class NamespaceModel extends AbstractModel implements INamespace {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,60 +1,17 @@
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
||||||
import UserModel, { type IUser } from '@/models/user'
|
import UserModel from '@/models/user'
|
||||||
import TaskModel, { type ITask } from '@/models/task'
|
import TaskModel from '@/models/task'
|
||||||
import TaskCommentModel, { type ITaskComment } from '@/models/taskComment'
|
import TaskCommentModel from '@/models/taskComment'
|
||||||
import ListModel, { type IList } from '@/models/list'
|
import ListModel from '@/models/list'
|
||||||
import TeamModel, { type ITeam } from '@/models/team'
|
import TeamModel from '@/models/team'
|
||||||
|
|
||||||
export const NOTIFICATION_NAMES = {
|
import {NOTIFICATION_NAMES, type INotification} from '@/modelTypes/INotification'
|
||||||
'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: IUser
|
|
||||||
}
|
|
||||||
interface NotificationTask extends Notification {
|
|
||||||
task: ITask
|
|
||||||
comment: ITaskComment
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NotificationAssigned extends Notification {
|
|
||||||
task: ITask
|
|
||||||
assignee: IUser
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NotificationDeleted extends Notification {
|
|
||||||
task: ITask
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NotificationCreated extends Notification {
|
|
||||||
task: ITask
|
|
||||||
list: IList
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NotificationMemberAdded extends Notification {
|
|
||||||
member: IUser
|
|
||||||
team: ITeam
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INotification extends IAbstract {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
notification: NotificationTask | NotificationAssigned | NotificationDeleted | NotificationCreated | NotificationMemberAdded
|
|
||||||
read: boolean
|
|
||||||
readAt: Date | null
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class NotificationModel extends AbstractModel implements INotification {
|
export default class NotificationModel extends AbstractModel implements INotification {
|
||||||
id = 0
|
id = 0
|
||||||
name = ''
|
name = ''
|
||||||
notification: NotificationTask | NotificationAssigned | NotificationDeleted | NotificationCreated | NotificationMemberAdded = null
|
notification: INotification['notification'] = null
|
||||||
read = false
|
read = false
|
||||||
readAt: Date | null = null
|
readAt: Date | null = null
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
export interface IPasswordReset extends IAbstract {
|
import type {IPasswordReset} from '@/modelTypes/IPasswordReset'
|
||||||
token: string
|
|
||||||
newPassword: string
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class PasswordResetModel extends AbstractModel implements IPasswordReset {
|
export default class PasswordResetModel extends AbstractModel implements IPasswordReset {
|
||||||
token = ''
|
token = ''
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
export interface IPasswordUpdate extends IAbstract {
|
import type {IPasswordUpdate} from '@/modelTypes/IPasswordUpdate'
|
||||||
newPassword: string
|
|
||||||
oldPassword: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class PasswordUpdateModel extends AbstractModel implements IPasswordUpdate {
|
export default class PasswordUpdateModel extends AbstractModel implements IPasswordUpdate {
|
||||||
newPassword = ''
|
newPassword = ''
|
||||||
|
|
|
@ -1,38 +1,14 @@
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from '@/models/user'
|
import UserModel from '@/models/user'
|
||||||
|
|
||||||
export interface ISavedFilter extends IAbstract {
|
import type {ISavedFilter} from '@/modelTypes/ISavedFilter'
|
||||||
id: number
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
filters: {
|
|
||||||
sortBy: ('done' | 'id')[]
|
|
||||||
orderBy: ('asc' | 'desc')[]
|
|
||||||
filterBy: 'done'[]
|
|
||||||
filterValue: 'false'[]
|
|
||||||
filterComparator: 'equals'[]
|
|
||||||
filterConcat: 'and'
|
|
||||||
filterIncludeNulls: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
owner: IUser
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class SavedFilterModel extends AbstractModel implements ISavedFilter {
|
export default class SavedFilterModel extends AbstractModel implements ISavedFilter {
|
||||||
id = 0
|
id = 0
|
||||||
title = ''
|
title = ''
|
||||||
description = ''
|
description = ''
|
||||||
filters: {
|
filters: ISavedFilter['filters'] = {
|
||||||
sortBy: ('done' | 'id')[]
|
|
||||||
orderBy: ('asc' | 'desc')[]
|
|
||||||
filterBy: 'done'[]
|
|
||||||
filterValue: 'false'[]
|
|
||||||
filterComparator: 'equals'[]
|
|
||||||
filterConcat: 'and'
|
|
||||||
filterIncludeNulls: boolean
|
|
||||||
} = {
|
|
||||||
sortBy: ['done', 'id'],
|
sortBy: ['done', 'id'],
|
||||||
orderBy: ['asc', 'desc'],
|
orderBy: ['asc', 'desc'],
|
||||||
filterBy: ['done'],
|
filterBy: ['done'],
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from '@/models/user'
|
import UserModel from '@/models/user'
|
||||||
|
|
||||||
export interface ISubscription extends IAbstract {
|
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||||
id: number
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
entity: string // FIXME: correct type?
|
|
||||||
entityId: number // FIXME: correct type?
|
|
||||||
user: IUser
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class SubscriptionModel extends AbstractModel implements ISubscription {
|
export default class SubscriptionModel extends AbstractModel implements ISubscription {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,63 +1,35 @@
|
||||||
|
|
||||||
import { PRIORITIES, type Priority } from '@/constants/priorities'
|
import { PRIORITIES, type Priority } from '@/constants/priorities'
|
||||||
|
|
||||||
import AbstractModel, { type IAbstract } from '@/models/abstractModel'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import UserModel, { type IUser } from '@/models/user'
|
import type {ILabel} from '@/modelTypes/ILabel'
|
||||||
import LabelModel, { type ILabel } from '@/models/label'
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
import AttachmentModel, {type IAttachment} from '@/models/attachment'
|
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
import SubscriptionModel, { type ISubscription } from '@/models/subscription'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
import type { IList } from '@/models/list'
|
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||||
import type {IRepeats} from '@/types/IRepeats'
|
import type {IBucket} from '@/modelTypes/IBucket'
|
||||||
|
|
||||||
|
import type {IRepeatAfter} from '@/types/IRepeatAfter'
|
||||||
|
import {TASK_REPEAT_MODES, type IRepeatMode} from '@/types/IRepeatMode'
|
||||||
|
|
||||||
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
||||||
import type { IBucket } from './bucket'
|
import type { IRelationKind } from '@/types/IRelationKind'
|
||||||
|
|
||||||
|
import AbstractModel from './abstractModel'
|
||||||
|
import LabelModel from './label'
|
||||||
|
import UserModel from './user'
|
||||||
|
import AttachmentModel from './attachment'
|
||||||
|
import SubscriptionModel from './subscription'
|
||||||
|
|
||||||
const SUPPORTS_TRIGGERED_NOTIFICATION = 'Notification' in window && 'showTrigger' in Notification.prototype
|
const SUPPORTS_TRIGGERED_NOTIFICATION = 'Notification' in window && 'showTrigger' in Notification.prototype
|
||||||
export const TASK_DEFAULT_COLOR = '#1973ff'
|
export const TASK_DEFAULT_COLOR = '#1973ff'
|
||||||
|
|
||||||
export const TASK_REPEAT_MODES = {
|
export function getHexColor(hexColor: string) {
|
||||||
'REPEAT_MODE_DEFAULT': 0,
|
if (hexColor === '' || hexColor === '#') {
|
||||||
'REPEAT_MODE_MONTH': 1,
|
return TASK_DEFAULT_COLOR
|
||||||
'REPEAT_MODE_FROM_CURRENT_DATE': 2,
|
}
|
||||||
} as const
|
|
||||||
|
|
||||||
export type TaskRepeatMode = typeof TASK_REPEAT_MODES[keyof typeof TASK_REPEAT_MODES]
|
return hexColor
|
||||||
|
|
||||||
export interface ITask extends IAbstract {
|
|
||||||
id: number
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
done: boolean
|
|
||||||
doneAt: Date | null
|
|
||||||
priority: Priority
|
|
||||||
labels: ILabel[]
|
|
||||||
assignees: IUser[]
|
|
||||||
|
|
||||||
dueDate: Date | null
|
|
||||||
startDate: Date | null
|
|
||||||
endDate: Date | null
|
|
||||||
repeatAfter: number | IRepeats
|
|
||||||
repeatFromCurrentDate: boolean
|
|
||||||
repeatMode: TaskRepeatMode
|
|
||||||
reminderDates: Date[]
|
|
||||||
parentTaskId: ITask['id']
|
|
||||||
hexColor: string
|
|
||||||
percentDone: number
|
|
||||||
relatedTasks: { [relationKind: string]: ITask } // FIXME: use relationKinds
|
|
||||||
attachments: IAttachment[]
|
|
||||||
identifier: string
|
|
||||||
index: number
|
|
||||||
isFavorite: boolean
|
|
||||||
subscription: ISubscription
|
|
||||||
|
|
||||||
position: number
|
|
||||||
kanbanPosition: number
|
|
||||||
|
|
||||||
createdBy: IUser
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
|
|
||||||
listId: IList['id'] // Meta, only used when creating a new task
|
|
||||||
bucketId: IBucket['id']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TaskModel extends AbstractModel implements ITask {
|
export default class TaskModel extends AbstractModel implements ITask {
|
||||||
|
@ -73,14 +45,14 @@ export default class TaskModel extends AbstractModel implements ITask {
|
||||||
dueDate: Date | null = 0
|
dueDate: Date | null = 0
|
||||||
startDate: Date | null = 0
|
startDate: Date | null = 0
|
||||||
endDate: Date | null = 0
|
endDate: Date | null = 0
|
||||||
repeatAfter: number | IRepeats = 0
|
repeatAfter: number | IRepeatAfter = 0
|
||||||
repeatFromCurrentDate = false
|
repeatFromCurrentDate = false
|
||||||
repeatMode: TaskRepeatMode = TASK_REPEAT_MODES.REPEAT_MODE_DEFAULT
|
repeatMode: IRepeatMode = TASK_REPEAT_MODES.REPEAT_MODE_DEFAULT
|
||||||
reminderDates: Date[] = []
|
reminderDates: Date[] = []
|
||||||
parentTaskId: ITask['id'] = 0
|
parentTaskId: ITask['id'] = 0
|
||||||
hexColor = ''
|
hexColor = ''
|
||||||
percentDone = 0
|
percentDone = 0
|
||||||
relatedTasks: { [relationKind: string]: ITask } = {}
|
relatedTasks: Partial<Record<IRelationKind, ITask>> = {}
|
||||||
attachments: IAttachment[] = []
|
attachments: IAttachment[] = []
|
||||||
identifier = ''
|
identifier = ''
|
||||||
index = 0
|
index = 0
|
||||||
|
@ -168,11 +140,7 @@ export default class TaskModel extends AbstractModel implements ITask {
|
||||||
}
|
}
|
||||||
|
|
||||||
getHexColor() {
|
getHexColor() {
|
||||||
if (this.hexColor === '' || this.hexColor === '#') {
|
return getHexColor(this.hexColor)
|
||||||
return TASK_DEFAULT_COLOR
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.hexColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import type { ITask } from './task'
|
|
||||||
import type { IUser } from './user'
|
|
||||||
|
|
||||||
export interface ITaskAssignee extends IAbstract {
|
import type {ITaskAssignee} from '@/modelTypes/ITaskAssignee'
|
||||||
created: Date
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
userId: IUser['id']
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
taskId: ITask['id']
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TaskAssigneeModel extends AbstractModel implements ITaskAssignee {
|
export default class TaskAssigneeModel extends AbstractModel implements ITaskAssignee {
|
||||||
created: Date = null
|
created: Date = null
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import type { ITask } from './task'
|
|
||||||
|
|
||||||
export interface ITaskComment extends IAbstract {
|
import type {ITaskComment} from '@/modelTypes/ITaskComment'
|
||||||
id: number
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
taskId: ITask['id']
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
comment: string
|
|
||||||
author: IUser
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TaskCommentModel extends AbstractModel implements ITaskComment {
|
export default class TaskCommentModel extends AbstractModel implements ITaskComment {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,39 +1,16 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import type { ITask } from './task'
|
|
||||||
|
|
||||||
export const RELATION_KIND = {
|
import type {ITaskRelation} from '@/modelTypes/ITaskRelation'
|
||||||
'SUBTASK': 'subtask',
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
'PARENTTASK': 'parenttask',
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
'RELATED': 'related',
|
|
||||||
'DUPLICATES': 'duplicates',
|
|
||||||
'BLOCKING': 'blocking',
|
|
||||||
'BLOCKED': 'blocked',
|
|
||||||
'PROCEDES': 'precedes',
|
|
||||||
'FOLLOWS': 'follows',
|
|
||||||
'COPIEDFROM': 'copiedfrom',
|
|
||||||
'COPIEDTO': 'copiedto',
|
|
||||||
} as const
|
|
||||||
|
|
||||||
export const RELATION_KINDS = [...Object.values(RELATION_KIND)] as const
|
|
||||||
|
|
||||||
export type RelationKind = typeof RELATION_KINDS[number]
|
|
||||||
|
|
||||||
export interface ITaskRelation extends IAbstract {
|
|
||||||
id: number
|
|
||||||
otherTaskId: ITask['id']
|
|
||||||
taskId: ITask['id']
|
|
||||||
relationKind: RelationKind
|
|
||||||
|
|
||||||
createdBy: IUser
|
|
||||||
created: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
|
import type {IRelationKind} from '@/types/IRelationKind'
|
||||||
export default class TaskRelationModel extends AbstractModel implements ITaskRelation {
|
export default class TaskRelationModel extends AbstractModel implements ITaskRelation {
|
||||||
id = 0
|
id = 0
|
||||||
otherTaskId: ITask['id'] = 0
|
otherTaskId: ITask['id'] = 0
|
||||||
taskId: ITask['id'] = 0
|
taskId: ITask['id'] = 0
|
||||||
relationKind: RelationKind = ''
|
relationKind: IRelationKind = ''
|
||||||
|
|
||||||
createdBy: IUser = UserModel
|
createdBy: IUser = UserModel
|
||||||
created: Date = null
|
created: Date = null
|
||||||
|
|
|
@ -1,19 +1,11 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserModel, { type IUser } from './user'
|
import UserModel from './user'
|
||||||
import TeamMemberModel, { type ITeamMember } from './teamMember'
|
import TeamMemberModel from './teamMember'
|
||||||
|
|
||||||
import {RIGHTS, type Right} from '@/constants/rights'
|
import {RIGHTS, type Right} from '@/constants/rights'
|
||||||
|
import type {ITeam} from '@/modelTypes/ITeam'
|
||||||
export interface ITeam extends IAbstract {
|
import type {ITeamMember} from '@/modelTypes/ITeamMember'
|
||||||
id: number
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
members: ITeamMember[]
|
|
||||||
right: Right
|
|
||||||
|
|
||||||
createdBy: IUser
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TeamModel extends AbstractModel implements ITeam {
|
export default class TeamModel extends AbstractModel implements ITeam {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import TeamShareBaseModel from './teamShareBase'
|
import TeamShareBaseModel from './teamShareBase'
|
||||||
import type { IList } from './list'
|
|
||||||
|
|
||||||
export interface ITeamList extends TeamShareBaseModel {
|
import type {ITeamList} from '@/modelTypes/ITeamList'
|
||||||
listId: IList['id']
|
import type {IList} from '@/modelTypes/IList'
|
||||||
}
|
|
||||||
|
|
||||||
export default class TeamListModel extends TeamShareBaseModel implements ITeamList {
|
export default class TeamListModel extends TeamShareBaseModel implements ITeamList {
|
||||||
listId: IList['id'] = 0
|
listId: IList['id'] = 0
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import UserModel from './user'
|
import UserModel from './user'
|
||||||
import type { IList } from './list'
|
|
||||||
|
|
||||||
export interface ITeamMember extends UserModel {
|
import type {ITeamMember} from '@/modelTypes/ITeamMember'
|
||||||
admin: boolean
|
import type {IList} from '@/modelTypes/IList'
|
||||||
teamId: IList['id']
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TeamMemberModel extends UserModel implements ITeamMember {
|
export default class TeamMemberModel extends UserModel implements ITeamMember {
|
||||||
admin = false
|
admin = false
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import TeamShareBaseModel from './teamShareBase'
|
import TeamShareBaseModel from './teamShareBase'
|
||||||
import type { INamespace } from './namespace'
|
|
||||||
|
|
||||||
export interface ITeamNamespace extends TeamShareBaseModel {
|
import type {ITeamNamespace} from '@/modelTypes/ITeamNamespace'
|
||||||
namespaceId: INamespace['id']
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
}
|
|
||||||
|
|
||||||
export default class TeamNamespaceModel extends TeamShareBaseModel implements ITeamNamespace {
|
export default class TeamNamespaceModel extends TeamShareBaseModel implements ITeamNamespace {
|
||||||
namespaceId: INamespace['id'] = 0
|
namespaceId: INamespace['id'] = 0
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
import {RIGHTS, type Right} from '@/constants/rights'
|
import {RIGHTS, type Right} from '@/constants/rights'
|
||||||
import type { ITeam } from './team'
|
import type {ITeamShareBase} from '@/modelTypes/ITeamShareBase'
|
||||||
|
import type {ITeam} from '@/modelTypes/ITeam'
|
||||||
export interface ITeamShareBase extends IAbstract {
|
|
||||||
teamId: ITeam['id']
|
|
||||||
right: Right
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a base class for common team sharing model.
|
* This class is a base class for common team sharing model.
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
export interface ITotp extends IAbstract {
|
import type {ITotp} from '@/modelTypes/ITotp'
|
||||||
secret: string
|
|
||||||
enabled: boolean
|
|
||||||
url: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TotpModel extends AbstractModel implements ITotp {
|
export default class TotpModel extends AbstractModel implements ITotp {
|
||||||
secret = ''
|
secret = ''
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import UserSettingsModel, { type IUserSettings } from '@/models/userSettings'
|
import UserSettingsModel from '@/models/userSettings'
|
||||||
|
|
||||||
export interface IUser extends IAbstract {
|
import type { IUser } from '@/modelTypes/IUser'
|
||||||
id: number
|
import type { IUserSettings } from '@/modelTypes/IUserSettings'
|
||||||
email: string
|
|
||||||
username: string
|
|
||||||
name: string
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
settings: IUserSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class UserModel extends AbstractModel implements IUser {
|
export default class UserModel extends AbstractModel implements IUser {
|
||||||
id = 0
|
id = 0
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import UserShareBaseModel from './userShareBase'
|
import UserShareBaseModel from './userShareBase'
|
||||||
import type { IList } from './list'
|
|
||||||
|
|
||||||
export interface IUserList extends UserShareBaseModel {
|
import type {IUserList} from '@/modelTypes/IUserList'
|
||||||
listId: IList['id']
|
import type {IList} from '@/modelTypes/IList'
|
||||||
}
|
|
||||||
|
|
||||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||||
export default class UserListModel extends UserShareBaseModel implements IUserList {
|
export default class UserListModel extends UserShareBaseModel implements IUserList {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import UserShareBaseModel from './userShareBase'
|
import UserShareBaseModel from './userShareBase'
|
||||||
import type { INamespace } from './namespace'
|
|
||||||
|
|
||||||
export interface IUserNamespace extends UserShareBaseModel {
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
namespaceId: INamespace['id']
|
import type {IUserNamespace} from '@/modelTypes/IUserNamespace'
|
||||||
}
|
|
||||||
|
|
||||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||||
export default class UserNamespaceModel extends UserShareBaseModel implements IUserNamespace {
|
export default class UserNamespaceModel extends UserShareBaseModel implements IUserNamespace {
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
|
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
import type { IList } from './list'
|
|
||||||
|
|
||||||
export interface IUserSettings extends IAbstract {
|
import type {IUserSettings} from '@/modelTypes/IUserSettings'
|
||||||
name: string
|
import type {IList} from '@/modelTypes/IList'
|
||||||
emailRemindersEnabled: boolean
|
|
||||||
discoverableByName: boolean
|
|
||||||
discoverableByEmail: boolean
|
|
||||||
overdueTasksRemindersEnabled: boolean
|
|
||||||
defaultListId: undefined | IList['id']
|
|
||||||
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6
|
|
||||||
timezone: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class UserSettingsModel extends AbstractModel implements IUserSettings {
|
export default class UserSettingsModel extends AbstractModel implements IUserSettings {
|
||||||
name = ''
|
name = ''
|
||||||
|
@ -20,7 +11,7 @@ export default class UserSettingsModel extends AbstractModel implements IUserSet
|
||||||
discoverableByEmail = false
|
discoverableByEmail = false
|
||||||
overdueTasksRemindersEnabled = true
|
overdueTasksRemindersEnabled = true
|
||||||
defaultListId: undefined | IList['id'] = undefined
|
defaultListId: undefined | IList['id'] = undefined
|
||||||
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0
|
weekStart: IUserSettings['weekStart'] = 0
|
||||||
timezone = ''
|
timezone = ''
|
||||||
|
|
||||||
constructor(data: Partial<IUserSettings>) {
|
constructor(data: Partial<IUserSettings>) {
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
import AbstractModel, { type IAbstract } from './abstractModel'
|
import AbstractModel from './abstractModel'
|
||||||
|
|
||||||
import {RIGHTS, type Right} from '@/constants/rights'
|
import {RIGHTS, type Right} from '@/constants/rights'
|
||||||
import type { IUser } from './user'
|
import type {IUserShareBase} from '@/modelTypes/IUserShareBase'
|
||||||
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
export interface IUserShareBase extends IAbstract {
|
|
||||||
userId: IUser['id']
|
|
||||||
right: Right
|
|
||||||
|
|
||||||
created: Date
|
|
||||||
updated: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class UserShareBaseModel extends AbstractModel implements IUserShareBase {
|
export default class UserShareBaseModel extends AbstractModel implements IUserShareBase {
|
||||||
userId: IUser['id'] = ''
|
userId: IUser['id'] = ''
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {parseDate} from '../helpers/time/parseDate'
|
import {parseDate} from '../helpers/time/parseDate'
|
||||||
import {PRIORITIES} from '@/constants/priorities'
|
import {PRIORITIES} from '@/constants/priorities'
|
||||||
import {REPEAT_TYPES, type IRepeats, type RepeatType} from '@/types/IRepeats'
|
import {REPEAT_TYPES, type IRepeatAfter, type IRepeatType} from '@/types/IRepeatAfter'
|
||||||
|
|
||||||
const VIKUNJA_PREFIXES: Prefixes = {
|
const VIKUNJA_PREFIXES: Prefixes = {
|
||||||
label: '*',
|
label: '*',
|
||||||
|
@ -30,7 +30,7 @@ export const PREFIXES = {
|
||||||
|
|
||||||
interface repeatParsedResult {
|
interface repeatParsedResult {
|
||||||
textWithoutMatched: string,
|
textWithoutMatched: string,
|
||||||
repeats: IRepeats | null,
|
repeats: IRepeatAfter | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ParsedTaskText {
|
export interface ParsedTaskText {
|
||||||
|
@ -40,7 +40,7 @@ export interface ParsedTaskText {
|
||||||
list: string | null,
|
list: string | null,
|
||||||
priority: number | null,
|
priority: number | null,
|
||||||
assignees: string[],
|
assignees: string[],
|
||||||
repeats: IRepeats | null,
|
repeats: IRepeatAfter | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Prefixes {
|
interface Prefixes {
|
||||||
|
@ -185,7 +185,7 @@ const getRepeats = (text: string): repeatParsedResult => {
|
||||||
default:
|
default:
|
||||||
amount = results[3] ? parseInt(results[3]) : 1
|
amount = results[3] ? parseInt(results[3]) : 1
|
||||||
}
|
}
|
||||||
let type: RepeatType = REPEAT_TYPES.Hours
|
let type: IRepeatType = REPEAT_TYPES.Hours
|
||||||
|
|
||||||
switch (results[0]) {
|
switch (results[0]) {
|
||||||
case 'biennially':
|
case 'biennially':
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import type {InjectionKey} from 'vue'
|
import type {InjectionKey} from 'vue'
|
||||||
import {createStore, useStore as baseUseStore, Store} from 'vuex'
|
import {createStore, useStore as baseUseStore, Store} from 'vuex'
|
||||||
|
|
||||||
|
|
||||||
import {getBlobFromBlurHash} from '../helpers/getBlobFromBlurHash'
|
import {getBlobFromBlurHash} from '../helpers/getBlobFromBlurHash'
|
||||||
import {
|
import {
|
||||||
BACKGROUND,
|
BACKGROUND,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { Module } from 'vuex'
|
||||||
import {findIndexById} from '@/helpers/utils'
|
import {findIndexById} from '@/helpers/utils'
|
||||||
|
|
||||||
import type { AttachmentState, RootStoreState } from '@/store/types'
|
import type { AttachmentState, RootStoreState } from '@/store/types'
|
||||||
import type { IAttachment } from '@/models/attachment'
|
import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||||
|
|
||||||
const store : Module<AttachmentState, RootStoreState> = {
|
const store : Module<AttachmentState, RootStoreState> = {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {success} from '@/message'
|
||||||
import {redirectToProvider} from '@/helpers/redirectToProvider'
|
import {redirectToProvider} from '@/helpers/redirectToProvider'
|
||||||
import type { RootStoreState, AuthState, Info} from '@/store/types'
|
import type { RootStoreState, AuthState, Info} from '@/store/types'
|
||||||
import {AUTH_TYPES} from '@/store/types'
|
import {AUTH_TYPES} from '@/store/types'
|
||||||
import type { IUserSettings } from '@/models/userSettings'
|
import type { IUserSettings } from '@/modelTypes/IUserSettings'
|
||||||
|
|
||||||
|
|
||||||
const defaultSettings = settings => {
|
const defaultSettings = settings => {
|
||||||
|
|
|
@ -9,9 +9,9 @@ import BucketService from '../../services/bucket'
|
||||||
import {setLoading} from '../helper'
|
import {setLoading} from '../helper'
|
||||||
import TaskCollectionService from '@/services/taskCollection'
|
import TaskCollectionService from '@/services/taskCollection'
|
||||||
import type { RootStoreState, KanbanState } from '@/store/types'
|
import type { RootStoreState, KanbanState } from '@/store/types'
|
||||||
import type { ITask } from '@/models/task'
|
import type { ITask } from '@/modelTypes/ITask'
|
||||||
import type { IList } from '@/models/list'
|
import type { IList } from '@/modelTypes/IList'
|
||||||
import type { IBucket } from '@/models/bucket'
|
import type { IBucket } from '@/modelTypes/IBucket'
|
||||||
|
|
||||||
const TASKS_PER_BUCKET = 25
|
const TASKS_PER_BUCKET = 25
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {setLoading} from '@/store/helper'
|
||||||
import type { LabelState, RootStoreState } from '@/store/types'
|
import type { LabelState, RootStoreState } from '@/store/types'
|
||||||
import {getLabelsByIds, filterLabelsByQuery} from '@/helpers/labels'
|
import {getLabelsByIds, filterLabelsByQuery} from '@/helpers/labels'
|
||||||
import {createNewIndexer} from '@/indexes'
|
import {createNewIndexer} from '@/indexes'
|
||||||
import type { ILabel } from '@/models/label'
|
import type { ILabel } from '@/modelTypes/ILabel'
|
||||||
|
|
||||||
const {add, remove, update} = createNewIndexer('labels', ['title', 'description'])
|
const {add, remove, update} = createNewIndexer('labels', ['title', 'description'])
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {setLoading} from '@/store/helper'
|
||||||
import {removeListFromHistory} from '@/modules/listHistory'
|
import {removeListFromHistory} from '@/modules/listHistory'
|
||||||
import {createNewIndexer} from '@/indexes'
|
import {createNewIndexer} from '@/indexes'
|
||||||
import type {ListState, RootStoreState} from '@/store/types'
|
import type {ListState, RootStoreState} from '@/store/types'
|
||||||
import type {IList} from '@/models/list'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
|
||||||
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import NamespaceService from '../../services/namespace'
|
||||||
import {setLoading} from '@/store/helper'
|
import {setLoading} from '@/store/helper'
|
||||||
import {createNewIndexer} from '@/indexes'
|
import {createNewIndexer} from '@/indexes'
|
||||||
import type {NamespaceState, RootStoreState} from '@/store/types'
|
import type {NamespaceState, RootStoreState} from '@/store/types'
|
||||||
import type {INamespace} from '@/models/namespace'
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
import type {IList} from '@/models/list'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
|
||||||
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
|
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,27 @@ import {formatISO} from 'date-fns'
|
||||||
|
|
||||||
import TaskService from '@/services/task'
|
import TaskService from '@/services/task'
|
||||||
import TaskAssigneeService from '@/services/taskAssignee'
|
import TaskAssigneeService from '@/services/taskAssignee'
|
||||||
import TaskAssigneeModel from '@/models/taskAssignee'
|
|
||||||
import LabelTaskModel from '@/models/labelTask'
|
|
||||||
import LabelTaskService from '@/services/labelTask'
|
import LabelTaskService from '@/services/labelTask'
|
||||||
|
import UserService from '@/services/user'
|
||||||
|
|
||||||
import {HAS_TASKS} from '../mutation-types'
|
import {HAS_TASKS} from '../mutation-types'
|
||||||
import {setLoading} from '../helper'
|
import {setLoading} from '../helper'
|
||||||
import {getQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
import {getQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
||||||
|
|
||||||
import {parseTaskText} from '@/modules/parseTaskText'
|
import {parseTaskText} from '@/modules/parseTaskText'
|
||||||
import TaskModel, { type ITask } from '@/models/task'
|
|
||||||
|
import TaskAssigneeModel from '@/models/taskAssignee'
|
||||||
|
import LabelTaskModel from '@/models/labelTask'
|
||||||
|
import TaskModel from '@/models/task'
|
||||||
import LabelTask from '@/models/labelTask'
|
import LabelTask from '@/models/labelTask'
|
||||||
import LabelModel, { type ILabel } from '@/models/label'
|
import LabelModel from '@/models/label'
|
||||||
import UserService from '@/services/user'
|
|
||||||
|
import type {ILabel} from '@/modelTypes/ILabel'
|
||||||
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
import type { IUser } from '@/modelTypes/IUser'
|
||||||
|
import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||||
|
import type { IList } from '@/modelTypes/IList'
|
||||||
|
|
||||||
import type { RootStoreState, TaskState } from '@/store/types'
|
import type { RootStoreState, TaskState } from '@/store/types'
|
||||||
import type { IUser } from '@/models/user'
|
|
||||||
import type { IAttachment } from '@/models/attachment'
|
|
||||||
import type { IList } from '@/models/list'
|
|
||||||
|
|
||||||
// IDEA: maybe use a small fuzzy search here to prevent errors
|
// IDEA: maybe use a small fuzzy search here to prevent errors
|
||||||
function findPropertyByValue(object, key, value) {
|
function findPropertyByValue(object, key, value) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { IBucket } from '@/models/bucket'
|
import type { IBucket } from '@/modelTypes/IBucket'
|
||||||
import type { IUserSettings } from '@/models/userSettings'
|
import type { IUserSettings } from '@/modelTypes/IUserSettings'
|
||||||
import type { IList } from '@/models/list'
|
import type { IList } from '@/modelTypes/IList'
|
||||||
import type { IAttachment } from '@/models/attachment'
|
import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||||
import type { ILabel } from '@/models/label'
|
import type { ILabel } from '@/modelTypes/ILabel'
|
||||||
import type { INamespace } from '@/models/namespace'
|
import type { INamespace } from '@/modelTypes/INamespace'
|
||||||
|
|
||||||
export interface RootStoreState {
|
export interface RootStoreState {
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
|
|
9
src/types/IFilter.ts
Normal file
9
src/types/IFilter.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export interface IFilter {
|
||||||
|
sortBy: ('done' | 'id')[]
|
||||||
|
orderBy: ('asc' | 'desc')[]
|
||||||
|
filterBy: 'done'[]
|
||||||
|
filterValue: 'false'[]
|
||||||
|
filterComparator: 'equals'[]
|
||||||
|
filterConcat: 'and'
|
||||||
|
filterIncludeNulls: boolean
|
||||||
|
}
|
16
src/types/IRelationKind.ts
Normal file
16
src/types/IRelationKind.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export enum RELATION_KIND {
|
||||||
|
'SUBTASK' = 'subtask',
|
||||||
|
'PARENTTASK' = 'parenttask',
|
||||||
|
'RELATED' = 'related',
|
||||||
|
'DUPLICATES' = 'duplicates',
|
||||||
|
'BLOCKING' = 'blocking',
|
||||||
|
'BLOCKED' = 'blocked',
|
||||||
|
'PROCEDES' = 'precedes',
|
||||||
|
'FOLLOWS' = 'follows',
|
||||||
|
'COPIEDFROM' = 'copiedfrom',
|
||||||
|
'COPIEDTO' = 'copiedto',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IRelationKind = typeof RELATION_KIND[keyof typeof RELATION_KIND]
|
||||||
|
|
||||||
|
export const RELATION_KINDS = [...Object.values(RELATION_KIND)] as const
|
|
@ -6,9 +6,9 @@ export const REPEAT_TYPES = {
|
||||||
Years: 'years',
|
Years: 'years',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type RepeatType = typeof REPEAT_TYPES[keyof typeof REPEAT_TYPES]
|
export type IRepeatType = typeof REPEAT_TYPES[keyof typeof REPEAT_TYPES]
|
||||||
|
|
||||||
export interface IRepeats {
|
export interface IRepeatAfter {
|
||||||
type: RepeatType,
|
type: IRepeatType,
|
||||||
amount: number,
|
amount: number,
|
||||||
}
|
}
|
7
src/types/IRepeatMode.ts
Normal file
7
src/types/IRepeatMode.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export const TASK_REPEAT_MODES = {
|
||||||
|
'REPEAT_MODE_DEFAULT': 0,
|
||||||
|
'REPEAT_MODE_MONTH': 1,
|
||||||
|
'REPEAT_MODE_FROM_CURRENT_DATE': 2,
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type IRepeatMode = typeof TASK_REPEAT_MODES[keyof typeof TASK_REPEAT_MODES]
|
|
@ -156,7 +156,7 @@ import {calculateItemPosition} from '../../helpers/calculateItemPosition'
|
||||||
import type { ITask } from '@/models/task'
|
import type { ITask } from '@/models/task'
|
||||||
|
|
||||||
function sortTasks(tasks: ITask[]) {
|
function sortTasks(tasks: ITask[]) {
|
||||||
if (tasks === null || tasks === []) {
|
if (tasks === null || Array.isArray(tasks) && tasks.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return tasks.sort((a, b) => {
|
return tasks.sort((a, b) => {
|
||||||
|
|
|
@ -170,6 +170,7 @@ import {useStore} from '@/store'
|
||||||
import TeamService from '@/services/team'
|
import TeamService from '@/services/team'
|
||||||
import TeamMemberService from '@/services/teamMember'
|
import TeamMemberService from '@/services/teamMember'
|
||||||
import UserService from '@/services/user'
|
import UserService from '@/services/user'
|
||||||
|
|
||||||
import {RIGHTS as Rights} from '@/constants/rights'
|
import {RIGHTS as Rights} from '@/constants/rights'
|
||||||
|
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
|
|
Loading…
Reference in a new issue