feat: allow marking a related task done directly from the list
This commit is contained in:
parent
943d5f7975
commit
ce0f58c783
5 changed files with 60 additions and 33 deletions
|
@ -68,7 +68,6 @@
|
|||
<script lang="ts">
|
||||
import {defineComponent, type PropType} from 'vue'
|
||||
|
||||
import {playPop} from '../../../helpers/playPop'
|
||||
import PriorityLabel from '../../../components/tasks/partials/priorityLabel.vue'
|
||||
import User from '../../../components/misc/user.vue'
|
||||
import Done from '@/components/misc/Done.vue'
|
||||
|
@ -126,9 +125,6 @@ export default defineComponent({
|
|||
...task,
|
||||
done,
|
||||
})
|
||||
if (done) {
|
||||
playPop()
|
||||
}
|
||||
} finally {
|
||||
this.loadingInternal = false
|
||||
}
|
||||
|
|
|
@ -83,26 +83,34 @@
|
|||
<span class="title">{{ rts.title }}</span>
|
||||
<div class="tasks">
|
||||
<div :key="t.id" class="task" v-for="t in rts.tasks">
|
||||
<router-link
|
||||
:to="{ name: route.name as string, params: { id: t.id } }"
|
||||
:class="{ 'is-strikethrough': t.done}">
|
||||
<span
|
||||
class="different-list"
|
||||
v-if="t.listId !== listId"
|
||||
<div class="is-flex is-align-items-center">
|
||||
<Fancycheckbox
|
||||
class="task-done-checkbox"
|
||||
v-model="t.done"
|
||||
@update:model-value="toggleTaskDone(t)"
|
||||
/>
|
||||
<router-link
|
||||
:to="{ name: route.name as string, params: { id: t.id } }"
|
||||
:class="{ 'is-strikethrough': t.done}"
|
||||
>
|
||||
<span
|
||||
v-if="t.differentNamespace !== null"
|
||||
v-tooltip="$t('task.relation.differentNamespace')">
|
||||
{{ t.differentNamespace }} >
|
||||
class="different-list"
|
||||
v-if="t.listId !== listId"
|
||||
>
|
||||
<span
|
||||
v-if="t.differentNamespace !== null"
|
||||
v-tooltip="$t('task.relation.differentNamespace')">
|
||||
{{ t.differentNamespace }} >
|
||||
</span>
|
||||
<span
|
||||
v-if="t.differentList !== null"
|
||||
v-tooltip="$t('task.relation.differentList')">
|
||||
{{ t.differentList }} >
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
v-if="t.differentList !== null"
|
||||
v-tooltip="$t('task.relation.differentList')">
|
||||
{{ t.differentList }} >
|
||||
</span>
|
||||
</span>
|
||||
{{ t.title }}
|
||||
</router-link>
|
||||
{{ t.title }}
|
||||
</router-link>
|
||||
</div>
|
||||
<BaseButton
|
||||
v-if="editEnabled"
|
||||
@click="setRelationToDelete({
|
||||
|
@ -154,7 +162,9 @@ import TaskRelationModel from '@/models/taskRelation'
|
|||
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import Multiselect from '@/components/input/multiselect.vue'
|
||||
import { error } from '@/message'
|
||||
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
||||
|
||||
import {error, success} from '@/message'
|
||||
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
|
@ -330,6 +340,23 @@ async function createAndRelateTask(title: string) {
|
|||
newTaskRelation.task = newTask
|
||||
await addTaskRelation()
|
||||
}
|
||||
|
||||
async function toggleTaskDone(task: ITask) {
|
||||
await store.dispatch('tasks/update', task)
|
||||
|
||||
// Find the task in the list and update it so that it is correctly strike through
|
||||
Object.entries(relatedTasks.value).some(([kind, tasks]) => {
|
||||
return tasks.some((t, key) => {
|
||||
const found = t.id === task.id
|
||||
if (found) {
|
||||
relatedTasks.value[kind as IRelationKind]![key] = task
|
||||
}
|
||||
return found
|
||||
})
|
||||
})
|
||||
|
||||
success({message: t('task.detail.updateSuccess')})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -402,5 +429,13 @@ async function createAndRelateTask(title: string) {
|
|||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
// FIXME: The height of the actual checkbox in the <Fancycheckbox/> component is too much resulting in a
|
||||
// weired positioning of the checkbox. Setting the height here is a workaround until we fix the styling
|
||||
// of the component.
|
||||
.task-done-checkbox {
|
||||
padding: 0;
|
||||
height: 18px; // The exact height of the checkbox in the container
|
||||
}
|
||||
|
||||
@include modal-transition();
|
||||
</style>
|
|
@ -114,7 +114,6 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
|||
import Fancycheckbox from '../../input/fancycheckbox.vue'
|
||||
import DeferTask from './defer-task.vue'
|
||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||
import {playPop} from '@/helpers/playPop'
|
||||
import ChecklistSummary from './checklist-summary.vue'
|
||||
import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatDate'
|
||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||
|
@ -208,10 +207,7 @@ export default defineComponent({
|
|||
|
||||
async markAsDone(checked: boolean) {
|
||||
const updateFunc = async () => {
|
||||
const task = await this.taskService.update(this.task)
|
||||
if (this.task.done) {
|
||||
playPop()
|
||||
}
|
||||
const task = await this.$store.dispatch('tasks/update', this.task)
|
||||
this.task = task
|
||||
this.$emit('task-updated', task)
|
||||
this.$message.success({
|
||||
|
|
|
@ -25,8 +25,9 @@ import type { IAttachment } from '@/modelTypes/IAttachment'
|
|||
import type { IList } from '@/modelTypes/IList'
|
||||
|
||||
import type { RootStoreState, TaskState } from '@/store/types'
|
||||
import { useLabelStore } from '@/stores/labels'
|
||||
import { useListStore } from '@/stores/lists'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {playPop} from '@/helpers/playPop'
|
||||
|
||||
// IDEA: maybe use a small fuzzy search here to prevent errors
|
||||
function findPropertyByValue(object, key, value) {
|
||||
|
@ -96,6 +97,9 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
|||
try {
|
||||
const updatedTask = await taskService.update(task)
|
||||
ctx.commit('kanban/setTaskInBucket', updatedTask, {root: true})
|
||||
if (task.done) {
|
||||
playPop()
|
||||
}
|
||||
return updatedTask
|
||||
} finally {
|
||||
cancel()
|
||||
|
|
|
@ -451,7 +451,6 @@ import ColorPicker from '../../components/input/colorPicker.vue'
|
|||
import heading from '@/components/tasks/partials/heading.vue'
|
||||
import Datepicker from '@/components/input/datepicker.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import {playPop} from '@/helpers/playPop'
|
||||
import TaskSubscription from '@/components/misc/subscription.vue'
|
||||
import {CURRENT_LIST} from '@/store/mutation-types'
|
||||
|
||||
|
@ -733,9 +732,6 @@ export default defineComponent({
|
|||
...this.task,
|
||||
done: !this.task.done,
|
||||
}
|
||||
if (newTask.done) {
|
||||
playPop()
|
||||
}
|
||||
|
||||
this.saveTask({
|
||||
task: newTask,
|
||||
|
|
Loading…
Reference in a new issue