feat: fix some Kanban errors with vue3
This commit is contained in:
parent
6b358107b6
commit
7bb1b1b769
1 changed files with 52 additions and 48 deletions
|
@ -26,7 +26,6 @@
|
||||||
@end="updateBucketPosition"
|
@end="updateBucketPosition"
|
||||||
group="buckets"
|
group="buckets"
|
||||||
:disabled="!canWrite"
|
:disabled="!canWrite"
|
||||||
:class="{'dragging-disabled': !canWrite}"
|
|
||||||
tag="transition-group"
|
tag="transition-group"
|
||||||
:item-key="({id}) => `bucket${id}`"
|
:item-key="({id}) => `bucket${id}`"
|
||||||
:component-data="bucketDraggableComponentData"
|
:component-data="bucketDraggableComponentData"
|
||||||
|
@ -45,9 +44,9 @@
|
||||||
<icon icon="check-double"/>
|
<icon icon="check-double"/>
|
||||||
</span>
|
</span>
|
||||||
<h2
|
<h2
|
||||||
:ref="`bucket${bucket.id}title`"
|
@keydown.enter.prevent.stop="$event.target.blur()"
|
||||||
@focusout="() => saveBucketTitle(bucket.id)"
|
@keydown.esc.prevent.stop="$event.target.blur()"
|
||||||
@keydown.enter.prevent.stop="() => saveBucketTitle(bucket.id)"
|
@blur="saveBucketTitle(bucket.id, $event.target.textContent)"
|
||||||
@click="focusBucketTitle"
|
@click="focusBucketTitle"
|
||||||
class="title input"
|
class="title input"
|
||||||
:contenteditable="bucketTitleEditable && canWrite && !collapsedBuckets[bucket.id]"
|
:contenteditable="bucketTitleEditable && canWrite && !collapsedBuckets[bucket.id]"
|
||||||
|
@ -124,7 +123,11 @@
|
||||||
</a>
|
</a>
|
||||||
</dropdown>
|
</dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div :ref="`tasks-container${bucket.id}`" class="tasks">
|
<div
|
||||||
|
:ref="(el) => setTaskContainerRef(bucket.id, el)"
|
||||||
|
@scroll="(el) => handleTaskContainerScroll(bucket.id, el)"
|
||||||
|
class="tasks"
|
||||||
|
>
|
||||||
<draggable
|
<draggable
|
||||||
v-bind="dragOptions"
|
v-bind="dragOptions"
|
||||||
v-model="bucket.tasks"
|
v-model="bucket.tasks"
|
||||||
|
@ -132,9 +135,7 @@
|
||||||
@end="updateTaskPosition"
|
@end="updateTaskPosition"
|
||||||
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
||||||
:disabled="!canWrite"
|
:disabled="!canWrite"
|
||||||
:class="{'dragging-disabled': !canWrite}"
|
|
||||||
:data-bucket-index="bucketIndex"
|
:data-bucket-index="bucketIndex"
|
||||||
class="dropper"
|
|
||||||
tag="transition-group"
|
tag="transition-group"
|
||||||
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
||||||
:component-data="taskDraggableTaskComponentData"
|
:component-data="taskDraggableTaskComponentData"
|
||||||
|
@ -184,9 +185,9 @@
|
||||||
<input
|
<input
|
||||||
:class="{'is-loading': loading}"
|
:class="{'is-loading': loading}"
|
||||||
:disabled="loading || null"
|
:disabled="loading || null"
|
||||||
@focusout="() => showNewBucketInput = false"
|
@blur="() => showNewBucketInput = false"
|
||||||
@keyup.enter="createNewBucket"
|
@keyup.enter="createNewBucket"
|
||||||
@keyup.esc="() => showNewBucketInput = false"
|
@keyup.esc="$event.target.blur()"
|
||||||
class="input"
|
class="input"
|
||||||
:placeholder="$t('list.kanban.addBucketPlaceholder')"
|
:placeholder="$t('list.kanban.addBucketPlaceholder')"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -198,7 +199,7 @@
|
||||||
@click="() => showNewBucketInput = true"
|
@click="() => showNewBucketInput = true"
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
class="is-transparent is-fullwidth has-text-centered"
|
class="is-transparent is-fullwidth has-text-centered"
|
||||||
v-if="!showNewBucketInput"
|
v-else
|
||||||
type="secondary"
|
type="secondary"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
>
|
>
|
||||||
|
@ -255,6 +256,8 @@ const DRAG_OPTIONS = {
|
||||||
delay: 150,
|
delay: 150,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MIN_SCROLL_HEIGHT_PERCENT = 0.25
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Kanban',
|
name: 'Kanban',
|
||||||
components: {
|
components: {
|
||||||
|
@ -265,6 +268,8 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
taskContainerRefs: {},
|
||||||
|
|
||||||
dragOptions: DRAG_OPTIONS,
|
dragOptions: DRAG_OPTIONS,
|
||||||
|
|
||||||
drag: false,
|
drag: false,
|
||||||
|
@ -313,7 +318,10 @@ export default {
|
||||||
type: 'transition',
|
type: 'transition',
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
name: !this.dragBucket ? 'move-bucket': null,
|
name: !this.dragBucket ? 'move-bucket': null,
|
||||||
class: 'kanban-bucket-container',
|
class: [
|
||||||
|
'kanban-bucket-container',
|
||||||
|
{ 'dragging-disabled': !this.canWrite },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
taskDraggableTaskComponentData() {
|
taskDraggableTaskComponentData() {
|
||||||
|
@ -321,6 +329,10 @@ export default {
|
||||||
type: 'transition',
|
type: 'transition',
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
name: !this.drag ? 'move-card': null,
|
name: !this.drag ? 'move-card': null,
|
||||||
|
class: [
|
||||||
|
'dropper',
|
||||||
|
{ 'dragging-disabled': !this.canWrite },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
buckets: {
|
buckets: {
|
||||||
|
@ -361,30 +373,26 @@ export default {
|
||||||
console.debug(`Loading buckets, loadedListId = ${this.loadedListId}, $route.params =`, this.$route.params)
|
console.debug(`Loading buckets, loadedListId = ${this.loadedListId}, $route.params =`, this.$route.params)
|
||||||
this.filtersChanged = false
|
this.filtersChanged = false
|
||||||
|
|
||||||
const minScrollHeightPercent = 0.25
|
|
||||||
|
|
||||||
this.$store.dispatch('kanban/loadBucketsForList', {listId: this.$route.params.listId, params: this.params})
|
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]
|
setTaskContainerRef(id, el) {
|
||||||
e.addEventListener('scroll', () => {
|
if (!el) return
|
||||||
const scrollTopMax = e.scrollHeight - e.clientHeight
|
this.taskContainerRefs[id] = el
|
||||||
if (scrollTopMax <= e.scrollTop + e.scrollTop * minScrollHeightPercent) {
|
},
|
||||||
this.$store.dispatch('kanban/loadNextTasksForBucket', {
|
|
||||||
listId: this.$route.params.listId,
|
handleTaskContainerScroll(id, el) {
|
||||||
params: this.params,
|
const scrollTopMax = el.scrollHeight - el.clientHeight
|
||||||
bucketId: b.id,
|
const threshold = el.scrollTop + el.scrollTop * MIN_SCROLL_HEIGHT_PERCENT
|
||||||
})
|
if (scrollTopMax > threshold) {
|
||||||
.catch(e => {
|
return
|
||||||
this.$message.error(e)
|
}
|
||||||
})
|
|
||||||
}
|
this.$store.dispatch('kanban/loadNextTasksForBucket', {
|
||||||
})
|
listId: this.$route.params.listId,
|
||||||
})
|
params: this.params,
|
||||||
})
|
bucketId: id,
|
||||||
.catch(e => {
|
})
|
||||||
this.$message.error(e)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
updateTaskPosition(e) {
|
updateTaskPosition(e) {
|
||||||
this.drag = false
|
this.drag = false
|
||||||
|
@ -392,7 +400,7 @@ export default {
|
||||||
// While we could just pass the bucket index in through the function call, this would not give us the
|
// While we could just pass the bucket index in through the function call, this would not give us the
|
||||||
// new bucket id when a task has been moved between buckets, only the new bucket. Using the data-bucket-id
|
// new bucket id when a task has been moved between buckets, only the new bucket. Using the data-bucket-id
|
||||||
// of the drop target works all the time.
|
// of the drop target works all the time.
|
||||||
const bucketIndex = parseInt(e.to.parentNode.dataset.bucketIndex)
|
const bucketIndex = parseInt(e.to.dataset.bucketIndex)
|
||||||
|
|
||||||
const newBucket = this.buckets[bucketIndex]
|
const newBucket = this.buckets[bucketIndex]
|
||||||
const task = newBucket.tasks[e.newIndex]
|
const task = newBucket.tasks[e.newIndex]
|
||||||
|
@ -430,16 +438,15 @@ export default {
|
||||||
.then(r => {
|
.then(r => {
|
||||||
this.newTaskText = ''
|
this.newTaskText = ''
|
||||||
this.$store.commit('kanban/addTaskToBucket', r)
|
this.$store.commit('kanban/addTaskToBucket', r)
|
||||||
|
this.scrollTaskContainerToBottom(bucketId)
|
||||||
})
|
})
|
||||||
.catch(e => {
|
},
|
||||||
this.$message.error(e)
|
scrollTaskContainerToBottom(bucketId) {
|
||||||
})
|
const bucketEl = this.taskContainerRefs[bucketId]
|
||||||
.finally(() => {
|
if (!bucketEl) {
|
||||||
if (!this.$refs[`tasks-container${bucketId}`][0]) {
|
return
|
||||||
return
|
}
|
||||||
}
|
bucketEl.scrollTop = bucketEl.scrollHeight
|
||||||
this.$refs[`tasks-container${bucketId}`][0].scrollTop = this.$refs[`tasks-container${bucketId}`][0].scrollHeight
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
createNewBucket() {
|
createNewBucket() {
|
||||||
if (this.newBucketTitle === '') {
|
if (this.newBucketTitle === '') {
|
||||||
|
@ -490,10 +497,8 @@ export default {
|
||||||
this.bucketTitleEditable = true
|
this.bucketTitleEditable = true
|
||||||
this.$nextTick(() => e.target.focus())
|
this.$nextTick(() => e.target.focus())
|
||||||
},
|
},
|
||||||
saveBucketTitle(bucketId) {
|
saveBucketTitle(bucketId, bucketTitle) {
|
||||||
this.bucketTitleEditable = false
|
this.bucketTitleEditable = false
|
||||||
const bucketTitleElement = this.$refs[`bucket${bucketId}title`][0]
|
|
||||||
const bucketTitle = bucketTitleElement.textContent
|
|
||||||
const bucket = new BucketModel({
|
const bucket = new BucketModel({
|
||||||
id: bucketId,
|
id: bucketId,
|
||||||
title: bucketTitle,
|
title: bucketTitle,
|
||||||
|
@ -511,7 +516,6 @@ export default {
|
||||||
this.$store.dispatch('kanban/updateBucket', bucket)
|
this.$store.dispatch('kanban/updateBucket', bucket)
|
||||||
.then(r => {
|
.then(r => {
|
||||||
realBucket.title = r.title
|
realBucket.title = r.title
|
||||||
bucketTitleElement.blur()
|
|
||||||
this.$message.success({message: this.$t('list.kanban.bucketTitleSavedSuccess')})
|
this.$message.success({message: this.$t('list.kanban.bucketTitleSavedSuccess')})
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
|
|
Loading…
Reference in a new issue