calcom/apps/web/lib/emails/templates/organizer-request-email.ts
Leo Giovanetti 1a79e0624c
Recurring Events (#2562)
* Init dev

* UI changes for recurring event + prisma

* Revisiting schema + changes WIP

* UI done, BE WIP

* Feature completion

* Unused query param removed

* Invalid comment removed

* Removed unused translation

* Update apps/web/public/static/locales/en/common.json

Thanks!

Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* Success page changes

* More progress

* Email text tweaks + test + seed

* Tweaking emails + Cal Apps support WIP

* No app integration for now
Final email and pages tweaks to avoid recurring info showed

* Missing comment for clarity

* Yet again, comment

* Last minute fix

* Missing tooltip for upcoming bookings

* Fixing seed

* Fixing import

* Increasing timeout for e2e

* Fixing any

* Apply suggestions from code review

Co-authored-by: Omar López <zomars@me.com>

* Update apps/web/pages/d/[link]/book.tsx

Co-authored-by: Omar López <zomars@me.com>

* Code improvements

* More code improvements

* Reverting back number input arrows

* Update BookingPage.tsx

* Update BookingPage.tsx

* Adds fallback for sendOrganizerPaymentRefundFailedEmail

* Type overkill

* Type fixes

* Type fixes

* Nitpicks

* Update success.tsx

* Update success.tsx

* Update success.tsx

* Fixing types

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
2022-05-05 18:16:25 -03:00

176 lines
9.2 KiB
TypeScript

import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
import timezone from "dayjs/plugin/timezone";
import toArray from "dayjs/plugin/toArray";
import utc from "dayjs/plugin/utc";
import {
emailHead,
emailSchedulingBodyHeader,
emailBodyLogo,
emailScheduledBodyHeaderContent,
emailSchedulingBodyDivider,
linkIcon,
} from "./common";
import OrganizerScheduledEmail from "./organizer-scheduled-email";
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(localizedFormat);
dayjs.extend(toArray);
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);
}
});
}
return {
from: `Cal.com <${this.getMailerOptions().from}>`,
to: toAddresses.join(","),
subject: `${this.calEvent.organizer.language.translate("event_awaiting_approval_subject", {
eventType: this.calEvent.type,
name: this.calEvent.attendees[0].name,
date: `${this.getOrganizerStart().format("h:mma")} - ${this.getOrganizerEnd().format(
"h:mma"
)}, ${this.calEvent.organizer.language.translate(
this.getOrganizerStart().format("dddd").toLowerCase()
)}, ${this.calEvent.organizer.language.translate(
this.getOrganizerStart().format("MMMM").toLowerCase()
)} ${this.getOrganizerStart().format("D")}, ${this.getOrganizerStart().format("YYYY")}`,
})}`,
html: this.getHtmlBody(),
text: this.getTextBody(),
};
}
protected getTextBody(): string {
return `
${this.calEvent.organizer.language.translate("event_awaiting_approval")}
${this.calEvent.organizer.language.translate("someone_requested_an_event")}
${this.getWhat()}
${this.getWhen()}
${this.getLocation()}
${this.getDescription()}
${this.getAdditionalNotes()}
${this.calEvent.organizer.language.translate("confirm_or_reject_request")}
${process.env.NEXT_PUBLIC_WEBAPP_URL} + "/bookings/upcoming"
`.replace(/(<([^>]+)>)/gi, "");
}
protected getHtmlBody(): string {
const headerContent = this.calEvent.organizer.language.translate("event_awaiting_approval_subject", {
eventType: this.calEvent.type,
name: this.calEvent.attendees[0].name,
date: `${this.getOrganizerStart().format("h:mma")} - ${this.getOrganizerEnd().format(
"h:mma"
)}, ${this.calEvent.organizer.language.translate(
this.getOrganizerStart().format("dddd").toLowerCase()
)}, ${this.calEvent.organizer.language.translate(
this.getOrganizerStart().format("MMMM").toLowerCase()
)} ${this.getOrganizerStart().format("D")}, ${this.getOrganizerStart().format("YYYY")}`,
});
return `
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
${emailHead(headerContent)}
<body style="word-spacing:normal;background-color:#F5F5F5;">
<div style="background-color:#F5F5F5;">
${emailSchedulingBodyHeader("calendarCircle")}
${emailScheduledBodyHeaderContent(
this.calEvent.organizer.language.translate(
this.recurringEvent?.count ? "event_awaiting_approval_recurring" : "event_awaiting_approval"
),
this.calEvent.organizer.language.translate("someone_requested_an_event")
)}
${emailSchedulingBodyDivider()}
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#FFFFFF" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="background:#FFFFFF;background-color:#FFFFFF;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#FFFFFF;background-color:#FFFFFF;width:100%;">
<tbody>
<tr>
<td style="border-left:1px solid #E1E1E1;border-right:1px solid #E1E1E1;direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:598px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto, Helvetica, sans-serif;font-size:16px;font-weight:500;line-height:1;text-align:left;color:#3E3E3E;">
${this.getWhat()}
${this.getWhen()}
${this.getWho()}
${this.getLocation()}
${this.getAdditionalNotes()}
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
${emailSchedulingBodyDivider()}
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#FFFFFF" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="background:#FFFFFF;background-color:#FFFFFF;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#FFFFFF;background-color:#FFFFFF;width:100%;">
<tbody>
<tr>
<td style="border-bottom:1px solid #E1E1E1;border-left:1px solid #E1E1E1;border-right:1px solid #E1E1E1;direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:598px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="center" vertical-align="middle" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:separate;line-height:100%;">
<tr>
<td align="center" bgcolor="#292929" role="presentation" style="border:none;border-radius:3px;cursor:auto;mso-padding-alt:10px 25px;background:#292929;" valign="middle">
<p style="display:inline-block;background:#292929;color:#ffffff;font-family:Roboto, Helvetica, sans-serif;font-size:16px;font-weight:500;line-height:120%;margin:0;text-decoration:none;text-transform:none;padding:10px 25px;mso-padding-alt:0px;border-radius:3px;">
${this.getManageLink()}
</p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto, Helvetica, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;"></div>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
${emailBodyLogo()}
<!--[if mso | IE]></td></tr></table><![endif]-->
</div>
</body>
</html>
`;
}
protected getManageLink(): string {
const manageText = this.calEvent.organizer.language.translate("confirm_or_reject_request");
const manageLink = process.env.NEXT_PUBLIC_WEBAPP_URL + "/bookings/upcoming";
return `<a style="color: #FFFFFF; text-decoration: none;" href="${manageLink}" target="_blank">${manageText} <img src="${linkIcon()}" width="12px"></img></a>`;
}
}