♻️ Refactor code for generating absolute url (#904)

This commit is contained in:
Luke Vella 2023-10-19 18:01:00 +01:00 committed by GitHub
parent eaa8f5813d
commit 703d551aac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 108 additions and 61 deletions

View file

@ -7,6 +7,7 @@ import previewEmail from "preview-email";
import React from "react";
import * as templates from "./templates";
import { EmailContext } from "./templates/components/email-context";
type Templates = typeof templates;
@ -15,7 +16,6 @@ type TemplateName = keyof typeof templates;
type TemplateProps<T extends TemplateName> = React.ComponentProps<
TemplateComponent<T>
>;
type TemplateComponent<T extends TemplateName> = Templates[T];
type SendEmailOptions<T extends TemplateName> = {
@ -59,6 +59,10 @@ type EmailClientConfig = {
address: string;
};
};
/**
* Context to pass to each email
*/
context: EmailContext;
};
export class EmailClient {
@ -79,8 +83,14 @@ export class EmailClient {
}
const Template = templates[templateName] as TemplateComponent<T>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const html = render(<Template {...(options.props as any)} />);
const html = render(
<EmailContext.Provider value={this.config.context}>
<Template
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{...(options.props as any)}
/>
</EmailContext.Provider>,
);
try {
await this.sendEmail({

View file

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

View file

@ -1,4 +1,3 @@
import { absoluteUrl } from "@rallly/utils";
import {
Body,
Container,
@ -9,6 +8,7 @@ import {
Preview,
} from "@react-email/components";
import { useEmailContext } from "./email-context";
import { fontFamily, Section, Text } from "./styled-components";
export interface EmailLayoutProps {
@ -43,13 +43,14 @@ export const EmailLayout = ({
children,
footNote,
}: React.PropsWithChildren<EmailLayoutProps>) => {
const { logoUrl, baseUrl } = useEmailContext();
return (
<Html>
<Head />
<Preview>{preview}</Preview>
<Body style={{ backgroundColor: "#F3F4F6", padding: "16px" }}>
<Container style={containerStyles}>
<Img src={absoluteUrl("/logo.png")} alt="Rallly" width={128} />
<Img src={logoUrl} alt="Rallly" width={128} />
<Section style={sectionStyles}>
<Text>Hi {recipientName},</Text>
{children}
@ -68,7 +69,7 @@ export const EmailLayout = ({
) : null}
</Section>
<Section style={{ ...sectionStyles, fontSize: 14, marginBottom: 0 }}>
<Link style={linkStyles} href={absoluteUrl()}>
<Link style={linkStyles} href={baseUrl}>
Home
</Link>
<span>&nbsp;&bull;&nbsp;</span>

View file

@ -1,6 +1,6 @@
import { useEmailContext } from "./email-context";
import { EmailLayout } from "./email-layout";
import { Button, Link, Text } from "./styled-components";
import { getDomain } from "./utils";
export interface NotificationBaseProps {
name: string;
@ -20,6 +20,7 @@ export const NotificationEmail = ({
preview,
children,
}: React.PropsWithChildren<NotificationEmailProps>) => {
const { domain } = useEmailContext();
return (
<EmailLayout
recipientName={name}
@ -36,7 +37,7 @@ export const NotificationEmail = ({
>
{children}
<Text>
<Button href={pollUrl}>View on {getDomain()}</Button>
<Button href={pollUrl}>View on {domain}</Button>
</Text>
</EmailLayout>
);

View file

@ -1,4 +1,3 @@
import { absoluteUrl } from "@rallly/utils";
import {
Button as UnstyledButton,
ButtonProps,
@ -11,7 +10,7 @@ import {
TextProps,
} from "@react-email/components";
import { getDomain } from "./utils";
import { useEmailContext } from "./email-context";
export const borderColor = "#E2E8F0";
export const Text = (
@ -34,7 +33,8 @@ export const Text = (
};
export const Domain = () => {
return <Link href={absoluteUrl()}>{getDomain()}</Link>;
const { baseUrl, domain } = useEmailContext();
return <Link href={baseUrl}>{domain}</Link>;
};
export const Button = (props: ButtonProps) => {

View file

@ -1,7 +0,0 @@
import { absoluteUrl } from "@rallly/utils";
export const removeProtocalFromUrl = (url: string) => {
return url.replace(/(^\w+:|^)\/\//, "");
};
export const getDomain = () => removeProtocalFromUrl(absoluteUrl());

View file

@ -1,3 +1,4 @@
import { useEmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout";
import {
Button,
@ -7,7 +8,6 @@ import {
Text,
trackingWide,
} from "./components/styled-components";
import { getDomain } from "./components/utils";
interface LoginEmailProps {
name: string;
@ -20,6 +20,7 @@ export const LoginEmail = ({
code = "123456",
magicLink = "https://rallly.co",
}: LoginEmailProps) => {
const { domain } = useEmailContext();
return (
<EmailLayout
footNote={
@ -39,7 +40,7 @@ export const LoginEmail = ({
<Heading>Option 1: Magic Link</Heading>
<Text>Click this magic link to log in on this device.</Text>
<Button href={magicLink} id="magicLink">
Log in to {getDomain()}
Log in to {domain}
</Button>
<Text light={true}>This link will expire in 15 minutes.</Text>
</Card>

View file

@ -1,6 +1,6 @@
import { useEmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout";
import { Button, Domain, Section, Text } from "./components/styled-components";
import { getDomain } from "./components/utils";
interface NewParticipantConfirmationEmailProps {
name: string;
@ -12,6 +12,7 @@ export const NewParticipantConfirmationEmail = ({
name = "John",
editSubmissionUrl = "https://rallly.co",
}: NewParticipantConfirmationEmailProps) => {
const { domain } = useEmailContext();
return (
<EmailLayout
footNote={
@ -32,7 +33,7 @@ export const NewParticipantConfirmationEmail = ({
</Text>
<Section>
<Button id="editSubmissionUrl" href={editSubmissionUrl}>
Review response on {getDomain()}
Review response on {domain}
</Button>
</Section>
</EmailLayout>

View file

@ -1,8 +1,6 @@
import { absoluteUrl } from "@rallly/utils";
import { useEmailContext } from "./components/email-context";
import { EmailLayout } from "./components/email-layout";
import { Button, Card, Link, Text } from "./components/styled-components";
import { getDomain } from "./components/utils";
export interface NewPollEmailProps {
title: string;
@ -40,13 +38,14 @@ export const NewPollEmail = ({
adminLink = "https://rallly.co/admin/abcdefg123",
participantLink = "https://rallly.co/invite/wxyz9876",
}: NewPollEmailProps) => {
const { baseUrl, domain } = useEmailContext();
return (
<EmailLayout
footNote={
<>
You are receiving this email because a new poll was created with this
email address on <Link href={absoluteUrl()}>{getDomain()}</Link>. If
this wasn&apos;t you, please ignore this email.
email address on <Link href={baseUrl}>{domain}</Link>. If this
wasn&apos;t you, please ignore this email.
</>
}
recipientName={name}