calendar/src/models/calendar.js

182 lines
5.2 KiB
JavaScript

/**
* @copyright Copyright (c) 2019 Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.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 { detectColor, uidToHexColor } from '../utils/color.js'
import { mapDavShareeToCalendarShareObject } from './calendarShare.js'
/**
* Creates a complete calendar-object based on given props
*
* @param {Object} props Calendar-props already provided
* @returns {Object}
*/
const getDefaultCalendarObject = (props = {}) => Object.assign({}, {
// Id of the calendar
id: '',
// Visible display name
displayName: '',
// Color of the calendar
color: uidToHexColor(''),
// Whether or not the calendar is visible in the grid
enabled: true,
// Whether or not the calendar is loading events at the moment
loading: false,
// Whether this calendar supports VEvents
supportsEvents: true,
// Whether this calendar supports VJournals
supportsJournals: false,
// Whether this calendar supports VTodos
supportsTasks: false,
// The principal uri of the owner
owner: '',
// Timezone set for this calendar
timezone: null,
// List of shares
shares: [],
// Published url
publishURL: null,
// Internal CalDAV url of this calendar
url: '',
// Whether this calendar is read-only
readOnly: false,
// The order of this calendar in the calendar-list
order: 0,
// Whether or not the calendar is shared with me
isSharedWithMe: false,
// Whether or not the calendar can be shared by me
canBeShared: false,
// Whether or not the calendar can be published by me
canBePublished: false,
// Reference to cdav-lib object
dav: false,
// All calendar-objects from this calendar that have already been fetched
calendarObjects: [],
// Time-ranges that have already been fetched for this calendar
fetchedTimeRanges: [],
}, props)
/**
* Map 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}
*/
const mapDavCollectionToCalendar = (calendar, currentUserPrincipal) => {
const id = btoa(calendar.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 supportsEvents = calendar.components.includes('VEVENT')
const supportsJournals = calendar.components.includes('VJOURNAL')
const supportsTasks = calendar.components.includes('VTODO')
const owner = calendar.owner
const readOnly = !calendar.isWriteable()
const canBeShared = calendar.isShareable()
const canBePublished = calendar.isPublishable()
const order = calendar.order || 0
const url = calendar.url
const publishURL = calendar.publishURL || null
const timezone = calendar.timezone || null
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)
}
let enabled
if (!currentUserPrincipal) {
// If the user is not authenticated,
// always enable the calendar
enabled = true
} else if (typeof calendar.enabled === 'boolean') {
// If calendar-enabled is set, we will just take that
enabled = calendar.enabled
} else {
// If there is no calendar-enabled,
// we will display the calendar by default if it's owned by the user
// or hide it by default it it's just shared with them
enabled = !isSharedWithMe
}
const shares = []
if (!!currentUserPrincipal && Array.isArray(calendar.shares)) {
for (const share of calendar.shares) {
if (share.href === currentUserPrincipal.principalScheme) {
continue
}
shares.push(mapDavShareeToCalendarShareObject(share))
}
}
return getDefaultCalendarObject({
id,
displayName,
color,
order,
url,
enabled,
supportsEvents,
supportsJournals,
supportsTasks,
isSharedWithMe,
owner,
readOnly,
publishURL,
canBeShared,
canBePublished,
shares,
timezone,
dav: calendar,
})
}
/**
* 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)
}
export {
getDefaultCalendarObject,
mapDavCollectionToCalendar,
}