1
0

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:
konrad
2020-05-09 17:00:54 +00:00
parent 2270272a8f
commit 4e42810522
8 changed files with 304 additions and 42 deletions

141
src/store/modules/kanban.js Normal file
View 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
View 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)
})
},
},
}