feat: increase task drop area size for bucket list
This commit is contained in:
parent
80664b6182
commit
69654b823e
3 changed files with 89 additions and 84 deletions
|
@ -132,7 +132,7 @@ describe('List View Kanban', () => {
|
||||||
cy.getSettled('.kanban .bucket .tasks .task')
|
cy.getSettled('.kanban .bucket .tasks .task')
|
||||||
.contains(tasks[0].title)
|
.contains(tasks[0].title)
|
||||||
.first()
|
.first()
|
||||||
.drag('.kanban .bucket:nth-child(2) .tasks .dropper')
|
.drag('.kanban .bucket:nth-child(2) .tasks')
|
||||||
|
|
||||||
cy.get('.kanban .bucket:nth-child(2) .tasks')
|
cy.get('.kanban .bucket:nth-child(2) .tasks')
|
||||||
.should('contain', tasks[0].title)
|
.should('contain', tasks[0].title)
|
||||||
|
|
|
@ -138,7 +138,6 @@ $task-background: var(--white);
|
||||||
border: 3px solid transparent;
|
border: 3px solid transparent;
|
||||||
|
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
margin: .5rem;
|
|
||||||
padding: .4rem;
|
padding: .4rem;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
background: $task-background;
|
background: $task-background;
|
||||||
|
|
|
@ -123,61 +123,59 @@
|
||||||
</a>
|
</a>
|
||||||
</dropdown>
|
</dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
:ref="(el) => setTaskContainerRef(bucket.id, el)"
|
<draggable
|
||||||
@scroll="($event) => handleTaskContainerScroll(bucket.id, bucket.listId, $event.target)"
|
v-bind="dragOptions"
|
||||||
class="tasks"
|
:modelValue="bucket.tasks"
|
||||||
|
@update:modelValue="(tasks) => updateTasks(bucket.id, tasks)"
|
||||||
|
@start="() => dragstart(bucket)"
|
||||||
|
@end="updateTaskPosition"
|
||||||
|
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
||||||
|
:disabled="!canWrite"
|
||||||
|
:data-bucket-index="bucketIndex"
|
||||||
|
tag="transition-group"
|
||||||
|
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
||||||
|
:component-data="getTaskDraggableTaskComponentData(bucket)"
|
||||||
>
|
>
|
||||||
<draggable
|
<template #footer>
|
||||||
v-bind="dragOptions"
|
<div class="bucket-footer" v-if="canWrite">
|
||||||
:modelValue="bucket.tasks"
|
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||||
@update:modelValue="(tasks) => updateTasks(bucket.id, tasks)"
|
<div class="control" :class="{'is-loading': loading}">
|
||||||
@start="() => dragstart(bucket)"
|
<input
|
||||||
@end="updateTaskPosition"
|
class="input"
|
||||||
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
:disabled="loading || undefined"
|
||||||
:disabled="!canWrite"
|
@focusout="toggleShowNewTaskInput(bucket.id)"
|
||||||
:data-bucket-index="bucketIndex"
|
@keyup.enter="addTaskToBucket(bucket.id)"
|
||||||
tag="transition-group"
|
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
||||||
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
:placeholder="$t('list.kanban.addTaskPlaceholder')"
|
||||||
:component-data="taskDraggableTaskComponentData"
|
type="text"
|
||||||
>
|
v-focus.always
|
||||||
<template #item="{element: task}">
|
v-model="newTaskText"
|
||||||
<kanban-card :task="task"/>
|
/>
|
||||||
</template>
|
</div>
|
||||||
</draggable>
|
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||||
</div>
|
{{ $t('list.create.addTitleRequired') }}
|
||||||
<div class="bucket-footer" v-if="canWrite">
|
</p>
|
||||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
</div>
|
||||||
<div class="control" :class="{'is-loading': loading}">
|
<x-button
|
||||||
<input
|
@click="toggleShowNewTaskInput(bucket.id)"
|
||||||
class="input"
|
class="is-fullwidth has-text-centered"
|
||||||
:disabled="loading || null"
|
:shadow="false"
|
||||||
@focusout="toggleShowNewTaskInput(bucket.id)"
|
v-else
|
||||||
@keyup.enter="addTaskToBucket(bucket.id)"
|
icon="plus"
|
||||||
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
variant="secondary"
|
||||||
:placeholder="$t('list.kanban.addTaskPlaceholder')"
|
>
|
||||||
type="text"
|
{{ bucket.tasks.length === 0 ? $t('list.kanban.addTask') : $t('list.kanban.addAnotherTask') }}
|
||||||
v-focus.always
|
</x-button>
|
||||||
v-model="newTaskText"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
</template>
|
||||||
{{ $t('list.create.addTitleRequired') }}
|
|
||||||
</p>
|
<template #item="{element: task}">
|
||||||
</div>
|
<div class="task-item">
|
||||||
<x-button
|
<kanban-card class="kanban-card" :task="task"/>
|
||||||
@click="toggleShowNewTaskInput(bucket.id)"
|
</div>
|
||||||
class="is-transparent is-fullwidth has-text-centered"
|
</template>
|
||||||
:shadow="false"
|
</draggable>
|
||||||
v-if="!showNewTaskInput[bucket.id]"
|
|
||||||
icon="plus"
|
|
||||||
variant="secondary"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
bucket.tasks.length === 0 ? $t('list.kanban.addTask') : $t('list.kanban.addAnotherTask')
|
|
||||||
}}
|
|
||||||
</x-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
|
@ -197,10 +195,10 @@
|
||||||
v-model="newBucketTitle"
|
v-model="newBucketTitle"
|
||||||
/>
|
/>
|
||||||
<x-button
|
<x-button
|
||||||
|
v-else
|
||||||
@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-else
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
>
|
>
|
||||||
|
@ -313,6 +311,20 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
getTaskDraggableTaskComponentData() {
|
||||||
|
return (bucket) => ({
|
||||||
|
ref: (el) => this.setTaskContainerRef(bucket.id, el),
|
||||||
|
onScroll: (event) => this.handleTaskContainerScroll(bucket.id, bucket.listId, event.target),
|
||||||
|
type: 'transition',
|
||||||
|
tag: 'div',
|
||||||
|
name: !this.drag ? 'move-card' : null,
|
||||||
|
class: [
|
||||||
|
'tasks',
|
||||||
|
{'dragging-disabled': !this.canWrite},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
isSavedFilter() {
|
isSavedFilter() {
|
||||||
return this.list.isSavedFilter && !this.list.isSavedFilter()
|
return this.list.isSavedFilter && !this.list.isSavedFilter()
|
||||||
},
|
},
|
||||||
|
@ -333,17 +345,6 @@ export default {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
taskDraggableTaskComponentData() {
|
|
||||||
return {
|
|
||||||
type: 'transition',
|
|
||||||
tag: 'div',
|
|
||||||
name: !this.drag ? 'move-card' : null,
|
|
||||||
class: [
|
|
||||||
'dropper',
|
|
||||||
{'dragging-disabled': !this.canWrite},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buckets() {
|
buckets() {
|
||||||
return this.$store.state.kanban.buckets
|
return this.$store.state.kanban.buckets
|
||||||
},
|
},
|
||||||
|
@ -610,7 +611,6 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
|
|
||||||
&-bucket-container {
|
&-bucket-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ghost {
|
.ghost {
|
||||||
|
@ -624,7 +624,6 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
}
|
}
|
||||||
|
|
||||||
.bucket {
|
.bucket {
|
||||||
background-color: var(--grey-100);
|
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -632,22 +631,20 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
width: $bucket-width;
|
width: $bucket-width;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.tasks {
|
.tasks {
|
||||||
max-height: calc(#{$crazy-height-calculation-tasks});
|
overflow: hidden auto;
|
||||||
overflow: auto;
|
height: 100%;
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
|
||||||
max-height: calc(#{$crazy-height-calculation-tasks} - #{$filter-container-height});
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropper {
|
|
||||||
&, > div {
|
|
||||||
min-height: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-item {
|
||||||
|
background-color: var(--grey-100);
|
||||||
|
padding: .5rem .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.move-card-move {
|
.move-card-move {
|
||||||
transition: transform $transition-duration;
|
transition: transform $transition-duration;
|
||||||
}
|
}
|
||||||
|
@ -682,10 +679,11 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-collapsed {
|
&.is-collapsed {
|
||||||
transform: rotate(90deg) translateX(math.div($bucket-width, 2) - math.div($bucket-header-height, 2));
|
align-self: flex-start;
|
||||||
|
transform: rotate(90deg) translateY(-100%);
|
||||||
|
transform-origin: top left;
|
||||||
// Using negative margins instead of translateY here to make all other buckets fill the empty space
|
// Using negative margins instead of translateY here to make all other buckets fill the empty space
|
||||||
margin-left: (math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1;
|
margin-right: calc((#{$bucket-width} - #{$bucket-header-height} - #{$bucket-right-margin}) * -1);
|
||||||
margin-right: calc(#{(math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1} + #{$bucket-right-margin});
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.tasks, .bucket-footer {
|
.tasks, .bucket-footer {
|
||||||
|
@ -695,6 +693,8 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
}
|
}
|
||||||
|
|
||||||
.bucket-header {
|
.bucket-header {
|
||||||
|
background-color: var(--grey-100);
|
||||||
|
height: min-content;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -724,7 +724,13 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||||
}
|
}
|
||||||
|
|
||||||
.bucket-footer {
|
.bucket-footer {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
height: min-content;
|
||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
|
background-color: var(--grey-100);
|
||||||
|
border-bottom-left-radius: $radius;
|
||||||
|
border-bottom-right-radius: $radius;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
Loading…
Reference in a new issue