This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/components/tasks/reusable/relatedTasks.vue

222 lines
6.0 KiB
Vue
Raw Normal View History

2019-11-24 13:16:24 +00:00
<template>
<div class="task-relations">
<label class="label">New Task Relation</label>
2020-04-26 13:44:23 +00:00
<div class="field">
<multiselect
v-model="newTaskRelationTask"
:options="foundTasks"
:multiple="false"
:searchable="true"
:loading="taskService.loading"
:internal-search="true"
@search-change="findTasks"
placeholder="Type search for a new task to add as related..."
label="text"
track-by="id"
:taggable="true"
:showNoOptions="false"
@tag="createAndRelateTask"
tag-placeholder="Add this as new related task"
>
<template slot="clear" slot-scope="props">
<div
class="multiselect__clear"
2020-03-04 20:29:40 +00:00
v-if="newTaskRelationTask !== null && newTaskRelationTask.id !== 0"
@mousedown.prevent.stop="clearAllFoundTasks(props.search)"></div>
2020-04-26 13:44:23 +00:00
</template>
<span slot="noResult">No task found. Consider changing the search query.</span>
</multiselect>
</div>
<div class="field has-addons">
<div class="control is-expanded">
<div class="select is-fullwidth has-defaults">
<select v-model="newTaskRelationKind">
<option value="unset">Select a relation kind</option>
<option v-for="(label, rk) in relationKinds" :key="rk" :value="rk">
{{ label[0] }}
</option>
</select>
2019-11-24 13:16:24 +00:00
</div>
</div>
2020-04-26 13:44:23 +00:00
<div class="control">
<a class="button is-primary" @click="addTaskRelation()">Add task Relation</a>
</div>
2019-11-24 13:16:24 +00:00
</div>
2019-12-15 20:42:40 +00:00
<div class="related-tasks" v-for="(rts, kind ) in relatedTasks" :key="kind">
<template v-if="rts.length > 0">
<span class="title">{{ relationKindTitle(kind, rts.length) }}</span>
2019-12-15 20:42:40 +00:00
<div class="tasks noborder">
<div class="task" v-for="t in rts" :key="t.id">
Kanban (#118) Add error message when trying to create an invalid new task in a bucket Prevent creation of new buckets if the bucket title is empty Disable deleting a bucket if it's the last one Disable dragging tasks when they are being updated Fix transition when opening tasks Send the user to list view by default Show loading spinner when updating multiple tasks Add loading spinner when moving tasks Add loading animation when bucket is loading / updating etc Add bucket title edit Fix creating new buckets Add loading animation Add removing buckets Fix creating a new bucket after tasks were moved Fix warning about labels on tasks Fix labels on tasks not updating after retrieval from api Fix property width Add closing and mobile design Make the task detail popup look good Move list views Move task detail view in a popup Add link to tasks Add saving the new task position after it was moved Fix creating new bucket Fix creating a new task Cleanup Disable user selection for task cards Fix drag placeholder Add dragging style to task Add placeholder + change animation duration More cleanup Cleanup / docs Working of dragging and dropping tasks Adjust markup and styling for new library Change kanban library to something that works Add basic calculation of new positions Don't try to create empty tasks Add indicator if a task is done Add moving tasks between buckets Make empty buckets a little smaller Add gimmick for button description Fix color Fix scrolling bucket layout Add creating a new bucket Add hiding the task input field Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/118
2020-04-25 23:11:34 +00:00
<router-link :to="{ name: 'task.kanban.detail', params: { id: t.id } }">
2019-12-15 20:42:40 +00:00
<span class="tasktext" :class="{ 'done': t.done}">
{{t.text}}
</span>
</router-link>
2020-04-26 13:44:23 +00:00
<a
class="remove"
@click="() => {showDeleteModal = true; relationToDelete = {relationKind: kind, otherTaskId: t.id}}">
2019-12-15 20:42:40 +00:00
<icon icon="trash-alt"/>
</a>
</div>
2019-11-24 13:16:24 +00:00
</div>
2019-12-15 20:42:40 +00:00
</template>
2019-11-24 13:16:24 +00:00
</div>
2020-03-04 20:29:40 +00:00
<p v-if="showNoRelationsNotice && Object.keys(relatedTasks).length === 0" class="none">
No task relations yet.
</p>
2019-11-24 13:16:24 +00:00
<!-- Delete modal -->
<modal
v-if="showDeleteModal"
@close="showDeleteModal = false"
@submit="removeTaskRelation()">
<span slot="header">Delete Task Relation</span>
<p slot="text">Are you sure you want to delete this task relation?<br/>
<b>This CANNOT BE UNDONE!</b></p>
</modal>
</div>
</template>
<script>
import TaskService from '../../../services/task'
import TaskModel from '../../../models/task'
import TaskRelationService from '../../../services/taskRelation'
import relationKinds from '../../../models/relationKinds'
import TaskRelationModel from '../../../models/taskRelation'
import multiselect from 'vue-multiselect'
export default {
name: 'relatedTasks',
data() {
return {
relatedTasks: {},
taskService: TaskService,
foundTasks: [],
relationKinds: relationKinds,
newTaskRelationTask: TaskModel,
2020-03-04 20:29:40 +00:00
newTaskRelationKind: 'related',
2019-11-24 13:16:24 +00:00
taskRelationService: TaskRelationService,
showDeleteModal: false,
relationToDelete: {},
}
},
components: {
multiselect,
},
props: {
taskId: {
2019-11-24 13:16:24 +00:00
type: Number,
required: true,
},
initialRelatedTasks: {
type: Object,
2020-03-04 20:29:40 +00:00
default: () => {
},
2019-11-24 13:16:24 +00:00
},
showNoRelationsNotice: {
type: Boolean,
default: false,
},
2020-03-04 20:29:40 +00:00
listId: {
type: Number,
default: 0,
}
2019-11-24 13:16:24 +00:00
},
created() {
this.taskService = new TaskService()
this.taskRelationService = new TaskRelationService()
this.newTaskRelationTask = new TaskModel()
},
watch: {
initialRelatedTasks(newVal) {
this.relatedTasks = newVal
},
},
mounted() {
this.relatedTasks = this.initialRelatedTasks
},
methods: {
findTasks(query) {
if (query === '') {
this.clearAllFoundTasks()
return
}
this.taskService.getAll({}, {s: query})
.then(response => {
this.$set(this, 'foundTasks', response)
})
.catch(e => {
this.error(e, this)
2019-11-24 13:16:24 +00:00
})
},
clearAllFoundTasks() {
this.$set(this, 'foundTasks', [])
},
addTaskRelation() {
let rel = new TaskRelationModel({
taskId: this.taskId,
otherTaskId: this.newTaskRelationTask.id,
relationKind: this.newTaskRelationKind,
2019-11-24 13:16:24 +00:00
})
this.taskRelationService.create(rel)
.then(() => {
if (!this.relatedTasks[this.newTaskRelationKind]) {
this.$set(this.relatedTasks, this.newTaskRelationKind, [])
}
this.relatedTasks[this.newTaskRelationKind].push(this.newTaskRelationTask)
this.newTaskRelationKind = 'unset'
this.newTaskRelationTask = new TaskModel()
this.success({message: 'The task relation was created successfully'}, this)
2019-11-24 13:16:24 +00:00
})
.catch(e => {
this.error(e, this)
2019-11-24 13:16:24 +00:00
})
},
removeTaskRelation() {
let rel = new TaskRelationModel({
relationKind: this.relationToDelete.relationKind,
taskId: this.taskId,
otherTaskId: this.relationToDelete.otherTaskId,
2019-11-24 13:16:24 +00:00
})
this.taskRelationService.delete(rel)
.then(r => {
2020-03-04 20:29:40 +00:00
Object.keys(this.relatedTasks).forEach(relationKind => {
2019-11-24 13:16:24 +00:00
for (const t in this.relatedTasks[relationKind]) {
if (this.relatedTasks[relationKind][t].id === this.relationToDelete.otherTaskId && relationKind === this.relationToDelete.relationKind) {
2019-11-24 13:16:24 +00:00
this.relatedTasks[relationKind].splice(t, 1)
}
}
})
this.success(r, this)
2019-11-24 13:16:24 +00:00
})
.catch(e => {
this.error(e, this)
2019-11-24 13:16:24 +00:00
})
.finally(() => {
this.showDeleteModal = false
})
},
2020-03-04 20:29:40 +00:00
createAndRelateTask(text) {
const newTask = new TaskModel({text: text, listId: this.listId})
2020-03-04 20:29:40 +00:00
this.taskService.create(newTask)
.then(r => {
this.newTaskRelationTask = r
this.addTaskRelation()
})
.catch(e => {
this.error(e, this)
})
},
relationKindTitle(kind, length) {
if (length > 1) {
return relationKinds[kind][1]
}
return relationKinds[kind][0]
}
2019-11-24 13:16:24 +00:00
},
}
</script>