Move task heading to separate component which handles all saving related things
This commit is contained in:
parent
fde740784b
commit
7556a8f126
101
src/components/tasks/partials/heading.vue
Normal file
101
src/components/tasks/partials/heading.vue
Normal file
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<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="save()"
|
||||
@keyup.ctrl.enter="save()"
|
||||
class="title input"
|
||||
contenteditable="true"
|
||||
ref="taskTitle">
|
||||
{{ task.title }}
|
||||
</h1>
|
||||
<transition name="fade">
|
||||
<span class="is-inline-flex is-align-items-center" v-if="loading && saving">
|
||||
<span class="loader is-inline-block mr-2"></span>
|
||||
Saving...
|
||||
</span>
|
||||
<span class="has-text-success is-inline-flex is-align-content-center" v-if="!loading && saved">
|
||||
<icon icon="check" class="mr-2"/>
|
||||
Saved!
|
||||
</span>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {LOADING} from '@/store/mutation-types'
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'heading',
|
||||
data() {
|
||||
return {
|
||||
task: {title: '', identifier: '', index:''},
|
||||
taskTitle: '',
|
||||
saved: false,
|
||||
saving: false, // Since loading is global state, this variable ensures we're only showing the saving icon when saving the description.
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
loading: LOADING,
|
||||
}),
|
||||
props: {
|
||||
value: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
this.task = newVal
|
||||
this.taskTitle = this.task.title
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.task = this.value
|
||||
this.taskTitle = this.task.title
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
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() {
|
||||
this.saving = true
|
||||
|
||||
this.$store.dispatch('tasks/update', this.task)
|
||||
.then(() => {
|
||||
this.$emit('input', this.task)
|
||||
this.saved = true
|
||||
setTimeout(() => {
|
||||
this.saved = false
|
||||
}, 2000)
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
})
|
||||
.finally(() => {
|
||||
this.saving = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -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 } }">
|
||||
|
@ -389,6 +373,7 @@ 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 heading from '@/components/tasks/partials/heading'
|
||||
|
||||
export default {
|
||||
name: 'TaskDetailView',
|
||||
|
@ -406,6 +391,7 @@ export default {
|
|||
Comments,
|
||||
flatPickr,
|
||||
description,
|
||||
heading,
|
||||
},
|
||||
mixins: [
|
||||
attachmentUpload,
|
||||
|
@ -428,7 +414,6 @@ export default {
|
|||
taskColor: '',
|
||||
|
||||
showDeleteModal: false,
|
||||
taskTitle: '',
|
||||
descriptionChanged: false,
|
||||
listViewName: 'list.list',
|
||||
|
||||
|
@ -509,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)
|
||||
|
@ -537,22 +521,6 @@ 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(showNotification = true, undoCallback = null) {
|
||||
|
||||
if (!this.canWrite) {
|
||||
|
|
Reference in New Issue
Block a user