Fix - add team members to emails (#7207)
* On booking add team members & translation
* Add team members to round robin create
* Only update calendars on reschedule if there is a calendar reference
* Send email on reschedules
* Send team email on cancelled event
* Add team members to calendar event description
* Clean up
* Convert other emails to organizer & teams
* Type check fixes
* More type fixes
* Change organizer scheduled input to an object
* early return updateCalendarEvent
* Introduce team member type
* Fix type errors
* Put team members before attendees
* Remove lodash cloneDeep
* Update packages/core/EventManager.ts
Co-authored-by: Omar López <zomars@me.com>
* Remove booking select object
* Revert "Remove booking select object"
This reverts commit 9f121ff4eb
.
* Refactor email manager (#7270)
Co-authored-by: zomars <zomars@me.com>
* Type change
* Remove conditional check for updateAllCalendarEvents
---------
Co-authored-by: zomars <zomars@me.com>
This commit is contained in:
parent
2a98ca4b91
commit
8b07b839e9
|
@ -1603,6 +1603,7 @@
|
|||
"booking_with_payment_cancelled_refunded": "This booking payment has been refunded.",
|
||||
"booking_confirmation_failed": "Booking confirmation failed",
|
||||
"get_started_zapier_templates": "Get started with Zapier templates",
|
||||
"team_member": "Team member",
|
||||
"a_routing_form": "A Routing Form",
|
||||
"form_description_placeholder": "Form Description",
|
||||
"keep_me_connected_with_form": "Keep me connected with the form",
|
||||
|
|
|
@ -255,7 +255,6 @@ export default class EventManager {
|
|||
results.push(result);
|
||||
}
|
||||
|
||||
// Update all calendar events.
|
||||
results.push(...(await this.updateAllCalendarEvents(evt, booking)));
|
||||
|
||||
const bookingPayment = booking?.payment;
|
||||
|
@ -442,7 +441,7 @@ export default class EventManager {
|
|||
// Bookings should only have one calendar reference
|
||||
calendarReference = booking.references.filter((reference) => reference.type.includes("_calendar"))[0];
|
||||
if (!calendarReference) {
|
||||
throw new Error("bookingRef");
|
||||
return [];
|
||||
}
|
||||
const { uid: bookingRefUid, externalCalendarId: bookingExternalCalendarId } = calendarReference;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DestinationCalendar } from "@prisma/client";
|
||||
import type { DestinationCalendar } from "@prisma/client";
|
||||
|
||||
import type {
|
||||
AdditionalInformation,
|
||||
|
@ -16,7 +16,7 @@ class CalendarEventClass implements CalendarEvent {
|
|||
organizer!: Person;
|
||||
attendees!: Person[];
|
||||
description?: string | null;
|
||||
team?: { name: string; members: string[] };
|
||||
team?: { name: string; members: Person[] };
|
||||
location?: string | null;
|
||||
conferenceData?: ConferenceData;
|
||||
additionalInformation?: AdditionalInformation;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { TFunction } from "next-i18next";
|
||||
import type { TFunction } from "next-i18next";
|
||||
|
||||
import type BaseEmail from "@calcom/emails/templates/_base-email";
|
||||
import type { CalendarEvent, Person } from "@calcom/types/Calendar";
|
||||
|
||||
import AttendeeAwaitingPaymentEmail from "./templates/attendee-awaiting-payment-email";
|
||||
|
@ -12,8 +13,10 @@ import AttendeeScheduledEmail from "./templates/attendee-scheduled-email";
|
|||
import AttendeeWasRequestedToRescheduleEmail from "./templates/attendee-was-requested-to-reschedule-email";
|
||||
import BrokenIntegrationEmail from "./templates/broken-integration-email";
|
||||
import DisabledAppEmail from "./templates/disabled-app-email";
|
||||
import FeedbackEmail, { Feedback } from "./templates/feedback-email";
|
||||
import ForgotPasswordEmail, { PasswordReset } from "./templates/forgot-password-email";
|
||||
import type { Feedback } from "./templates/feedback-email";
|
||||
import FeedbackEmail from "./templates/feedback-email";
|
||||
import type { PasswordReset } from "./templates/forgot-password-email";
|
||||
import ForgotPasswordEmail from "./templates/forgot-password-email";
|
||||
import OrganizerCancelledEmail from "./templates/organizer-cancelled-email";
|
||||
import OrganizerLocationChangeEmail from "./templates/organizer-location-change-email";
|
||||
import OrganizerPaymentRefundFailedEmail from "./templates/organizer-payment-refund-failed-email";
|
||||
|
@ -22,32 +25,34 @@ import OrganizerRequestReminderEmail from "./templates/organizer-request-reminde
|
|||
import OrganizerRequestedToRescheduleEmail from "./templates/organizer-requested-to-reschedule-email";
|
||||
import OrganizerRescheduledEmail from "./templates/organizer-rescheduled-email";
|
||||
import OrganizerScheduledEmail from "./templates/organizer-scheduled-email";
|
||||
import TeamInviteEmail, { TeamInvite } from "./templates/team-invite-email";
|
||||
import type { TeamInvite } from "./templates/team-invite-email";
|
||||
import TeamInviteEmail from "./templates/team-invite-email";
|
||||
|
||||
const sendEmail = (prepare: () => BaseEmail) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const email = prepare();
|
||||
resolve(email.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error(`${prepare.constructor.name}.sendEmail failed`, e));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const sendScheduledEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new AttendeeScheduledEmail(calEvent, attendee);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeRescheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new OrganizerScheduledEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerScheduledEmail({ calEvent, teamMember })));
|
||||
}
|
||||
}
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new OrganizerScheduledEmail(calEvent);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerScheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return sendEmail(() => new AttendeeScheduledEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -56,28 +61,19 @@ export const sendScheduledEmails = async (calEvent: CalendarEvent) => {
|
|||
|
||||
export const sendRescheduledEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRescheduledEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRescheduledEmail({ calEvent, teamMember })));
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO: we should obtain who is rescheduling the event and send them a different email
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new AttendeeRescheduledEmail(calEvent, attendee);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeRescheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new OrganizerRescheduledEmail(calEvent);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerRescheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
return sendEmail(() => new AttendeeRescheduledEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -92,51 +88,35 @@ export const sendScheduledSeatsEmails = async (
|
|||
) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new AttendeeScheduledEmail(calEvent, invitee, showAttendees);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeScheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new OrganizerScheduledEmail({ calEvent, newSeat })));
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new OrganizerScheduledEmail(calEvent, newSeat);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerScheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
})
|
||||
);
|
||||
if (calEvent.team) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerScheduledEmail({ calEvent, newSeat, teamMember })));
|
||||
}
|
||||
}
|
||||
|
||||
emailsToSend.push(sendEmail(() => new AttendeeScheduledEmail(calEvent, invitee, showAttendees)));
|
||||
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
|
||||
export const sendOrganizerRequestEmail = async (calEvent: CalendarEvent) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const organizerRequestEmail = new OrganizerRequestEmail(calEvent);
|
||||
resolve(organizerRequestEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerRequestEmail.sendEmail failed", e));
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRequestEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team?.members) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRequestEmail({ calEvent, teamMember })));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
|
||||
export const sendAttendeeRequestEmail = async (calEvent: CalendarEvent, attendee: Person) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const attendeeRequestEmail = new AttendeeRequestEmail(calEvent, attendee);
|
||||
resolve(attendeeRequestEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendRequestEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new AttendeeRequestEmail(calEvent, attendee));
|
||||
};
|
||||
|
||||
export const sendDeclinedEmails = async (calEvent: CalendarEvent) => {
|
||||
|
@ -144,14 +124,7 @@ export const sendDeclinedEmails = async (calEvent: CalendarEvent) => {
|
|||
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const declinedEmail = new AttendeeDeclinedEmail(calEvent, attendee);
|
||||
resolve(declinedEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeRescheduledEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
return sendEmail(() => new AttendeeDeclinedEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -161,27 +134,17 @@ export const sendDeclinedEmails = async (calEvent: CalendarEvent) => {
|
|||
export const sendCancelledEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new AttendeeCancelledEmail(calEvent, attendee);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeCancelledEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new OrganizerCancelledEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team?.members) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerCancelledEmail({ calEvent, teamMember })));
|
||||
}
|
||||
}
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new OrganizerCancelledEmail(calEvent);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerCancelledEmail.sendEmail failed", e));
|
||||
}
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return sendEmail(() => new AttendeeCancelledEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -189,14 +152,15 @@ export const sendCancelledEmails = async (calEvent: CalendarEvent) => {
|
|||
};
|
||||
|
||||
export const sendOrganizerRequestReminderEmail = async (calEvent: CalendarEvent) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const organizerRequestReminderEmail = new OrganizerRequestReminderEmail(calEvent);
|
||||
resolve(organizerRequestReminderEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerRequestReminderEmail.sendEmail failed", e));
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRequestReminderEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team?.members) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRequestReminderEmail({ calEvent, teamMember })));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const sendAwaitingPaymentEmail = async (calEvent: CalendarEvent) => {
|
||||
|
@ -204,50 +168,31 @@ export const sendAwaitingPaymentEmail = async (calEvent: CalendarEvent) => {
|
|||
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const paymentEmail = new AttendeeAwaitingPaymentEmail(calEvent, attendee);
|
||||
resolve(paymentEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeAwaitingPaymentEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
return sendEmail(() => new AttendeeAwaitingPaymentEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
|
||||
export const sendOrganizerPaymentRefundFailedEmail = async (calEvent: CalendarEvent) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const paymentRefundFailedEmail = new OrganizerPaymentRefundFailedEmail(calEvent);
|
||||
resolve(paymentRefundFailedEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerPaymentRefundFailedEmail.sendEmail failed", e));
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
emailsToSend.push(sendEmail(() => new OrganizerPaymentRefundFailedEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team?.members) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerPaymentRefundFailedEmail({ calEvent, teamMember })));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
|
||||
export const sendPasswordResetEmail = async (passwordResetEvent: PasswordReset) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const passwordResetEmail = new ForgotPasswordEmail(passwordResetEvent);
|
||||
resolve(passwordResetEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerPaymentRefundFailedEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new ForgotPasswordEmail(passwordResetEvent));
|
||||
};
|
||||
|
||||
export const sendTeamInviteEmail = async (teamInviteEvent: TeamInvite) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const teamInviteEmail = new TeamInviteEmail(teamInviteEvent);
|
||||
resolve(teamInviteEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("TeamInviteEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new TeamInviteEmail(teamInviteEvent));
|
||||
};
|
||||
|
||||
export const sendRequestRescheduleEmail = async (
|
||||
|
@ -256,27 +201,9 @@ export const sendRequestRescheduleEmail = async (
|
|||
) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const requestRescheduleEmail = new AttendeeWasRequestedToRescheduleEmail(calEvent, metadata);
|
||||
resolve(requestRescheduleEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeWasRequestedToRescheduleEmail.sendEmail failed", e));
|
||||
}
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRequestedToRescheduleEmail(calEvent, metadata)));
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const requestRescheduleEmail = new OrganizerRequestedToRescheduleEmail(calEvent, metadata);
|
||||
resolve(requestRescheduleEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerRequestedToRescheduleEmail.sendEmail failed", e));
|
||||
}
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new AttendeeWasRequestedToRescheduleEmail(calEvent, metadata)));
|
||||
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
|
@ -284,52 +211,28 @@ export const sendRequestRescheduleEmail = async (
|
|||
export const sendLocationChangeEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
emailsToSend.push(
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new AttendeeLocationChangeEmail(calEvent, attendee);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("AttendeeLocationChangeEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
emailsToSend.push(sendEmail(() => new OrganizerLocationChangeEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team?.members) {
|
||||
for (const teamMember of calEvent.team.members) {
|
||||
emailsToSend.push(sendEmail(() => new OrganizerLocationChangeEmail({ calEvent, teamMember })));
|
||||
}
|
||||
}
|
||||
|
||||
emailsToSend.push(
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
const scheduledEmail = new OrganizerLocationChangeEmail(calEvent);
|
||||
resolve(scheduledEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("OrganizerLocationChangeEmail.sendEmail failed", e));
|
||||
}
|
||||
...calEvent.attendees.map((attendee) => {
|
||||
return sendEmail(() => new AttendeeLocationChangeEmail(calEvent, attendee));
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(emailsToSend);
|
||||
};
|
||||
export const sendFeedbackEmail = async (feedback: Feedback) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const feedbackEmail = new FeedbackEmail(feedback);
|
||||
resolve(feedbackEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("FeedbackEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new FeedbackEmail(feedback));
|
||||
};
|
||||
|
||||
export const sendBrokenIntegrationEmail = async (evt: CalendarEvent, type: "video" | "calendar") => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const brokenIntegrationEmail = new BrokenIntegrationEmail(evt, type);
|
||||
resolve(brokenIntegrationEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("FeedbackEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new BrokenIntegrationEmail(evt, type));
|
||||
};
|
||||
|
||||
export const sendDisabledAppEmail = async ({
|
||||
|
@ -347,12 +250,5 @@ export const sendDisabledAppEmail = async ({
|
|||
title?: string;
|
||||
eventTypeId?: number;
|
||||
}) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const disabledPaymentEmail = new DisabledAppEmail(email, appName, appType, t, title, eventTypeId);
|
||||
resolve(disabledPaymentEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("DisabledPaymentEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
await sendEmail(() => new DisabledAppEmail(email, appName, appType, t, title, eventTypeId));
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { TFunction } from "next-i18next";
|
||||
import type { TFunction } from "next-i18next";
|
||||
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
|
@ -27,6 +27,9 @@ export function WhoInfo(props: { calEvent: CalendarEvent; t: TFunction }) {
|
|||
role={t("organizer")}
|
||||
email={props.calEvent.organizer.email}
|
||||
/>
|
||||
{props.calEvent.team?.members.map((member) => (
|
||||
<PersonInfo key={member.name} name={member.name} role={t("team_member")} email={member.email} />
|
||||
))}
|
||||
{props.calEvent.attendees.map((attendee) => (
|
||||
<PersonInfo
|
||||
key={attendee.id || attendee.name}
|
||||
|
|
|
@ -7,6 +7,7 @@ export const OrganizerScheduledEmail = (
|
|||
calEvent: CalendarEvent;
|
||||
attendee: Person;
|
||||
newSeat?: boolean;
|
||||
teamMember?: Person;
|
||||
} & Partial<React.ComponentProps<typeof BaseScheduledEmail>>
|
||||
) => {
|
||||
let subject;
|
||||
|
@ -26,10 +27,10 @@ export const OrganizerScheduledEmail = (
|
|||
title = "new_event_scheduled";
|
||||
}
|
||||
|
||||
const t = props.calEvent.organizer.language.translate;
|
||||
const t = props.teamMember?.language.translate || props.calEvent.organizer.language.translate;
|
||||
return (
|
||||
<BaseScheduledEmail
|
||||
timeZone={props.calEvent.organizer.timeZone}
|
||||
timeZone={props.teamMember?.timeZone || props.calEvent.organizer.timeZone}
|
||||
t={t}
|
||||
subject={t(subject)}
|
||||
title={t(title)}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import nodemailer from "nodemailer";
|
||||
|
||||
import dayjs, { Dayjs } from "@calcom/dayjs";
|
||||
import type { Dayjs } from "@calcom/dayjs";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { serverConfig } from "@calcom/lib/serverConfig";
|
||||
|
||||
|
|
|
@ -5,15 +5,7 @@ import AttendeeScheduledEmail from "./attendee-scheduled-email";
|
|||
|
||||
export default class AttendeeRequestEmail extends AttendeeScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.attendees[0].email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = this.calEvent.attendees.map((attendee) => attendee.email);
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { createEvent, DateArray } from "ics";
|
||||
import { TFunction } from "next-i18next";
|
||||
import type { DateArray } from "ics";
|
||||
import { createEvent } from "ics";
|
||||
import type { TFunction } from "next-i18next";
|
||||
import { RRule } from "rrule";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
|
@ -47,10 +48,18 @@ export default class AttendeeScheduledEmail extends BaseEmail {
|
|||
description: this.getTextBody(),
|
||||
duration: { minutes: dayjs(this.calEvent.endTime).diff(dayjs(this.calEvent.startTime), "minute") },
|
||||
organizer: { name: this.calEvent.organizer.name, email: this.calEvent.organizer.email },
|
||||
attendees: this.calEvent.attendees.map((attendee: Person) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
})),
|
||||
attendees: [
|
||||
...this.calEvent.attendees.map((attendee: Person) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
})),
|
||||
...(this.calEvent.team?.members
|
||||
? this.calEvent.team?.members.map((member: Person) => ({
|
||||
name: member.name,
|
||||
email: member.email,
|
||||
}))
|
||||
: []),
|
||||
],
|
||||
...{ recurrenceRule },
|
||||
status: "CONFIRMED",
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { createEvent, DateArray, Person } from "ics";
|
||||
import type { DateArray, Person } from "ics";
|
||||
import { createEvent } from "ics";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getManageLink } from "@calcom/lib/CalEventParser";
|
||||
|
@ -11,7 +12,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerScheduledEmail {
|
||||
private metadata: { rescheduleLink: string };
|
||||
constructor(calEvent: CalendarEvent, metadata: { rescheduleLink: string }) {
|
||||
super(calEvent);
|
||||
super({ calEvent });
|
||||
this.metadata = metadata;
|
||||
}
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { TFunction } from "next-i18next";
|
||||
import type { TFunction } from "next-i18next";
|
||||
|
||||
import { getRichDescription } from "@calcom/lib/CalEventParser";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
@ -22,14 +22,6 @@ export default class BrokenIntegrationEmail extends BaseEmail {
|
|||
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
|
||||
export default class OrganizerCancelledEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
|
||||
export default class OrganizerLocationChangeEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
icalEvent: {
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
|
||||
export default class OrganizerPaymentRefundFailedEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
|
||||
export default class OrganizerRequestEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerRequestEmail from "./organizer-request-email";
|
|||
|
||||
export default class OrganizerRequestReminderEmail extends OrganizerRequestEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { createEvent, DateArray, Person } from "ics";
|
||||
import type { DateArray, Person } from "ics";
|
||||
import { createEvent } from "ics";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getRichDescription } from "@calcom/lib/CalEventParser";
|
||||
|
@ -11,7 +12,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
export default class OrganizerRequestedToRescheduleEmail extends OrganizerScheduledEmail {
|
||||
private metadata: { rescheduleLink: string };
|
||||
constructor(calEvent: CalendarEvent, metadata: { rescheduleLink: string }) {
|
||||
super(calEvent);
|
||||
super({ calEvent });
|
||||
this.metadata = metadata;
|
||||
}
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
|
|
|
@ -5,15 +5,7 @@ import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
|||
|
||||
export default class OrganizerRescheduledEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
icalEvent: {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { createEvent, DateArray, Person } from "ics";
|
||||
import { TFunction } from "next-i18next";
|
||||
import type { DateArray } from "ics";
|
||||
import { createEvent } from "ics";
|
||||
import type { TFunction } from "next-i18next";
|
||||
import { RRule } from "rrule";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getRichDescription } from "@calcom/lib/CalEventParser";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type { CalendarEvent, Person } from "@calcom/types/Calendar";
|
||||
|
||||
import { renderEmail } from "../";
|
||||
import BaseEmail from "./_base-email";
|
||||
|
@ -14,13 +15,15 @@ export default class OrganizerScheduledEmail extends BaseEmail {
|
|||
calEvent: CalendarEvent;
|
||||
t: TFunction;
|
||||
newSeat?: boolean;
|
||||
teamMember?: Person;
|
||||
|
||||
constructor(calEvent: CalendarEvent, newSeat?: boolean) {
|
||||
constructor(input: { calEvent: CalendarEvent; newSeat?: boolean; teamMember?: Person }) {
|
||||
super();
|
||||
this.name = "SEND_BOOKING_CONFIRMATION";
|
||||
this.calEvent = calEvent;
|
||||
this.calEvent = input.calEvent;
|
||||
this.t = this.calEvent.organizer.language.translate;
|
||||
this.newSeat = newSeat;
|
||||
this.newSeat = input.newSeat;
|
||||
this.teamMember = input.teamMember;
|
||||
}
|
||||
|
||||
protected getiCalEventAsString(): string | undefined {
|
||||
|
@ -43,10 +46,18 @@ export default class OrganizerScheduledEmail extends BaseEmail {
|
|||
duration: { minutes: dayjs(this.calEvent.endTime).diff(dayjs(this.calEvent.startTime), "minute") },
|
||||
organizer: { name: this.calEvent.organizer.name, email: this.calEvent.organizer.email },
|
||||
...{ recurrenceRule },
|
||||
attendees: this.calEvent.attendees.map((attendee: Person) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
})),
|
||||
attendees: [
|
||||
...this.calEvent.attendees.map((attendee: Person) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
})),
|
||||
...(this.calEvent.team?.members
|
||||
? this.calEvent.team?.members.map((member: Person) => ({
|
||||
name: member.name,
|
||||
email: member.email,
|
||||
}))
|
||||
: []),
|
||||
],
|
||||
status: "CONFIRMED",
|
||||
});
|
||||
if (icsEvent.error) {
|
||||
|
@ -56,15 +67,7 @@ export default class OrganizerScheduledEmail extends BaseEmail {
|
|||
}
|
||||
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email];
|
||||
|
||||
return {
|
||||
icalEvent: {
|
||||
|
@ -79,6 +82,7 @@ export default class OrganizerScheduledEmail extends BaseEmail {
|
|||
html: renderEmail("OrganizerScheduledEmail", {
|
||||
calEvent: this.calEvent,
|
||||
attendee: this.calEvent.organizer,
|
||||
teamMember: this.teamMember,
|
||||
newSeat: this.newSeat,
|
||||
}),
|
||||
text: this.getTextBody(),
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import {
|
||||
BookingStatus,
|
||||
MembershipRole,
|
||||
WebhookTriggerEvents,
|
||||
WorkflowMethods,
|
||||
WorkflowReminder,
|
||||
} from "@prisma/client";
|
||||
import { NextApiRequest } from "next";
|
||||
import type { WebhookTriggerEvents, WorkflowReminder } from "@prisma/client";
|
||||
import { BookingStatus, MembershipRole, WorkflowMethods } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import appStore from "@calcom/app-store";
|
||||
import { getCalendar } from "@calcom/app-store/_utils/getCalendar";
|
||||
|
@ -19,7 +14,8 @@ import { deleteScheduledEmailReminder } from "@calcom/features/ee/workflows/lib/
|
|||
import { sendCancelledReminders } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
|
||||
import { deleteScheduledSMSReminder } from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager";
|
||||
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import sendPayload, { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import type { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { handleRefundError } from "@calcom/lib/payment/handleRefundError";
|
||||
|
@ -74,6 +70,11 @@ async function handler(req: NextApiRequest & { userId?: number }) {
|
|||
price: true,
|
||||
currency: true,
|
||||
length: true,
|
||||
hosts: {
|
||||
select: {
|
||||
user: true,
|
||||
},
|
||||
},
|
||||
workflows: {
|
||||
include: {
|
||||
workflow: {
|
||||
|
@ -118,8 +119,12 @@ async function handler(req: NextApiRequest & { userId?: number }) {
|
|||
},
|
||||
});
|
||||
|
||||
const attendeesListPromises = bookingToDelete.attendees.map(async (attendee) => {
|
||||
return {
|
||||
const teamMembersPromises = [];
|
||||
const attendeesListPromises = [];
|
||||
const hostsPresent = !!bookingToDelete.eventType?.hosts;
|
||||
|
||||
for (const attendee of bookingToDelete.attendees) {
|
||||
const attendeeObject = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
|
@ -128,9 +133,24 @@ async function handler(req: NextApiRequest & { userId?: number }) {
|
|||
locale: attendee.locale ?? "en",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Check for the presence of hosts to determine if it is a team event type
|
||||
if (hostsPresent) {
|
||||
// If the attendee is a host then they are a team member
|
||||
const teamMember = bookingToDelete.eventType?.hosts.some((host) => host.user.email === attendee.email);
|
||||
if (teamMember) {
|
||||
teamMembersPromises.push(attendeeObject);
|
||||
// If not then they are an attendee
|
||||
} else {
|
||||
attendeesListPromises.push(attendeeObject);
|
||||
}
|
||||
} else {
|
||||
attendeesListPromises.push(attendeeObject);
|
||||
}
|
||||
}
|
||||
|
||||
const attendeesList = await Promise.all(attendeesListPromises);
|
||||
const teamMembers = await Promise.all(teamMembersPromises);
|
||||
const tOrganizer = await getTranslation(organizer.locale ?? "en", "common");
|
||||
|
||||
const evt: CalendarEvent = {
|
||||
|
@ -155,7 +175,9 @@ async function handler(req: NextApiRequest & { userId?: number }) {
|
|||
location: bookingToDelete?.location,
|
||||
destinationCalendar: bookingToDelete?.destinationCalendar || bookingToDelete?.user.destinationCalendar,
|
||||
cancellationReason: cancellationReason,
|
||||
...(teamMembers && { team: { name: "", members: teamMembers } }),
|
||||
};
|
||||
|
||||
// Hook up the webhook logic here
|
||||
const eventTrigger: WebhookTriggerEvents = "BOOKING_CANCELLED";
|
||||
// Send Webhook call if hooked to BOOKING.CANCELLED
|
||||
|
|
|
@ -335,6 +335,10 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
|||
|
||||
if (!eventType) throw new HttpError({ statusCode: 404, message: "eventType.notFound" });
|
||||
|
||||
const isTeamEventType =
|
||||
eventType.schedulingType === SchedulingType.COLLECTIVE ||
|
||||
eventType.schedulingType === SchedulingType.ROUND_ROBIN;
|
||||
|
||||
const paymentAppData = getPaymentAppData(eventType);
|
||||
|
||||
// Check if required custom inputs exist
|
||||
|
@ -495,12 +499,23 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
|||
language: { translate: tAttendees, locale: language ?? "en" },
|
||||
},
|
||||
];
|
||||
const guests = (reqBody.guests || []).map((guest) => ({
|
||||
email: guest,
|
||||
name: "",
|
||||
timeZone: reqBody.timeZone,
|
||||
language: { translate: tGuests, locale: "en" },
|
||||
}));
|
||||
|
||||
const guests = (reqBody.guests || []).reduce((guestArray, guest) => {
|
||||
// If it's a team event, remove the team member from guests
|
||||
if (isTeamEventType) {
|
||||
if (users.some((user) => user.email === guest)) {
|
||||
return guestArray;
|
||||
} else {
|
||||
guestArray.push({
|
||||
email: guest,
|
||||
name: "",
|
||||
timeZone: reqBody.timeZone,
|
||||
language: { translate: tGuests, locale: "en" },
|
||||
});
|
||||
}
|
||||
}
|
||||
return guestArray;
|
||||
}, [] as typeof invitee);
|
||||
|
||||
const seed = `${organizerUser.username}:${dayjs(reqBody.start).utc().format()}:${new Date().getTime()}`;
|
||||
const uid = translator.fromUUID(uuidv5(seed, uuidv5.URL));
|
||||
|
@ -539,7 +554,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
|||
|
||||
const teamMembers = await Promise.all(teamMemberPromises);
|
||||
|
||||
const attendeesList = [...invitee, ...guests, ...teamMembers];
|
||||
const attendeesList = [...invitee, ...guests];
|
||||
|
||||
const eventNameObject = {
|
||||
attendeeName: reqBody.name || "Nameless",
|
||||
|
@ -720,11 +735,11 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
|||
});
|
||||
}
|
||||
|
||||
if (eventType.schedulingType === SchedulingType.COLLECTIVE) {
|
||||
if (isTeamEventType) {
|
||||
evt.team = {
|
||||
members: users.map((user) => user.name || user.username || "Nameless"),
|
||||
members: teamMembers,
|
||||
name: eventType.team?.name || "Nameless",
|
||||
}; // used for invitee emails
|
||||
};
|
||||
}
|
||||
|
||||
if (reqBody.recurringEventId && eventType.recurringEvent) {
|
||||
|
@ -810,17 +825,30 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
|||
metadata: reqBody.metadata,
|
||||
attendees: {
|
||||
createMany: {
|
||||
data: evt.attendees.map((attendee) => {
|
||||
//if attendee is team member, it should fetch their locale not booker's locale
|
||||
//perhaps make email fetch request to see if his locale is stored, else
|
||||
const retObj = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
locale: attendee.language.locale,
|
||||
};
|
||||
return retObj;
|
||||
}),
|
||||
data: [
|
||||
...evt.attendees.map((attendee) => {
|
||||
//if attendee is team member, it should fetch their locale not booker's locale
|
||||
//perhaps make email fetch request to see if his locale is stored, else
|
||||
const retObj = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
locale: attendee.language.locale,
|
||||
};
|
||||
return retObj;
|
||||
}),
|
||||
// Have this for now until we change the relationship between bookings & team members
|
||||
...(evt.team?.members
|
||||
? evt.team.members.map((member) => {
|
||||
return {
|
||||
email: member.email,
|
||||
name: member.name,
|
||||
timeZone: member.timeZone,
|
||||
locale: member.language.locale,
|
||||
};
|
||||
})
|
||||
: []),
|
||||
],
|
||||
},
|
||||
},
|
||||
dynamicEventSlugRef,
|
||||
|
|
|
@ -46,9 +46,18 @@ ${calEvent.organizer.name} - ${calEvent.organizer.language.translate("organizer"
|
|||
${calEvent.organizer.email}
|
||||
`;
|
||||
|
||||
const teamMembers = calEvent.team?.members
|
||||
? calEvent.team.members.map((member) => {
|
||||
return `
|
||||
${member.name} - ${calEvent.organizer.language.translate("team_member")}
|
||||
${member.email}
|
||||
`;
|
||||
})
|
||||
: [];
|
||||
|
||||
return `
|
||||
${calEvent.organizer.language.translate("who")}:
|
||||
${organizer + attendees}
|
||||
${organizer + attendees + teamMembers.join("")}
|
||||
`;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,13 @@ export type Person = {
|
|||
locale?: string;
|
||||
};
|
||||
|
||||
export type TeamMember = {
|
||||
name: string;
|
||||
email: string;
|
||||
timeZone: string;
|
||||
language: { translate: TFunction; locale: string };
|
||||
};
|
||||
|
||||
export type EventBusyDate = {
|
||||
start: Date | string;
|
||||
end: Date | string;
|
||||
|
@ -137,7 +144,7 @@ export interface CalendarEvent {
|
|||
description?: string | null;
|
||||
team?: {
|
||||
name: string;
|
||||
members: string[];
|
||||
members: TeamMember[];
|
||||
};
|
||||
location?: string | null;
|
||||
conferenceData?: ConferenceData;
|
||||
|
|
Loading…
Reference in New Issue
Block a user