diff options
-rw-r--r-- | lib/Service/CollectionsService.php | 12 | ||||
-rw-r--r-- | lib/Service/SettingsService.php | 2 | ||||
-rw-r--r-- | package-lock.json | 7 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/app.vue | 32 | ||||
-rw-r--r-- | src/components/Task.vue | 2 | ||||
-rw-r--r-- | src/components/TheCollections/Calendar.vue | 8 | ||||
-rw-r--r-- | src/components/TheCollections/General.vue | 22 | ||||
-rw-r--r-- | src/components/TheDetails.vue | 14 | ||||
-rw-r--r-- | src/components/TheList.vue | 50 | ||||
-rw-r--r-- | src/components/TheSettings.vue | 17 | ||||
-rw-r--r-- | src/models/todo.js | 2 | ||||
-rw-r--r-- | src/services/cdav.js | 47 | ||||
-rw-r--r-- | src/services/parseIcs.js | 3 | ||||
-rw-r--r-- | src/store/calendars.js | 462 | ||||
-rw-r--r-- | src/store/collections.js | 2 | ||||
-rw-r--r-- | src/store/dummyCalendars.js | 420 | ||||
-rw-r--r-- | src/store/storeHelper.js | 2 | ||||
-rw-r--r-- | src/store/tasks.js | 10 |
19 files changed, 604 insertions, 512 deletions
diff --git a/lib/Service/CollectionsService.php b/lib/Service/CollectionsService.php index ea22317e..6f7ffa80 100644 --- a/lib/Service/CollectionsService.php +++ b/lib/Service/CollectionsService.php @@ -48,32 +48,32 @@ class CollectionsService { $collections = array( array( 'id' => "starred", - 'displayname' => (string)$this->l10n->t('Important'), + 'displayName' => (string)$this->l10n->t('Important'), 'show' => 2, 'icon' => 'icon-task-star'), array( 'id' => "today", - 'displayname' => (string)$this->l10n->t('Today'), + 'displayName' => (string)$this->l10n->t('Today'), 'show' => 2, 'icon' => 'icon-calendar'), array( 'id' => "week", - 'displayname' => (string)$this->l10n->t('Week'), + 'displayName' => (string)$this->l10n->t('Week'), 'show' => 2, 'icon' => 'icon-calendar'), array( 'id' => "all", - 'displayname' => (string)$this->l10n->t('All'), + 'displayName' => (string)$this->l10n->t('All'), 'show' => 2, 'icon' => 'icon-all'), array( 'id' => "current", - 'displayname' => (string)$this->l10n->t('Current'), + 'displayName' => (string)$this->l10n->t('Current'), 'show' => 2, 'icon' => 'icon-current'), array( 'id' => "completed", - 'displayname' => (string)$this->l10n->t('Completed'), + 'displayName' => (string)$this->l10n->t('Completed'), 'show' => 2, 'icon' => 'icon-checkmark') ); diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index 14686f2c..cc27ce26 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -43,7 +43,7 @@ class SettingsService { */ public function get() { $settings = array( - 'defaultCalendarUri' => (string)$this->settings->getUserValue($this->userId, $this->appName,'various_defaultCalendarUri'), + 'defaultCalendarId' => (string)$this->settings->getUserValue($this->userId, $this->appName,'various_defaultCalendarId'), 'showHidden' => (int)$this->settings->getUserValue($this->userId, $this->appName,'various_showHidden'), 'sortOrder' => (string)$this->settings->getUserValue($this->userId, $this->appName,'various_sortOrder'), 'sortDirection' => (bool)$this->settings->getUserValue($this->userId, $this->appName,'various_sortDirection'), diff --git a/package-lock.json b/package-lock.json index fbdb78dd..66085197 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2255,6 +2255,13 @@ "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", "dev": true }, + "cdav-library": { + "version": "github:nextcloud/cdav-library#46f1313d6d3843f7a55b8c065f2ff370f5357562", + "from": "github:nextcloud/cdav-library", + "requires": { + "@babel/polyfill": "^7.0.0" + } + }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", diff --git a/package.json b/package.json index e7425934..5128d34c 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,11 @@ "dependencies": { "axios": "^0.18.0", "babel-polyfill": "^6.26.0", + "cdav-library": "github:nextcloud/cdav-library", "ical.js": "~1.2.2", "jstimezonedetect": "", "nextcloud-vue": "^0.2.0", + "p-limit": "^2.0.0", "ui-select": "git+https://github.com/angular-ui/ui-select.git#v0.19.8", "v-tooltip": "2.0.0-rc.33", "vue": "^2.5.17", diff --git a/src/app.vue b/src/app.vue index 65ab4abd..1fe9eb29 100644 --- a/src/app.vue +++ b/src/app.vue @@ -41,12 +41,44 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <script> import TheList from './components/TheList' import TheSettings from './components/TheSettings' +import client from './services/cdav.js' export default { name: 'App', components: { 'theSettings': TheSettings, 'theList': TheList + }, + beforeMount() { + // get calendars then get todos + client.connect({ enableCalDAV: true }).then(() => { + this.$store.dispatch('getCalendars') + .then((calendars) => { + // No calendars? Create a new one! + if (calendars.length === 0) { + this.$store.dispatch('appendCalendar', { displayName: t('tasks', 'Tasks') }) + .then(() => { + this.fetchTodos() + }) + // else, let's get those todos! + } else { + this.fetchTodos() + } + }) + }) + }, + methods: { + /** + * Fetch the todos of each calendar + */ + fetchTodos() { + // wait for all calendars to have fetch their todos + // Promise.all(this.calendars.map(calendar => this.$store.dispatch('getTodosFromCalendar', { calendar }))) + // .then(results => { + // this.loading = false + // console.log(results) + // }) + } } } </script> diff --git a/src/components/Task.vue b/src/components/Task.vue index fbe576e9..b0ae1a7f 100644 --- a/src/components/Task.vue +++ b/src/components/Task.vue @@ -45,7 +45,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <a class="task-star" @click="toggleStarred(task.uri)"> <span :class="[iconStar]" class="icon icon-task-star right large reactive" /> </a> - <a v-show="task.calendar.writable" + <a v-show="!task.calendar.readOnly" class="task-addsubtask add-subtask"> <span :taskId="task.uri" :title="subtasksCreationPlaceholder(task.summary)" class="icon icon-add right large reactive" diff --git a/src/components/TheCollections/Calendar.vue b/src/components/TheCollections/Calendar.vue index 9af7ac73..0e0c6496 100644 --- a/src/components/TheCollections/Calendar.vue +++ b/src/components/TheCollections/Calendar.vue @@ -20,8 +20,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. --> <template> - <div> - <div v-show="calendar.writable" + <div v-if="calendar"> + <div v-show="!calendar.readOnly" id="add-task" class="add-task"> <form name="addTaskForm" @submit="addTask"> @@ -129,7 +129,7 @@ export default { }, inputString: function() { - return t('tasks', 'Add a task to "{calendar}"...', { calendar: this.calendar.displayname }) + return t('tasks', 'Add a task to "{calendar}"...', { calendar: this.calendar.displayName }) }, /** @@ -155,7 +155,7 @@ export default { }, addTask: function() { - console.log('Add task with name ' + this.newTaskName + ' to calendar ' + this.calendar.displayname) + console.log('Add task with name ' + this.newTaskName + ' to calendar ' + this.calendar.displayName) this.newTaskName = '' } } diff --git a/src/components/TheCollections/General.vue b/src/components/TheCollections/General.vue index 6bc20101..3ec2c9eb 100644 --- a/src/components/TheCollections/General.vue +++ b/src/components/TheCollections/General.vue @@ -20,8 +20,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. --> <template> - <div> - <div v-show="collectionId !== 'completed' && calendar.writable" + <div v-if="calendar"> + <div v-show="collectionId !== 'completed' && !calendar.readOnly" id="add-task" class="add-task"> <form name="addTaskForm" @submit="addTask"> @@ -36,17 +36,17 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <div class="task-list"> <div v-for="calendar in filteredCalendars" :key="calendar.id" - :rel="calendar.uri" + :rel="calendar.id" class="grouped-tasks ui-droppable"> - <h2 class="heading">{{ calendar.displayname }}</h2> - <ol :calendarID="calendar.uri" + <h2 class="heading">{{ calendar.displayName }}</h2> + <ol :calendarID="calendar.id" :collectionID="collectionId" class="tasks" type="list" dnd-list="draggedTasks" dnd-drop="dropAsRootTask(event, item, index)" dnd-dragover="dragover(event, index)"> - <router-link v-for="task in filteredTasks = tasks(calendar.uri)" + <router-link v-for="task in filteredTasks = tasks(calendar.id)" :task-id="task.uri" :key="task.uid" :to="'/collections/' + collectionId + '/tasks/' + task.uri" @@ -109,20 +109,20 @@ export default { */ filteredCalendars: function() { return this.calendars.filter(calendar => { - return this.calendarCount(calendar.uri, this.$route.params.collectionId) + return this.calendarCount(calendar.id, this.$route.params.collectionId) }) }, inputString: function() { switch (this.collectionId) { case 'starred': - return t('tasks', 'Add an important task to "{calendar}"...', { calendar: this.calendar.displayname }) + return t('tasks', 'Add an important task to "{calendar}"...', { calendar: this.calendar.displayName }) case 'today': - return t('tasks', 'Add a task due today to "{calendar}"...', { calendar: this.calendar.displayname }) + return t('tasks', 'Add a task due today to "{calendar}"...', { calendar: this.calendar.displayName }) case 'all': - return t('tasks', 'Add a task to "{calendar}"...', { calendar: this.calendar.displayname }) + return t('tasks', 'Add a task to "{calendar}"...', { calendar: this.calendar.displayName }) case 'current': - return t('tasks', 'Add a current task to "{calendar}"...', { calendar: this.calendar.displayname }) + return t('tasks', 'Add a current task to "{calendar}"...', { calendar: this.calendar.displayName }) } } }, diff --git a/src/components/TheDetails.vue b/src/components/TheDetails.vue index 007f7523..b172dbad 100644 --- a/src/components/TheDetails.vue +++ b/src/components/TheDetails.vue @@ -22,7 +22,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <template> <div class="content-wrapper"> <div v-if="task!=undefined" - :class="{'disabled': !task.calendar.writable}" + :class="{'disabled': task.calendar.readOnly}" class="flex-container"> <div :class="{'editing': edit=='summary'}" class="title"> <a :aria-checked="task.completed" @@ -30,10 +30,10 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. class="checkbox reactive" role="checkbox" @click="toggleCompleted(task.uri)"> - <span :class="{'icon-checkmark': task.completed, 'disabled': !task.calendar.writable}" class="icon detail-checkbox" /> + <span :class="{'icon-checkmark': task.completed, 'disabled': task.calendar.readOnly}" class="icon detail-checkbox" /> </a> <a class="star reactive" @click="toggleStarred(task.uri)"> - <span :class="[{'disabled': !task.calendar.writable}, iconStar]" + <span :class="[{'disabled': task.calendar.readOnly}, iconStar]" class="icon icon-task-star" /> </a> <div v-click-outside="() => finishEditing('summary')"> @@ -117,7 +117,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. role="checkbox" @click="toggleAllDay(task.uri)"> <div> - <span :class="{'icon-checkmark': task.allDay, 'disabled': !task.calendar.writable}" class="icon detail-checkbox" /> + <span :class="{'icon-checkmark': task.allDay, 'disabled': task.calendar.readOnly}" class="icon detail-checkbox" /> <span class="section-title">{{ t('tasks', 'All day') }}</span> </div> </li> @@ -227,7 +227,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. </ul> </div> <div class="footer"> - <a v-show="task.calendar.writable" + <a v-show="!task.calendar.readOnly" class="left close-all reactive" @click="deleteTask(task.uri)"> <span class="icon icon-trash" /> @@ -389,7 +389,7 @@ export default { }, computed: Object.assign({ isAllDayPossible: function() { - return this.task.calendar.writable && (this.task.due || this.task.start) + return !this.task.calendar.readOnly && (this.task.due || this.task.start) }, priorityString: function() { if (this.task.priority > 5) { @@ -452,7 +452,7 @@ export default { if (event && event.target.classList.contains('mx-datepicker-btn-confirm')) { return } - if (this.task.calendar.writable && this.edit !== type) { + if (!this.task.calendar.readOnly && this.edit !== type) { this.edit = type this.tmpTask[type] = this.task[type] } diff --git a/src/components/TheList.vue b/src/components/TheList.vue index 0dab655f..877bdfe3 100644 --- a/src/components/TheList.vue +++ b/src/components/TheList.vue @@ -35,7 +35,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. dnd-dragover="dragoverCollection(event, index)"> <a class="sprite"> <span v-if="collection.id=='today'" class="date">{{ dayOfMonth }}</span> - <span class="title">{{ collection.displayname }}</span> + <span class="title">{{ collection.displayName }}</span> </a> <div v-if="collection.id!='completed'" class="app-navigation-entry-utils"> <ul> @@ -46,11 +46,11 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <router-link v-click-outside="() => resetView(calendar)" v-for="calendar in calendars" - :id="'list_' + calendar.uri" - :calendar-id="calendar.uri" - :to="'/calendars/' + calendar.uri" - :key="calendar.uri" - :class="{edit: editing == calendar.uri, caldav: caldav == calendar.uri}" + :id="'list_' + calendar.id" + :calendar-id="calendar.id" + :to="'/calendars/' + calendar.id" + :key="calendar.id" + :class="{edit: editing == calendar.id, caldav: caldav == calendar.id}" tag="li" class="list with-menu editing" active-class="active" @@ -59,12 +59,12 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. dnd-dragover="dragoverList(event, index)"> <div :style="{'background-color': calendar.color}" class="app-navigation-entry-bullet" /> <a> - <span class="title">{{ calendar.displayname }}</span> + <span class="title">{{ calendar.displayName }}</span> </a> <div class="app-navigation-entry-utils"> <ul> - <li class="app-navigation-entry-utils-counter">{{ calendarCount(calendar.uri) | counterFormatter }}</li> - <popover v-show="calendar.writable" tag="li" class="app-navigation-entry-utils-menu-button"> + <li class="app-navigation-entry-utils-counter">{{ calendarCount(calendar.id) | counterFormatter }}</li> + <popover v-show="!calendar.readOnly" tag="li" class="app-navigation-entry-utils-menu-button"> <ul> <li> <a @click="edit(calendar)"> @@ -79,12 +79,12 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. </a> </li> <li> - <a :href="exportUrl(calendar)" :download="calendar.uri + '.ics'"> + <a :href="exportUrl(calendar)" :download="calendar.id + '.ics'"> <span class="icon-download" /> <span>{{ t('tasks', 'Download') }}</span> </a> </li> - <confirmation :message="deleteMessage(calendar.displayname)" @delete-calendar="deleteCalendar(calendar, ...arguments)" /> + <confirmation :message="deleteMessage(calendar.displayName)" @delete-calendar="deleteCalendar(calendar, ...arguments)" /> </ul> </popover> </ul> @@ -93,14 +93,14 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <form> <input v-tooltip="{ content: tooltipMessage, - show: showTooltip(calendar.uri), + show: showTooltip(calendar.id), trigger: 'manual' }" v-model="newCalendarName" class="edit" type="text" autofocus-on-insert - @keyup="checkName($event, calendar.uri)"> + @keyup="checkName($event, calendar.id)"> <input :title="t('tasks', 'Cancel')" type="cancel" value="" @@ -234,23 +234,23 @@ export default { return this.tooltipTarget === target }, edit: function(calendar) { - this.editing = calendar.uri - this.newCalendarName = calendar.displayname + this.editing = calendar.id + this.newCalendarName = calendar.displayName this.selectedColor = calendar.color this.nameError = false this.tooltipTarget = '' }, resetView: function(calendar) { - if (this.editing === calendar.uri) { + if (this.editing === calendar.id) { this.editing = '' } - if (this.caldav === calendar.uri) { + if (this.caldav === calendar.id) { this.caldav = '' } this.tooltipTarget = '' }, showCalDAVUrl: function(calendar) { - this.caldav = calendar.uri + this.caldav = calendar.id }, exportUrl(calendar) { var url = calendar.url @@ -284,14 +284,14 @@ export default { }, save: function(calendar) { // TODO: Call correct methods of store - console.log('Change name and color of calendar ' + calendar.uri + ' to ' + this.newCalendarName + ' and ' + this.selectedColor) + console.log('Change name and color of calendar ' + calendar.id + ' to ' + this.newCalendarName + ' and ' + this.selectedColor) this.editing = false }, - checkName: function(event, uri) { - var check = this.isNameAllowed(this.newCalendarName, uri) + checkName: function(event, id) { + var check = this.isNameAllowed(this.newCalendarName, id) this.tooltipMessage = check.msg if (!check.allowed) { - this.tooltipTarget = uri + this.tooltipTarget = id this.nameError = true } else { this.tooltipTarget = '' @@ -305,12 +305,12 @@ export default { this.nameError = false } }, - isNameAllowed: function(name, uri) { + isNameAllowed: function(name, id) { var check = { allowed: false, msg: '' } - if (this.isCalendarNameUsed(name, uri)) { + if (this.isCalendarNameUsed(name, id)) { check.msg = t('tasks', 'The name "%s" is already used.').replace('%s', name) } else if (!name) { check.msg = t('tasks', 'An empty name is not allowed.') @@ -323,7 +323,7 @@ export default { return t('tasks', 'This will delete the calendar "%s" and all corresponding events and tasks.').replace('%s', name) }, deleteCalendar: function(calendar) { - console.log('Delete calendar ' + calendar.uri) + console.log('Delete calendar ' + calendar.id) } } } diff --git a/src/components/TheSettings.vue b/src/components/TheSettings.vue index 2851defc..7d8cb574 100644 --- a/src/components/TheSettings.vue +++ b/src/components/TheSettings.vue @@ -30,11 +30,11 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <ul> <li> <label for="defaultCalendar">{{ t('tasks', 'Default list') }}</label> - <select id="defaultCalendar" v-model="defaultCalendarUri"> + <select id="defaultCalendar" v-model="defaultCalendarId"> <option v-for="calendar in calendars" - :value="calendar.uri" - :key="calendar.uri"> - {{ calendar.displayname }} + :value="calendar.id" + :key="calendar.id"> + {{ calendar.displayName }} </option> </select> </li> @@ -47,7 +47,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. <span :class="collection.icon" class="icon"> <span v-if="collection.id=='today'">{{ dayOfMonth }}</span> </span> - <label :for="'visibilityCollection-' + collection.id" class="title">{{ collection.displayname }}</label> + <label :for="'visibilityCollection-' + collection.id" class="title">{{ collection.displayName }}</label> </div> <select :id="'visibilityCollection-' + collection.id" :value="collection.show" @@ -90,12 +90,13 @@ export default { } }, computed: Object.assign({ - defaultCalendarUri: { + defaultCalendarId: { get() { - return this.$store.getters.getDefaultCalendar.uri + var cal = this.$store.getters.getDefaultCalendar + return cal ? cal.id : '' }, set(value) { - this.$store.dispatch('setSetting', { type: 'defaultCalendarUri', value: value }) + this.$store.dispatch('setSetting', { type: 'defaultCalendarId', value: value }) } } }, diff --git a/src/models/todo.js b/src/models/todo.js new file mode 100644 index 00000000..81484fa7 --- /dev/null +++ b/src/models/todo.js @@ -0,0 +1,2 @@ +export default class { +} diff --git a/src/services/cdav.js b/src/services/cdav.js new file mode 100644 index 00000000..a913404b --- /dev/null +++ b/src/services/cdav.js @@ -0,0 +1,47 @@ +/** + * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +import DavClient from 'cdav-library' + +function xhrProvider() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'requesttoken': OC.requestToken + } + var xhr = new XMLHttpRequest() + var oldOpen = xhr.open + + // override open() method to add headers + xhr.open = function() { + var result = oldOpen.apply(this, arguments) + for (let name in headers) { + xhr.setRequestHeader(name, headers[name]) + } + return result + } + OC.registerXHRForErrorProcessing(xhr) + return xhr +} + +export default new DavClient({ + rootUrl: OC.linkToRemote('dav') +}, xhrProvider) diff --git a/src/services/parseIcs.js b/src/services/parseIcs.js new file mode 100644 index 00000000..be5499a2 --- /dev/null +++ b/src/services/parseIcs.js @@ -0,0 +1,3 @@ +export default function(ics, calendar) { + +} diff --git a/src/store/calendars.js b/src/store/calendars.js index ad778e1d..2d745a11 100644 --- a/src/store/calendars.js +++ b/src/store/calendars.js @@ -4,6 +4,15 @@ * @author Raimund Schlüßler * @copyright 2018 Raimund Schlüßler <raimund.schluessler@mailbox.org> * + * @author John Molakvoæ + * @copyright 2018 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author Georg Ehrke + * @copyright 2018 Georg Ehrke <oc.list@georgehrke.com> + * + * @author Thomas Citharel <tcit@tcit.fr> + * @copyright 2018 Thomas Citharel <tcit@tcit.fr> + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE * License as published by the Free Software Foundation; either @@ -21,15 +30,49 @@ 'use strict' import Vue from 'vue' -import Vuex from 'vuex' -import DummyCalendars from './dummyCalendars' - +import ICAL from 'ical.js' +import parseIcs from '../services/parseIcs' +import client from '../services/cdav' +import Event from '../models/todo' +import pLimit from 'p-limit' import { isTaskInList } from './storeHelper' -Vue.use(Vuex) +const calendarModel = { + id: '', + color: '', + displayName: '', + enabled: true, + owner: '', + shares: [], + tasks: [], + url: '', + readOnly: false, + dav: false +} const state = { - calendars: DummyCalendars.calendars + calendars: [] +} + +/** + * map a dav collection to our calendar object model + * + * @param {Object} calendar the calendar object from the cdav library + * @returns {Object} + */ +export function mapDavCollectionToCalendar(calendar) { + return { + // get last part of url + id: calendar.url.split('/').slice(-2, -1)[0], + displayName: calendar.displayname, + color: calendar.color, + enabled: calendar.enabled !== false, + owner: calendar.owner, + readOnly: false, // this currently does not work correctly. Need to get the state from the actual calendar! + tasks: [], + url: calendar.url, + dav: calendar + } } const getters = { @@ -38,13 +81,18 @@ const getters = { * Returns the calendars sorted alphabetically */ getSortedCalendars: state => { - return Object.values(state.calendars).sort(function(cal1, cal2) { - var n1 = cal1.displayname.toUpperCase() - var n2 = cal2.displayname.toUpperCase() + return state.calendars.sort(function(cal1, cal2) { + var n1 = cal1.displayName.toUpperCase() + var n2 = cal2.displayName.toUpperCase() return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0 }) }, + getCalendarById: state => (calendarId) => { + var calendar = state.calendars.find(search => search.id === calendarId) + return calendar + }, + /** * Returns the count of tasks in a calendar * @@ -54,8 +102,9 @@ const getters = { * * @param {String} calendarId the Id of the calendar in question */ - getCalendarCount: state => (calendarId) => { - return Object.values(state.calendars[calendarId].tasks) + getCalendarCount: (state, getters) => (calendarId) => { + var calendar = getters.getCalendarById(calendarId) + return Object.values(calendar.tasks) .filter(task => { return task.completed === false && !task.related }).length @@ -72,8 +121,8 @@ const getters = { * @param {String} calendarId the Id of the calendar in question * @param {String} collectionId the Id of the collection in question */ - getCalendarCountByCollectionId: state => (calendarId, collectionId) => { - var calendar = state.calendars[calendarId] + getCalendarCountByCollectionId: (state, getters) => (calendarId, collectionId) => { + var calendar = getters.getCalendarById(calendarId) var count = calendar.tasks.filter(task => { return isTaskInList(task, collectionId) && !task.related }).length @@ -89,8 +138,9 @@ const getters = { * * @param {String} calendarId the Id of the calendar in question */ - getCalendarCountCompleted: state => (calendarId) => { - return Object.values(state.calendars[calendarId].tasks) + getCalendarCountCompleted: (state, getters) => (calendarId) => { + var calendar = getters.getCalendarById(calendarId) + return Object.values(calendar.tasks) .filter(task => { return task.completed === true && !task.related }).length @@ -100,12 +150,11 @@ const getters = { * Returns if a calendar name is already used by an other calendar * * @param {String} name the name to check - * @param {String} uri the uri of the calendar to exclude + * @param {String} id the Id of the calendar to exclude */ - isCalendarNameUsed: state => (name, uri) => { - var calendars = Object.values(state.calendars) - return calendars.some(calendar => { - return (calendar.displayname === name && calendar.uri !== uri) + isCalendarNameUsed: state => (name, id) => { + return state.calendars.some(calendar => { + return (calendar.displayname === name && calendar.id !== id) }) }, @@ -113,7 +162,7 @@ const getters = { * Returns the current calendar */ getCalendarByRoute: (state, getters, rootState) => { - return state.calendars[rootState.route.params.calendarId] + return getters.getCalendarById(rootState.route.params.calendarId) }, /** @@ -123,12 +172,379 @@ const getters = { * Calendar order might change randomly. */ getDefaultCalendar: (state, getters, rootState) => { - return state.calendars[rootState.settings.settings.defaultCalendarUri] || getters.getSortedCalendars[0] + return getters.getCalendarById(rootState.settings.settings.defaultCalendarId) || getters.getSortedCalendars[0] } } -const mutations = {} +const mutations = { + + /** + * Add calendar into state + * + * @param {Object} state the store data + * @param {Object} calendar the calendar to add + */ + addCalendar(state, calendar) { + // extend the calendar to the default model + state.calendars.push(Object.assign({}, calendarModel, calendar)) + }, + + /** + * Delete calendar + * + * @param {Object} state the store data + * @param {Object} calendar the calendar to delete + */ + deleteCalendar(state, calendar) { + state.calendars.splice(state.calendars.indexOf(calendar), 1) + }, + + /** + * Toggle whether a calendar is Enabled + * @param {Object} context the store mutations + * @param {Object} calendar the calendar to toggle + */ + toggleCalendarEnabled(context, calendar) { + calendar = state.calendars.find(search => search.id === calendar.id) + calendar.enabled = !calendar.enabled + }, + + /** + * Rename a calendar + * @param {Object} context the store mutations + * @param {Object} data destructuring object + * @param {Object} data.calendar the calendar to rename + * @param {String} data.newName the new name of the calendar + */ + renameCalendar(context, { calendar, newName }) { + calendar = state.calendars.find(search => search.id === calendar.id) + calendar.displayName = newName + }, + + /** + * Append a list of events to an calendar + * and remove duplicates + * + * @param {Object} state the store data + * @param {Object} data destructuring object + * @param {Object} data.calendar the calendar to add the event to + * @param {Event[]} data.events array of events to append + */ + appendEventsToCalendar(state, { calendar, events }) { + calendar = state.calendars.find(search => search === calendar) + + // convert list into an array and remove duplicate + calendar.events = events.reduce((list, event) => { + if (list[event.uid]) { + console.debug('Duplicate event overrided', list[event.uid], event) + } + Vue.set(list, event.uid, event) + return list + }, calendar.events) + }, + + /** + * Add an event to an calendar and overwrite if duplicate uid + * + * @param {Object} state the store data + * @param {Event} event the event to add + */ + addEventToCalendar(state, event) { + let calendar = state.calendars.find(search => search.id === event.calendar.id) + Vue.set(calendar.events, event.uid, event) + }, + + /** + * Delete an event in a specified calendar + * + * @param {Object} state the store data + * @param {Event} event the event to delete + */ + deleteEventFromCalendar(state, event) { + let calendar = state.calendars.find(search => search.id === event.calendar.id) + Vue.delete(calendar, event.uid) + }, -const actions = {} + /** + * Share calendar with a user or group + * + * @param {Object} state the store data + * @param {Object} data destructuring object + * @param {Object} data.calendar the calendar + * @param {string} data.sharee the sharee + * @param {string} data.id id + * @param {Boolean} data.group group + */ + shareCalendar(state, { calendar, sharee, id, group }) { + calendar = state.calendars.find(search => search.id === calendar.id) + let newSharee = { + displayname: sharee, + id, + writeable: false, + group + } + calendar.shares.push(newSharee) + }, + + /** + * Remove Sharee from calendar shares list + * + * @param {Object} state the store data + * @param {Object} sharee the sharee + */ + removeSharee(state, sharee) { + let calendar = state.calendars.find(search => { + for (let i in search.shares) { + if (search.shares[i] === sharee) { + return true + } + } + }) + calendar.shares.splice(calendar.shares.indexOf(sharee), 1) + }, + + /** + * Toggle sharee's writable permission + * + * @param {Object} state the store data + * @param {Object} sharee the sharee + */ + updateShareeWritable(state, sharee) { + let calendar = state.calendars.find(search => { + for (let i in search.shares) { + if (search.shares[i] === sharee) { + return true + } + } + }) + sharee = calendar.shares.find(search => search === sharee) + sharee.writeable = !sharee.writeable + } +} + +const actions = { + /** + * Retrieve and commit calendars + * + * @param {Object} context the store mutations + * @returns {Promise<Array>} the calendars + */ + async getCalendars(context) { + let calendars = await client.calendarHomes[0].findAllCalendars() + .then(calendars => { + return calendars.map(calendar => { + return mapDavCollectionToCalendar(calendar) + }) + }) + + calendars.forEach(calendar => { + context.commit('addCalendar', calendar) + }) + + return calendars + }, + + /** + * Append a new calendar to array of existing calendars + * + * @param {Object} context the store mutations + * @param {Object} calendar The calendar to append + * @returns {Promise} + */ + async appendCalendar(context, calendar) { + return client.calendarHomes[0].createCalendarCollection(calendar.displayName) + .then((response) => { + calendar = mapDavCollectionToCalendar(response) + context.commit('addCalendar', calendar) + }) + .catch((error) => { throw error }) + }, + + /** + * Delete calendar + * @param {Object} context the store mutations Current context + * @param {Object} calendar the calendar to delete + * @returns {Promise} + */ + async deleteCalendar(context, calendar) { + return calendar.dav.delete() + .then((response) => { + // delete all the events from the store that belong to this calendar + Object.values(calendar.events) + .forEach(event => context.commit('deleteEvent', event)) + // then delete the calendar + context.commit('deleteCalendar', calendar) + }) + .catch((error) => { throw error }) + }, + + /** + * Toggle whether a calendar is Enabled + * @param {Object} context the store mutations Current context + * @param {Object} calendar the calendar to toggle + * @returns {Promise} + */ + async toggleCalendarEnabled(context, calendar) { + calendar.dav.enabled = !calendar.dav.enabled + return calendar.dav.update() + .then((response) => context.commit('toggleCalendarEnabled', calendar)) + .catch((error) => { throw error }) + }, + + /** + * Rename a calendar + * @param {Object} context the store mutations Current context + * @param {Object} data.calendar the calendar to rename + * @param {String} data.newName the new name of the calendar + * @returns {Promise} + */ + async renameCalendar(context, { calendar, newName }) { + calendar.dav.displayname = newName + return calendar.dav.update() + .then((response) => context.commit('renameCalendar', { calendar, newName })) + .catch((error) => { throw error }) + }, + + /** + * Retrieve the events of the specified calendar + * and commit the results + * + * @param {Object} context the store mutations + * @param {Object} importDetails = { ics, calendar } + * @returns {Promise} + */ + async getTodosFromCalendar(context, { calendar }) { + return calendar.dav.findByType('VTODO') + .then((response) => { + // We don't want to lose the url information + // so we need to parse one by one + const events = response.map(item => { + let event = new Event(item.data, calendar) + Vue.set(event, 'dav', item) + return event + }) + context.commit('appendTodosToCalendar', { calendar, events }) + context.commit('appendTodos', events) + return events + }) + .catch((error) => { + // unrecoverable error, if no events were loaded, + // remove the calendar + // TODO: create a failed calendar state and show that there was an issue? + context.commit('deleteCalendar', calendar) + console.error(error) + }) + }, + + /** + * + * @param {Object} context the store mutations + * @param {Object} importDetails = { ics, calendar } + */ + async importEventsIntoCalendar(context, { ics, calendar }) { + const events = parseIcs(ics, calendar) + context.commit('changeStage', 'importing') + + // max simultaneous requests + const limit = pLimit(3) + const requests = [] + + // create the array of requests to send + events.map(async event => { + // Get vcard string + try { + let vData = ICAL.stringify(event.vCard.jCal) + // push event to server and use limit + requests.push(limit(() => event.calendar.dav.createVCard(vData) + .then((response) => { + // setting the event dav property + Vue.set(event, 'dav', response) + + // success, update store + context.commit('addEvent', event) + context.commit('addEventToCalendar', event) + context.commit('incrementAccepted') + }) + .catch((error) => { + // error + context.commit('incrementDenied') + console.error(error) + }) + )) + } catch (e) { + context.commit('incrementDenied') + } + }) + + Promise.all(requests).then(() => { + context.commit('changeStage', 'default') + }) + }, + + /** + * Remove sharee from calendar + * @param {Object} context the store mutations Current context + * @param {Object} sharee calendar sharee object + */ + removeSharee(context, sharee) { + context.commit('removeSharee', sharee) + }, + + /** + * Toggle permissions of calendar Sharees writeable rights + * @param {Object} context the store mutations Current context + * @param {Object} sharee calendar sharee object + */ + toggleShareeWritable(context, sharee) { + context.commit('updateShareeWritable', sharee) + }, + + /** + * Share calendar with User or Group + * @param {Object} context the store mutations Current context + * @param {Object} data.calendar the calendar + * @param {String} data.sharee the sharee + * @param {Boolean} data.id id + * @param {Boolean} data.group group + */ + shareCalendar(context, { calendar, sharee, id, group }) { + // Share calendar with entered group or user + context.commit('shareCalendar', { calendar, sharee, id, group }) + }, + + /** + * Move an event to the provided calendar + * + * @param {Object} context the store mutations + * @param {Object} data destructuring object + * @param {Event} data.event the event to move + * @param {Object} data.calendar the calendar to move the event to + */ + async moveEventToCalendar(context, { event, calendar }) { + // only local move if the event doesn't exists on the server + if (event.dav) { + // TODO: implement proper move + // await events.dav.move(calendar.dav) + // .catch((error) => { + // console.error(error) + // OC.Notification.showTemporary(t('calendars', 'An error occurred')) + // }) + let vData = ICAL.stringify(event.vCard.jCal) + let newDav + await calendar.dav.createVCard(vData) + .then((response) => { newDav = response }) + .catch((error) => { throw error }) + await event.dav.delete() + .catch((error) => { + console.error(error) + OC.Notification.showTemporary(t('calendars', 'An error occurred')) + }) + await Vue.set(event, 'dav', newDav) + } + await context.commit('deleteEventFromCalendar', event) + await context.commit('updateEventCalendar', { event, calendar }) + await context.commit('addEventToCalendar', event) + } +} export default { state, getters, mutations, actions } diff --git a/src/store/collections.js b/src/store/collections.js index 55515864..d62d7a64 100644 --- a/src/store/collections.js +++ b/src/store/collections.js @@ -46,7 +46,7 @@ const getters = { */ getCollectionCount: (state, getters, rootState) => (collectionId) => { var count = 0 - Object.values(rootState.calendars.calendars).forEach(calendar => { + rootState.calendars.calendars.forEach(calendar => { count += calendar.tasks.filter(task => { return isTaskInList(task, collectionId) && !task.related }).length diff --git a/src/store/dummyCalendars.js b/src/store/dummyCalendars.js deleted file mode 100644 index 62964c23..00000000 --- a/src/store/dummyCalendars.js +++ /dev/null @@ -1,420 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler <raimund.schluessler@mailbox.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - */ -'use strict' - -export default ({ - calendars: { - 'test-1': { - uri: 'test-1', - displayname: 'Test 1', - color: '#ff0000', - writable: true, - url: '/nextcloud/remote.php/dav/calendars/raimund.schluessler/test-1', - caldav: 'caldav-url', - tasks: [ - { - calendar: { - writable: true, - color: '#ff0000' - }, - uid: 'ydf95848mn', - uri: 'ydf95848mn.ics', - // construct dates for tomorrow - due: moment().add(1, 'days').format('YYYYMMDDTHHmmss'), - start: moment().add(1, 'days').format('YYYYMMDDTHHmmss'), - summary: 'Test 1 - Task 1', - complete: 0, - completed: true, - priority: 1, - categories: [ - { - id: 1, - name: 'Test 1 Category 1' - }, - { - id: 2, - name: 'Test 1 Category 2' - }, - { - id: 3, - name: 'Test 1 Category 3' - }, - { - id: 4, - name: 'Test 1 Category 4' - }, - { - id: 5, - name: 'Test 1 Category 5' - }, - { - id: 6, - name: 'Test 1 Category 6' - } - ], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: true, - color: '#ff0000' - }, - uid: 'ydf95748mn', - uri: 'ydf95748mn.ics', - // construct dates for yesterday - due: moment().subtract(1, 'days').format('YYYYMMDDTHHmmss'), - start: moment().subtract(1, 'days').format('YYYYMMDDTHHmmss'), - summary: 'Test 1 - Task 2', - complete: 20, - completed: false, - priority: 5, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: true, - color: '#ff0000' - }, - uid: 'ydf95849mn', - uri: 'ydf95849mn.ics', - // construct dates for last week - due: moment().subtract(5, 'days').format('YYYYMMDDTHHmmss'), - start: moment().subtract(5, 'days').format('YYYYMMDDTHHmmss'), - summary: 'Test 1 - Task 3', - complete: 60, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - related: 'ydf95748mn', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: true, - color: '#ff0000' - }, - uid: 'rtf95849mn', - uri: 'rtf95849mn.ics', - // construct dates for next week - due: moment().add(5, 'days').format('YYYYMMDDTHHmmss'), - start: moment().add(5, 'days').format('YYYYMMDDTHHmmss'), - summary: 'Test 1 - Task 4', - complete: 0, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - related: 'ydf95748mn', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: true, - color: '#ff0000' - }, - uid: 'yaf92889mn', - uri: 'yaf92889mn.ics', - // construct dates for today future - due: moment().add(1, 'hours').format('YYYYMMDDTHHmmss'), - start: moment().add(1, 'hours').format('YYYYMMDDTHHmmss'), - summary: 'Test 1 - Task 5', - complete: 80, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - related: 'ydf95849mn', - hideSubtasks: false, - allDay: false - } - ] - }, - 'test-2': { - uri: 'test-2', - displayname: 'Test 2', - color: '#eef', - writable: false, - url: '/nextcloud/remote.php/dav/calendars/raimund.schluessler/test-2', - tasks: [ - { - calendar: { - writable: false, - color: '#eef' - }, - uid: 'ydf91848mn', - uri: 'ydf91848mn.ics', - // construct dates for today past - due: moment().subtract(1, 'hours').format('YYYYMMDDTHHmmss'), - start: moment().subtract(1, 'hours').format('YYYYMMDDTHHmmss'), - summary: 'Test 2 - Task 1', - complete: 90, - completed: true, - priority: 1, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: false, - color: '#eef' - }, - uid: 'yef91848mn', - uri: 'yef91848mn.ics', - // construct dates for far future - due: moment().add(5, 'years').format('YYYYMMDDTHHmmss'), - start: moment().add(5, 'years').format('YYYYMMDDTHHmmss'), - summary: 'Test 2 - Task 2', - complete: 0, - completed: false, - priority: 5, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: false, - color: '#eef' - }, - uid: 'yff91848mn', - uri: 'yff91848mn.ics', - // construct dates for far past - due: moment().subtract(5, 'years').format('YYYYMMDDTHHmmss'), - start: moment().subtract(5, 'years').format('YYYYMMDDTHHmmss'), - summary: 'Test 2 - Task 3', - complete: 6, - completed: true, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: false, - color: '#eef' - }, - uid: 'ydg91848mn', - uri: 'ydg91848mn.ics', - // construct dates for tomorrow, date only - due: moment().add(1, 'days').format('YYYYMMDD'), - start: moment().add(1, 'days').format('YYYYMMDD'), - summary: 'Test 2 - Task 4', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - }, - { - calendar: { - writable: false, - color: '#eef' - }, - uid: 'ydh91848mn', - uri: 'ydh91848mn.ics', - // construct dates for yesterday, date only - due: moment().subtract(1, 'days').format('YYYYMMDD'), - start: moment().subtract(1, 'days').format('YYYYMMDD'), - summary: 'Test 2 - Task 5', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - } - ] - }, - 'test-3': { - uri: 'test-3', - displayname: 'Test 3', - color: '#112233', - writable: true, - url: '/nextcloud/remote.php/dav/calendars/raimund.schluessler/test-3', - tasks: [ - - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'ydi92848mn', - uri: 'ydi92848mn.ics', - // construct dates for last week, date only - due: moment().subtract(5, 'days').format('YYYYMMDD'), - start: moment().subtract(5, 'days').format('YYYYMMDD'), - summary: 'Test 3 - Task 1', - complete: 1, - completed: false, - priority: 1, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - }, - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'ydj91848mn', - uri: 'ydj91848mn.ics', - // construct dates for next week, date only - due: moment().add(5, 'days').format('YYYYMMDD'), - start: moment().add(5, 'days').format('YYYYMMDD'), - summary: 'Test 3 - Task 2', - complete: 3, - completed: true, - priority: 5, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - }, - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'ydk91848mn', - uri: 'ydk91848mn.ics', - // construct dates for today future, date only - due: moment().add(1, 'hours').format('YYYYMMDD'), - start: moment().add(1, 'hours').format('YYYYMMDD'), - summary: 'Test 3 - Task 3', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - }, - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'ydl91848mn', - uri: 'ydl91848mn.ics', - // construct dates for today past, date only - due: moment().subtract(1, 'hours').format('YYYYMMDD'), - start: moment().subtract(1, 'hours').format('YYYYMMDD'), - summary: 'Test 3 - Task 4', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: true - }, - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'ydl913r8mn', - uri: 'ydl913r8mn.ics', - // construct dates for today past, date only - due: '', - start: '', - summary: 'Test 3 - Task 5', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - }, - { - calendar: { - writable: true, - color: '#112233' - }, - uid: 'y2w913r8mn', - uri: 'y2w913r8mn.ics', - summary: 'Test 3 - Task 6', - complete: 6, - completed: false, - priority: 7, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - } - ] - }, - 'test-4': { - uri: 'test-4', - displayname: 'Test 4', - color: '#112245', - writable: true, - url: '/nextcloud/remote.php/dav/calendars/raimund.schluessler/test-4', - tasks: [] - }, - 'a-list': { - uri: 'a-list', - displayname: 'A list', - color: '#dd2245', - writable: true, - url: '/nextcloud/remote.php/dav/calendars/raimund.schluessler/a-list', - tasks: [ - { - calendar: { - writable: true, - color: '#dd2245' - }, - uid: 'ydl92pr8mn', - uri: 'ydl92pr8mn.ics', - // construct dates for today past, date only - due: '', - start: '', - summary: 'A list - Task 1', - complete: 0, - completed: false, - priority: 0, - categories: [], - note: 'Migrate this app to vue.', - hideSubtasks: false, - allDay: false - } - ] - } - } -}) diff --git a/src/store/storeHelper.js b/src/store/storeHelper.js index 682005a1..de6228f3 100644 --- a/src/store/storeHelper.js +++ b/src/store/storeHelper.js @@ -42,7 +42,7 @@ function isTaskInList(task, listId) { case 'week': return task.completed === false && (week(task.start) || week(task.due)) default: - return '' + task.calendar.uri === '' + listId + return '' + task.calendar.id === '' + listId } } diff --git a/src/store/tasks.js b/src/store/tasks.js index 12105cad..da3306c0 100644 --- a/src/store/tasks.js +++ b/src/store/tasks.js @@ -32,7 +32,8 @@ const getters = { * @param {String} calendarId the Id of the calendar in question */ getTasksByCalendarId: (state, getters, rootState) => (calendarId) => { - return Object.values(rootState.calendars.calendars[calendarId].tasks) + var calendar = getters.getCalendarById(calendarId) + return Object.values(calendar.tasks) }, /** @@ -47,7 +48,7 @@ const getters = { */ getAllTasks: (state, getters, rootState) => { var tasks = [] - Object.values(rootState.calendars.calendars).forEach(calendar => { + rootState.calendars.calendars.forEach(calendar => { tasks.concat(calendar.tasks) }) return tasks @@ -59,13 +60,14 @@ const getters = { getTaskByRoute: (state, getters, rootState) => { // If a calendar is given, only search in that calendar. if (rootState.route.params.calendarId) { - return rootState.calendars.calendars[rootState.route.params.calendarId].tasks.find(task => { + var calendar = getters.getCalendarById(rootState.route.params.calendarId) + return calendar.tasks.find(task => { return task.uri === rootState.route.params.taskId }) } // Else, we have to search all calendars var task - for (let calendar of Object.values(rootState.calendars.calendars)) { + for (let calendar of rootState.calendars.calendars) { task = calendar.tasks.find(task => { return task.uri === rootState.route.params.taskId }) |