Update tasks in kanban board after editing them in task detail view (#130)
Fix due date disappearing after moving it Fix removing labels not being updated in store Fix adding labels not being updated in store Fix removing assignees not being updated in store Fix adding assignees not being updated in store Fix due date not resetting Fix task attachments not updating in store after being modified in popup view Fix due date not updating in store after being modified in popup view Fix using filters for overview views Fix not re-loading tasks when switching between overviews Only show undone tasks on task overview page Update task in bucket when updating in task detail view Put all bucket related stuff in store Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/130
This commit is contained in:
141
src/store/modules/kanban.js
Normal file
141
src/store/modules/kanban.js
Normal file
@ -0,0 +1,141 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
import BucketService from '../../services/bucket'
|
||||
import {filterObject} from '../../helpers/filterObject'
|
||||
|
||||
/**
|
||||
* This store is intended to hold the currently active kanban view.
|
||||
* It should hold only the current buckets.
|
||||
*/
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: () => ({
|
||||
buckets: [],
|
||||
}),
|
||||
mutations: {
|
||||
setBuckets(state, buckets) {
|
||||
state.buckets = buckets
|
||||
},
|
||||
addBucket(state, bucket) {
|
||||
state.buckets.push(bucket)
|
||||
},
|
||||
removeBucket(state, bucket) {
|
||||
for (const b in state.buckets) {
|
||||
if (state.buckets[b].id === bucket.id) {
|
||||
state.buckets.splice(b, 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
setBucketById(state, bucket) {
|
||||
for (const b in state.buckets) {
|
||||
if (state.buckets[b].id === bucket.id) {
|
||||
Vue.set(state.buckets, b, bucket)
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
setBucketByIndex(state, {bucketIndex, bucket}) {
|
||||
Vue.set(state.buckets, bucketIndex, bucket)
|
||||
},
|
||||
setTaskInBucketByIndex(state, {bucketIndex, taskIndex, task}) {
|
||||
const bucket = state.buckets[bucketIndex]
|
||||
bucket.tasks[taskIndex] = task
|
||||
Vue.set(state.buckets, bucketIndex, bucket)
|
||||
},
|
||||
setTaskInBucket(state, task) {
|
||||
// If this gets invoked without any tasks actually loaded, we can save the hassle of finding the task
|
||||
if (state.buckets.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const b in state.buckets) {
|
||||
if (state.buckets[b].id === task.bucketId) {
|
||||
for (const t in state.buckets[b].tasks) {
|
||||
if (state.buckets[b].tasks[t].id === task.id) {
|
||||
const bucket = state.buckets[b]
|
||||
bucket.tasks[t] = task
|
||||
Vue.set(state.buckets, b, bucket)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
addTaskToBucket(state, task) {
|
||||
const bi = filterObject(state.buckets, b => b.id === task.bucketId)
|
||||
state.buckets[bi].tasks.push(task)
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getTaskById: state => id => {
|
||||
for (const b in state.buckets) {
|
||||
for (const t in state.buckets[b].tasks) {
|
||||
if (state.buckets[b].tasks[t].id === id) {
|
||||
return {
|
||||
bucketIndex: b,
|
||||
taskIndex: t,
|
||||
task: state.buckets[b].tasks[t],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
bucketIndex: null,
|
||||
taskIndex: null,
|
||||
task: null,
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
loadBucketsForList(ctx, listId) {
|
||||
const bucketService = new BucketService()
|
||||
return bucketService.getAll({listId: listId})
|
||||
.then(r => {
|
||||
ctx.commit('setBuckets', r)
|
||||
return Promise.resolve()
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
createBucket(ctx, bucket) {
|
||||
const bucketService = new BucketService()
|
||||
return bucketService.create(bucket)
|
||||
.then(r => {
|
||||
ctx.commit('addBucket', r)
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
deleteBucket(ctx, bucket) {
|
||||
const bucketService = new BucketService()
|
||||
return bucketService.delete(bucket)
|
||||
.then(r => {
|
||||
ctx.commit('removeBucket', bucket)
|
||||
// We reload all buckets because tasks are being moved from the deleted bucket
|
||||
ctx.dispatch('loadBucketsForList', bucket.listId)
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
updateBucket(ctx, bucket) {
|
||||
const bucketService = new BucketService()
|
||||
return bucketService.update(bucket)
|
||||
.then(r => {
|
||||
const bi = filterObject(ctx.state.buckets, b => b.id === r.id)
|
||||
const bucket = r
|
||||
bucket.tasks = ctx.state.buckets[bi].tasks
|
||||
ctx.commit('setBucketByIndex', {bucketIndex: bi, bucket})
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
127
src/store/modules/tasks.js
Normal file
127
src/store/modules/tasks.js
Normal file
@ -0,0 +1,127 @@
|
||||
import TaskService from '../../services/task'
|
||||
import TaskAssigneeService from '../../services/taskAssignee'
|
||||
import TaskAssigneeModel from '../../models/taskAssignee'
|
||||
import LabelTaskModel from '../../models/labelTask'
|
||||
import LabelTaskService from '../../services/labelTask'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: () => ({}),
|
||||
actions: {
|
||||
update(ctx, task) {
|
||||
const taskService = new TaskService()
|
||||
return taskService.update(task)
|
||||
.then(t => {
|
||||
ctx.commit('kanban/setTaskInBucket', t, {root: true})
|
||||
return Promise.resolve(t)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
// Adds a task attachment in store.
|
||||
// This is an action to be able to commit other mutations
|
||||
addTaskAttachment(ctx, {taskId, attachment}) {
|
||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
||||
if (t.task === null) {
|
||||
return
|
||||
}
|
||||
t.task.attachments.push(attachment)
|
||||
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
|
||||
},
|
||||
addAssignee(ctx, {user, taskId}) {
|
||||
|
||||
const taskAssignee = new TaskAssigneeModel({userId: user.id, taskId: taskId})
|
||||
const taskAssigneeService = new TaskAssigneeService()
|
||||
|
||||
return taskAssigneeService.create(taskAssignee)
|
||||
.then(r => {
|
||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
||||
if (t.task === null) {
|
||||
return Promise.reject('Task not found.')
|
||||
}
|
||||
t.task.assignees.push(user)
|
||||
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
removeAssignee(ctx, {user, taskId}) {
|
||||
|
||||
const taskAssignee = new TaskAssigneeModel({userId: user.id, taskId: taskId})
|
||||
const taskAssigneeService = new TaskAssigneeService()
|
||||
|
||||
return taskAssigneeService.delete(taskAssignee)
|
||||
.then(r => {
|
||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
||||
if (t.task === null) {
|
||||
return Promise.reject('Task not found.')
|
||||
}
|
||||
|
||||
for (const a in t.task.assignees) {
|
||||
if (t.task.assignees[a].id === user.id) {
|
||||
t.task.assignees.splice(a, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
|
||||
},
|
||||
addLabel(ctx, {label, taskId}) {
|
||||
|
||||
const labelTaskService = new LabelTaskService()
|
||||
const labelTask = new LabelTaskModel({taskId: taskId, labelId: label.id})
|
||||
|
||||
return labelTaskService.create(labelTask)
|
||||
.then(r => {
|
||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
||||
if (t.task === null) {
|
||||
return Promise.reject('Task not found.')
|
||||
}
|
||||
t.task.labels.push(label)
|
||||
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
|
||||
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
removeLabel(ctx, {label, taskId}) {
|
||||
|
||||
const labelTaskService = new LabelTaskService()
|
||||
const labelTask = new LabelTaskModel({taskId: taskId, labelId: label.id})
|
||||
|
||||
return labelTaskService.delete(labelTask)
|
||||
.then(r => {
|
||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
||||
if (t.task === null) {
|
||||
return Promise.reject('Task not found.')
|
||||
}
|
||||
|
||||
// Remove the label from the list
|
||||
for (const l in t.task.labels) {
|
||||
if (t.task.labels[l].id === label.id) {
|
||||
t.task.labels.splice(l, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
|
||||
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
Reference in New Issue
Block a user