Load tasks from the server

This commit is contained in:
Raimund Schlüßler 2018-11-05 20:58:06 +01:00
parent 84ac32f761
commit f9c98968c7
No known key found for this signature in database
GPG key ID: 036FA7EB1A599178
8 changed files with 229 additions and 43 deletions

38
package-lock.json generated
View file

@ -4629,8 +4629,8 @@
"dev": true
},
"cdav-library": {
"version": "github:nextcloud/cdav-library#ff47e205ef07cd38c174a3d0582f371cd4bc93f9",
"from": "github:nextcloud/cdav-library",
"version": "github:nextcloud/cdav-library#0da67555ae708c903fb11d025397a6f6465b4c39",
"from": "github:nextcloud/cdav-library#bugfix/noid/fix_addressbook_calendar_queries",
"requires": {
"@babel/polyfill": "^7.0.0"
}
@ -5705,7 +5705,7 @@
"dependencies": {
"pify": {
"version": "2.3.0",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
@ -7484,14 +7484,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -7506,20 +7504,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -7636,8 +7631,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -7649,7 +7643,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -7664,7 +7657,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -7776,8 +7768,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -7789,7 +7780,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -7911,7 +7901,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -8178,7 +8167,7 @@
"dependencies": {
"pify": {
"version": "2.3.0",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
@ -8212,7 +8201,7 @@
"dependencies": {
"minimist": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
"integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=",
"dev": true
}
@ -16139,7 +16128,7 @@
},
"through": {
"version": "2.3.8",
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@ -16766,8 +16755,7 @@
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"v-tooltip": {
"version": "2.0.0-rc.33",

View file

@ -27,11 +27,12 @@
"dependencies": {
"@babel/polyfill": "^7.0.0",
"axios": "^0.18.0",
"cdav-library": "github:nextcloud/cdav-library",
"cdav-library": "github:nextcloud/cdav-library#bugfix/noid/fix_addressbook_calendar_queries",
"ical.js": "~1.2.2",
"jstimezonedetect": "",
"nextcloud-vue": "^0.3.1",
"p-limit": "^2.0.0",
"uuid": "^3.3.2",
"v-tooltip": "2.0.0-rc.33",
"vue": "^2.5.17",
"vue-router": "3.0.1",

View file

@ -82,7 +82,7 @@ export default {
Promise.all(this.calendars.map(calendar => this.$store.dispatch('getTasksFromCalendar', { calendar })))
.then(results => {
this.loading = false
console.log(results)
// console.log(results)
})
}
}

View file

@ -72,8 +72,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
<span>{{ task.summary }}</span>
</div>
<div class="categories-list">
<span v-for="category in task.categories" :key="category.id" class="category">
<span :title="category.name" class="category-label">{{ category.name }}</span>
<span v-for="category in task.categories" :key="category" class="category">
<span :title="category" class="category-label">{{ category }}</span>
</span>
</div>
</div>

View file

@ -199,8 +199,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
:tag-placeholder="t('tasks', 'Add this as a new category')"
:close-on-select="false"
class="multiselect-vue"
track-by="id"
label="name"
@input="updateCategories"
@tag="addCategory" />
</div>

View file

@ -1,2 +1,206 @@
export default class {
/**
* Nextcloud - Tasks
*
* @author John Molakvoæ
* @copyright 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @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/>.
*
*/
import uuid from 'uuid'
import ICAL from 'ical.js'
export default class Task {
/**
* Creates an instance of Task
*
* @param {string} vcalendar the vcalendar data as string with proper new lines
* @param {object} calendar the calendar which the task belongs to
* @memberof Task
*/
constructor(vcalendar, calendar, raw) {
if (typeof vcalendar !== 'string' || vcalendar.length === 0) {
throw new Error('Invalid vCalendar')
}
this.vcalendar = vcalendar
let jCal = ICAL.parse(vcalendar)
if (jCal[0] !== 'vcalendar') {
throw new Error('Only one task is allowed in the vCalendar data')
}
this.jCal = jCal
this.calendar = calendar
this.vCalendar = new ICAL.Component(this.jCal)
// used to state a task is not up to date with
// the server and cannot be pushed (etag)
this.conflict = false
// if no uid set, create one
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
if (!vtodo.hasProperty('uid')) {
console.debug('This task did not have a proper uid. Setting a new one for ', this)
vtodo.addPropertyWithValue('uid', uuid())
}
this.uri = raw.url.substr(raw.url.lastIndexOf('/') + 1)
}
/**
* Update internal data of this task
*
* @param {jCal} jCal jCal object from ICAL.js
* @memberof Task
*/
updateTask(jCal) {
this.jCal = jCal
this.vCalendar = new ICAL.Component(this.jCal)
}
/**
* Update linked calendar of this task
*
* @param {Object} calendar the calendar
* @memberof Contact
*/
updateCalendar(calendar) {
this.calendar = calendar
}
/**
* Ensure we're normalizing the possible arrays
* into a string by taking the first element
* e.g. ORG:ABC\, Inc.; will output an array because of the semi-colon
*
* @param {Array|string} data the data to normalize
* @returns {string}
* @memberof Task
*/
firstIfArray(data) {
return Array.isArray(data) ? data[0] : data
}
/**
* Return the url
*
* @readonly
* @memberof Task
*/
get url() {
if (this.dav) {
return this.dav.url
}
return ''
}
/**
* Return the uid
*
* @readonly
* @memberof Task
*/
get uid() {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
return vtodo.getFirstPropertyValue('uid') || ''
}
/**
* Set the uid
*
* @param {string} uid the uid to set
* @memberof Task
*/
set uid(uid) {
this.vCalendar.updatePropertyWithValue('uid', uid)
this.vcalendar = this.vCalendar.toString()
return true
}
/**
* Return the first summary
*
* @readonly
* @memberof Task
*/
get summary() {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
return vtodo.getFirstPropertyValue('summary');
}
/**
* Set the summary
*
* @param {string} summary the summary
* @memberof Task
*/
set summary(summary) {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
vtodo.updatePropertyWithValue('summary', summary)
this.updateLastModified()
this.vcalendar = this.vCalendar.toString()
}
/**
* Return the categories
*
* @readonly
* @memberof Task
*/
get categories() {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
var categories = vtodo.getFirstProperty('categories')
if (categories) {
return categories.getValues()
} else {
return []
}
}
/**
* Set the categories
*
* @param {string} categories the categories
* @memberof Task
*/
set categories(cats) {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
var categories = vtodo.getFirstProperty('categories')
if (cats.length > 0) {
if (categories) {
categories.setValues(cats)
} else {
var prop = new ICAL.Property('categories')
prop.setValues(cats)
categories = vtodo.addProperty(prop)
}
} else {
vtodo.removeProperty('categories')
}
this.updateLastModified()
this.vcalendar = this.vCalendar.toString()
}
updateLastModified () {
var vtodo = this.vCalendar.getFirstSubcomponent('vtodo')
vtodo.updatePropertyWithValue('last-modified', ICAL.Time.now())
vtodo.updatePropertyWithValue('dtstamp', ICAL.Time.now())
}
}

View file

@ -31,7 +31,6 @@
import Vue from 'vue'
import ICAL from 'ical.js'
import parseIcs from '../services/parseIcs'
import client from '../services/cdav'
import Task from '../models/task'
import pLimit from 'p-limit'
@ -258,14 +257,7 @@ const mutations = {
appendTasksToCalendar(state, { calendar, tasks }) {
calendar = state.calendars.find(search => search === calendar)
// convert list into an array and remove duplicate
calendar.tasks = tasks.reduce((list, task) => {
if (list[task.uid]) {
console.debug('Duplicate task overridden', list[task.uid], task)
}
Vue.set(list, task.uid, task)
return list
}, calendar.tasks)
Vue.set(calendar, 'tasks', tasks)
},
/**
@ -449,12 +441,12 @@ const actions = {
// We don't want to lose the url information
// so we need to parse one by one
const tasks = response.map(item => {
let task = new Task(item.data, calendar)
let task = new Task(item.data, calendar, item)
Vue.set(task, 'dav', item)
return task
})
context.commit('appendTasksToCalendar', { calendar, tasks })
context.commit('appendTasks', tasks)
// context.commit('appendTasks', tasks)
return tasks
})
.catch((error) => {

View file

@ -80,6 +80,9 @@ const getters = {
// If a calendar is given, only search in that calendar.
if (rootState.route.params.calendarId) {
var calendar = getters.getCalendarById(rootState.route.params.calendarId)
if (!calendar) {
return null
}
return calendar.tasks.find(task => {
return task.uri === rootState.route.params.taskId
})