1
0

feat(views): save task position

This commit is contained in:
kolaente 2024-03-16 11:36:37 +01:00
parent c36fdb9f5d
commit 786e67f692
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
6 changed files with 59 additions and 4 deletions

View File

@ -0,0 +1,8 @@
import type {IProjectView} from '@/modelTypes/IProjectView'
import type {IAbstract} from '@/modelTypes/IAbstract'
export interface ITaskPosition extends IAbstract {
position: number
projectViewId: IProjectView['id']
taskId: number
}

View File

@ -0,0 +1,13 @@
import AbstractModel from '@/models/abstractModel'
import type {ITaskPosition} from '@/modelTypes/ITaskPosition'
export default class TaskPositionModel extends AbstractModel<ITaskPosition> implements ITaskPosition {
position = 0
projectViewId = 0
taskId = 0
constructor(data: Partial<ITaskPosition>) {
super()
this.assignData(data)
}
}

View File

@ -0,0 +1,15 @@
import AbstractService from '@/services/abstractService'
import type {ITaskPosition} from '@/modelTypes/ITaskPosition'
import TaskPositionModel from '@/models/taskPosition'
export default class TaskPositionService extends AbstractService<ITaskPosition> {
constructor() {
super({
update: '/tasks/{taskId}/position',
})
}
modelFactory(data: Partial<ITaskPosition>) {
return new TaskPositionModel(data)
}
}

View File

@ -302,6 +302,8 @@ import {success} from '@/message'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import type {TaskFilterParams} from '@/services/taskCollection' import type {TaskFilterParams} from '@/services/taskCollection'
import type {IProjectView} from '@/modelTypes/IProjectView' import type {IProjectView} from '@/modelTypes/IProjectView'
import TaskPositionService from '@/services/taskPosition'
import TaskPositionModel from '@/models/taskPosition'
const { const {
projectId = undefined, projectId = undefined,
@ -328,6 +330,7 @@ const baseStore = useBaseStore()
const kanbanStore = useKanbanStore() const kanbanStore = useKanbanStore()
const taskStore = useTaskStore() const taskStore = useTaskStore()
const projectStore = useProjectStore() const projectStore = useProjectStore()
const taskPositionService = ref(new TaskPositionService())
const taskContainerRefs = ref<{ [id: IBucket['id']]: HTMLElement }>({}) const taskContainerRefs = ref<{ [id: IBucket['id']]: HTMLElement }>({})
const bucketLimitInputRef = ref<HTMLInputElement | null>(null) const bucketLimitInputRef = ref<HTMLInputElement | null>(null)
@ -390,7 +393,7 @@ const project = computed(() => projectId ? projectStore.projects[projectId] : nu
const buckets = computed(() => kanbanStore.buckets) const buckets = computed(() => kanbanStore.buckets)
const loading = computed(() => kanbanStore.isLoading) const loading = computed(() => kanbanStore.isLoading)
const taskLoading = computed(() => taskStore.isLoading) const taskLoading = computed(() => taskStore.isLoading || taskPositionService.value.loading)
watch( watch(
() => ({ () => ({
@ -478,7 +481,7 @@ async function updateTaskPosition(e) {
const newTask = klona(task) // cloning the task to avoid pinia store manipulation const newTask = klona(task) // cloning the task to avoid pinia store manipulation
newTask.bucketId = newBucket.id newTask.bucketId = newBucket.id
newTask.kanbanPosition = calculateItemPosition( const position = calculateItemPosition(
taskBefore !== null ? taskBefore.kanbanPosition : null, taskBefore !== null ? taskBefore.kanbanPosition : null,
taskAfter !== null ? taskAfter.kanbanPosition : null, taskAfter !== null ? taskAfter.kanbanPosition : null,
) )
@ -488,6 +491,8 @@ async function updateTaskPosition(e) {
) { ) {
newTask.done = project.value?.doneBucketId === newBucket.id newTask.done = project.value?.doneBucketId === newBucket.id
} }
let bucketHasChanged = false
if ( if (
oldBucket !== undefined && // This shouldn't actually be `undefined`, but let's play it safe. oldBucket !== undefined && // This shouldn't actually be `undefined`, but let's play it safe.
newBucket.id !== oldBucket.id newBucket.id !== oldBucket.id
@ -500,10 +505,20 @@ async function updateTaskPosition(e) {
...newBucket, ...newBucket,
count: newBucket.count + 1, count: newBucket.count + 1,
}) })
bucketHasChanged = true
} }
try { try {
await taskStore.update(newTask) const newPosition = new TaskPositionModel({
position,
projectViewId: view.id,
taskId: newTask.id,
})
await taskPositionService.value.update(newPosition)
if(bucketHasChanged) {
await taskStore.update(newTask)
}
// Make sure the first and second task don't both get position 0 assigned // Make sure the first and second task don't both get position 0 assigned
if (newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) { if (newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) {

View File

@ -306,6 +306,7 @@ func GetProjectViewByIDAndProject(s *xorm.Session, id, projectID int64) (view *P
} }
func GetProjectViewByID(s *xorm.Session, id int64) (view *ProjectView, err error) { func GetProjectViewByID(s *xorm.Session, id int64) (view *ProjectView, err error) {
view = &ProjectView{}
exists, err := s. exists, err := s.
Where("id = ?", id). Where("id = ?", id).
NoAutoCondition(). NoAutoCondition().

View File

@ -46,7 +46,10 @@ func (tp *TaskPosition) TableName() string {
} }
func (tp *TaskPosition) CanUpdate(s *xorm.Session, a web.Auth) (bool, error) { func (tp *TaskPosition) CanUpdate(s *xorm.Session, a web.Auth) (bool, error) {
pv := &ProjectView{ID: tp.ProjectViewID} pv, err := GetProjectViewByID(s, tp.ProjectViewID)
if err != nil {
return false, err
}
return pv.CanUpdate(s, a) return pv.CanUpdate(s, a)
} }