Compare commits
12 Commits
main
...
write-ical
Author | SHA1 | Date |
---|---|---|
Joe Au-Yeung | 16fffd6258 | |
Joe Au-Yeung | 674c0e2b54 | |
Joe Au-Yeung | 833d3a25bf | |
Joe Au-Yeung | 83cb60b0cc | |
Joe Au-Yeung | 4813b34feb | |
Joe Au-Yeung | 757c878200 | |
Joe Au-Yeung | 25b83c3978 | |
Joe Au-Yeung | f050f0c869 | |
Joe Au-Yeung | 8371a311b1 | |
Joe Au-Yeung | e401431e60 | |
Joe Au-Yeung | 11e1d6fd00 | |
Joe Au-Yeung | b045e996b4 |
|
@ -200,6 +200,7 @@ export default class GoogleCalendarService implements Calendar {
|
|||
useDefault: true,
|
||||
},
|
||||
guestsCanSeeOtherGuests: !!calEventRaw.seatsPerTimeSlot ? calEventRaw.seatsShowAttendees : true,
|
||||
iCalUID: calEventRaw.iCalUID,
|
||||
};
|
||||
|
||||
if (calEventRaw.location) {
|
||||
|
@ -248,7 +249,6 @@ export default class GoogleCalendarService implements Calendar {
|
|||
type: "google_calendar",
|
||||
password: "",
|
||||
url: "",
|
||||
iCalUID: event.data.iCalUID,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("There was an error contacting google calendar service: ", error);
|
||||
|
|
|
@ -23,6 +23,7 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
|
|||
icalEvent: {
|
||||
filename: "event.ics",
|
||||
content: this.getiCalEventAsString(),
|
||||
method: "request",
|
||||
},
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
to: toAddresses.join(","),
|
||||
|
@ -42,6 +43,8 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
|
|||
// @OVERRIDE
|
||||
protected getiCalEventAsString(): string | undefined {
|
||||
const icsEvent = createEvent({
|
||||
uid: this.calEvent.iCalUID || this.calEvent.uid!,
|
||||
sequence: 100,
|
||||
start: dayjs(this.calEvent.startTime)
|
||||
.utc()
|
||||
.toArray()
|
||||
|
@ -61,7 +64,7 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
|
|||
email: attendee.email,
|
||||
})),
|
||||
status: "CANCELLED",
|
||||
method: "CANCEL",
|
||||
method: "REQUEST",
|
||||
});
|
||||
if (icsEvent.error) {
|
||||
throw icsEvent.error;
|
||||
|
|
|
@ -110,6 +110,8 @@ async function getBookingToDelete(id: number | undefined, uid: string | undefine
|
|||
scheduledJobs: true,
|
||||
seatsReferences: true,
|
||||
responses: true,
|
||||
iCalUID: true,
|
||||
iCalSequence: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -261,6 +263,8 @@ async function handler(req: CustomRequest) {
|
|||
...(teamMembers && { team: { name: "", members: teamMembers } }),
|
||||
seatsPerTimeSlot: bookingToDelete.eventType?.seatsPerTimeSlot,
|
||||
seatsShowAttendees: bookingToDelete.eventType?.seatsShowAttendees,
|
||||
iCalUID: bookingToDelete.iCalUID,
|
||||
iCalSequence: bookingToDelete.iCalSequence + 1,
|
||||
};
|
||||
|
||||
const dataForWebhooks = { evt, webhooks, eventTypeInfo };
|
||||
|
@ -387,6 +391,7 @@ async function handler(req: CustomRequest) {
|
|||
data: {
|
||||
status: BookingStatus.CANCELLED,
|
||||
cancellationReason: cancellationReason,
|
||||
iCalSequence: evt.iCalSequence,
|
||||
},
|
||||
select: {
|
||||
startTime: true,
|
||||
|
|
|
@ -1099,6 +1099,14 @@ async function handler(
|
|||
const calEventUserFieldsResponses =
|
||||
"calEventUserFieldsResponses" in reqBody ? reqBody.calEventUserFieldsResponses : null;
|
||||
|
||||
const iCalUID = originalRescheduledBooking?.iCalUID ?? `${uid}@cal.com`;
|
||||
// For bookings made before introducing iCalSequence, assume that the sequence should start at 1. For new bookings start at 0.
|
||||
const iCalSequence = originalRescheduledBooking?.iCalSequence
|
||||
? originalRescheduledBooking.iCalSequence + 1
|
||||
: originalRescheduledBooking
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
let evt: CalendarEvent = {
|
||||
bookerUrl: await getBookerUrl(organizerUser),
|
||||
type: eventType.title,
|
||||
|
@ -1135,6 +1143,8 @@ async function handler(
|
|||
seatsPerTimeSlot: eventType.seatsPerTimeSlot,
|
||||
seatsShowAvailabilityCount: eventType.seatsPerTimeSlot ? eventType.seatsShowAvailabilityCount : true,
|
||||
schedulingType: eventType.schedulingType,
|
||||
iCalUID,
|
||||
iCalSequence,
|
||||
};
|
||||
|
||||
if (isTeamEventType && eventType.schedulingType === "COLLECTIVE") {
|
||||
|
@ -1963,6 +1973,8 @@ async function handler(
|
|||
connect: { id: evt.destinationCalendar[0].id },
|
||||
}
|
||||
: undefined,
|
||||
iCalUID: evt.iCalUID ?? "",
|
||||
iCalSequence: evt.iCalSequence ?? 0,
|
||||
};
|
||||
|
||||
if (reqBody.recurringEventId) {
|
||||
|
@ -2299,6 +2311,18 @@ async function handler(
|
|||
evt.appsStatus = handleAppsStatus(results, booking);
|
||||
videoCallUrl =
|
||||
metadata.hangoutLink || organizerOrFirstDynamicGroupMemberDefaultLocationUrl || videoCallUrl;
|
||||
|
||||
if (evt.iCalUID !== booking.iCalUID) {
|
||||
// The eventManager and handleAppsStatus could change the iCalUID. At this point we can update the DB record
|
||||
await prisma.booking.update({
|
||||
where: {
|
||||
id: booking.id,
|
||||
},
|
||||
data: {
|
||||
iCalUID: evt.iCalUID,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
if (noEmail !== true) {
|
||||
let isHostConfirmationEmailsDisabled = false;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `iCalUID` to the `Booking` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Booking"
|
||||
ADD COLUMN "iCalUID" VARCHAR NOT NULL ,
|
||||
ADD COLUMN "iCalSequence" INTEGER NOT NULL DEFAULT 0;
|
|
@ -417,6 +417,8 @@ model Booking {
|
|||
/// @zod.custom(imports.bookingMetadataSchema)
|
||||
metadata Json?
|
||||
isRecorded Boolean @default(false)
|
||||
iCalUID String @db.VarChar()
|
||||
iCalSequence Int @default(0)
|
||||
|
||||
@@index([eventTypeId])
|
||||
@@index([userId])
|
||||
|
|
|
@ -133,6 +133,7 @@ export async function createUserAndEventType({
|
|||
},
|
||||
},
|
||||
status: bookingInput.status,
|
||||
iCalUID: "",
|
||||
},
|
||||
});
|
||||
console.log(
|
||||
|
|
|
@ -62,6 +62,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
|
|||
scheduledJobs: true,
|
||||
workflowReminders: true,
|
||||
responses: true,
|
||||
iCalUID: true,
|
||||
},
|
||||
where: {
|
||||
uid: bookingId,
|
||||
|
@ -176,6 +177,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
|
|||
tAttendees
|
||||
),
|
||||
organizer: userAsPeopleType,
|
||||
iCalUID: bookingToReschedule.iCalUID,
|
||||
});
|
||||
|
||||
const director = new CalendarEventDirector();
|
||||
|
@ -246,6 +248,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
|
|||
? [bookingToReschedule?.destinationCalendar]
|
||||
: [],
|
||||
cancellationReason: `Please reschedule. ${cancellationReason}`, // TODO::Add i18-next for this
|
||||
iCalUID: bookingToReschedule?.iCalUID,
|
||||
};
|
||||
|
||||
// Send webhook
|
||||
|
|
|
@ -184,6 +184,7 @@ export interface CalendarEvent {
|
|||
seatsPerTimeSlot?: number | null;
|
||||
schedulingType?: SchedulingType | null;
|
||||
iCalUID?: string | null;
|
||||
iCalSequence?: number | null;
|
||||
|
||||
// It has responses to all the fields(system + user)
|
||||
responses?: CalEventResponses | null;
|
||||
|
|
Loading…
Reference in New Issue