Skip to content

Commit

Permalink
fix(Google Calendar Node): Errors with after/before options (#8628)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-radency authored Feb 19, 2024
1 parent 40c7f77 commit bee17dd
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 25 deletions.
56 changes: 36 additions & 20 deletions packages/nodes-base/nodes/Google/Calendar/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,28 +154,44 @@ type RecurentEvent = {
export function addNextOccurrence(items: RecurentEvent[]) {
for (const item of items) {
if (item.recurrence) {
const rrule = RRule.fromString(item.recurrence[0]);
const until = rrule.options?.until;

const now = new Date();
if (until && until < now) {
continue;
let eventRecurrence;
try {
eventRecurrence = item.recurrence.find((r) => r.toUpperCase().startsWith('RRULE'));
if (!eventRecurrence) continue;

const rrule = RRule.fromString(eventRecurrence);
const until = rrule.options?.until;

const now = new Date();
if (until && until < now) {
continue;
}

const nextOccurrence = rrule.after(new Date());

item.nextOccurrence = {
start: {
dateTime: moment(nextOccurrence).format(),
timeZone: item.start.timeZone,
},
end: {
dateTime: moment(nextOccurrence)
.add(moment(item.end.dateTime).diff(moment(item.start.dateTime)))
.format(),
timeZone: item.end.timeZone,
},
};
} catch (error) {
console.log(`Error adding next occurrence ${eventRecurrence}`);
}

const nextOccurrence = rrule.after(new Date());
item.nextOccurrence = {
start: {
dateTime: moment(nextOccurrence).format(),
timeZone: item.start.timeZone,
},
end: {
dateTime: moment(nextOccurrence)
.add(moment(item.end.dateTime).diff(moment(item.start.dateTime)))
.format(),
timeZone: item.end.timeZone,
},
};
}
}
return items;
}

const hasTimezone = (date: string) => date.endsWith('Z') || /\+\d{2}:\d{2}$/.test(date);

export function addTimezoneToDate(date: string, timezone: string) {
if (hasTimezone(date)) return date;
return moment.tz(date, timezone).utc().format();
}
25 changes: 20 additions & 5 deletions packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import moment from 'moment-timezone';
import { v4 as uuid } from 'uuid';
import {
addNextOccurrence,
addTimezoneToDate,
encodeURIComponentOnce,
getCalendars,
getTimezones,
Expand All @@ -33,7 +34,7 @@ export class GoogleCalendar implements INodeType {
name: 'googleCalendar',
icon: 'file:googleCalendar.svg',
group: ['input'],
version: 1,
version: [1, 1.1],
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Google Calendar API',
defaults: {
Expand Down Expand Up @@ -69,6 +70,13 @@ export class GoogleCalendar implements INodeType {
...calendarFields,
...eventOperations,
...eventFields,
{
displayName:
'This node will use the time zone set in n8n’s settings, but you can override this in the workflow settings',
name: 'useN8nTimeZone',
type: 'notice',
default: '',
},
],
};

Expand Down Expand Up @@ -127,9 +135,12 @@ export class GoogleCalendar implements INodeType {
const length = items.length;
const qs: IDataObject = {};
let responseData;

const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
const timezone = this.getTimezone();
const nodeVersion = this.getNode().typeVersion;

for (let i = 0; i < length; i++) {
try {
if (resource === 'calendar') {
Expand Down Expand Up @@ -414,16 +425,16 @@ export class GoogleCalendar implements INodeType {
qs.singleEvents = options.singleEvents as boolean;
}
if (options.timeMax) {
qs.timeMax = options.timeMax as string;
qs.timeMax = addTimezoneToDate(options.timeMax as string, tz || timezone);
}
if (options.timeMin) {
qs.timeMin = options.timeMin as string;
qs.timeMin = addTimezoneToDate(options.timeMin as string, tz || timezone);
}
if (tz) {
qs.timeZone = tz;
}
if (options.updatedMin) {
qs.updatedMin = options.updatedMin as string;
qs.updatedMin = addTimezoneToDate(options.updatedMin as string, tz || timezone);
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(
Expand Down Expand Up @@ -458,7 +469,11 @@ export class GoogleCalendar implements INodeType {
const eventId = this.getNodeParameter('eventId', i) as string;
const useDefaultReminders = this.getNodeParameter('useDefaultReminders', i) as boolean;
const updateFields = this.getNodeParameter('updateFields', i);
const updateTimezone = updateFields.timezone as string;
let updateTimezone = updateFields.timezone as string;

if (nodeVersion > 1 && updateTimezone === undefined) {
updateTimezone = timezone;
}

if (updateFields.maxAttendees) {
qs.maxAttendees = updateFields.maxAttendees as number;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { addTimezoneToDate } from '../GenericFunctions';

describe('addTimezoneToDate', () => {
it('should add timezone to date', () => {
const dateWithTimezone = '2021-09-01T12:00:00.000Z';
const result1 = addTimezoneToDate(dateWithTimezone, 'Europe/Prague');
expect(result1).toBe('2021-09-01T12:00:00.000Z');

const dateWithoutTimezone = '2021-09-01T12:00:00';
const result2 = addTimezoneToDate(dateWithoutTimezone, 'Europe/Prague');
expect(result2).toBe('2021-09-01T10:00:00Z');

const result3 = addTimezoneToDate(dateWithoutTimezone, 'Asia/Tokyo');
expect(result3).toBe('2021-09-01T03:00:00Z');

const dateWithDifferentTimezone = '2021-09-01T12:00:00.000+08:00';
const result4 = addTimezoneToDate(dateWithDifferentTimezone, 'Europe/Prague');
expect(result4).toBe('2021-09-01T12:00:00.000+08:00');
});
});

0 comments on commit bee17dd

Please sign in to comment.