mirror of https://github.com/nextcloud/calendar
167 lines
5.1 KiB
JavaScript
167 lines
5.1 KiB
JavaScript
/**
|
|
* @copyright Copyright (c) 2019 Georg Ehrke
|
|
*
|
|
* @author Georg Ehrke <oc.list@georgehrke.com>
|
|
*
|
|
* @license AGPL-3.0-or-later
|
|
*
|
|
* 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 { translate as t } from '@nextcloud/l10n'
|
|
import {
|
|
hexToRGB,
|
|
isLight,
|
|
generateTextColorForHex,
|
|
getHexForColorName,
|
|
} from '../../utils/color.js'
|
|
import logger from '../../utils/logger.js'
|
|
import { getAllObjectsInTimeRange } from '../../utils/calendarObject.js'
|
|
|
|
/**
|
|
* convert an array of calendar-objects to events
|
|
*
|
|
* @param {CalendarObject[]} calendarObjects Array of calendar-objects to turn into fc events
|
|
* @param {object} calendar The calendar object
|
|
* @param {Date} start Start of time-range
|
|
* @param {Date} end End of time-range
|
|
* @param {Timezone} timezone Desired time-zone
|
|
* @return {object}[]
|
|
*/
|
|
export function eventSourceFunction(calendarObjects, calendar, start, end, timezone) {
|
|
const fcEvents = []
|
|
for (const calendarObject of calendarObjects) {
|
|
let allObjectsInTimeRange
|
|
try {
|
|
allObjectsInTimeRange = getAllObjectsInTimeRange(calendarObject, start, end)
|
|
} catch (error) {
|
|
logger.error(error.message)
|
|
continue
|
|
}
|
|
|
|
for (const object of allObjectsInTimeRange) {
|
|
const classNames = []
|
|
let hasAlarms = false
|
|
|
|
if (object.status === 'CANCELLED') {
|
|
classNames.push('fc-event-nc-cancelled')
|
|
} else if (object.status === 'TENTATIVE') {
|
|
classNames.push('fc-event-nc-tentative')
|
|
}
|
|
|
|
if (object.hasComponent('VALARM')) {
|
|
hasAlarms = true
|
|
classNames.push('fc-event-nc-alarms')
|
|
}
|
|
|
|
// For now, we only display
|
|
if (object.name === 'VTODO' && object.endDate === null) {
|
|
continue
|
|
}
|
|
|
|
let jsStart, jsEnd
|
|
if (object.name === 'VEVENT') {
|
|
jsStart = object.startDate.getInTimezone(timezone).jsDate
|
|
jsEnd = object.endDate.getInTimezone(timezone).jsDate
|
|
} else if (object.name === 'VTODO') {
|
|
// For tasks, we only want to display when it is due,
|
|
// not for how long it has been in progress already
|
|
jsStart = object.endDate.getInTimezone(timezone).jsDate
|
|
jsEnd = object.endDate.getInTimezone(timezone).jsDate
|
|
} else {
|
|
// We do not want to display anything that's neither
|
|
// an event nor a task
|
|
continue
|
|
}
|
|
|
|
// Technically, an event's end is not allowed to be equal to it's start,
|
|
// because the event's end is exclusive. Most calendar applications
|
|
// (including all big ones) allow creating such events anyway (we do too).
|
|
// If the event's start is equal to it's end, fullcalendar is giving
|
|
// the event a default length of one hour. We are preventing that by
|
|
// adding one second to the end in that case.
|
|
if (jsStart.getTime() === jsEnd.getTime()) {
|
|
jsEnd.setSeconds(jsEnd.getSeconds() + 1)
|
|
}
|
|
|
|
if (object.name === 'VTODO') {
|
|
classNames.push('fc-event-nc-task')
|
|
if (object.percent === 100 || object.status === 'COMPLETED') {
|
|
classNames.push('fc-event-nc-task-completed')
|
|
}
|
|
}
|
|
|
|
let title
|
|
if (object.name === 'VEVENT') {
|
|
if (object.title) {
|
|
title = object.title.replace(/\n/g, ' ')
|
|
} else {
|
|
title = t('calendar', 'Untitled event')
|
|
}
|
|
} else {
|
|
if (object.title) {
|
|
title = object.title.replace(/\n/g, ' ')
|
|
} else {
|
|
title = t('calendar', 'Untitled task')
|
|
}
|
|
|
|
if (object.percent !== null) {
|
|
title += ` (${object.percent}%)`
|
|
}
|
|
}
|
|
|
|
const fcEvent = {
|
|
id: [calendarObject.id, object.id].join('###'),
|
|
title,
|
|
allDay: object.isAllDay(),
|
|
start: jsStart,
|
|
end: jsEnd,
|
|
// start: formatLocal(jsStart, object.isAllDay()),
|
|
// end: formatLocal(jsEnd, object.isAllDay()),
|
|
classNames,
|
|
extendedProps: {
|
|
objectId: calendarObject.id,
|
|
recurrenceId: object.getReferenceRecurrenceId()
|
|
? object.getReferenceRecurrenceId().unixTime
|
|
: null,
|
|
canModifyAllDay: object.canModifyAllDay(),
|
|
calendarOrder: calendar.order,
|
|
calendarName: calendar.displayName,
|
|
calendarId: calendar.id,
|
|
darkText: isLight(hexToRGB(calendar.color)),
|
|
objectType: object.name,
|
|
percent: object.percent || null,
|
|
davUrl: calendarObject.dav.url,
|
|
location: object.location,
|
|
description: object.description,
|
|
hasAlarms,
|
|
hasAttendees: object.hasProperty('ATTENDEE'),
|
|
},
|
|
}
|
|
|
|
// Color of event object is a name while calendar color already is a hex value
|
|
const customColor = getHexForColorName(object.color) ?? calendar.color
|
|
if (customColor) {
|
|
fcEvent.backgroundColor = customColor
|
|
fcEvent.borderColor = customColor
|
|
fcEvent.textColor = generateTextColorForHex(customColor)
|
|
}
|
|
|
|
fcEvents.push(fcEvent)
|
|
}
|
|
}
|
|
|
|
return fcEvents
|
|
}
|