Better save messages for tasks (#307)
Add success messages when managing assignees Add success messages when managing labels Add better loading animations for related tasks Add better loading animations for comments Don't block everything while loading Move task heading to separate component which handles all saving related things Make sure to only show the loading spinner and saved message when saving the description Show a maximum of 2 notifications Move task description to separate component Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/307 Co-Authored-By: konrad <konrad@kola-entertainments.de> Co-Committed-By: konrad <konrad@kola-entertainments.de>
This commit is contained in:
@ -1,104 +1,105 @@
|
||||
<template>
|
||||
<div :class="{ 'is-loading': loading}" class="kanban loader-container">
|
||||
<div :key="`bucket${bucket.id}`" class="bucket" v-for="bucket in buckets">
|
||||
<div class="bucket-header">
|
||||
<h2
|
||||
:ref="`bucket${bucket.id}title`"
|
||||
@focusout="() => saveBucketTitle(bucket.id)"
|
||||
@keyup.enter="() => saveBucketTitle(bucket.id)"
|
||||
class="title input"
|
||||
contenteditable="true"
|
||||
spellcheck="false">{{ bucket.title }}</h2>
|
||||
<span
|
||||
:class="{'is-max': bucket.tasks.length >= bucket.limit}"
|
||||
class="limit"
|
||||
v-if="bucket.limit > 0">
|
||||
<div>
|
||||
<div :class="{ 'is-loading': loading}" class="kanban loader-container">
|
||||
<div :key="`bucket${bucket.id}`" class="bucket" v-for="bucket in buckets">
|
||||
<div class="bucket-header">
|
||||
<h2
|
||||
:ref="`bucket${bucket.id}title`"
|
||||
@focusout="() => saveBucketTitle(bucket.id)"
|
||||
@keyup.enter="() => saveBucketTitle(bucket.id)"
|
||||
class="title input"
|
||||
contenteditable="true"
|
||||
spellcheck="false">{{ bucket.title }}</h2>
|
||||
<span
|
||||
:class="{'is-max': bucket.tasks.length >= bucket.limit}"
|
||||
class="limit"
|
||||
v-if="bucket.limit > 0">
|
||||
{{ bucket.tasks.length }}/{{ bucket.limit }}
|
||||
</span>
|
||||
<div
|
||||
:class="{ 'is-active': bucketOptionsDropDownActive[bucket.id] }"
|
||||
class="dropdown is-right options"
|
||||
v-if="canWrite"
|
||||
>
|
||||
<div @click.stop="toggleBucketDropdown(bucket.id)" class="dropdown-trigger">
|
||||
<div
|
||||
:class="{ 'is-active': bucketOptionsDropDownActive[bucket.id] }"
|
||||
class="dropdown is-right options"
|
||||
v-if="canWrite"
|
||||
>
|
||||
<div @click.stop="toggleBucketDropdown(bucket.id)" class="dropdown-trigger">
|
||||
<span class="icon">
|
||||
<icon icon="ellipsis-v"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a
|
||||
@click.stop="showSetLimitInput = true"
|
||||
class="dropdown-item"
|
||||
>
|
||||
<div class="field has-addons" v-if="showSetLimitInput">
|
||||
<div class="control">
|
||||
<input
|
||||
@change="() => updateBucket(bucket)"
|
||||
@keyup.enter="() => updateBucket(bucket)"
|
||||
class="input"
|
||||
type="number"
|
||||
v-focus.always
|
||||
v-model="bucket.limit"
|
||||
/>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-primary has-no-shadow">
|
||||
</div>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a
|
||||
@click.stop="showSetLimitInput = true"
|
||||
class="dropdown-item"
|
||||
>
|
||||
<div class="field has-addons" v-if="showSetLimitInput">
|
||||
<div class="control">
|
||||
<input
|
||||
@change="() => updateBucket(bucket)"
|
||||
@keyup.enter="() => updateBucket(bucket)"
|
||||
class="input"
|
||||
type="number"
|
||||
v-focus.always
|
||||
v-model="bucket.limit"
|
||||
/>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-primary has-no-shadow">
|
||||
<span class="icon">
|
||||
<icon :icon="['far', 'save']"/>
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
Limit: {{ bucket.limit > 0 ? bucket.limit : 'Not set' }}
|
||||
</template>
|
||||
</a>
|
||||
<a
|
||||
:class="{'is-disabled': buckets.length <= 1}"
|
||||
@click="() => deleteBucketModal(bucket.id)"
|
||||
class="dropdown-item has-text-danger"
|
||||
v-tooltip="buckets.length <= 1 ? 'You cannot remove the last bucket.' : ''"
|
||||
>
|
||||
<span class="icon is-small"><icon icon="trash-alt"/></span>
|
||||
Delete
|
||||
</a>
|
||||
<template v-else>
|
||||
Limit: {{ bucket.limit > 0 ? bucket.limit : 'Not set' }}
|
||||
</template>
|
||||
</a>
|
||||
<a
|
||||
:class="{'is-disabled': buckets.length <= 1}"
|
||||
@click="() => deleteBucketModal(bucket.id)"
|
||||
class="dropdown-item has-text-danger"
|
||||
v-tooltip="buckets.length <= 1 ? 'You cannot remove the last bucket.' : ''"
|
||||
>
|
||||
<span class="icon is-small"><icon icon="trash-alt"/></span>
|
||||
Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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"
|
||||
>
|
||||
<div :ref="`tasks-container${bucket.id}`" class="tasks">
|
||||
<!-- 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"
|
||||
: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"
|
||||
>
|
||||
<div
|
||||
:class="{
|
||||
<!-- 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"
|
||||
>
|
||||
<div
|
||||
:class="{
|
||||
'is-loading': taskService.loading && taskUpdating[task.id],
|
||||
'draggable': !taskService.loading || !taskUpdating[task.id],
|
||||
'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)"
|
||||
@click.exact="() => $router.push({ name: 'task.kanban.detail', params: { id: task.id } })"
|
||||
@click.meta="() => markTaskAsDone(task)"
|
||||
class="task loader-container draggable"
|
||||
>
|
||||
:style="{'background-color': task.hexColor !== '#' && task.hexColor !== `#${task.defaultColor}` ? task.hexColor : false}"
|
||||
@click.ctrl="() => markTaskAsDone(task)"
|
||||
@click.exact="() => $router.push({ name: 'task.kanban.detail', params: { id: task.id } })"
|
||||
@click.meta="() => markTaskAsDone(task)"
|
||||
class="task loader-container draggable"
|
||||
>
|
||||
<span class="task-id">
|
||||
<span class="is-done" v-if="task.done">Done</span>
|
||||
<template v-if="task.identifier === ''">
|
||||
@ -108,11 +109,11 @@
|
||||
{{ task.identifier }}
|
||||
</template>
|
||||
</span>
|
||||
<span
|
||||
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
|
||||
class="due-date"
|
||||
v-if="task.dueDate > 0"
|
||||
v-tooltip="formatDate(task.dueDate)">
|
||||
<span
|
||||
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
|
||||
class="due-date"
|
||||
v-if="task.dueDate > 0"
|
||||
v-tooltip="formatDate(task.dueDate)">
|
||||
<span class="icon">
|
||||
<icon :icon="['far', 'calendar-alt']"/>
|
||||
</span>
|
||||
@ -120,22 +121,22 @@
|
||||
{{ formatDateSince(task.dueDate) }}
|
||||
</span>
|
||||
</span>
|
||||
<h3>{{ task.title }}</h3>
|
||||
<labels :labels="task.labels"/>
|
||||
<div class="footer">
|
||||
<div class="items">
|
||||
<priority-label :priority="task.priority" class="priority-label"/>
|
||||
<div class="assignees" v-if="task.assignees.length > 0">
|
||||
<user
|
||||
:avatar-size="24"
|
||||
:key="task.id + 'assignee' + u.id"
|
||||
:show-username="false"
|
||||
:user="u"
|
||||
v-for="u in task.assignees"
|
||||
/>
|
||||
<h3>{{ task.title }}</h3>
|
||||
<labels :labels="task.labels"/>
|
||||
<div class="footer">
|
||||
<div class="items">
|
||||
<priority-label :priority="task.priority" class="priority-label"/>
|
||||
<div class="assignees" v-if="task.assignees.length > 0">
|
||||
<user
|
||||
:avatar-size="24"
|
||||
:key="task.id + 'assignee' + u.id"
|
||||
:show-username="false"
|
||||
:user="u"
|
||||
v-for="u in task.assignees"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span class="icon" v-if="task.attachments.length > 0">
|
||||
<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="none" rx="0" ry="0"></rect>
|
||||
@ -145,74 +146,75 @@
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</component>
|
||||
</component>
|
||||
</div>
|
||||
<div class="bucket-footer" v-if="canWrite">
|
||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||
<div class="control">
|
||||
<input
|
||||
|
||||
:class="{'is-loading': taskService.loading}"
|
||||
:disabled="taskService.loading"
|
||||
@focusout="toggleShowNewTaskInput(bucket.id)"
|
||||
@keyup.enter="addTaskToBucket(bucket.id)"
|
||||
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
||||
class="input"
|
||||
placeholder="Enter the new task text..."
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-model="newTaskText"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||
Please specify a title.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
@click="toggleShowNewTaskInput(bucket.id)"
|
||||
class="button noshadow is-transparent is-fullwidth has-text-centered"
|
||||
v-if="!showNewTaskInput[bucket.id]">
|
||||
<div class="bucket-footer" v-if="canWrite">
|
||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||
<div class="control">
|
||||
<input
|
||||
|
||||
:class="{'is-loading': taskService.loading}"
|
||||
:disabled="taskService.loading"
|
||||
@focusout="toggleShowNewTaskInput(bucket.id)"
|
||||
@keyup.enter="addTaskToBucket(bucket.id)"
|
||||
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
||||
class="input"
|
||||
placeholder="Enter the new task text..."
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-model="newTaskText"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||
Please specify a title.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
@click="toggleShowNewTaskInput(bucket.id)"
|
||||
class="button noshadow is-transparent is-fullwidth has-text-centered"
|
||||
v-if="!showNewTaskInput[bucket.id]">
|
||||
<span class="icon is-small">
|
||||
<icon icon="plus"/>
|
||||
</span>
|
||||
<span v-if="bucket.tasks.length === 0">
|
||||
<span v-if="bucket.tasks.length === 0">
|
||||
Add a task
|
||||
</span>
|
||||
<span v-else>
|
||||
<span v-else>
|
||||
Add another task
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bucket new-bucket" v-if="!loading && canWrite">
|
||||
<input
|
||||
:class="{'is-loading': loading}"
|
||||
:disabled="loading"
|
||||
@focusout="() => showNewBucketInput = false"
|
||||
@keyup.enter="createNewBucket"
|
||||
@keyup.esc="() => showNewBucketInput = false"
|
||||
class="input"
|
||||
placeholder="Enter the new bucket title..."
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-if="showNewBucketInput"
|
||||
v-model="newBucketTitle"
|
||||
/>
|
||||
<a
|
||||
@click="() => showNewBucketInput = true"
|
||||
class="button noshadow is-transparent is-fullwidth has-text-centered" v-if="!showNewBucketInput">
|
||||
<div class="bucket new-bucket" v-if="!loading && canWrite">
|
||||
<input
|
||||
:class="{'is-loading': loading}"
|
||||
:disabled="loading"
|
||||
@focusout="() => showNewBucketInput = false"
|
||||
@keyup.enter="createNewBucket"
|
||||
@keyup.esc="() => showNewBucketInput = false"
|
||||
class="input"
|
||||
placeholder="Enter the new bucket title..."
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-if="showNewBucketInput"
|
||||
v-model="newBucketTitle"
|
||||
/>
|
||||
<a
|
||||
@click="() => showNewBucketInput = true"
|
||||
class="button noshadow is-transparent is-fullwidth has-text-centered" v-if="!showNewBucketInput">
|
||||
<span class="icon is-small">
|
||||
<icon icon="plus"/>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
Create a new bucket
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- This router view is used to show the task popup while keeping the kanban board itself -->
|
||||
|
@ -1,23 +1,7 @@
|
||||
<template>
|
||||
<div :class="{ 'is-loading': taskService.loading}" class="loader-container task-view-container">
|
||||
<div class="task-view">
|
||||
<div class="heading">
|
||||
<h1 class="title task-id" v-if="task.identifier === ''">
|
||||
#{{ task.index }}
|
||||
</h1>
|
||||
<h1 class="title task-id" v-else>
|
||||
{{ task.identifier }}
|
||||
</h1>
|
||||
<div class="is-done" v-if="task.done">Done</div>
|
||||
<h1
|
||||
@focusout="saveTaskOnChange()"
|
||||
@keyup.ctrl.enter="saveTaskOnChange()"
|
||||
class="title input"
|
||||
contenteditable="true"
|
||||
ref="taskTitle">
|
||||
{{ task.title }}
|
||||
</h1>
|
||||
</div>
|
||||
<heading v-model="task"/>
|
||||
<h6 class="subtitle" v-if="parent && parent.namespace && parent.list">
|
||||
{{ parent.namespace.title }} >
|
||||
<router-link :to="{ name: listViewName, params: { listId: parent.list.id } }">
|
||||
@ -67,7 +51,7 @@
|
||||
:class="{ 'disabled': taskService.loading}"
|
||||
:config="flatPickerConfig"
|
||||
:disabled="taskService.loading || !canWrite"
|
||||
@on-close="saveTask"
|
||||
@on-close="() => saveTask()"
|
||||
class="input"
|
||||
placeholder="Click here to set a due date"
|
||||
ref="dueDate"
|
||||
@ -104,7 +88,7 @@
|
||||
:class="{ 'disabled': taskService.loading}"
|
||||
:config="flatPickerConfig"
|
||||
:disabled="taskService.loading || !canWrite"
|
||||
@on-close="saveTask"
|
||||
@on-close="() => saveTask()"
|
||||
class="input"
|
||||
placeholder="Click here to set a start date"
|
||||
ref="startDate"
|
||||
@ -129,7 +113,7 @@
|
||||
:class="{ 'disabled': taskService.loading}"
|
||||
:config="flatPickerConfig"
|
||||
:disabled="taskService.loading || !canWrite"
|
||||
@on-close="saveTask"
|
||||
@on-close="() => saveTask()"
|
||||
class="input"
|
||||
placeholder="Click here to set an end date"
|
||||
ref="endDate"
|
||||
@ -194,19 +178,11 @@
|
||||
|
||||
<!-- Description -->
|
||||
<div :class="{ 'has-top-border': activeFields.labels }" class="details content description">
|
||||
<h3>
|
||||
<span class="icon is-grey">
|
||||
<icon icon="align-left"/>
|
||||
</span>
|
||||
Description
|
||||
</h3>
|
||||
<editor
|
||||
:is-edit-enabled="canWrite"
|
||||
:upload-callback="attachmentUpload"
|
||||
:upload-enabled="true"
|
||||
@change="saveTask"
|
||||
placeholder="Click here to enter a description..."
|
||||
v-model="task.description"/>
|
||||
<description
|
||||
v-model="task"
|
||||
:can-write="canWrite"
|
||||
:attachment-upload="attachmentUpload"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Attachments -->
|
||||
@ -346,7 +322,8 @@
|
||||
|
||||
<!-- Created / Updated [by] -->
|
||||
<p class="created">
|
||||
Created <span v-tooltip="formatDate(task.created)">{{ formatDateSince(task.created) }}</span> by {{ task.createdBy.getDisplayName() }}
|
||||
Created <span v-tooltip="formatDate(task.created)">{{ formatDateSince(task.created) }}</span>
|
||||
by {{ task.createdBy.getDisplayName() }}
|
||||
<template v-if="+new Date(task.created) !== +new Date(task.updated)">
|
||||
<br/>
|
||||
<!-- Computed properties to show the actual date every time it gets updated -->
|
||||
@ -393,10 +370,10 @@ import Reminders from '../../components/tasks/partials/reminders'
|
||||
import Comments from '../../components/tasks/partials/comments'
|
||||
import router from '../../router'
|
||||
import ListSearch from '../../components/tasks/partials/listSearch'
|
||||
import description from '@/components/tasks/partials/description'
|
||||
import ColorPicker from '../../components/input/colorPicker'
|
||||
import attachmentUpload from '../../components/tasks/mixins/attachmentUpload'
|
||||
import LoadingComponent from '../../components/misc/loading'
|
||||
import ErrorComponent from '../../components/misc/error'
|
||||
import heading from '@/components/tasks/partials/heading'
|
||||
|
||||
export default {
|
||||
name: 'TaskDetailView',
|
||||
@ -413,12 +390,8 @@ export default {
|
||||
PrioritySelect,
|
||||
Comments,
|
||||
flatPickr,
|
||||
editor: () => ({
|
||||
component: import(/* webpackChunkName: "editor" */ '../../components/input/editor'),
|
||||
loading: LoadingComponent,
|
||||
error: ErrorComponent,
|
||||
timeout: 60000,
|
||||
}),
|
||||
description,
|
||||
heading,
|
||||
},
|
||||
mixins: [
|
||||
attachmentUpload,
|
||||
@ -441,10 +414,12 @@ export default {
|
||||
taskColor: '',
|
||||
|
||||
showDeleteModal: false,
|
||||
taskTitle: '',
|
||||
descriptionChanged: false,
|
||||
listViewName: 'list.list',
|
||||
|
||||
descriptionSaving: false,
|
||||
descriptionRecentlySaved: false,
|
||||
|
||||
priorities: priorites,
|
||||
flatPickerConfig: {
|
||||
altFormat: 'j M Y H:i',
|
||||
@ -519,7 +494,6 @@ export default {
|
||||
.then(r => {
|
||||
this.$set(this, 'task', r)
|
||||
this.$store.commit('attachments/set', r.attachments)
|
||||
this.taskTitle = this.task.title
|
||||
this.taskColor = this.task.hexColor
|
||||
this.setActiveFields()
|
||||
this.setTitle(this.task.title)
|
||||
@ -547,23 +521,7 @@ export default {
|
||||
this.activeFields.attachments = this.task.attachments.length > 0
|
||||
this.activeFields.relatedTasks = Object.keys(this.task.relatedTasks).length > 0
|
||||
},
|
||||
saveTaskOnChange() {
|
||||
this.$refs.taskTitle.spellcheck = false
|
||||
|
||||
// Pull the task title from the contenteditable
|
||||
let taskTitle = this.$refs.taskTitle.textContent
|
||||
this.task.title = taskTitle
|
||||
|
||||
// We only want to save if the title was actually change.
|
||||
// Because the contenteditable does not have a change event,
|
||||
// we're building it ourselves and only calling saveTask()
|
||||
// if the task title changed.
|
||||
if (this.task.title !== this.taskTitle) {
|
||||
this.saveTask()
|
||||
this.taskTitle = taskTitle
|
||||
}
|
||||
},
|
||||
saveTask(undoCallback = null) {
|
||||
saveTask(showNotification = true, undoCallback = null) {
|
||||
|
||||
if (!this.canWrite) {
|
||||
return
|
||||
@ -584,15 +542,20 @@ export default {
|
||||
this.$store.dispatch('tasks/update', this.task)
|
||||
.then(r => {
|
||||
this.$set(this, 'task', r)
|
||||
this.setActiveFields()
|
||||
|
||||
if (!showNotification) {
|
||||
return
|
||||
}
|
||||
|
||||
let actions = []
|
||||
if (undoCallback !== null) {
|
||||
actions = [{
|
||||
title: 'Undo',
|
||||
callback: undoCallback,
|
||||
}]
|
||||
this.success({message: 'The task was saved successfully.'}, this, actions)
|
||||
}
|
||||
this.setActiveFields()
|
||||
this.success({message: 'The task was saved successfully.'}, this, actions)
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
@ -610,7 +573,7 @@ export default {
|
||||
deleteTask() {
|
||||
this.$store.dispatch('tasks/delete', this.task)
|
||||
.then(() => {
|
||||
this.success({message: 'The task been deleted successfully.'}, this)
|
||||
this.success({message: 'The task has been deleted successfully.'}, this)
|
||||
router.back()
|
||||
})
|
||||
.catch(e => {
|
||||
@ -619,7 +582,7 @@ export default {
|
||||
},
|
||||
toggleTaskDone() {
|
||||
this.task.done = !this.task.done
|
||||
this.saveTask(() => this.toggleTaskDone())
|
||||
this.saveTask(true, () => this.toggleTaskDone())
|
||||
},
|
||||
setDescriptionChanged(e) {
|
||||
if (e.key === 'Enter' || e.key === 'Control') {
|
||||
|
Reference in New Issue
Block a user