mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(Google Calendar Node): Errors with after/before options (#8628)
This commit is contained in:
parent
40c7f77a35
commit
bee17dd6cc
|
@ -154,28 +154,44 @@ type RecurentEvent = {
|
||||||
export function addNextOccurrence(items: RecurentEvent[]) {
|
export function addNextOccurrence(items: RecurentEvent[]) {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (item.recurrence) {
|
if (item.recurrence) {
|
||||||
const rrule = RRule.fromString(item.recurrence[0]);
|
let eventRecurrence;
|
||||||
const until = rrule.options?.until;
|
try {
|
||||||
|
eventRecurrence = item.recurrence.find((r) => r.toUpperCase().startsWith('RRULE'));
|
||||||
|
if (!eventRecurrence) continue;
|
||||||
|
|
||||||
const now = new Date();
|
const rrule = RRule.fromString(eventRecurrence);
|
||||||
if (until && until < now) {
|
const until = rrule.options?.until;
|
||||||
continue;
|
|
||||||
|
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;
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import moment from 'moment-timezone';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import {
|
import {
|
||||||
addNextOccurrence,
|
addNextOccurrence,
|
||||||
|
addTimezoneToDate,
|
||||||
encodeURIComponentOnce,
|
encodeURIComponentOnce,
|
||||||
getCalendars,
|
getCalendars,
|
||||||
getTimezones,
|
getTimezones,
|
||||||
|
@ -33,7 +34,7 @@ export class GoogleCalendar implements INodeType {
|
||||||
name: 'googleCalendar',
|
name: 'googleCalendar',
|
||||||
icon: 'file:googleCalendar.svg',
|
icon: 'file:googleCalendar.svg',
|
||||||
group: ['input'],
|
group: ['input'],
|
||||||
version: 1,
|
version: [1, 1.1],
|
||||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||||
description: 'Consume Google Calendar API',
|
description: 'Consume Google Calendar API',
|
||||||
defaults: {
|
defaults: {
|
||||||
|
@ -69,6 +70,13 @@ export class GoogleCalendar implements INodeType {
|
||||||
...calendarFields,
|
...calendarFields,
|
||||||
...eventOperations,
|
...eventOperations,
|
||||||
...eventFields,
|
...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: '',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,9 +135,12 @@ export class GoogleCalendar implements INodeType {
|
||||||
const length = items.length;
|
const length = items.length;
|
||||||
const qs: IDataObject = {};
|
const qs: IDataObject = {};
|
||||||
let responseData;
|
let responseData;
|
||||||
|
|
||||||
const resource = this.getNodeParameter('resource', 0);
|
const resource = this.getNodeParameter('resource', 0);
|
||||||
const operation = this.getNodeParameter('operation', 0);
|
const operation = this.getNodeParameter('operation', 0);
|
||||||
const timezone = this.getTimezone();
|
const timezone = this.getTimezone();
|
||||||
|
const nodeVersion = this.getNode().typeVersion;
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
try {
|
try {
|
||||||
if (resource === 'calendar') {
|
if (resource === 'calendar') {
|
||||||
|
@ -414,16 +425,16 @@ export class GoogleCalendar implements INodeType {
|
||||||
qs.singleEvents = options.singleEvents as boolean;
|
qs.singleEvents = options.singleEvents as boolean;
|
||||||
}
|
}
|
||||||
if (options.timeMax) {
|
if (options.timeMax) {
|
||||||
qs.timeMax = options.timeMax as string;
|
qs.timeMax = addTimezoneToDate(options.timeMax as string, tz || timezone);
|
||||||
}
|
}
|
||||||
if (options.timeMin) {
|
if (options.timeMin) {
|
||||||
qs.timeMin = options.timeMin as string;
|
qs.timeMin = addTimezoneToDate(options.timeMin as string, tz || timezone);
|
||||||
}
|
}
|
||||||
if (tz) {
|
if (tz) {
|
||||||
qs.timeZone = tz;
|
qs.timeZone = tz;
|
||||||
}
|
}
|
||||||
if (options.updatedMin) {
|
if (options.updatedMin) {
|
||||||
qs.updatedMin = options.updatedMin as string;
|
qs.updatedMin = addTimezoneToDate(options.updatedMin as string, tz || timezone);
|
||||||
}
|
}
|
||||||
if (returnAll) {
|
if (returnAll) {
|
||||||
responseData = await googleApiRequestAllItems.call(
|
responseData = await googleApiRequestAllItems.call(
|
||||||
|
@ -458,7 +469,11 @@ export class GoogleCalendar implements INodeType {
|
||||||
const eventId = this.getNodeParameter('eventId', i) as string;
|
const eventId = this.getNodeParameter('eventId', i) as string;
|
||||||
const useDefaultReminders = this.getNodeParameter('useDefaultReminders', i) as boolean;
|
const useDefaultReminders = this.getNodeParameter('useDefaultReminders', i) as boolean;
|
||||||
const updateFields = this.getNodeParameter('updateFields', i);
|
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) {
|
if (updateFields.maxAttendees) {
|
||||||
qs.maxAttendees = updateFields.maxAttendees as number;
|
qs.maxAttendees = updateFields.maxAttendees as number;
|
||||||
|
|
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue