feat: email templates

adds email templates using `react-email` which will be used for invites,
signing and document completion.

authored by @dephraiim
This commit is contained in:
Mythie
2023-06-24 14:59:08 +10:00
parent 0b1c4fadc6
commit ca0f4eefd2
17 changed files with 6850 additions and 131 deletions

6577
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@
"packageManager": "npm@8.19.2",
"workspaces": [
"apps/*",
"packages/*"
"packages/*",
"packages/email/.react-email"
]
}

1
packages/email/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.react-email/

1
packages/email/ambient.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module '@documenso/tailwind-config';

1
packages/email/index.ts Normal file
View File

@ -0,0 +1 @@
export { render, renderAsync } from '@react-email/components';

View File

@ -0,0 +1,22 @@
{
"name": "@documenso/email",
"version": "1.0.0",
"main": "./index.ts",
"types": "./index.ts",
"license": "MIT",
"files": [
"templates/"
],
"scripts": {
"dev": "email dev --port 3002 --dir templates"
},
"dependencies": {
"@documenso/tsconfig": "*",
"@documenso/tailwind-config": "*",
"@documenso/ui": "*",
"@react-email/components": "^0.0.7"
},
"devDependencies": {
"react-email": "^1.9.4"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

View File

@ -0,0 +1,11 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const baseConfig = require('@documenso/tailwind-config');
const path = require('path');
module.exports = {
...baseConfig,
content: [
`templates/**/*.{ts,tsx}`,
`${path.join(require.resolve('@documenso/ui'), '..')}/**/*.{ts,tsx}`,
],
};

View File

@ -0,0 +1,129 @@
import {
Body,
Button,
Container,
Head,
Html,
Img,
Link,
Preview,
Section,
Tailwind,
Text,
} from '@react-email/components';
import * as config from '@documenso/tailwind-config';
interface DocumentCompletedEmailTemplateProps {
downloadLink?: string;
reviewLink?: string;
documentName?: string;
assetBaseUrl?: string;
}
export const DocumentCompletedEmailTemplate = ({
downloadLink = 'https://documenso.com',
reviewLink = 'https://documenso.com',
documentName = 'Open Source Pledge.pdf',
assetBaseUrl = 'http://localhost:3002',
}: DocumentCompletedEmailTemplateProps) => {
const previewText = `Completed Document`;
const getAssetUrl = (path: string) => {
return new URL(path, assetBaseUrl).toString();
};
return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind
config={{
theme: {
extend: {
colors: config.theme.extend.colors,
},
},
}}
>
<Body className="mx-auto my-auto font-sans">
<Section className="bg-white">
<Container className="mx-auto mb-2 mt-8 max-w-xl rounded-lg border border-solid border-slate-200 p-2 backdrop-blur-sm">
<Section className="p-2">
<Img src={getAssetUrl('/static/logo.png')} alt="Documenso Logo" className="h-6" />
<Section className="mt-4 flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img
className="h-42"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</div>
<Text className="mb-4 flex items-center justify-center text-center text-base font-semibold text-[#7AC455]">
<Img
src={getAssetUrl('/static/completed.png')}
className="-mb-0.5 mr-2 inline h-7 w-7"
/>
Completed
</Text>
<Text className="text-primary mb-0 text-center text-lg font-semibold">
{documentName} was signed by all signers
</Text>
<Text className="my-1 text-center text-base text-slate-400">
Continue by downloading or reviewing the document.
</Text>
<Section className="mb-6 mt-8 text-center">
<Button
className="mr-4 inline-flex items-center justify-center rounded-lg border border-solid border-slate-200 px-4 py-2 text-center text-sm font-medium text-black no-underline"
href={reviewLink}
>
<Img
src={getAssetUrl('/static/review.png')}
className="-mb-1 mr-2 inline h-5 w-5"
/>
Review
</Button>
<Button
className="inline-flex items-center justify-center rounded-lg border border-solid border-slate-200 px-4 py-2 text-center text-sm font-medium text-black no-underline"
href={downloadLink}
>
<Img
src={getAssetUrl('/static/download.png')}
className="-mb-1 mr-2 inline h-5 w-5"
/>
Download
</Button>
</Section>
</Section>
</Section>
</Container>
<Container className="mx-auto max-w-xl">
<Section>
<Text className="my-4 text-base text-slate-400">
This document was sent using{' '}
<Link className="text-[#7AC455]" href="https://documenso.com">
Documenso.
</Link>
</Text>
<Text className="my-8 text-sm text-slate-400">
Documenso
<br />
2261 Market Street, #5211, San Francisco, CA 94114, USA
</Text>
</Section>
</Container>
</Section>
</Body>
</Tailwind>
</Html>
);
};
export default DocumentCompletedEmailTemplate;

View File

@ -0,0 +1,127 @@
import {
Body,
Button,
Container,
Head,
Hr,
Html,
Img,
Link,
Preview,
Section,
Tailwind,
Text,
} from '@react-email/components';
import * as config from '@documenso/tailwind-config';
interface DocumentInviteEmailTemplateProps {
inviterName?: string;
inviterEmail?: string;
documentName?: string;
signDocumentLink?: string;
assetBaseUrl?: string;
}
export const DocumentInviteEmailTemplate = ({
inviterName = 'Lucas Smith',
inviterEmail = 'lucas@documenso.com',
documentName = 'Open Source Pledge.pdf',
signDocumentLink = 'https://documenso.com',
assetBaseUrl = 'http://localhost:3002',
}: DocumentInviteEmailTemplateProps) => {
const previewText = `Completed Document`;
const getAssetUrl = (path: string) => {
return new URL(path, assetBaseUrl).toString();
};
return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind
config={{
theme: {
extend: {
colors: config.theme.extend.colors,
},
},
}}
>
<Body className="mx-auto my-auto bg-white font-sans">
<Section>
<Container className="mx-auto mb-2 mt-8 max-w-xl rounded-lg border border-solid border-slate-200 p-2 backdrop-blur-sm">
<Section className="p-2">
<Img src={getAssetUrl('/static/logo.png')} alt="Documenso Logo" className="h-6" />
<Section className="mt-4 flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img
className="h-42"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</div>
<Text className="text-primary mx-auto mb-0 max-w-[80%] text-center text-lg font-semibold">
{inviterName} has invited you to sign "{documentName}"
</Text>
<Text className="my-1 text-center text-base text-slate-400">
Continue by signing the document.
</Text>
<Section className="mb-6 mt-8 text-center">
<Button
className="bg-documenso-500 inline-flex items-center justify-center rounded-lg px-6 py-3 text-center text-sm font-medium text-black no-underline"
href={signDocumentLink}
>
Sign Document
</Button>
</Section>
</Section>
</Section>
</Container>
<Container className="mx-auto mt-12 max-w-xl">
<Section>
<Text className="my-4 text-base font-semibold">
{inviterName}{' '}
<Link className="font-normal text-slate-400" href="mailto:{inviterEmail}">
({inviterEmail})
</Link>
</Text>
<Text className="mt-2 text-base text-slate-400">
{inviterName} has invited you to sign the document "{documentName}".
</Text>
</Section>
</Container>
<Hr className="mx-auto mt-12 max-w-xl" />
<Container className="mx-auto max-w-xl">
<Section>
<Text className="my-4 text-base text-slate-400">
This document was sent using{' '}
<Link className="text-[#7AC455]" href="https://documenso.com">
Documenso.
</Link>
</Text>
<Text className="my-8 text-sm text-slate-400">
Documenso
<br />
2261 Market Street, #5211, San Francisco, CA 94114, USA
</Text>
</Section>
</Container>
</Section>
</Body>
</Tailwind>
</Html>
);
};
export default DocumentInviteEmailTemplate;

View File

@ -0,0 +1,104 @@
import {
Body,
Button,
Container,
Head,
Html,
Img,
Link,
Preview,
Section,
Tailwind,
Text,
} from '@react-email/components';
import * as config from '@documenso/tailwind-config';
interface DocumentPendingEmailTemplateProps {
documentName?: string;
assetBaseUrl?: string;
}
export const DocumentPendingEmailTemplate = ({
documentName = 'Open Source Pledge.pdf',
assetBaseUrl = 'http://localhost:3002',
}: DocumentPendingEmailTemplateProps) => {
const previewText = `Pending Document`;
const getAssetUrl = (path: string) => {
return new URL(path, assetBaseUrl).toString();
};
return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind
config={{
theme: {
extend: {
colors: config.theme.extend.colors,
},
},
}}
>
<Body className="mx-auto my-auto font-sans">
<Section className="bg-white">
<Container className="mx-auto mb-2 mt-8 max-w-xl rounded-lg border border-solid border-slate-200 p-2 backdrop-blur-sm">
<Section className="p-2">
<Img src={getAssetUrl('/static/logo.png')} alt="Documenso Logo" className="h-6" />
<Section className="mt-4 flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img
className="h-42"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</div>
<Text className="mb-4 flex items-center justify-center text-center text-base font-semibold text-blue-500">
<Img
src={getAssetUrl('/static/clock.png')}
className="-mb-0.5 mr-2 inline h-7 w-7"
/>
Waiting for others
</Text>
<Text className="text-primary mb-0 text-center text-lg font-semibold">
{documentName} has been signed
</Text>
<Text className="mx-auto mb-6 mt-1 max-w-[80%] text-center text-base text-slate-400">
We're still waiting for other signers to sign this document.
<br />
We'll notify you as soon as it's ready.
</Text>
</Section>
</Section>
</Container>
<Container className="mx-auto max-w-xl">
<Section>
<Text className="my-4 text-base text-slate-400">
This document was sent using{' '}
<Link className="text-[#7AC455]" href="https://documenso.com">
Documenso.
</Link>
</Text>
<Text className="my-8 text-sm text-slate-400">
Documenso
<br />
2261 Market Street, #5211, San Francisco, CA 94114, USA
</Text>
</Section>
</Container>
</Section>
</Body>
</Tailwind>
</Html>
);
};
export default DocumentPendingEmailTemplate;

View File

@ -0,0 +1,5 @@
{
"extends": "@documenso/tsconfig/react-library.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}