Skip to content

Commit 4bdbd52

Browse files
committed
Fixed: Remove cancelled occurrences
1 parent 46a4e4d commit 4bdbd52

5 files changed

Lines changed: 56 additions & 10 deletions

File tree

.changeset/strict-bats-cover.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@plotday/twister": patch
3+
---
4+
5+
Added: addRecurrenceExdates and removeRecurrenceExdates

.changeset/young-files-ask.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@plotday/tool-outlook-calendar": minor
3+
"@plotday/tool-google-calendar": minor
4+
---
5+
6+
Fixed: Remove cancelled occurrences

tools/google-calendar/src/google-calendar.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ export class GoogleCalendar
894894
// Transform the instance data
895895
const instanceData = transformGoogleEvent(event, calendarId);
896896

897-
// Handle cancelled recurring instances by archiving the occurrence
897+
// Handle cancelled recurring instances by adding to recurrence exdates
898898
if (event.status === "cancelled") {
899899
// Extract start/end from the event (they're present even for cancelled events)
900900
const start = event.start?.dateTime
@@ -909,20 +909,12 @@ export class GoogleCalendar
909909
? event.end.date
910910
: null;
911911

912-
const occurrence: Omit<NewActivityOccurrence, "activity"> = {
913-
occurrence: new Date(originalStartTime),
914-
start: start instanceof Date ? start : new Date(originalStartTime),
915-
archived: true,
916-
};
917-
918-
// Include start/end at activity level to allow master activity creation
919-
// during initial sync (upsert_activity needs these to infer scheduling)
920912
const occurrenceUpdate = {
921913
type: ActivityType.Event,
922914
source: masterCanonicalUrl,
923915
start: start,
924916
end: end,
925-
occurrences: [occurrence],
917+
addRecurrenceExdates: [new Date(originalStartTime)],
926918
};
927919

928920
await this.tools.callbacks.run(callbackToken, occurrenceUpdate);

tools/outlook-calendar/src/outlook-calendar.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,23 @@ export class OutlookCalendar
692692
return; // Skip deleted events
693693
}
694694

695+
// Handle cancelled recurring instances by adding to recurrence exdates
696+
if (event.isCancelled) {
697+
const start = instanceData?.start ?? new Date(originalStart);
698+
const end = instanceData?.end ?? null;
699+
700+
const occurrenceUpdate = {
701+
type: ActivityType.Event,
702+
source: masterCanonicalUrl,
703+
start: start,
704+
end: end,
705+
addRecurrenceExdates: [new Date(originalStart)],
706+
};
707+
708+
await this.tools.callbacks.run(callbackToken, occurrenceUpdate);
709+
return;
710+
}
711+
695712
// Determine RSVP status for attendees
696713
const validAttendees =
697714
event.attendees?.filter(

twister/src/plot.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,19 @@ export type NewActivity = Pick<Activity, "type"> &
872872
* ```
873873
*/
874874
occurrences?: NewActivityOccurrence[];
875+
876+
/**
877+
* Dates to add to the recurrence exclusion list.
878+
* These are merged with existing exdates. Use this for incremental updates
879+
* (e.g., cancelling a single occurrence) instead of replacing the full list.
880+
*/
881+
addRecurrenceExdates?: Date[];
882+
883+
/**
884+
* Dates to remove from the recurrence exclusion list.
885+
* Use this to "uncancel" a previously excluded occurrence.
886+
*/
887+
removeRecurrenceExdates?: Date[];
875888
};
876889

877890
export type ActivityUpdate = (
@@ -962,6 +975,19 @@ export type ActivityUpdate = (
962975
* ```
963976
*/
964977
occurrences?: (NewActivityOccurrence | ActivityOccurrenceUpdate)[];
978+
979+
/**
980+
* Dates to add to the recurrence exclusion list.
981+
* These are merged with existing exdates. Use this for incremental updates
982+
* (e.g., cancelling a single occurrence) instead of replacing the full list.
983+
*/
984+
addRecurrenceExdates?: Date[];
985+
986+
/**
987+
* Dates to remove from the recurrence exclusion list.
988+
* Use this to "uncancel" a previously excluded occurrence.
989+
*/
990+
removeRecurrenceExdates?: Date[];
965991
};
966992

967993
/**

0 commit comments

Comments
 (0)