Rudimentary kanban using sortable
This commit is contained in:
parent
7f3cfccfbb
commit
cf49adb381
@ -61,10 +61,11 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||
-ms-user-select: none; // Internet Explorer/Edge
|
||||
user-select: none; // Non-prefixed version, currently supported by Chrome, Opera and Firefox
|
||||
|
||||
transition: $ease-out;
|
||||
//transition: $ease-out;
|
||||
cursor: pointer;
|
||||
box-shadow: $shadow-xs;
|
||||
display: block;
|
||||
border: 3px solid transparent;
|
||||
|
||||
font-size: .9rem;
|
||||
padding: .5rem;
|
||||
@ -205,7 +206,7 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||
}
|
||||
}
|
||||
|
||||
.drop-preview {
|
||||
.ghost {
|
||||
border-radius: $radius;
|
||||
margin: 0 .5rem .5rem;
|
||||
background: transparent;
|
||||
@ -213,6 +214,13 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||
}
|
||||
}
|
||||
|
||||
.move-card-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
.no-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1rem;
|
||||
margin: 0;
|
||||
|
@ -108,28 +108,43 @@
|
||||
</dropdown>
|
||||
</div>
|
||||
<div :ref="`tasks-container${bucket.id}`" class="tasks">
|
||||
<!-- Make the component either a div or a draggable component based on the user rights -->
|
||||
<component
|
||||
:animation-duration="150"
|
||||
:drop-placeholder="dropPlaceholderOptions"
|
||||
:get-child-payload="getTaskPayload(bucket.id)"
|
||||
:is="canWrite ? 'Container' : 'div'"
|
||||
:should-accept-drop="() => shouldAcceptDrop(bucket)"
|
||||
@drop="e => onDrop(bucket.id, e)"
|
||||
drag-class="ghost-task"
|
||||
drag-class-drop="ghost-task-drop"
|
||||
drag-handle-selector=".task.draggable"
|
||||
group-name="buckets"
|
||||
{{ drag }}
|
||||
<draggable
|
||||
v-model="bucket.tasks"
|
||||
@start="() => drag = true"
|
||||
@end="e => onDrop(bucket.id, e)"
|
||||
group="buckets"
|
||||
v-bind="dragOptions"
|
||||
>
|
||||
<transition-group type="transition" :name="!drag ? 'move-card': null">
|
||||
<!-- Make the component either a div or a draggable component based on the user rights -->
|
||||
<component
|
||||
:is="canWrite ? 'Draggable' : 'div'"
|
||||
<!-- <component-->
|
||||
<!-- :animation-duration="150"-->
|
||||
<!-- :drop-placeholder="dropPlaceholderOptions"-->
|
||||
<!-- :get-child-payload="getTaskPayload(bucket.id)"-->
|
||||
<!-- :is="canWrite ? 'Container' : 'div'"-->
|
||||
<!-- :should-accept-drop="() => shouldAcceptDrop(bucket)"-->
|
||||
<!-- @drop="e => onDrop(bucket.id, e)"-->
|
||||
<!-- drag-class="ghost-task"-->
|
||||
<!-- drag-class-drop="ghost-task-drop"-->
|
||||
<!-- drag-handle-selector=".task.draggable"-->
|
||||
<!-- group-name="buckets"-->
|
||||
<!-- >-->
|
||||
<!-- <!– Make the component either a div or a draggable component based on the user rights –>-->
|
||||
<!-- <component-->
|
||||
<!-- :is="canWrite ? 'Draggable' : 'div'"-->
|
||||
<!-- :key="`bucket${bucket.id}-task${task.id}`"-->
|
||||
<!-- v-for="task in bucket.tasks"-->
|
||||
<!-- >-->
|
||||
<kanban-card
|
||||
:key="`bucket${bucket.id}-task${task.id}`"
|
||||
v-for="task in bucket.tasks"
|
||||
>
|
||||
<kanban-card :task="task"/>
|
||||
</component>
|
||||
</component>
|
||||
:task="task"
|
||||
/>
|
||||
</transition-group>
|
||||
<!-- </component>-->
|
||||
<!-- </component>-->
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="bucket-footer" v-if="canWrite">
|
||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||
@ -248,6 +263,11 @@ export default {
|
||||
animationDuration: 150,
|
||||
showOnTop: true,
|
||||
},
|
||||
drag: false,
|
||||
dragOptions: {
|
||||
animation: 150,
|
||||
ghostClass: 'ghost',
|
||||
},
|
||||
sourceBucket: 0,
|
||||
|
||||
showBucketDeleteModal: false,
|
||||
@ -345,54 +365,56 @@ export default {
|
||||
})
|
||||
},
|
||||
onDrop(bucketId, dropResult) {
|
||||
console.log('drop', bucketId, dropResult)
|
||||
this.drag = false
|
||||
|
||||
// Note: A lot of this example comes from the excellent kanban example on https://github.com/kutlugsahin/vue-smooth-dnd/blob/master/demo/src/pages/cards.vue
|
||||
|
||||
const bucketIndex = filterObject(this.buckets, b => b.id === bucketId)
|
||||
|
||||
if (dropResult.removedIndex !== null || dropResult.addedIndex !== null) {
|
||||
|
||||
// FIXME: This is probably not the best solution and more of a naive brute-force approach
|
||||
|
||||
// Duplicate the buckets to avoid stuff moving around without noticing
|
||||
const buckets = Object.assign({}, this.buckets)
|
||||
// Get the index of the bucket and the bucket itself
|
||||
const bucket = buckets[bucketIndex]
|
||||
|
||||
// Rebuild the tasks from the bucket, removing/adding the moved task
|
||||
bucket.tasks = applyDrag(bucket.tasks, dropResult)
|
||||
// Update the bucket in the list of all buckets
|
||||
delete buckets[bucketIndex]
|
||||
buckets[bucketIndex] = bucket
|
||||
// Set the buckets, triggering a state update in vue
|
||||
// FIXME: This seems to set some task attributes (like due date) wrong. Commented out, but seems to still work?
|
||||
// Not sure what to do about this.
|
||||
// this.$store.commit('kanban/setBuckets', buckets)
|
||||
}
|
||||
|
||||
if (dropResult.addedIndex !== null) {
|
||||
|
||||
const taskIndex = dropResult.addedIndex
|
||||
const taskBefore = typeof this.buckets[bucketIndex].tasks[taskIndex - 1] === 'undefined' ? null : this.buckets[bucketIndex].tasks[taskIndex - 1]
|
||||
const taskAfter = typeof this.buckets[bucketIndex].tasks[taskIndex + 1] === 'undefined' ? null : this.buckets[bucketIndex].tasks[taskIndex + 1]
|
||||
const task = this.buckets[bucketIndex].tasks[taskIndex]
|
||||
this.$set(this.taskUpdating, task.id, true)
|
||||
this.oneTaskUpdating = true
|
||||
|
||||
task.kanbanPosition = calculateItemPosition(taskBefore !== null ? taskBefore.kanbanPosition : null, taskAfter !== null ? taskAfter.kanbanPosition : null)
|
||||
console.log(task.kanbanPosition)
|
||||
|
||||
task.bucketId = bucketId
|
||||
|
||||
this.$store.dispatch('tasks/update', task)
|
||||
.catch(e => {
|
||||
this.error(e)
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this.taskUpdating, task.id, false)
|
||||
this.oneTaskUpdating = false
|
||||
})
|
||||
}
|
||||
// const bucketIndex = filterObject(this.buckets, b => b.id === bucketId)
|
||||
//
|
||||
// if (dropResult.removedIndex !== null || dropResult.addedIndex !== null) {
|
||||
//
|
||||
// // FIXME: This is probably not the best solution and more of a naive brute-force approach
|
||||
//
|
||||
// // Duplicate the buckets to avoid stuff moving around without noticing
|
||||
// const buckets = Object.assign({}, this.buckets)
|
||||
// // Get the index of the bucket and the bucket itself
|
||||
// const bucket = buckets[bucketIndex]
|
||||
//
|
||||
// // Rebuild the tasks from the bucket, removing/adding the moved task
|
||||
// bucket.tasks = applyDrag(bucket.tasks, dropResult)
|
||||
// // Update the bucket in the list of all buckets
|
||||
// delete buckets[bucketIndex]
|
||||
// buckets[bucketIndex] = bucket
|
||||
// // Set the buckets, triggering a state update in vue
|
||||
// // FIXME: This seems to set some task attributes (like due date) wrong. Commented out, but seems to still work?
|
||||
// // Not sure what to do about this.
|
||||
// // this.$store.commit('kanban/setBuckets', buckets)
|
||||
// }
|
||||
//
|
||||
// if (dropResult.addedIndex !== null) {
|
||||
//
|
||||
// const taskIndex = dropResult.addedIndex
|
||||
// const taskBefore = typeof this.buckets[bucketIndex].tasks[taskIndex - 1] === 'undefined' ? null : this.buckets[bucketIndex].tasks[taskIndex - 1]
|
||||
// const taskAfter = typeof this.buckets[bucketIndex].tasks[taskIndex + 1] === 'undefined' ? null : this.buckets[bucketIndex].tasks[taskIndex + 1]
|
||||
// const task = this.buckets[bucketIndex].tasks[taskIndex]
|
||||
// this.$set(this.taskUpdating, task.id, true)
|
||||
// this.oneTaskUpdating = true
|
||||
//
|
||||
// task.kanbanPosition = calculateItemPosition(taskBefore !== null ? taskBefore.kanbanPosition : null, taskAfter !== null ? taskAfter.kanbanPosition : null)
|
||||
// console.log(task.kanbanPosition)
|
||||
//
|
||||
// task.bucketId = bucketId
|
||||
//
|
||||
// this.$store.dispatch('tasks/update', task)
|
||||
// .catch(e => {
|
||||
// this.error(e)
|
||||
// })
|
||||
// .finally(() => {
|
||||
// this.$set(this.taskUpdating, task.id, false)
|
||||
// this.oneTaskUpdating = false
|
||||
// })
|
||||
// }
|
||||
},
|
||||
getTaskPayload(bucketId) {
|
||||
return index => {
|
||||
|
Reference in New Issue
Block a user