1
0

Add limits for kanban boards (#234)

Prevent dropping a task onto a bucket which has its limit reached

Fix closing the dropdown

Add notice to show the limit

Add input to change kanban bucket limit

Add menu item to save bucket limit

Fix parsing dates from the api

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/234
This commit is contained in:
konrad
2020-09-04 20:01:02 +00:00
parent 89c602416c
commit cac8b09263
25 changed files with 124 additions and 43 deletions

View File

@ -9,6 +9,12 @@
@focusout="() => saveBucketTitle(bucket.id)"
:ref="`bucket${bucket.id}title`"
@keyup.ctrl.enter="() => saveBucketTitle(bucket.id)">{{ bucket.title }}</h2>
<span
class="limit"
:class="{'is-max': bucket.tasks.length >= bucket.limit}"
v-if="bucket.limit > 0">
{{ bucket.tasks.length }}/{{ bucket.limit }}
</span>
<div
class="dropdown is-right options"
:class="{ 'is-active': bucketOptionsDropDownActive[bucket.id] }"
@ -21,6 +27,33 @@
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content">
<a
class="dropdown-item"
@click.stop="showSetLimitInput = true"
>
<div class="field has-addons" v-if="showSetLimitInput">
<div class="control">
<input
type="number"
class="input"
v-focus.always
v-model="bucket.limit"
@keyup.enter="() => updateBucket(bucket)"
@change="() => updateBucket(bucket)"
/>
</div>
<div class="control">
<a class="button is-primary has-no-shadow">
<span class="icon">
<icon :icon="['far', 'save']"/>
</span>
</a>
</div>
</div>
<template v-else>
Limit: {{ bucket.limit > 0 ? bucket.limit : 'Not set' }}
</template>
</a>
<a
class="dropdown-item has-text-danger"
@click="() => deleteBucketModal(bucket.id)"
@ -43,6 +76,7 @@
:get-child-payload="getTaskPayload(bucket.id)"
:drop-placeholder="dropPlaceholderOptions"
:animation-duration="150"
:should-accept-drop="() => shouldAcceptDrop(bucket)"
drag-class="ghost-task"
drag-class-drop="ghost-task-drop"
drag-handle-selector=".task.draggable"
@ -58,7 +92,7 @@
:class="{
'is-loading': taskService.loading && taskUpdating[task.id],
'draggable': !taskService.loading || !taskUpdating[task.id],
'has-light-text': !colorIsDark(task.hexColor) && task.hexColor !== `#${task.defaultColor}`,
'has-light-text': !colorIsDark(task.hexColor) && task.hexColor !== `#${task.defaultColor}` && task.hexColor !== task.defaultColor,
}"
:style="{'background-color': task.hexColor !== '#' && task.hexColor !== `#${task.defaultColor}` ? task.hexColor : false}"
@click.ctrl="() => markTaskAsDone(task)"
@ -235,6 +269,7 @@
animationDuration: 150,
showOnTop: true,
},
sourceBucket: 0,
bucketOptionsDropDownActive: {},
showBucketDeleteModal: false,
@ -245,6 +280,7 @@
newBucketTitle: '',
showNewBucketInput: false,
newTaskError: {},
showSetLimitInput: false,
// We're using this to show the loading animation only at the task when updating it
taskUpdating: {},
@ -362,6 +398,7 @@
getTaskPayload(bucketId) {
return index => {
const bucket = this.buckets[filterObject(this.buckets, b => b.id === bucketId)]
this.sourceBucket = bucket.id
return bucket.tasks[index]
}
},
@ -369,9 +406,11 @@
this.$set(this.showNewTaskInput, bucket, !this.showNewTaskInput[bucket])
},
toggleBucketDropdown(bucketId) {
this.closeBucketDropdowns() // Close all eventually open dropdowns
this.$set(this.bucketOptionsDropDownActive, bucketId, !this.bucketOptionsDropDownActive[bucketId])
},
closeBucketDropdowns() {
this.showSetLimitInput = false
for (const bucketId in this.bucketOptionsDropDownActive) {
this.bucketOptionsDropDownActive[bucketId] = false
}
@ -481,6 +520,18 @@
this.error(e, this)
})
},
updateBucket(bucket) {
bucket.limit = parseInt(bucket.limit)
this.$store.dispatch('kanban/updateBucket', bucket)
.catch(e => {
this.error(e, this)
})
},
shouldAcceptDrop(bucket) {
return bucket.id === this.sourceBucket || // When dragging from a bucket who has its limit reached, dragging should still be possible
bucket.limit === 0 || // If there is no limit set, dragging & dropping should always work
bucket.tasks.length < bucket.limit // Disallow dropping to buckets which have their limit reached
},
},
}
</script>