feat(server): new email template (#9528)

use `yarn af server dev:mail` to preview all mail template
fix CLOUD-93
This commit is contained in:
darkskygit
2025-01-22 02:55:24 +00:00
parent 2db9cc3922
commit 83ed215f4a
54 changed files with 4794 additions and 892 deletions
@@ -0,0 +1,38 @@
import { TEST_WORKSPACE } from '../common';
import {
Button,
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export type TeamBecomeAdminProps = {
workspace: WorkspaceProps;
url: string;
};
export default function TeamBecomeAdmin(props: TeamBecomeAdminProps) {
const { workspace, url } = props;
return (
<Template>
<Title>You&apos;ve been promoted to admin.</Title>
<Content>
<P>
You have been promoted to admin of <Workspace {...workspace} />. As an
admin, you can help the workspace owner manage members in this
workspace.
</P>
<Button href={url}>Go to Workspace</Button>
</Content>
</Template>
);
}
TeamBecomeAdmin.PreviewProps = {
workspace: TEST_WORKSPACE,
role: 'admin',
url: 'https://app.affine.pro',
};
@@ -0,0 +1,40 @@
import { TEST_WORKSPACE } from '../common';
import {
Button,
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export type TeamBecomeCollaboratorProps = {
workspace: WorkspaceProps;
url: string;
};
export default function TeamBecomeCollaborator(
props: TeamBecomeCollaboratorProps
) {
const { workspace, url } = props;
return (
<Template>
<Title>Role update in workspace</Title>
<Content>
<P>
Your role in <Workspace {...workspace} /> has been changed to{' '}
collaborator. You can continue to collaborate in this workspace.
</P>
<Button href={url}>Go to Workspace</Button>
</Content>
</Template>
);
}
TeamBecomeCollaborator.PreviewProps = {
workspace: TEST_WORKSPACE,
role: 'admin',
url: 'https://app.affine.pro',
};
@@ -0,0 +1,55 @@
import { TEST_WORKSPACE } from '../common';
import {
Bold,
Button,
Content,
P,
Template,
Text,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export interface TeamDeleteInOneMonthProps {
workspace: WorkspaceProps;
expirationDate: Date;
deletionDate: Date;
url: string;
}
export default function TeamDeleteInOneMonth(props: TeamDeleteInOneMonthProps) {
const { workspace, expirationDate, deletionDate, url } = props;
return (
<Template>
<Title>Take action to prevent data loss</Title>
<Content>
<P>
Your <Workspace {...workspace} /> team workspace expired on{' '}
<Bold>{expirationDate.toLocaleDateString()}</Bold>. All workspace data
will be permanently deleted on{' '}
<Bold>{deletionDate.toLocaleDateString()}</Bold> (180 days after
expiration). To prevent data loss, please either:
<li>
<Text>Renew your subscription to restore team features</Text>
</li>
<li>
<Text>
Export your workspace data from Workspace Settings &gt; Export
Workspace
</Text>
</li>
</P>
<Button href={url}>Go to Billing</Button>
</Content>
</Template>
);
}
TeamDeleteInOneMonth.PreviewProps = {
workspace: TEST_WORKSPACE,
expirationDate: new Date('2025-01-01T00:00:00Z'),
deletionDate: new Date('2025-01-31T00:00:00Z'),
url: 'https://app.affine.pro',
};
@@ -0,0 +1,52 @@
import { TEST_WORKSPACE } from '../common';
import {
Bold,
Button,
Content,
P,
Template,
Text,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export interface TeamDeleteIn24HoursProps {
workspace: WorkspaceProps;
deletionDate: Date;
url: string;
}
export default function TeamDeleteIn24Hours(props: TeamDeleteIn24HoursProps) {
const { workspace, deletionDate, url } = props;
return (
<Template>
<Title>Urgent: Last chance to prevent data loss</Title>
<Content>
<P>
Your <Workspace {...workspace} /> team workspace data will be
permanently deleted in 24 hours on{' '}
<Bold>{deletionDate.toLocaleDateString()}</Bold>. To prevent data
loss, please take immediate action:
<li>
<Text>Renew your subscription to restore team features</Text>
</li>
<li>
<Text>
Export your workspace data from Workspace Settings &gt; Export
Workspace
</Text>
</li>
</P>
<Button href={url}>Go to Billing</Button>
</Content>
</Template>
);
}
TeamDeleteIn24Hours.PreviewProps = {
workspace: TEST_WORKSPACE,
deletionDate: new Date('2025-01-31T00:00:00Z'),
url: 'https://app.affine.pro',
};
@@ -0,0 +1,38 @@
import { TEST_WORKSPACE } from '../common';
import {
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export interface TeamWorkspaceDeletedProps {
workspace: WorkspaceProps;
}
export default function TeamWorkspaceDeleted(props: TeamWorkspaceDeletedProps) {
const { workspace } = props;
return (
<Template>
<Title>Workspace data deleted</Title>
<Content>
<P>
All data in <Workspace {...workspace} /> has been permanently deleted
as the workspace remained expired for 180 days. This action cannot be
undone.
</P>
<P>
Thank you for your support of AFFiNE. We hope to see you again in the
future.
</P>
</Content>
</Template>
);
}
TeamWorkspaceDeleted.PreviewProps = {
workspace: TEST_WORKSPACE,
};
@@ -0,0 +1,42 @@
import { TEST_WORKSPACE } from '../common';
import {
Bold,
Button,
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export interface TeamExpireSoonProps {
workspace: WorkspaceProps;
expirationDate: Date;
url: string;
}
export default function TeamExpireSoon(props: TeamExpireSoonProps) {
const { workspace, expirationDate, url } = props;
return (
<Template>
<Title>Team workspace will expire soon</Title>
<Content>
<P>
Your <Workspace {...workspace} /> team workspace will expire on{' '}
<Bold>{expirationDate.toLocaleDateString()}</Bold>. After expiration,
you won&apos;t be able to sync or collaborate with team members.
Please renew your subscription to continue using all team features.
</P>
<Button href={url}>Go to Billing</Button>
</Content>
</Template>
);
}
TeamExpireSoon.PreviewProps = {
workspace: TEST_WORKSPACE,
expirationDate: new Date('2025-01-01T00:00:00Z'),
url: 'https://app.affine.pro',
};
@@ -0,0 +1,42 @@
import { TEST_WORKSPACE } from '../common';
import {
Bold,
Button,
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export interface TeamExpiredProps {
workspace: WorkspaceProps;
expirationDate: Date;
url: string;
}
export default function TeamExpired(props: TeamExpiredProps) {
const { workspace, expirationDate, url } = props;
return (
<Template>
<Title>Team workspace expired</Title>
<Content>
<P>
Your <Workspace {...workspace} /> team workspace expired on{' '}
<Bold>{expirationDate.toLocaleDateString()}</Bold>. Your workspace
can&apos;t sync or collaborate with team members. Please renew your
subscription to restore all team features.
</P>
<Button href={url}>Go to Billing</Button>
</Content>
</Template>
);
}
TeamExpired.PreviewProps = {
workspace: TEST_WORKSPACE,
expirationDate: new Date('2025-01-01T00:00:00Z'),
url: 'https://app.affine.pro',
};
@@ -0,0 +1,29 @@
export {
default as TeamBecomeAdmin,
type TeamBecomeAdminProps,
} from './become-admin';
export {
default as TeamBecomeCollaborator,
type TeamBecomeCollaboratorProps,
} from './become-collaborator';
export {
default as TeamDeleteInOneMonth,
type TeamDeleteInOneMonthProps,
} from './delete-in-1m';
export {
default as TeamDeleteIn24Hours,
type TeamDeleteIn24HoursProps,
} from './delete-in-24h';
export {
default as TeamWorkspaceDeleted,
type TeamWorkspaceDeletedProps,
} from './deleted';
export {
default as TeamExpireSoon,
type TeamExpireSoonProps,
} from './expire-soon';
export { default as TeamExpired, type TeamExpiredProps } from './expired';
export {
default as TeamWorkspaceUpgraded,
type TeamWorkspaceUpgradedProps,
} from './workspace-upgraded';
@@ -0,0 +1,57 @@
import { TEST_WORKSPACE } from '../common';
import {
Button,
Content,
P,
Template,
Title,
Workspace,
type WorkspaceProps,
} from '../components';
export type TeamWorkspaceUpgradedProps = {
workspace: WorkspaceProps;
isOwner: boolean;
url: string;
};
export default function TeamWorkspaceUpgraded(
props: TeamWorkspaceUpgradedProps
) {
const { workspace, isOwner, url } = props;
return (
<Template>
<Title>Welcome to the team workspace!</Title>
<Content>
<P>
{isOwner ? (
<>
<Workspace {...workspace} /> has been upgraded to team workspace
with the following benefits:
</>
) : (
<>
Great news! <Workspace {...workspace} /> has been upgraded to team
workspace by the workspace owner.
<br />
You now have access to the following enhanced features:
</>
)}
<br /> 100 GB initial storage + 20 GB per seat
<br /> 500 MB of maximum file size
<br /> Unlimited team members (10+ seats)
<br /> Multiple admin roles
<br /> Priority customer support
</P>
<Button href={url}>Open Workspace</Button>
</Content>
</Template>
);
}
TeamWorkspaceUpgraded.PreviewProps = {
workspace: TEST_WORKSPACE,
isOwner: true,
url: 'https://app.affine.pro',
};