Skip to content

Commit

Permalink
feat: add tabby-email to build tabby email templates (#1573)
Browse files Browse the repository at this point in the history
* feat: add tabby-email to build tabby email templates

* ifx test

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
wsxiaoys and autofix-ci[bot] authored Feb 28, 2024
1 parent 8162476 commit ebd2937
Show file tree
Hide file tree
Showing 13 changed files with 3,625 additions and 47 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ update-ui:
cd ee/tabby-ui && yarn build
rm -rf ee/tabby-webserver/ui && cp -R ee/tabby-ui/out ee/tabby-webserver/ui

update-email-templates:
cd ee/tabby-email && yarn export
rm -rf ee/tabby-webserver/email_templates && cp -R ee/tabby-email/out ee/tabby-webserver/email_templates

caddy:
caddy run --watch --config ee/tabby-webserver/development/Caddyfile

Expand Down
2 changes: 2 additions & 0 deletions ee/tabby-email/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
.react-email
44 changes: 44 additions & 0 deletions ee/tabby-email/components/root-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
Body,
Button,
Container,
Column,
Head,
Heading,
Hr,
Html,
Img,
Link,
Preview,
Row,
Section,
Text,
} from "@react-email/components";
import { Tailwind } from "@react-email/tailwind";
import * as React from "react";

interface RootLayoutProps {
previewText: string
children: React.ReactNode
}

export const RootLayout = ({
previewText,
children,
}: RootLayoutProps) => {
return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-[#FBF9F5] my-auto mx-auto font-sans px-2">
<Container className="bg-[#E8E2D2] border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]">
{children}
</Container>
</Body>
</Tailwind>
</Html>
);
};

export default RootLayout;
60 changes: 60 additions & 0 deletions ee/tabby-email/emails/invitation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
Button, Heading,
Hr, Link, Section,
Text
} from "@react-email/components";
import * as React from "react";
import RootLayout from "../components/root-layout";

interface Invitation {
email?: string;
inviteLink?: string;
}

export const Invitation = ({
email = "{{EMAIL}}",
inviteLink = "{{EXTERNAL_URL}}/auth/signup?invitationCode={{CODE}}",
}: Invitation) => {
const title = `You've been invited to join a Tabby server!`;

return (
<RootLayout previewText={title}>
<Heading className="text-black text-[24px] font-normal text-center p-0 mb-[30px] mx-0">
{title}
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
Hello,
</Text>
<Text className="text-black text-[14px] leading-[24px]">
You have been invited to join a <strong>Tabby</strong> Server, where you can tap into AI-driven code completions and chat assistants.
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Button
className="bg-[#645740] rounded-md text-white text-sm font-semibold no-underline text-center px-5 py-3"
href={inviteLink}
>
Accept Invitation
</Button>
</Section>
<Text className="text-black text-[14px] leading-[24px]">
or copy and paste this URL into your browser:{" "}
<Link href={inviteLink} className="text-blue-600 no-underline">
{inviteLink}
</Link>
</Text>
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
<Text className="text-[#666666] text-[12px] leading-[24px]">
This invitation was intended for{" "}
<span className="text-black">{email}</span>. If you
were not expecting this invitation, you can ignore this email.
</Text>
</RootLayout>
);
};

Invitation.PreviewProps = {
email: "[email protected]",
inviteLink: "http://localhost:8080/auth/signup?invitationCode={{CODE}}",
} as Invitation;

export default Invitation;
57 changes: 57 additions & 0 deletions ee/tabby-email/emails/password_reset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
Button, Heading,
Hr, Link, Section,
Text
} from "@react-email/components";
import * as React from "react";
import RootLayout from "../components/root-layout";

interface PasswordReset {
email?: string;
resetLink?: string;
}

export const PasswordReset = ({
email = "{{EMAIL}}",
resetLink = "{{EXTERNAL_URL}}/auth/reset-password?code={{CODE}}",
}: PasswordReset) => {
const title = `Reset your Tabby account password`;

return (
<RootLayout previewText={title}>
<Heading className="text-black text-[24px] font-normal text-center p-0 mb-[30px] mx-0">
{title}
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
You recently requested a password reset for your Tabby account <strong>{email}</strong>.
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Button
className="bg-[#645740] rounded-md text-white text-sm font-semibold no-underline text-center px-5 py-3"
href={resetLink}
>
Reset Password
</Button>
</Section>
<Text className="text-black text-[14px] leading-[24px]">
or copy and paste this URL into your browser:{" "}
<Link href={resetLink} className="text-blue-600 no-underline">
{resetLink}
</Link>
</Text>
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
<Text className="text-[#666666] text-[12px] leading-[24px]">
This email was intended for{" "}
<span className="text-black">{email}</span>. If you
were not expecting this invitation, you can ignore this email.
</Text>
</RootLayout>
);
};

PasswordReset.PreviewProps = {
email: "[email protected]",
resetLink: "http://localhost:8080/auth/reset-password?code={{CODE}}",
} as PasswordReset;

export default PasswordReset;
25 changes: 25 additions & 0 deletions ee/tabby-email/emails/test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
Heading, Text
} from "@react-email/components";
import * as React from "react";
import RootLayout from "../components/root-layout";

export const Test = () => {
const title = `Your mail server is ready to go!`;

return (
<RootLayout previewText={title}>
<Heading className="text-black text-[24px] font-normal text-center p-0 mb-[30px] mx-0">
{title}
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
This is a test email from Tabby to confirm that your mail server configuration is correct.
</Text>
<Text className="text-black text-[14px] leading-[24px]">
If you have received this email, it means that your configuration was successful. Thank you for using Tabby!
</Text>
</RootLayout>
);
};

export default Test;
19 changes: 19 additions & 0 deletions ee/tabby-email/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "emails",
"version": "0.0.19",
"private": true,
"scripts": {
"build": "email build",
"dev": "email dev",
"export": "email export"
},
"dependencies": {
"@react-email/components": "0.0.15",
"react-email": "2.1.0",
"react": "18.2.0"
},
"devDependencies": {
"@types/react": "18.2.33",
"@types/react-dom": "18.2.14"
}
}
Loading

0 comments on commit ebd2937

Please sign in to comment.