diff --git a/CHANGELOG.md b/CHANGELOG.md index 543d5f4d7a40613c9b616ad7b81639fd795793ee..b64cf20c88521b7f26aff72b189af1bcaf3ced32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Changelog +## 3.5.4 - 2022-12-22 +### Fixed +- Handling of Email VALARMs + +## 3.5.3 - 2022-12-15 +### Fixed +- Delete X-ALT-DESC property on changing description +- Contrast issue with share icon +- Location in booking VEVENT + ## 3.5.2 - 2022-10-27 ### Fixed - Event calendar picker out of sync after moving event diff --git a/appinfo/info.xml b/appinfo/info.xml index 64487f58e7ab7f7d2b58921472693f76efab9148..195c859c98ff72c11baf5cbff4251033fa851f9b 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -15,7 +15,7 @@ * ☑️ Tasks! See tasks with a due date directly in the calendar * 🙈 **We’re not reinventing the wheel!** Based on the great [c-dav library](https://github.com/nextcloud/cdav-library), [ical.js](https://github.com/mozilla-comm/ical.js) and [fullcalendar](https://github.com/fullcalendar/fullcalendar) libraries. ]]> - 3.5.2 + 3.5.4 agpl Anna Larch Nextcloud Groupware Team diff --git a/lib/Service/Appointments/BookingCalendarWriter.php b/lib/Service/Appointments/BookingCalendarWriter.php index 9559d514e4764d70645df9709d7a245f024bc9db..1857f3a89dbd5e7b6bb4914bf83ee317e35e85b5 100644 --- a/lib/Service/Appointments/BookingCalendarWriter.php +++ b/lib/Service/Appointments/BookingCalendarWriter.php @@ -166,6 +166,10 @@ class BookingCalendarWriter { $vcalendar->VEVENT->add($alarm); } + if ($config->getLocation() !== null) { + $vcalendar->VEVENT->add('LOCATION', $config->getLocation()); + } + $vcalendar->VEVENT->add('X-NC-APPOINTMENT', $config->getToken()); $filename = $this->random->generate(32, ISecureRandom::CHAR_ALPHANUMERIC); diff --git a/package-lock.json b/package-lock.json index 7289a41867adecb0ddf1244f874b1d5d598e2b29..48205b81d5428790b9b524984f6a43ee0d6474c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "calendar", - "version": "3.5.2", + "version": "3.5.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "calendar", - "version": "3.5.2", + "version": "3.5.4", "license": "agpl", "dependencies": { "@fullcalendar/core": "5.11.0", diff --git a/package.json b/package.json index 98ecf87203f80886e1fff834eaedb0e5908d3e7c..b4067d429cffeeee6394285c13d2007717319ad3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "calendar", "description": "A calendar app for Nextcloud. Easily sync events from various devices, share and edit them online.", - "version": "3.5.2", + "version": "3.5.4", "author": "Georg Ehrke ", "contributors": [ "Georg Ehrke ", diff --git a/src/components/AppNavigation/CalendarList/CalendarListItem.vue b/src/components/AppNavigation/CalendarList/CalendarListItem.vue index 25d30fedf9c3aa4f011ba2c9b88dc541782eab38..0d5106b1549814e67eb42395c78877de752c2679 100644 --- a/src/components/AppNavigation/CalendarList/CalendarListItem.vue +++ b/src/components/AppNavigation/CalendarList/CalendarListItem.vue @@ -517,6 +517,6 @@ export default { diff --git a/src/store/calendarObjectInstance.js b/src/store/calendarObjectInstance.js index d43260af09c92f604de87d4797172d69c78c26a6..a23e95f8f678b8a794443a1b208c5d4e379625ab 100644 --- a/src/store/calendarObjectInstance.js +++ b/src/store/calendarObjectInstance.js @@ -34,7 +34,9 @@ import { import { getAmountAndUnitForTimedEvents, getAmountHoursMinutesAndUnitForAllDayEvents, - getTotalSecondsFromAmountAndUnitForTimedEvents, getTotalSecondsFromAmountHourMinutesAndUnitForAllDayEvents, + getTotalSecondsFromAmountAndUnitForTimedEvents, + getTotalSecondsFromAmountHourMinutesAndUnitForAllDayEvents, + updateEmailAlarms, } from '../utils/alarms.js' import { getClosestCSS3ColorNameForHex, @@ -332,6 +334,9 @@ const mutations = { } } + // Delete custom description properties + calendarObjectInstance.eventComponent.deleteAllProperties('X-ALT-DESC') + calendarObjectInstance.eventComponent.description = description calendarObjectInstance.description = description }, @@ -1538,6 +1543,8 @@ const actions = { const eventComponent = state.calendarObjectInstance.eventComponent const calendarObject = state.calendarObject + updateEmailAlarms(eventComponent) + if (eventComponent.isDirty()) { const isForkedItem = eventComponent.primaryItem !== null let original = null diff --git a/src/utils/alarms.js b/src/utils/alarms.js index 254a664dd9a9f2524b1b1375ccbfc64e2b3239dd..a77be36803c47585fe246c3bf859e959b7579756 100644 --- a/src/utils/alarms.js +++ b/src/utils/alarms.js @@ -2,6 +2,7 @@ * @copyright Copyright (c) 2019 Georg Ehrke * * @author Georg Ehrke + * @author Richard Steinmetz * * @license AGPL-3.0-or-later * @@ -20,6 +21,9 @@ * */ +import { AttendeeProperty, Property } from '@nextcloud/calendar-js' +import { translate as t } from '@nextcloud/l10n' + /** * Get the factor for a given unit * @@ -212,3 +216,44 @@ export function getTotalSecondsFromAmountHourMinutesAndUnitForAllDayEvents(amoun return amount } + +/** + * Propagate data from an event component to all EMAIL alarm components. + * An alarm component must contain a description, summary and all attendees to be notified. + * We don't have a separate UI for maintaining attendees of an alarm, so we just copy them from the event. + * + * https://www.rfc-editor.org/rfc/rfc5545#section-3.6.6 + * + * @param {AbstractRecurringComponent} eventComponent + */ +export function updateEmailAlarms(eventComponent) { + for (const alarmComponent of eventComponent.getAlarmIterator()) { + if (alarmComponent.action !== 'EMAIL') { + continue + } + + alarmComponent.deleteAllProperties('SUMMARY') + const summaryProperty = eventComponent.getFirstProperty('SUMMARY') + if (summaryProperty) { + alarmComponent.addProperty(summaryProperty.clone()) + } else { + const defaultSummary = t('calendar', 'Untitled event') + alarmComponent.addProperty(new Property('SUMMARY', defaultSummary)) + } + + if (!alarmComponent.hasProperty('DESCRIPTION')) { + const defaultDescription = t('calendar', 'This is an event reminder.') + alarmComponent.addProperty(new Property('DESCRIPTION', defaultDescription)) + } + + alarmComponent.deleteAllProperties('ATTENDEE') + for (const attendee of eventComponent.getAttendeeIterator()) { + if (['RESOURCE', 'ROOM'].includes(attendee.userType)) { + continue + } + + // Only copy the email address (value) of the attendee + alarmComponent.addProperty(new AttendeeProperty('ATTENDEE', attendee.value)) + } + } +}