From fc19d9c3e6b99207269e339c704a54fbba716cf4 Mon Sep 17 00:00:00 2001 From: Georg Bremer Date: Wed, 14 Feb 2024 19:45:20 +0100 Subject: [PATCH] Fun with timezones --- .../mutations/helpers/createGcalEvent.ts | 27 ++++++++++--------- .../public/mutations/startRetrospective.ts | 2 +- .../mutations/updateRecurrenceSettings.ts | 18 +++++++++++-- packages/server/package.json | 1 + yarn.lock | 8 +++--- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/packages/server/graphql/mutations/helpers/createGcalEvent.ts b/packages/server/graphql/mutations/helpers/createGcalEvent.ts index c0da25f13fb..4382ca7dedd 100644 --- a/packages/server/graphql/mutations/helpers/createGcalEvent.ts +++ b/packages/server/graphql/mutations/helpers/createGcalEvent.ts @@ -4,20 +4,23 @@ import appOrigin from '../../../appOrigin' import {DataLoaderWorker} from '../../graphql' import standardError from '../../../utils/standardError' import {CreateGcalEventInput, StandardMutationError} from '../../public/resolverTypes' +import {RRule} from 'rrule' +import {pick} from 'lodash' const emailRemindMinsBeforeMeeting = 24 * 60 const popupRemindMinsBeforeMeeting = 10 -const convertRruleToGcal = (rrule: string | null | undefined) => { - const recurrence = rrule - ? [ - rrule - .split('\n') - .filter((line) => !line.startsWith('DTSTART') && !line.startsWith('DTEND')) - .join('\n') - ] - : [] - return recurrence +const convertRruleToGcal = (rrule: RRule | null | undefined) => { + if (!rrule) { + return [] + } + + // Google does not allow for all fields in rrule. For example DTSTART and DTEND are not allowed. + // It also has trouble with BYHOUR, BYMINUTE, and BYSECOND. It's best to stick to fields known to work. + // Also strip TZID as google wants the UNTIL field in Z, but rrule only uses that if no TZID is present. + const options = pick(rrule.options, 'freq', 'interval', 'byweekday', 'until', 'count') + const gcalRule = new RRule(options) + return [gcalRule.toString()] } type Input = { @@ -25,7 +28,7 @@ type Input = { meetingId: string viewerId: string teamId: string - rrule?: string | null + rrule?: RRule | null dataLoader: DataLoaderWorker } @@ -113,7 +116,7 @@ const createGcalEvent = async ( export type UpdateGcalSeriesInput = { gcalSeriesId: string title?: string - rrule: string | null + rrule: RRule | null userId: string teamId: string dataLoader: DataLoaderWorker diff --git a/packages/server/graphql/public/mutations/startRetrospective.ts b/packages/server/graphql/public/mutations/startRetrospective.ts index 82f9f4a3a03..266664368c1 100644 --- a/packages/server/graphql/public/mutations/startRetrospective.ts +++ b/packages/server/graphql/public/mutations/startRetrospective.ts @@ -124,7 +124,7 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async ( meetingId, teamId, viewerId, - rrule: meetingSeries?.recurrenceRule, + rrule: recurrenceSettings?.rrule, dataLoader }) if (meetingSeries && gcalSeriesId) { diff --git a/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts b/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts index 590f85e7a27..daee90b7d61 100644 --- a/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts +++ b/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts @@ -112,6 +112,16 @@ const stopMeetingSeries = async (meetingSeries: MeetingSeries) => { .run() } +const updateGCalRecurrenceRule = (oldRule: RRule, newRule: RRule | null | undefined) => { + if (!newRule) { + return new RRule({ + ...oldRule.options, + until: new Date() + }) + } + return newRule +} + const updateRecurrenceSettings: MutationResolvers['updateRecurrenceSettings'] = async ( _source, {meetingId, recurrenceSettings}, @@ -139,7 +149,7 @@ const updateRecurrenceSettings: MutationResolvers['updateRecurrenceSettings'] = if (meeting.meetingSeriesId) { const meetingSeries = await dataLoader.get('meetingSeries').loadNonNull(meeting.meetingSeriesId) - const {gcalSeriesId, teamId, facilitatorId} = meetingSeries + const {gcalSeriesId, teamId, facilitatorId, recurrenceRule} = meetingSeries if (!recurrenceSettings.rrule) { await stopMeetingSeries(meetingSeries) @@ -149,10 +159,14 @@ const updateRecurrenceSettings: MutationResolvers['updateRecurrenceSettings'] = analytics.recurrenceStarted(viewer, meetingSeries) } if (gcalSeriesId) { + const rrule = updateGCalRecurrenceRule( + RRule.fromString(recurrenceRule), + recurrenceSettings.rrule + ) await updateGcalSeries({ gcalSeriesId, title: recurrenceSettings.name ?? undefined, - rrule: recurrenceSettings.rrule?.toString() ?? null, + rrule, teamId, userId: facilitatorId, dataLoader diff --git a/packages/server/package.json b/packages/server/package.json index 961c6e10534..6256aca6634 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -112,6 +112,7 @@ "ioredis": "^5.2.3", "jsdom": "^20.0.0", "jsonwebtoken": "^9.0.0", + "lodash.pick": "^4.4.0", "mailcomposer": "^4.0.1", "mailgun.js": "^9.3.0", "mime-types": "^2.1.16", diff --git a/yarn.lock b/yarn.lock index 50e12881143..c08a4168a24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9012,9 +9012,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001517, caniuse-lite@~1.0.0: - version "1.0.30001584" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz#5e3ea0625d048d5467670051687655b1f7bf7dfd" - integrity sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ== + version "1.0.30001587" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz#a0bce920155fa56a1885a69c74e1163fc34b4881" + integrity sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA== capital-case@^1.0.4: version "1.0.4" @@ -14573,7 +14573,7 @@ lodash.mergewith@4.6.2: lodash.pick@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q== lodash.setwith@^4.3.2: version "4.3.2"