2020-03-23 22:24:14 +00:00
|
|
|
<template>
|
2020-09-05 20:35:52 +00:00
|
|
|
<div :class="{'is-loading': taskService.loading}" class="task loader-container">
|
|
|
|
<fancycheckbox :disabled="isArchived || disabled" @change="markAsDone" v-model="task.done"/>
|
2020-12-10 12:06:49 +00:00
|
|
|
<span
|
|
|
|
:style="{backgroundColor: listColor }"
|
|
|
|
class="color-bubble"
|
|
|
|
v-if="listColor !== ''">
|
|
|
|
</span>
|
2020-09-05 20:35:52 +00:00
|
|
|
<span :class="{ 'done': task.done}" class="tasktext">
|
2020-08-01 13:17:10 +00:00
|
|
|
<router-link :to="{ name: taskDetailRoute, params: { id: task.id } }">
|
|
|
|
<router-link
|
2020-09-05 20:35:52 +00:00
|
|
|
:to="{ name: 'list.list', params: { listId: task.listId } }"
|
|
|
|
class="task-list"
|
|
|
|
v-if="showList && $store.getters['lists/getListById'](task.listId) !== null"
|
|
|
|
v-tooltip="`This task belongs to list '${$store.getters['lists/getListById'](task.listId).title}'`">
|
2020-08-01 13:17:10 +00:00
|
|
|
{{ $store.getters['lists/getListById'](task.listId).title }}
|
|
|
|
</router-link>
|
2020-05-11 14:52:58 +00:00
|
|
|
|
2020-08-01 13:17:10 +00:00
|
|
|
<!-- Show any parent tasks to make it clear this task is a sub task of something -->
|
|
|
|
<span class="parent-tasks" v-if="typeof task.relatedTasks.parenttask !== 'undefined'">
|
|
|
|
<template v-for="(pt, i) in task.relatedTasks.parenttask">
|
|
|
|
{{ pt.title }}<template v-if="(i + 1) < task.relatedTasks.parenttask.length">, </template>
|
|
|
|
</template>
|
|
|
|
>
|
|
|
|
</span>
|
|
|
|
{{ task.title }}
|
2020-05-11 14:52:58 +00:00
|
|
|
</router-link>
|
|
|
|
|
2020-04-01 20:13:57 +00:00
|
|
|
<labels :labels="task.labels"/>
|
|
|
|
<user
|
2020-09-05 20:35:52 +00:00
|
|
|
:avatar-size="27"
|
|
|
|
:is-inline="true"
|
|
|
|
:key="task.id + 'assignee' + a.id + i"
|
|
|
|
:show-username="false"
|
|
|
|
:user="a"
|
|
|
|
v-for="(a, i) in task.assignees"
|
2020-04-01 20:13:57 +00:00
|
|
|
/>
|
2020-08-01 13:17:10 +00:00
|
|
|
<i
|
2020-09-05 20:35:52 +00:00
|
|
|
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
|
|
|
|
@click.stop="showDefer = !showDefer"
|
|
|
|
v-if="+new Date(task.dueDate) > 0"
|
|
|
|
v-tooltip="formatDate(task.dueDate)"
|
2020-08-01 13:17:10 +00:00
|
|
|
>
|
2020-09-05 20:35:52 +00:00
|
|
|
- Due {{ formatDateSince(task.dueDate) }}
|
2020-08-01 13:17:10 +00:00
|
|
|
</i>
|
|
|
|
<transition name="fade">
|
2020-09-05 20:35:52 +00:00
|
|
|
<defer-task v-if="+new Date(task.dueDate) > 0 && showDefer" v-model="task"/>
|
2020-08-01 13:17:10 +00:00
|
|
|
</transition>
|
2020-03-23 22:24:14 +00:00
|
|
|
<priority-label :priority="task.priority"/>
|
2020-12-30 21:20:33 +00:00
|
|
|
<span>
|
|
|
|
<span class="list-task-icon" v-if="task.attachments.length > 0">
|
|
|
|
<icon icon="paperclip"/>
|
|
|
|
</span>
|
|
|
|
<span class="list-task-icon" v-if="task.description">
|
|
|
|
<icon icon="align-left"/>
|
|
|
|
</span>
|
|
|
|
</span>
|
2020-08-01 13:17:10 +00:00
|
|
|
</span>
|
2020-09-05 20:16:17 +00:00
|
|
|
<router-link
|
|
|
|
:to="{ name: 'list.list', params: { listId: task.listId } }"
|
2020-09-05 20:35:52 +00:00
|
|
|
class="task-list"
|
2020-09-05 21:42:34 +00:00
|
|
|
v-if="!showList && currentList.id !== task.listId && $store.getters['lists/getListById'](task.listId) !== null"
|
2020-09-05 20:35:52 +00:00
|
|
|
v-tooltip="`This task belongs to list '${$store.getters['lists/getListById'](task.listId).title}'`">
|
2020-09-05 20:16:17 +00:00
|
|
|
{{ $store.getters['lists/getListById'](task.listId).title }}
|
|
|
|
</router-link>
|
|
|
|
<a
|
|
|
|
:class="{'is-favorite': task.isFavorite}"
|
2020-09-05 20:35:52 +00:00
|
|
|
@click="toggleFavorite"
|
|
|
|
class="favorite">
|
2020-09-05 20:16:17 +00:00
|
|
|
<icon icon="star" v-if="task.isFavorite"/>
|
|
|
|
<icon :icon="['far', 'star']" v-else/>
|
|
|
|
</a>
|
|
|
|
<slot></slot>
|
|
|
|
</div>
|
2020-03-23 22:24:14 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2020-09-05 20:35:52 +00:00
|
|
|
import TaskModel from '../../../models/task'
|
|
|
|
import PriorityLabel from './priorityLabel'
|
|
|
|
import TaskService from '../../../services/task'
|
|
|
|
import Labels from './labels'
|
|
|
|
import User from '../../misc/user'
|
|
|
|
import Fancycheckbox from '../../input/fancycheckbox'
|
|
|
|
import DeferTask from './defer-task'
|
2020-03-23 22:24:14 +00:00
|
|
|
|
2020-09-05 20:35:52 +00:00
|
|
|
export default {
|
|
|
|
name: 'singleTaskInList',
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
taskService: TaskService,
|
|
|
|
task: TaskModel,
|
|
|
|
showDefer: false,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
components: {
|
|
|
|
DeferTask,
|
|
|
|
Fancycheckbox,
|
|
|
|
User,
|
|
|
|
Labels,
|
|
|
|
PriorityLabel,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
theTask: {
|
|
|
|
type: TaskModel,
|
|
|
|
required: true,
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
isArchived: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
taskDetailRoute: {
|
|
|
|
type: String,
|
|
|
|
default: 'task.list.detail',
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
showList: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
disabled: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
theTask(newVal) {
|
|
|
|
this.task = newVal
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
this.task = this.theTask
|
|
|
|
},
|
|
|
|
created() {
|
|
|
|
this.task = new TaskModel()
|
|
|
|
this.taskService = new TaskService()
|
|
|
|
},
|
|
|
|
computed: {
|
2020-12-10 12:06:49 +00:00
|
|
|
listColor() {
|
|
|
|
const list = this.$store.getters['lists/getListById'](this.task.listId)
|
|
|
|
return list !== null ? list.hexColor : ''
|
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
currentList() {
|
|
|
|
return typeof this.$store.state.currentList === 'undefined' ? {
|
|
|
|
id: 0,
|
|
|
|
title: '',
|
|
|
|
} : this.$store.state.currentList
|
2020-09-05 20:16:17 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
markAsDone(checked) {
|
|
|
|
const updateFunc = () => {
|
2020-09-05 20:16:17 +00:00
|
|
|
this.taskService.update(this.task)
|
|
|
|
.then(t => {
|
|
|
|
this.task = t
|
2020-10-02 16:47:45 +00:00
|
|
|
this.$emit('task-updated', t)
|
2020-09-05 20:35:52 +00:00
|
|
|
this.success(
|
|
|
|
{message: 'The task was successfully ' + (this.task.done ? '' : 'un-') + 'marked as done.'},
|
|
|
|
this,
|
|
|
|
[{
|
|
|
|
title: 'Undo',
|
|
|
|
callback: () => this.markAsDone({
|
|
|
|
target: {
|
|
|
|
checked: !checked,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
}],
|
|
|
|
)
|
2020-09-05 20:16:17 +00:00
|
|
|
})
|
|
|
|
.catch(e => {
|
|
|
|
this.error(e, this)
|
|
|
|
})
|
2020-09-05 20:35:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (checked) {
|
|
|
|
setTimeout(updateFunc, 300) // Delay it to show the animation when marking a task as done
|
|
|
|
} else {
|
|
|
|
updateFunc() // Don't delay it when un-marking it as it doesn't have an animation the other way around
|
|
|
|
}
|
|
|
|
},
|
|
|
|
toggleFavorite() {
|
|
|
|
this.task.isFavorite = !this.task.isFavorite
|
|
|
|
this.taskService.update(this.task)
|
|
|
|
.then(t => {
|
|
|
|
this.task = t
|
2020-10-02 16:47:45 +00:00
|
|
|
this.$emit('task-updated', t)
|
2020-09-05 20:35:52 +00:00
|
|
|
this.$store.dispatch('namespaces/loadNamespacesIfFavoritesDontExist')
|
|
|
|
})
|
|
|
|
.catch(e => {
|
|
|
|
this.error(e, this)
|
|
|
|
})
|
2020-03-23 22:24:14 +00:00
|
|
|
},
|
2020-09-05 20:35:52 +00:00
|
|
|
},
|
|
|
|
}
|
2020-03-23 22:24:14 +00:00
|
|
|
</script>
|