Load task from server if not found locally

Signed-off-by: Raimund Schlüßler <raimund.schluessler@mailbox.org>

Co-Authored-By: John Molakvoæ <skjnldsv@users.noreply.github.com>
This commit is contained in:
Raimund Schlüßler 2019-09-13 22:42:58 +02:00
parent e57091a08b
commit 741af5a5e5
No known key found for this signature in database
GPG key ID: 036FA7EB1A599178
3 changed files with 148 additions and 5 deletions

View file

@ -21,7 +21,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
<template>
<div class="content-wrapper">
<div v-if="task!=undefined"
<div v-if="task"
:class="{'disabled': task.calendar.readOnly}"
class="flex-container"
>
@ -340,7 +340,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
</div>
</div>
<div v-else class="notice">
<span>{{ $t('tasks', 'Task not found!') }}</span>
<span v-if="loading">{{ $t('tasks', 'Loading task from server.') }}</span>
<span v-else>{{ $t('tasks', 'Task not found!') }}</span>
</div>
</div>
</template>
@ -500,6 +501,7 @@ export default {
},
data: function() {
return {
loading: false,
edit: '',
tmpTask: {
summary: '',
@ -572,10 +574,21 @@ export default {
},
...mapGetters({
writableCalendars: 'getSortedWritableCalendars',
task: 'getTaskByRoute'
task: 'getTaskByRoute',
calendar: 'getCalendarByRoute',
calendars: 'getSortedCalendars',
}),
},
watch: {
$route: 'loadTask',
calendars: 'loadTask',
},
created() {
this.loadTask()
},
/**
* Before we close the details view, we save possible edits.
*
@ -615,8 +628,28 @@ export default {
'toggleAllDay',
'moveTask',
'setClassification',
'getTaskByUri',
]),
async loadTask() {
if (this.task === undefined || this.task === null) {
const calendars = this.calendar ? [this.calendar] : this.calendars
for (const calendar of calendars) {
this.loading = true
try {
const task = await this.getTaskByUri({ calendar, taskUri: this.$route.params.taskId })
// If we found the task, we don't need to query the other calendars.
if (task) {
break
}
} catch {
console.debug('Task ' + this.$route.params.taskId + ' not found in calendar ' + calendar.displayName + '.')
}
}
this.loading = false
}
},
removeTask: function() {
this.deleteTask({ task: this.task, dav: true })
this.closeDetails()

View file

@ -71,6 +71,33 @@ function findVTODObyState(calendar, completed, related) {
return calendar.dav.calendarQuery([query])
}
export {
findVTODObyState
function findVTODObyUid(calendar, taskUid) {
const query = {
name: [NS.IETF_CALDAV, 'comp-filter'],
attributes: [
['name', 'VCALENDAR']
],
children: [{
name: [NS.IETF_CALDAV, 'comp-filter'],
attributes: [
['name', 'VTODO']
]
}]
}
query.children[0].children = [{
name: [NS.IETF_CALDAV, 'prop-filter'],
attributes: [
['name', 'uid']
],
children: [{
name: [NS.IETF_CALDAV, 'text-match'],
value: taskUid
}]
}]
return calendar.dav.calendarQuery([query])
}
export {
findVTODObyState,
findVTODObyUid
}

View file

@ -27,6 +27,7 @@ import { isParentInList, momentToICALTime } from './storeHelper'
import ICAL from 'ical.js'
import TaskStatus from '../models/taskStatus'
import router from '../components/TheRouter'
import { findVTODObyUid } from './cdav-requests'
Vue.use(Vuex)
@ -720,6 +721,88 @@ const actions = {
}
},
/**
* Retrieves the task with the given uri from the given calendar
* and commits the result
*
* @param {Object} context The store mutations
* @param {Object} data Destructuring object
* @param {Calendar} data.calendar The calendar
* @param {String} data.taskUri The uri of the requested task
* @returns {Task}
*/
async getTaskByUri(context, { calendar, taskUri }) {
const response = await calendar.dav.find(taskUri)
if (response) {
const task = new Task(response.data, calendar)
Vue.set(task, 'dav', response)
if (task.related) {
let parent = context.getters.getTaskByUid(task.related)
// If the parent is not found locally, we try to get it from the server.
if (!parent) {
parent = await context.dispatch('getTaskByUid', { calendar, taskUid: task.related })
}
context.commit('addTaskToParent', { task, parent })
}
// In case we already have subtasks of this task in the store, add them as well.
const subTasksInStore = context.getters.getTasksByParent(task)
subTasksInStore.forEach(
subTask => {
context.commit('addTaskToParent', { task: subTask, parent: task })
}
)
context.commit('appendTasksToCalendar', { calendar, tasks: [task] })
context.commit('appendTasks', [task])
return task
} else {
return null
}
},
/**
* Retrieves the task with the given uid from the given calendar
* and commits the result
*
* @param {Object} context The store mutations
* @param {Object} data Destructuring object
* @param {Calendar} data.calendar The calendar
* @param {String} data.taskUid The uid of the requested task
* @returns {Task}
*/
async getTaskByUid(context, { calendar, taskUid }) {
const response = await findVTODObyUid(calendar, taskUid)
// We expect to only get zero or one task when we query by UID.
if (response.length) {
const task = new Task(response[0].data, calendar)
Vue.set(task, 'dav', response[0])
if (task.related) {
let parent = context.getters.getTaskByUid(task.related)
// If the parent is not found locally, we try to get it from the server.
if (!parent) {
parent = await context.dispatch('getTaskByUid', { calendar, taskUid: task.related })
}
context.commit('addTaskToParent', { task, parent })
}
// In case we already have subtasks of this task in the store, add them as well.
const subTasksInStore = context.getters.getTasksByParent(task)
subTasksInStore.forEach(
subTask => {
context.commit('addTaskToParent', { task: subTask, parent: task })
}
)
context.commit('appendTasksToCalendar', { calendar, tasks: [task] })
context.commit('appendTasks', [task])
return task
} else {
console.debug('no task')
return null
}
},
/**
* Toggles the completed state of a task
*