feat: always use index for buckets

This commit is contained in:
Dominik Pschenitschni 2021-09-07 15:42:41 +02:00
parent 672d63fbed
commit 8d88b3792d
No known key found for this signature in database
GPG key ID: B257AC0149F43A77
4 changed files with 94 additions and 54 deletions

View file

@ -1,10 +0,0 @@
export const filterObject = (obj, fn) => {
let key
for (key in obj) {
if (fn(obj[key])) {
return key
}
}
return null
}

View file

@ -1,3 +1,7 @@
export function findIndexById(array : [], id : string | number) { export function findIndexById(array : [], id : string | number) {
return array.findIndex(({id: currentId}) => currentId === id) return array.findIndex(({id: currentId}) => currentId === id)
} }
export function findById(array : [], id : string | number) {
return array.find(({id: currentId}) => currentId === id)
}

View file

@ -1,16 +1,36 @@
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import {findById, findIndexById} from '@/helpers/find'
import BucketService from '../../services/bucket' import BucketService from '../../services/bucket'
import {filterObject} from '@/helpers/filterObject'
import {setLoading} from '../helper' import {setLoading} from '../helper'
import TaskCollectionService from '@/services/taskCollection' import TaskCollectionService from '@/services/taskCollection'
const TASKS_PER_BUCKET = 25 const TASKS_PER_BUCKET = 25
function getTaskPosition(state, task) {
const bucketIndex = findIndexById(state.buckets, task.bucketId)
if (!bucketIndex) {
throw('Bucket not found')
}
const bucket = state.buckets[bucketIndex]
const taskIndex = findIndexById(bucket.tasks, task.id)
if (!bucketIndex) {
throw('Task not found')
}
return {
bucketIndex,
taskIndex,
}
}
const addTaskToBucketAndSort = (state, task) => { const addTaskToBucketAndSort = (state, task) => {
const bi = filterObject(state.buckets, b => b.id === task.bucketId) const bucketIndex = findIndexById(state.buckets, task.bucketId)
state.buckets[bi].tasks.push(task) state.buckets[bucketIndex].tasks.push(task)
state.buckets[bi].tasks.sort((a, b) => a.kanbanPosition > b.kanbanPosition ? 1 : -1) state.buckets[bucketIndex].tasks.sort((a, b) => a.kanbanPosition > b.kanbanPosition ? 1 : -1)
} }
/** /**
@ -19,6 +39,7 @@ const addTaskToBucketAndSort = (state, task) => {
*/ */
export default { export default {
namespaced: true, namespaced: true,
state: () => ({ state: () => ({
buckets: [], buckets: [],
listId: 0, listId: 0,
@ -26,10 +47,12 @@ export default {
taskPagesPerBucket: {}, taskPagesPerBucket: {},
allTasksLoadedForBucket: {}, allTasksLoadedForBucket: {},
}), }),
mutations: { mutations: {
setListId(state, listId) { setListId(state, listId) {
state.listId = parseInt(listId) state.listId = parseInt(listId)
}, },
setBuckets(state, buckets) { setBuckets(state, buckets) {
state.buckets = buckets state.buckets = buckets
buckets.forEach(b => { buckets.forEach(b => {
@ -37,32 +60,39 @@ export default {
state.allTasksLoadedForBucket[b.id] = false state.allTasksLoadedForBucket[b.id] = false
}) })
}, },
addBucket(state, bucket) { addBucket(state, bucket) {
state.buckets.push(bucket) state.buckets.push(bucket)
}, },
removeBucket(state, bucket) { removeBucket(state, bucket) {
for (const b in state.buckets) { const bucketIndex = findIndexById(state.buckets, bucket.id)
if (state.buckets[b].id === bucket.id) { state.buckets.splice(bucketIndex, 1)
state.buckets.splice(b, 1)
}
}
}, },
setBucketById(state, bucket) { setBucketById(state, bucket) {
for (const b in state.buckets) { const bucketIndex = findIndexById(state.buckets, bucket.id)
if (state.buckets[b].id === bucket.id) { state.buckets[bucketIndex] = bucket
state.buckets[b] = bucket
return
}
}
}, },
setBucketByIndex(state, {bucketIndex, bucket}) { setBucketByIndex(state, {bucketIndex, bucket}) {
state.buckets[bucketIndex] = bucket state.buckets[bucketIndex] = bucket
}, },
setTaskInBucketByIndex(state, {bucketIndex, taskIndex, task}) { setTaskInBucketByIndex(state, {bucketIndex, taskIndex, task}) {
const bucket = state.buckets[bucketIndex] const bucket = state.buckets[bucketIndex]
bucket.tasks[taskIndex] = task bucket.tasks[taskIndex] = task
state.buckets[bucketIndex] = bucket state.buckets[bucketIndex] = bucket
}, },
setTasksInBucketByBucketId(state, {bucketId, tasks}) {
const bucketIndex = findIndexById(state.buckets, bucketId)
state.buckets[bucketIndex] = {
...state.buckets[bucketIndex],
tasks,
}
},
setTaskInBucket(state, task) { setTaskInBucket(state, task) {
// If this gets invoked without any tasks actually loaded, we can save the hassle of finding the task // If this gets invoked without any tasks actually loaded, we can save the hassle of finding the task
if (state.buckets.length === 0) { if (state.buckets.length === 0) {
@ -106,49 +136,61 @@ export default {
} }
} }
}, },
addTaskToBucket(state, task) {
const bi = filterObject(state.buckets, b => b.id === task.bucketId)
state.buckets[bi].tasks.push(task)
},
addTasksToBucket(state, {tasks, bucketId}) {
const bi = filterObject(state.buckets, b => b.id === bucketId)
tasks.forEach(t => { addTaskToBucket(state, task) {
state.buckets[bi].tasks.push(t) const bucketIndex = findIndexById(state.buckets, task.bucketId)
}) const oldBucket = state.buckets[bucketIndex]
const newBucket = {
...oldBucket,
tasks: [
...oldBucket.tasks,
task,
],
}
state.buckets[bucketIndex] = newBucket
}, },
addTasksToBucket(state, {tasks, bucketId}) {
const bucketIndex = findIndexById(state.buckets, bucketId)
const oldBucket = state.buckets[bucketIndex]
const newBucket = {
...oldBucket,
tasks: [
...oldBucket.tasks,
tasks,
],
}
state.buckets[bucketIndex] = newBucket
},
removeTaskInBucket(state, task) { removeTaskInBucket(state, task) {
// If this gets invoked without any tasks actually loaded, we can save the hassle of finding the task // If this gets invoked without any tasks actually loaded, we can save the hassle of finding the task
if (state.buckets.length === 0) { if (state.buckets.length === 0) {
return return
} }
for (const b in state.buckets) { const { bucketIndex, taskIndex } = getTaskPosition(state, task)
if (state.buckets[b].id === task.bucketId) {
for (const t in state.buckets[b].tasks) { state.buckets[bucketIndex].tasks.splice(taskIndex, 1)
if (state.buckets[b].tasks[t].id === task.id) {
const bucket = state.buckets[b]
bucket.tasks.splice(t, 1)
state.buckets[b] = bucket
return
}
}
return
}
}
}, },
setBucketLoading(state, {bucketId, loading}) { setBucketLoading(state, {bucketId, loading}) {
state.bucketLoading[bucketId] = loading state.bucketLoading[bucketId] = loading
}, },
setTasksLoadedForBucketPage(state, {bucketId, page}) { setTasksLoadedForBucketPage(state, {bucketId, page}) {
state.taskPagesPerBucket[bucketId] = page state.taskPagesPerBucket[bucketId] = page
}, },
setAllTasksLoadedForBucket(state, bucketId) { setAllTasksLoadedForBucket(state, bucketId) {
state.allTasksLoadedForBucket[bucketId] = true state.allTasksLoadedForBucket[bucketId] = true
}, },
}, },
getters: { getters: {
getBucketById(state) {
return (bucketId) => findById(state.buckets, bucketId)
},
getTaskById: state => id => { getTaskById: state => id => {
for (const b in state.buckets) { for (const b in state.buckets) {
for (const t in state.buckets[b].tasks) { for (const t in state.buckets[b].tasks) {
@ -168,6 +210,7 @@ export default {
} }
}, },
}, },
actions: { actions: {
loadBucketsForList(ctx, {listId, params}) { loadBucketsForList(ctx, {listId, params}) {
const cancel = setLoading(ctx, 'kanban') const cancel = setLoading(ctx, 'kanban')
@ -191,15 +234,18 @@ export default {
cancel() cancel()
}) })
}, },
loadNextTasksForBucket(ctx, {listId, ps = {}, bucketId}) { loadNextTasksForBucket(ctx, {listId, ps = {}, bucketId}) {
const isLoading = ctx.state.bucketLoading[bucketId] ?? false const bucketIndex = findIndexById(ctx.state.buckets, bucketId)
const isLoading = ctx.state.bucketLoading[bucketIndex] ?? false
if (isLoading) { if (isLoading) {
return Promise.resolve() return Promise.resolve()
} }
const page = (ctx.state.taskPagesPerBucket[bucketId] ?? 1) + 1 const page = (ctx.state.taskPagesPerBucket[bucketIndex] ?? 1) + 1
const alreadyLoaded = ctx.state.allTasksLoadedForBucket[bucketId] ?? false const alreadyLoaded = ctx.state.allTasksLoadedForBucket[bucketIndex] ?? false
if (alreadyLoaded) { if (alreadyLoaded) {
return Promise.resolve() return Promise.resolve()
} }
@ -289,7 +335,7 @@ export default {
const bucketService = new BucketService() const bucketService = new BucketService()
return bucketService.update(bucket) return bucketService.update(bucket)
.then(r => { .then(r => {
const bi = filterObject(ctx.state.buckets, b => b.id === r.id) const bi = findById(ctx.state.buckets, r.id)
const bucket = r const bucket = r
bucket.tasks = ctx.state.buckets[bi].tasks bucket.tasks = ctx.state.buckets[bi].tasks
ctx.commit('setBucketByIndex', {bucketIndex: bi, bucket}) ctx.commit('setBucketByIndex', {bucketIndex: bi, bucket})

View file

@ -235,7 +235,7 @@
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import BucketModel from '../../../models/bucket' import BucketModel from '../../../models/bucket'
import {filterObject} from '@/helpers/filterObject' import {findById} from '@/helpers/find'
import {mapState} from 'vuex' import {mapState} from 'vuex'
import {saveListView} from '@/helpers/saveListView' import {saveListView} from '@/helpers/saveListView'
import Rights from '../../../models/constants/rights.json' import Rights from '../../../models/constants/rights.json'
@ -503,7 +503,7 @@ export default {
// Because the contenteditable does not have a change event, // Because the contenteditable does not have a change event,
// we're building it ourselves here and only updating the bucket // we're building it ourselves here and only updating the bucket
// if the title changed. // if the title changed.
const realBucket = this.buckets[filterObject(this.buckets, b => b.id === bucketId)] const realBucket = findById(this.buckets, bucketId)
if (realBucket.title === bucketTitle) { if (realBucket.title === bucketTitle) {
return return
} }