♻️ Remove use of context from email package (#981)

This commit is contained in:
Luke Vella 2024-01-17 10:33:30 +07:00 committed by GitHub
parent 668a4b5798
commit e2c4cc7ad2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 59 additions and 44 deletions

View file

@ -21,5 +21,6 @@ export const emailClient = new EmailClient({
context: { context: {
logoUrl: absoluteUrl("/logo.png"), logoUrl: absoluteUrl("/logo.png"),
baseUrl: absoluteUrl(""), baseUrl: absoluteUrl(""),
domain: absoluteUrl("").replace(/(^\w+:|^)\/\//, ""),
}, },
}); });

View file

@ -13,8 +13,9 @@ type Templates = typeof templates;
type TemplateName = keyof typeof templates; type TemplateName = keyof typeof templates;
type TemplateProps<T extends TemplateName> = React.ComponentProps< type TemplateProps<T extends TemplateName> = Omit<
TemplateComponent<T> React.ComponentProps<TemplateComponent<T>>,
"ctx"
>; >;
type TemplateComponent<T extends TemplateName> = Templates[T]; type TemplateComponent<T extends TemplateName> = Templates[T];
@ -79,12 +80,11 @@ export class EmailClient {
) { ) {
const Template = templates[templateName] as TemplateComponent<T>; const Template = templates[templateName] as TemplateComponent<T>;
const html = render( const html = render(
<EmailContext.Provider value={this.config.context}> <Template
<Template // eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any {...(options.props as any)}
{...(options.props as any)} ctx={this.config.context}
/> />,
</EmailContext.Provider>,
); );
try { try {

View file

@ -1,19 +1,5 @@
import React from "react";
export type EmailContext = { export type EmailContext = {
logoUrl: string; logoUrl: string;
baseUrl: string; baseUrl: string;
}; domain: string;
export const EmailContext = React.createContext<EmailContext>({
logoUrl: "/static/logo.png",
baseUrl: "",
});
export const useEmailContext = () => {
const context = React.useContext(EmailContext);
return {
...context,
domain: context.baseUrl.replace(/(^\w+:|^)\/\//, ""),
};
}; };

View file

@ -8,13 +8,14 @@ import {
Preview, Preview,
} from "@react-email/components"; } from "@react-email/components";
import { useEmailContext } from "./email-context"; import { EmailContext } from "./email-context";
import { fontFamily, Section, Text } from "./styled-components"; import { fontFamily, Section, Text } from "./styled-components";
export interface EmailLayoutProps { export interface EmailLayoutProps {
preview: string; preview: string;
recipientName: string; recipientName: string;
footNote?: React.ReactNode; footNote?: React.ReactNode;
ctx: EmailContext;
} }
const containerStyles = { const containerStyles = {
@ -42,8 +43,9 @@ export const EmailLayout = ({
recipientName = "Guest", recipientName = "Guest",
children, children,
footNote, footNote,
ctx,
}: React.PropsWithChildren<EmailLayoutProps>) => { }: React.PropsWithChildren<EmailLayoutProps>) => {
const { logoUrl, baseUrl } = useEmailContext(); const { logoUrl, baseUrl } = ctx;
return ( return (
<Html> <Html>
<Head /> <Head />

View file

@ -1,4 +1,4 @@
import { useEmailContext } from "./email-context"; import { EmailContext } from "./email-context";
import { EmailLayout } from "./email-layout"; import { EmailLayout } from "./email-layout";
import { Button, Link, Text } from "./styled-components"; import { Button, Link, Text } from "./styled-components";
@ -7,6 +7,7 @@ export interface NotificationBaseProps {
title: string; title: string;
pollUrl: string; pollUrl: string;
disableNotificationsUrl: string; disableNotificationsUrl: string;
ctx: EmailContext;
} }
export interface NotificationEmailProps extends NotificationBaseProps { export interface NotificationEmailProps extends NotificationBaseProps {
@ -19,10 +20,12 @@ export const NotificationEmail = ({
disableNotificationsUrl, disableNotificationsUrl,
preview, preview,
children, children,
ctx,
}: React.PropsWithChildren<NotificationEmailProps>) => { }: React.PropsWithChildren<NotificationEmailProps>) => {
const { domain } = useEmailContext(); const { domain } = ctx;
return ( return (
<EmailLayout <EmailLayout
ctx={ctx}
recipientName={name} recipientName={name}
footNote={ footNote={
<> <>

View file

@ -10,7 +10,7 @@ import {
TextProps, TextProps,
} from "@react-email/components"; } from "@react-email/components";
import { useEmailContext } from "./email-context"; import { EmailContext } from "./email-context";
export const borderColor = "#E2E8F0"; export const borderColor = "#E2E8F0";
export const Text = ( export const Text = (
@ -32,8 +32,8 @@ export const Text = (
); );
}; };
export const Domain = () => { export const Domain = ({ ctx }: { ctx: EmailContext }) => {
const { baseUrl, domain } = useEmailContext(); const { baseUrl, domain } = ctx;
return <Link href={baseUrl}>{domain}</Link>; return <Link href={baseUrl}>{domain}</Link>;
}; };

View file

@ -1,5 +1,6 @@
import { Column, Row, Section } from "@react-email/components"; import { Column, Row, Section } from "@react-email/components";
import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { borderColor, Button, Text } from "./components/styled-components"; import { borderColor, Button, Text } from "./components/styled-components";
@ -13,6 +14,7 @@ export interface FinalizeHostEmailProps {
location: string | null; location: string | null;
pollUrl: string; pollUrl: string;
attendees: string[]; attendees: string[];
ctx: EmailContext;
} }
export const FinalizeHostEmail = ({ export const FinalizeHostEmail = ({
@ -23,9 +25,10 @@ export const FinalizeHostEmail = ({
dow = "Fri", dow = "Fri",
date = "Friday, 12th June 2020", date = "Friday, 12th June 2020",
time = "6:00 PM to 11:00 PM BST", time = "6:00 PM to 11:00 PM BST",
ctx,
}: FinalizeHostEmailProps) => { }: FinalizeHostEmailProps) => {
return ( return (
<EmailLayout recipientName={name} preview="Final date booked!"> <EmailLayout ctx={ctx} recipientName={name} preview="Final date booked!">
<Text> <Text>
<strong>{title}</strong> has been booked for: <strong>{title}</strong> has been booked for:
</Text> </Text>

View file

@ -1,5 +1,6 @@
import { Column, Row, Section } from "@react-email/components"; import { Column, Row, Section } from "@react-email/components";
import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { borderColor, Button, Text } from "./components/styled-components"; import { borderColor, Button, Text } from "./components/styled-components";
@ -14,6 +15,7 @@ export interface FinalizeParticipantEmailProps {
location: string | null; location: string | null;
pollUrl: string; pollUrl: string;
attendees: string[]; attendees: string[];
ctx: EmailContext;
} }
export const FinalizeParticipantEmail = ({ export const FinalizeParticipantEmail = ({
@ -25,9 +27,10 @@ export const FinalizeParticipantEmail = ({
dow = "Fri", dow = "Fri",
date = "Friday, 12th June 2020", date = "Friday, 12th June 2020",
time = "6:00 PM to 11:00 PM BST", time = "6:00 PM to 11:00 PM BST",
ctx,
}: FinalizeParticipantEmailProps) => { }: FinalizeParticipantEmailProps) => {
return ( return (
<EmailLayout recipientName={name} preview="Final date booked!"> <EmailLayout ctx={ctx} recipientName={name} preview="Final date booked!">
<Text> <Text>
<strong>{hostName}</strong> has booked <strong>{title}</strong> for the <strong>{hostName}</strong> has booked <strong>{title}</strong> for the
following date: following date:

View file

@ -1,4 +1,4 @@
import { useEmailContext } from "./components/email-context"; import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { import {
Button, Button,
@ -13,21 +13,23 @@ interface LoginEmailProps {
name: string; name: string;
code: string; code: string;
magicLink: string; magicLink: string;
ctx: EmailContext;
} }
export const LoginEmail = ({ export const LoginEmail = ({
name = "Guest", name = "Guest",
code = "123456", code = "123456",
magicLink = "https://rallly.co", magicLink = "https://rallly.co",
ctx,
}: LoginEmailProps) => { }: LoginEmailProps) => {
const { domain } = useEmailContext();
return ( return (
<EmailLayout <EmailLayout
ctx={ctx}
footNote={ footNote={
<> <>
You&apos;re receiving this email because a request was made to login You&apos;re receiving this email because a request was made to login
to <Domain />. If this wasn&apos;t you, let us know by replying to to <Domain ctx={ctx} />. If this wasn&apos;t you, let us know by
this email. replying to this email.
</> </>
} }
recipientName={name} recipientName={name}
@ -40,7 +42,7 @@ export const LoginEmail = ({
<Heading>Option 1: Magic Link</Heading> <Heading>Option 1: Magic Link</Heading>
<Text>Click this magic link to log in on this device.</Text> <Text>Click this magic link to log in on this device.</Text>
<Button href={magicLink} id="magicLink"> <Button href={magicLink} id="magicLink">
Log in to {domain} Log in to {ctx.domain}
</Button> </Button>
<Text light={true}>This link will expire in 15 minutes.</Text> <Text light={true}>This link will expire in 15 minutes.</Text>
</Card> </Card>

View file

@ -13,9 +13,11 @@ export const NewCommentEmail = ({
authorName = "Someone", authorName = "Someone",
pollUrl = "https://rallly.co", pollUrl = "https://rallly.co",
disableNotificationsUrl = "https://rallly.co", disableNotificationsUrl = "https://rallly.co",
ctx,
}: NewCommentEmailProps) => { }: NewCommentEmailProps) => {
return ( return (
<NotificationEmail <NotificationEmail
ctx={ctx}
name={name} name={name}
title={title} title={title}
pollUrl={pollUrl} pollUrl={pollUrl}

View file

@ -1,4 +1,4 @@
import { useEmailContext } from "./components/email-context"; import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { Button, Domain, Section, Text } from "./components/styled-components"; import { Button, Domain, Section, Text } from "./components/styled-components";
@ -6,19 +6,23 @@ interface NewParticipantConfirmationEmailProps {
name: string; name: string;
title: string; title: string;
editSubmissionUrl: string; editSubmissionUrl: string;
ctx: EmailContext;
} }
export const NewParticipantConfirmationEmail = ({ export const NewParticipantConfirmationEmail = ({
title = "Untitled Poll", title = "Untitled Poll",
name = "John", name = "John",
editSubmissionUrl = "https://rallly.co", editSubmissionUrl = "https://rallly.co",
ctx,
}: NewParticipantConfirmationEmailProps) => { }: NewParticipantConfirmationEmailProps) => {
const { domain } = useEmailContext(); const { domain } = ctx;
return ( return (
<EmailLayout <EmailLayout
ctx={ctx}
footNote={ footNote={
<> <>
You are receiving this email because a response was submitted on{" "} You are receiving this email because a response was submitted on{" "}
<Domain />. If this wasn&apos;t you, please ignore this email. <Domain ctx={ctx} />. If this wasn&apos;t you, please ignore this
email.
</> </>
} }
recipientName={name} recipientName={name}

View file

@ -13,9 +13,11 @@ export const NewParticipantEmail = ({
participantName = "Someone", participantName = "Someone",
pollUrl = "https://rallly.co", pollUrl = "https://rallly.co",
disableNotificationsUrl = "https://rallly.co", disableNotificationsUrl = "https://rallly.co",
ctx,
}: NewParticipantEmailProps) => { }: NewParticipantEmailProps) => {
return ( return (
<NotificationEmail <NotificationEmail
ctx={ctx}
name={name} name={name}
title={title} title={title}
pollUrl={pollUrl} pollUrl={pollUrl}

View file

@ -1,4 +1,4 @@
import { useEmailContext } from "./components/email-context"; import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { Button, Card, Link, Text } from "./components/styled-components"; import { Button, Card, Link, Text } from "./components/styled-components";
@ -7,6 +7,7 @@ export interface NewPollEmailProps {
name: string; name: string;
adminLink: string; adminLink: string;
participantLink: string; participantLink: string;
ctx: EmailContext;
} }
const ShareLink = ({ const ShareLink = ({
@ -37,10 +38,12 @@ export const NewPollEmail = ({
name = "John", name = "John",
adminLink = "https://rallly.co/admin/abcdefg123", adminLink = "https://rallly.co/admin/abcdefg123",
participantLink = "https://rallly.co/invite/wxyz9876", participantLink = "https://rallly.co/invite/wxyz9876",
ctx,
}: NewPollEmailProps) => { }: NewPollEmailProps) => {
const { baseUrl, domain } = useEmailContext(); const { baseUrl, domain } = ctx;
return ( return (
<EmailLayout <EmailLayout
ctx={ctx}
footNote={ footNote={
<> <>
You are receiving this email because a new poll was created with this You are receiving this email because a new poll was created with this

View file

@ -1,3 +1,4 @@
import { EmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout"; import { EmailLayout } from "./components/email-layout";
import { import {
Domain, Domain,
@ -9,19 +10,22 @@ import {
interface RegisterEmailProps { interface RegisterEmailProps {
name: string; name: string;
code: string; code: string;
ctx: EmailContext;
} }
export const RegisterEmail = ({ export const RegisterEmail = ({
name = "John", name = "John",
code = "123456", code = "123456",
ctx,
}: RegisterEmailProps) => { }: RegisterEmailProps) => {
return ( return (
<EmailLayout <EmailLayout
ctx={ctx}
footNote={ footNote={
<> <>
You&apos;re receiving this email because a request was made to You&apos;re receiving this email because a request was made to
register an account on <Domain />. If this wasn&apos;t you, please register an account on <Domain ctx={ctx} />. If this wasn&apos;t you,
ignore this email. please ignore this email.
</> </>
} }
recipientName={name} recipientName={name}