Pagingation for tasks in kanban buckets (#419)
Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/419 Co-authored-by: konrad <konrad@kola-entertainments.de> Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
parent
1f33477f57
commit
f7d8095b5a
3 changed files with 110 additions and 8 deletions
|
@ -22,8 +22,6 @@ export default {
|
|||
text: err,
|
||||
actions: actions,
|
||||
})
|
||||
|
||||
context.loading = false
|
||||
},
|
||||
success(e, context, actions = []) {
|
||||
// Build the notification text from error response
|
||||
|
@ -41,7 +39,5 @@ export default {
|
|||
actions: actions,
|
||||
},
|
||||
})
|
||||
|
||||
context.loading = false
|
||||
},
|
||||
}
|
|
@ -1,8 +1,12 @@
|
|||
import Vue from 'vue'
|
||||
import {cloneDeep} from 'lodash'
|
||||
|
||||
import BucketService from '../../services/bucket'
|
||||
import {filterObject} from '@/helpers/filterObject'
|
||||
import {setLoading} from '../helper'
|
||||
import TaskCollectionService from '@/services/taskCollection'
|
||||
|
||||
const tasksPerBucket = 25
|
||||
|
||||
/**
|
||||
* This store is intended to hold the currently active kanban view.
|
||||
|
@ -13,6 +17,9 @@ export default {
|
|||
state: () => ({
|
||||
buckets: [],
|
||||
listId: 0,
|
||||
bucketLoading: {},
|
||||
taskPagesPerBucket: {},
|
||||
allTasksLoadedForBucket: {},
|
||||
}),
|
||||
mutations: {
|
||||
setListId(state, listId) {
|
||||
|
@ -20,6 +27,10 @@ export default {
|
|||
},
|
||||
setBuckets(state, buckets) {
|
||||
state.buckets = buckets
|
||||
buckets.forEach(b => {
|
||||
Vue.set(state.taskPagesPerBucket, b.id, 1)
|
||||
Vue.set(state.allTasksLoadedForBucket, b.id, false)
|
||||
})
|
||||
},
|
||||
addBucket(state, bucket) {
|
||||
state.buckets.push(bucket)
|
||||
|
@ -71,6 +82,13 @@ export default {
|
|||
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 => {
|
||||
state.buckets[bi].tasks.push(t)
|
||||
})
|
||||
},
|
||||
removeTaskInBucket(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) {
|
||||
|
@ -91,6 +109,15 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
setBucketLoading(state, {bucketId, loading}) {
|
||||
Vue.set(state.bucketLoading, bucketId, loading)
|
||||
},
|
||||
setTasksLoadedForBucketPage(state, {bucketId, page}) {
|
||||
Vue.set(state.taskPagesPerBucket, bucketId, page)
|
||||
},
|
||||
setAllTasksLoadedForBucket(state, bucketId) {
|
||||
Vue.set(state.allTasksLoadedForBucket, bucketId, true)
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getTaskById: state => id => {
|
||||
|
@ -119,6 +146,8 @@ export default {
|
|||
// Clear everything to prevent having old buckets in the list if loading the buckets from this list takes a few moments
|
||||
ctx.commit('setBuckets', [])
|
||||
|
||||
params.per_page = tasksPerBucket
|
||||
|
||||
const bucketService = new BucketService()
|
||||
return bucketService.getAll({listId: listId}, params)
|
||||
.then(r => {
|
||||
|
@ -133,6 +162,64 @@ export default {
|
|||
cancel()
|
||||
})
|
||||
},
|
||||
loadNextTasksForBucket(ctx, {listId, ps = {}, bucketId}) {
|
||||
const isLoading = ctx.state.bucketLoading[bucketId] ?? false
|
||||
if (isLoading) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const page = (ctx.state.taskPagesPerBucket[bucketId] ?? 1) + 1
|
||||
|
||||
const alreadyLoaded = ctx.state.allTasksLoadedForBucket[bucketId] ?? false
|
||||
if (alreadyLoaded) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const cancel = setLoading(ctx, 'kanban')
|
||||
ctx.commit('setBucketLoading', {bucketId: bucketId, loading: true})
|
||||
|
||||
const params = cloneDeep(ps)
|
||||
|
||||
params.sort_by = 'position'
|
||||
params.order_by = 'asc'
|
||||
|
||||
let hasBucketFilter = false
|
||||
for (const f in params.filter_by) {
|
||||
if (params.filter_by[f] === 'bucket_id') {
|
||||
hasBucketFilter = true
|
||||
if (params.filter_value[f] !== bucketId) {
|
||||
params.filter_value[f] = bucketId
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasBucketFilter) {
|
||||
params.filter_by = [...(params.filter_by ?? []), 'bucket_id']
|
||||
params.filter_value = [...(params.filter_value ?? []), bucketId]
|
||||
params.filter_comparator = [...(params.filter_comparator ?? []), 'equals']
|
||||
}
|
||||
|
||||
params.per_page = tasksPerBucket
|
||||
|
||||
const taskService = new TaskCollectionService()
|
||||
return taskService.getAll({listId: listId}, params, page)
|
||||
.then(r => {
|
||||
ctx.commit('addTasksToBucket', {tasks: r, bucketId: bucketId})
|
||||
ctx.commit('setTasksLoadedForBucketPage', {bucketId, page})
|
||||
if (taskService.totalPages <= page) {
|
||||
ctx.commit('setAllTasksLoadedForBucket', bucketId)
|
||||
}
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
return Promise.reject(e)
|
||||
})
|
||||
.finally(() => {
|
||||
cancel()
|
||||
ctx.commit('setBucketLoading', {bucketId: bucketId, loading: false})
|
||||
})
|
||||
},
|
||||
createBucket(ctx, bucket) {
|
||||
const cancel = setLoading(ctx, 'kanban')
|
||||
|
||||
|
@ -149,7 +236,7 @@ export default {
|
|||
cancel()
|
||||
})
|
||||
},
|
||||
deleteBucket(ctx, bucket) {
|
||||
deleteBucket(ctx, {bucket, params}) {
|
||||
const cancel = setLoading(ctx, 'kanban')
|
||||
|
||||
const bucketService = new BucketService()
|
||||
|
@ -157,7 +244,7 @@ export default {
|
|||
.then(r => {
|
||||
ctx.commit('removeBucket', bucket)
|
||||
// We reload all buckets because tasks are being moved from the deleted bucket
|
||||
ctx.dispatch('loadBucketsForList', {listId: bucket.listId})
|
||||
ctx.dispatch('loadBucketsForList', {listId: bucket.listId, params: params})
|
||||
return Promise.resolve(r)
|
||||
})
|
||||
.catch(e => {
|
||||
|
|
|
@ -352,7 +352,26 @@ export default {
|
|||
console.debug(`Loading buckets, loadedListId = ${this.loadedListId}, $route.params =`, this.$route.params)
|
||||
this.filtersChanged = false
|
||||
|
||||
const minScrollHeightPercent = 0.25
|
||||
|
||||
this.$store.dispatch('kanban/loadBucketsForList', {listId: this.$route.params.listId, params: this.params})
|
||||
.then(bs => {
|
||||
bs.forEach(b => {
|
||||
const e = this.$refs[`tasks-container${b.id}`][0]
|
||||
e.onscroll = () => {
|
||||
if (e.scrollTopMax <= e.scrollTop + e.scrollTop * minScrollHeightPercent) {
|
||||
this.$store.dispatch('kanban/loadNextTasksForBucket', {
|
||||
listId: this.$route.params.listId,
|
||||
params: this.params,
|
||||
bucketId: b.id,
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
})
|
||||
|
@ -423,7 +442,7 @@ export default {
|
|||
task.done = !task.done
|
||||
this.$store.dispatch('tasks/update', task)
|
||||
.then(() => {
|
||||
if(task.done) {
|
||||
if (task.done) {
|
||||
playPop()
|
||||
}
|
||||
})
|
||||
|
@ -518,7 +537,7 @@ export default {
|
|||
listId: this.$route.params.listId,
|
||||
})
|
||||
|
||||
this.$store.dispatch('kanban/deleteBucket', bucket)
|
||||
this.$store.dispatch('kanban/deleteBucket', {bucket: bucket, params: this.params})
|
||||
.then(() => {
|
||||
this.success({message: 'The bucket has been deleted successfully.'}, this)
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue