757 lines
22 KiB
JavaScript
757 lines
22 KiB
JavaScript
/**
|
|
* Nextcloud - Tasks
|
|
*
|
|
* @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
|
|
* 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'
|
|
|
|
import parseIcs from '../services/parseIcs.js'
|
|
import client from '../services/cdav.js'
|
|
import Task from '../models/task.js'
|
|
import { isParentInList, searchSubTasks } from './storeHelper.js'
|
|
import { findVTODObyState } from './cdav-requests.js'
|
|
import router from '../router.js'
|
|
import { detectColor, uidToHexColor } from '../utils/color.js'
|
|
|
|
import ICAL from 'ical.js'
|
|
import pLimit from 'p-limit'
|
|
import Vue from 'vue'
|
|
|
|
const calendarModel = {
|
|
id: '',
|
|
color: '',
|
|
displayName: '',
|
|
enabled: true,
|
|
owner: '',
|
|
shares: [],
|
|
tasks: {},
|
|
url: '',
|
|
readOnly: false,
|
|
dav: false,
|
|
supportsEvents: true,
|
|
supportsTasks: true,
|
|
loadedCompleted: false,
|
|
// Whether or not the calendar is shared with me
|
|
isSharedWithMe: false,
|
|
// Whether or not the calendar can be shared by me
|
|
canBeShared: false,
|
|
// The order of this calendar in the calendar-list
|
|
order: 0,
|
|
}
|
|
|
|
const state = {
|
|
calendars: [],
|
|
}
|
|
|
|
/**
|
|
* Maps a dav collection to our calendar object model
|
|
*
|
|
* @param {Object} calendar The calendar object from the cdav library
|
|
* @param {Object} currentUserPrincipal The principal model of the current user principal
|
|
* @returns {Object}
|
|
*/
|
|
export function mapDavCollectionToCalendar(calendar, currentUserPrincipal) {
|
|
const owner = calendar.owner
|
|
let isSharedWithMe = false
|
|
if (!currentUserPrincipal) {
|
|
// If the user is not authenticated, the calendar
|
|
// will always be marked as shared with them
|
|
isSharedWithMe = true
|
|
} else {
|
|
isSharedWithMe = (owner !== currentUserPrincipal.url)
|
|
}
|
|
const displayName = calendar.displayname || getCalendarUriFromUrl(calendar.url)
|
|
// calendar.color can be set to anything on the server,
|
|
// so make sure it's something that remotely looks like a color
|
|
let color = detectColor(calendar.color)
|
|
if (!color) {
|
|
// As fallback if we don't know what color that is supposed to be
|
|
color = uidToHexColor(displayName)
|
|
}
|
|
|
|
const shares = []
|
|
if (!!currentUserPrincipal && Array.isArray(calendar.shares)) {
|
|
for (const share of calendar.shares) {
|
|
if (share.href === currentUserPrincipal.principalScheme) {
|
|
continue
|
|
}
|
|
|
|
shares.push(mapDavShareeToSharee(share))
|
|
}
|
|
}
|
|
|
|
const order = +calendar.order || 0
|
|
|
|
return {
|
|
// get last part of url
|
|
id: calendar.url.split('/').slice(-2, -1)[0],
|
|
displayName,
|
|
color,
|
|
order,
|
|
enabled: calendar.enabled !== false,
|
|
owner,
|
|
readOnly: !calendar.isWriteable(),
|
|
tasks: {},
|
|
url: calendar.url,
|
|
dav: calendar,
|
|
shares,
|
|
supportsEvents: calendar.components.includes('VEVENT'),
|
|
supportsTasks: calendar.components.includes('VTODO'),
|
|
loadedCompleted: false,
|
|
isSharedWithMe,
|
|
canBeShared: calendar.isShareable(),
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maps a dav collection to the sharee array
|
|
*
|
|
* @param {Object} sharee The sharee object from the cdav library shares
|
|
* @returns {Object}
|
|
*/
|
|
export function mapDavShareeToSharee(sharee) {
|
|
const id = sharee.href.split('/').slice(-1)[0]
|
|
let name = sharee['common-name']
|
|
? sharee['common-name']
|
|
: sharee.href
|
|
|
|
if (sharee.href.startsWith('principal:principals/groups/') && name === sharee.href) {
|
|
name = sharee.href.substr(28)
|
|
}
|
|
|
|
return {
|
|
displayName: name,
|
|
id,
|
|
writeable: sharee.access[0].endsWith('read-write'),
|
|
isGroup: sharee.href.startsWith('principal:principals/groups/'),
|
|
isCircle: sharee.href.startsWith('principal:principals/circles/'),
|
|
uri: sharee.href,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the calendar uri from the url
|
|
*
|
|
* @param {String} url The url to get calendar uri from
|
|
* @returns {string}
|
|
*/
|
|
function getCalendarUriFromUrl(url) {
|
|
if (url.endsWith('/')) {
|
|
url = url.substring(0, url.length - 1)
|
|
}
|
|
|
|
return url.substring(url.lastIndexOf('/') + 1)
|
|
}
|
|
|
|
const getters = {
|
|
|
|
/**
|
|
* Returns the calendars sorted alphabetically
|
|
*
|
|
* @param {Object} state The store data
|
|
* @returns {Array<Calendar>} Array of the calendars sorted alphabetically
|
|
*/
|
|
getSortedCalendars: state => {
|
|
return state.calendars.sort(function(cal1, cal2) {
|
|
const n1 = cal1.order
|
|
const n2 = cal2.order
|
|
return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Returns the calendars sorted alphabetically
|
|
*
|
|
* @param {Object} state The store data
|
|
* @returns {Array<Calendar>} Array of the calendars sorted alphabetically
|
|
*/
|
|
getSortedWritableCalendars: state => {
|
|
return state.calendars.filter(calendar => {
|
|
return !calendar.readOnly
|
|
})
|
|
.sort(function(cal1, cal2) {
|
|
const n1 = cal1.order
|
|
const n2 = cal2.order
|
|
return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Returns the calendar with the given calendarId
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {String} calendarId The id of the requested calendar
|
|
* @returns {Calendar} The requested calendar
|
|
*/
|
|
getCalendarById: state => (calendarId) => {
|
|
const calendar = state.calendars.find(search => search.id === calendarId)
|
|
return calendar
|
|
},
|
|
|
|
/**
|
|
* Returns the number of tasks in a calendar
|
|
*
|
|
* Tasks have to be
|
|
* - a root task
|
|
* - uncompleted
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} getters The store getters
|
|
* @param {Object} rootState The store root state
|
|
* @param {String} calendarId The id of the requested calendar
|
|
* @returns {Integer} The number of tasks
|
|
*/
|
|
getCalendarCount: (state, getters, rootState) => (calendarId) => {
|
|
const calendar = getters.getCalendarById(calendarId)
|
|
let tasks = Object.values(calendar.tasks)
|
|
.filter(task => {
|
|
return task.closed === false && (!task.related || !isParentInList(task, calendar.tasks))
|
|
})
|
|
if (rootState.tasks.searchQuery) {
|
|
tasks = tasks.filter(task => {
|
|
if (task.matches(rootState.tasks.searchQuery)) {
|
|
return true
|
|
}
|
|
// We also have to show tasks for which one sub(sub...)task matches.
|
|
return searchSubTasks(task, rootState.tasks.searchQuery)
|
|
})
|
|
}
|
|
return tasks.length
|
|
},
|
|
|
|
/**
|
|
* Returns the count of closed tasks in a calendar
|
|
*
|
|
* Tasks have to be
|
|
* - a root task
|
|
* - closed
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} getters The store getters
|
|
* @param {String} calendarId The id of the calendar in question
|
|
* @returns {Integer} The count of closed tasks in a calendar
|
|
*/
|
|
getCalendarCountClosed: (state, getters) => (calendarId) => {
|
|
const calendar = getters.getCalendarById(calendarId)
|
|
return Object.values(calendar.tasks)
|
|
.filter(task => {
|
|
return task.closed === true && (!task.related || !isParentInList(task, calendar.tasks))
|
|
}).length
|
|
},
|
|
|
|
/**
|
|
* Returns if a calendar name is already used by an other calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {String} name The name to check
|
|
* @param {String} id The id of the calendar to exclude
|
|
* @returns {Boolean} If a calendar name is already used
|
|
*/
|
|
isCalendarNameUsed: state => (name, id) => {
|
|
return state.calendars.some(calendar => {
|
|
return (calendar.displayName === name && calendar.id !== id)
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Returns the current calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} getters The store getters
|
|
* @param {Object} rootState The store root state
|
|
* @returns {Calendar} The calendar by route
|
|
*/
|
|
getCalendarByRoute: (state, getters, rootState) => {
|
|
if (rootState.route.params.collectionId) {
|
|
return getters.getDefaultCalendar
|
|
}
|
|
return getters.getCalendarById(rootState.route.params.calendarId)
|
|
},
|
|
|
|
/**
|
|
* Returns the default calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} getters The store getters
|
|
* @param {Object} rootState The store root state
|
|
* @returns {Calendar} The default calendar
|
|
*/
|
|
getDefaultCalendar: (state, getters, rootState) => {
|
|
const defaultCalendar = getters.getCalendarById(rootState.settings.settings.defaultCalendarId)
|
|
// If the default calendar is read only we return the first calendar that is writable
|
|
if (!defaultCalendar || defaultCalendar.readOnly) {
|
|
return getters.getSortedCalendars.find(calendar => !calendar.readOnly) || getters.getSortedCalendars[0]
|
|
}
|
|
return defaultCalendar
|
|
},
|
|
}
|
|
|
|
const mutations = {
|
|
|
|
/**
|
|
* Adds a calendar to the state
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Calendar} calendar The calendar to add
|
|
*/
|
|
addCalendar(state, calendar) {
|
|
// extend the calendar to the default model
|
|
calendar = Object.assign({}, calendarModel, calendar)
|
|
// Only add the calendar if it is not already present
|
|
if (state.calendars.some(cal => {
|
|
return cal.id === calendar.id
|
|
})) {
|
|
return
|
|
}
|
|
state.calendars.push(calendar)
|
|
},
|
|
|
|
/**
|
|
* Delete calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Calendar} calendar The calendar to delete
|
|
*/
|
|
deleteCalendar(state, calendar) {
|
|
state.calendars.splice(state.calendars.indexOf(calendar), 1)
|
|
},
|
|
|
|
/**
|
|
* Toggles whether a calendar is enabled
|
|
*
|
|
* @param {Object} context The store mutations
|
|
* @param {Calendar} calendar The calendar to toggle
|
|
*/
|
|
toggleCalendarEnabled(context, calendar) {
|
|
calendar.enabled = !calendar.enabled
|
|
},
|
|
|
|
/**
|
|
* Changes the name and the color of a calendar
|
|
*
|
|
* @param {Object} context The store mutations
|
|
* @param {Object} data Destructuring object
|
|
* @param {Calendar} data.calendar The calendar to change
|
|
* @param {String} data.newName The new name of the calendar
|
|
* @param {String} data.newColor The new color of the calendar
|
|
*/
|
|
renameCalendar(context, { calendar, newName, newColor }) {
|
|
calendar.displayName = newName
|
|
calendar.color = newColor
|
|
},
|
|
|
|
/**
|
|
* Appends a list of tasks to a calendar
|
|
* and removes duplicates
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} data Destructuring object
|
|
* @param {Calendar} data.calendar The calendar to add the tasks to
|
|
* @param {Task[]} data.tasks Array of tasks to append
|
|
*/
|
|
appendTasksToCalendar(state, { calendar, tasks }) {
|
|
// 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)
|
|
|
|
},
|
|
|
|
/**
|
|
* Adds a task to a calendar and overwrites if duplicate uid
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Task} task The task to add
|
|
*/
|
|
addTaskToCalendar(state, task) {
|
|
Vue.set(task.calendar.tasks, task.uid, task)
|
|
},
|
|
|
|
/**
|
|
* Deletes a task from its calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Task} task The task to delete
|
|
*/
|
|
deleteTaskFromCalendar(state, task) {
|
|
Vue.delete(task.calendar.tasks, task.uid)
|
|
},
|
|
|
|
/**
|
|
* Shares a calendar with a user or group
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} data Destructuring object
|
|
* @param {Calendar} data.calendar The calendar
|
|
* @param {String} data.user The userId
|
|
* @param {String} data.displayName The displayName
|
|
* @param {String} data.uri The sharing principalScheme uri
|
|
* @param {Boolean} data.isGroup Is this a group ?
|
|
* @param {Boolean} data.isCircle Is this a circle?
|
|
*/
|
|
shareCalendar(state, { calendar, user, displayName, uri, isGroup, isCircle }) {
|
|
calendar = state.calendars.find(search => search.id === calendar.id)
|
|
const newSharee = {
|
|
displayName,
|
|
id: user,
|
|
writeable: false,
|
|
isGroup,
|
|
isCircle,
|
|
uri,
|
|
}
|
|
if (!calendar.shares.some((share) => share.uri === uri)) {
|
|
calendar.shares.push(newSharee)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes a sharee from calendar shares list
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} data Destructuring object
|
|
* @param {Calendar} data.calendar The calendar
|
|
* @param {String} data.uri The sharee uri
|
|
*/
|
|
removeSharee(state, { calendar, uri }) {
|
|
calendar = state.calendars.find(search => search.id === calendar.id)
|
|
const shareIndex = calendar.shares.findIndex(sharee => sharee.uri === uri)
|
|
calendar.shares.splice(shareIndex, 1)
|
|
},
|
|
|
|
/**
|
|
* Toggles sharee's writable permission
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Object} data Destructuring object
|
|
* @param {Object} data.calendar The calendar
|
|
* @param {String} data.uri The sharee uri
|
|
*/
|
|
updateShareeWritable(state, { calendar, uri }) {
|
|
calendar = state.calendars.find(search => search.id === calendar.id)
|
|
const sharee = calendar.shares.find(sharee => sharee.uri === uri)
|
|
sharee.writeable = !sharee.writeable
|
|
},
|
|
|
|
/**
|
|
* Sets the sort order of a calendar
|
|
*
|
|
* @param {Object} state The store data
|
|
* @param {Calendar} calendar The calendar
|
|
* @param {Integer} order The sort order
|
|
*/
|
|
setCalendarOrder(state, { calendar, order }) {
|
|
Vue.set(calendar, 'order', order)
|
|
},
|
|
}
|
|
|
|
const actions = {
|
|
/**
|
|
* Retrieves and commits 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, context.getters.getCurrentUserPrincipal)
|
|
})
|
|
})
|
|
|
|
// Remove calendars which don't support tasks
|
|
calendars = calendars.filter(calendar => calendar.supportsTasks)
|
|
|
|
calendars.forEach(calendar => {
|
|
context.commit('addCalendar', calendar)
|
|
})
|
|
|
|
return calendars
|
|
},
|
|
|
|
/**
|
|
* Appends a new calendar to array of existing calendars
|
|
*
|
|
* @param {Object} context The store mutations
|
|
* @param {Calendar} calendar The calendar to append
|
|
* @returns {Promise}
|
|
*/
|
|
async appendCalendar(context, calendar) {
|
|
return client.calendarHomes[0].createCalendarCollection(calendar.displayName, calendar.color, ['VTODO'])
|
|
.then((response) => {
|
|
calendar = mapDavCollectionToCalendar(response, context.getters.getCurrentUserPrincipal)
|
|
context.commit('addCalendar', calendar)
|
|
// Open the calendar
|
|
router.push({ name: 'calendars', params: { calendarId: calendar.id } })
|
|
})
|
|
.catch((error) => { throw error })
|
|
},
|
|
|
|
/**
|
|
* Delete calendar
|
|
* @param {Object} context The store mutations Current context
|
|
* @param {Calendar} calendar The calendar to delete
|
|
* @returns {Promise}
|
|
*/
|
|
async deleteCalendar(context, calendar) {
|
|
return calendar.dav.delete()
|
|
.then((response) => {
|
|
// Delete all the tasks from the store that belong to this calendar
|
|
Object.values(calendar.tasks)
|
|
.forEach(task => context.commit('deleteTask', task))
|
|
// Then delete the calendar
|
|
context.commit('deleteCalendar', calendar)
|
|
})
|
|
.catch((error) => { throw error })
|
|
},
|
|
|
|
/**
|
|
* Toggles whether a calendar is enabled
|
|
* @param {Object} context The store mutations current context
|
|
* @param {Calendar} 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 })
|
|
},
|
|
|
|
/**
|
|
* Changes the name and the color of a calendar
|
|
*
|
|
* @param {Object} context The store mutations Current context
|
|
* @param {Calendar} data.calendar The calendar to change
|
|
* @param {String} data.newName The new name of the calendar
|
|
* @param {String} data.newColor The new color of the calendar
|
|
* @returns {Promise}
|
|
*/
|
|
async changeCalendar(context, { calendar, newName, newColor }) {
|
|
calendar.dav.displayname = newName
|
|
calendar.dav.color = newColor
|
|
return calendar.dav.update()
|
|
.then((response) => context.commit('renameCalendar', { calendar, newName, newColor }))
|
|
.catch((error) => { throw error })
|
|
},
|
|
|
|
/**
|
|
* Retrieves the tasks of the specified calendar
|
|
* and commits the results
|
|
*
|
|
* @param {Object} context The store mutations
|
|
* @param {Object} data Destructuring object
|
|
* @param {Calendar} data.calendar The calendar
|
|
* @param {String} data.completed Are the requested tasks completed
|
|
* @param {String} data.related The uid of the parent task
|
|
* @returns {Promise}
|
|
*/
|
|
async getTasksFromCalendar(context, { calendar, completed = false, related = null }) {
|
|
try {
|
|
const response = await findVTODObyState(calendar, completed, related)
|
|
if (response) {
|
|
// If we loaded completed tasks, note that.
|
|
if (completed) {
|
|
calendar.loadedCompleted = true
|
|
}
|
|
// We don't want to lose the url information
|
|
// so we need to parse one by one
|
|
const tasks = response.map(item => {
|
|
const task = new Task(item.data, calendar)
|
|
Vue.set(task, 'dav', item)
|
|
return task
|
|
})
|
|
|
|
// Initialize subtasks so we don't have to search for them on every change.
|
|
// We do have to manually adjust this list when a task is added, deleted or moved.
|
|
tasks.forEach(
|
|
parent => {
|
|
const subTasks = tasks.filter(task => {
|
|
return task.related === parent.uid
|
|
})
|
|
|
|
// Convert list into an array and remove duplicate
|
|
parent.subTasks = subTasks.reduce((list, task) => {
|
|
if (list[task.uid]) {
|
|
console.debug('Duplicate task overridden', list[task.uid], task)
|
|
}
|
|
Vue.set(list, task.uid, task)
|
|
return list
|
|
}, parent.subTasks)
|
|
|
|
// In case we already have subtasks of this task in the store, add them as well.
|
|
const subTasksInStore = context.getters.getTasksByParent(parent)
|
|
subTasksInStore.forEach(
|
|
subTask => {
|
|
context.commit('addTaskToParent', { task: subTask, parent })
|
|
}
|
|
)
|
|
|
|
// If necessary, add the tasks as subtasks to parent tasks already present in the store.
|
|
if (!related) {
|
|
const parentParent = context.getters.getTaskByUid(parent.related)
|
|
context.commit('addTaskToParent', { task: parent, parent: parentParent })
|
|
}
|
|
}
|
|
)
|
|
|
|
// If the requested tasks are related to a task, add the tasks as subtasks
|
|
if (related) {
|
|
const parent = Object.values(calendar.tasks).find(search => search.uid === related)
|
|
if (parent) {
|
|
parent.loadedCompleted = true
|
|
tasks.map(task => Vue.set(parent.subTasks, task.uid, task))
|
|
}
|
|
}
|
|
|
|
context.commit('appendTasksToCalendar', { calendar, tasks })
|
|
context.commit('appendTasks', tasks)
|
|
return tasks
|
|
}
|
|
} catch (error) {
|
|
// unrecoverable error, if no tasks 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)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Imports tasks into a calendar from an ics file
|
|
*
|
|
* @param {Object} context The store mutations
|
|
* @param {Object} importDetails = { ics, calendar }
|
|
*/
|
|
async importTasksIntoCalendar(context, { ics, calendar }) {
|
|
const tasks = parseIcs(ics, calendar)
|
|
context.commit('changeStage', 'importing')
|
|
|
|
// max simultaneous requests
|
|
const limit = pLimit(3)
|
|
const requests = []
|
|
|
|
// create the array of requests to send
|
|
tasks.map(async task => {
|
|
// Get vcard string
|
|
try {
|
|
const vData = ICAL.stringify(task.vCard.jCal)
|
|
// push task to server and use limit
|
|
requests.push(limit(() => task.calendar.dav.createVCard(vData)
|
|
.then((response) => {
|
|
// setting the task dav property
|
|
Vue.set(task, 'dav', response)
|
|
|
|
// success, update store
|
|
context.commit('addTask', task)
|
|
context.commit('addTaskToCalendar', task)
|
|
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')
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Removes a sharee from a calendar
|
|
*
|
|
* @param {Object} context The store mutations Current context
|
|
* @param {Object} data Destructuring object
|
|
* @param {Object} data.calendar The calendar
|
|
* @param {String} data.uri The sharee uri
|
|
*/
|
|
async removeSharee(context, { calendar, uri }) {
|
|
await calendar.dav.unshare(uri)
|
|
context.commit('removeSharee', { calendar, uri })
|
|
},
|
|
|
|
/**
|
|
* Toggles permissions of calendar sharees writeable rights
|
|
*
|
|
* @param {Object} context The store mutations Current context
|
|
* @param {Object} data Destructuring object
|
|
* @param {Object} data.calendar The calendar
|
|
* @param {String} data.uri The sharee uri
|
|
* @param {Boolean} data.writeable The sharee permission
|
|
*/
|
|
async toggleShareeWritable(context, { calendar, uri, writeable }) {
|
|
await calendar.dav.share(uri, writeable)
|
|
context.commit('updateShareeWritable', { calendar, uri, writeable })
|
|
},
|
|
|
|
/**
|
|
* Shares a calendar with a user or a group
|
|
*
|
|
* @param {Object} context The store mutations Current context
|
|
* @param {Calendar} data.calendar The calendar
|
|
* @param {String} data.user The userId
|
|
* @param {String} data.displayName The displayName
|
|
* @param {String} data.uri The sharing principalScheme uri
|
|
* @param {Boolean} data.isGroup Is this a group ?
|
|
* @param {Boolean} data.isCircle Is this a circle?
|
|
*/
|
|
async shareCalendar(context, { calendar, user, displayName, uri, isGroup, isCircle }) {
|
|
// Share calendar with entered group or user
|
|
await calendar.dav.share(uri)
|
|
context.commit('shareCalendar', { calendar, user, displayName, uri, isGroup, isCircle })
|
|
},
|
|
|
|
/**
|
|
* Sets the sort order of a calendar
|
|
*
|
|
* @param {Object} context The store context
|
|
* @param {Calendar} calendar The calendar to update
|
|
* @param {Integer} order The sort order
|
|
*/
|
|
async setCalendarOrder(context, { calendar, order }) {
|
|
if (calendar.order === order) {
|
|
return
|
|
}
|
|
|
|
context.commit('setCalendarOrder', { calendar, order })
|
|
calendar.dav.order = order
|
|
await calendar.dav.update()
|
|
},
|
|
}
|
|
|
|
export default { state, getters, mutations, actions }
|