mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 15:53:02 +10:00
feat: add organisations (#1820)
This commit is contained in:
@ -2,7 +2,7 @@ import { useMemo } from 'react';
|
||||
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { RecipientRole } from '@prisma/client';
|
||||
import { OrganisationType, RecipientRole } from '@prisma/client';
|
||||
import { P, match } from 'ts-pattern';
|
||||
|
||||
import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles';
|
||||
@ -18,9 +18,9 @@ export interface TemplateDocumentInviteProps {
|
||||
assetBaseUrl: string;
|
||||
role: RecipientRole;
|
||||
selfSigner: boolean;
|
||||
isTeamInvite: boolean;
|
||||
teamName?: string;
|
||||
includeSenderDetails?: boolean;
|
||||
organisationType?: OrganisationType;
|
||||
}
|
||||
|
||||
export const TemplateDocumentInvite = ({
|
||||
@ -30,9 +30,9 @@ export const TemplateDocumentInvite = ({
|
||||
assetBaseUrl,
|
||||
role,
|
||||
selfSigner,
|
||||
isTeamInvite,
|
||||
teamName,
|
||||
includeSenderDetails,
|
||||
organisationType,
|
||||
}: TemplateDocumentInviteProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
@ -50,21 +50,28 @@ export const TemplateDocumentInvite = ({
|
||||
|
||||
<Section>
|
||||
<Text className="text-primary mx-auto mb-0 max-w-[80%] text-center text-lg font-semibold">
|
||||
{match({ selfSigner, isTeamInvite, includeSenderDetails, teamName })
|
||||
{match({ selfSigner, organisationType, includeSenderDetails, teamName })
|
||||
.with({ selfSigner: true }, () => (
|
||||
<Trans>
|
||||
Please {_(actionVerb).toLowerCase()} your document
|
||||
<br />"{documentName}"
|
||||
</Trans>
|
||||
))
|
||||
.with({ isTeamInvite: true, includeSenderDetails: true, teamName: P.string }, () => (
|
||||
<Trans>
|
||||
{inviterName} on behalf of "{teamName}" has invited you to{' '}
|
||||
{_(actionVerb).toLowerCase()}
|
||||
<br />"{documentName}"
|
||||
</Trans>
|
||||
))
|
||||
.with({ isTeamInvite: true, teamName: P.string }, () => (
|
||||
.with(
|
||||
{
|
||||
organisationType: OrganisationType.ORGANISATION,
|
||||
includeSenderDetails: true,
|
||||
teamName: P.string,
|
||||
},
|
||||
() => (
|
||||
<Trans>
|
||||
{inviterName} on behalf of "{teamName}" has invited you to{' '}
|
||||
{_(actionVerb).toLowerCase()}
|
||||
<br />"{documentName}"
|
||||
</Trans>
|
||||
),
|
||||
)
|
||||
.with({ organisationType: OrganisationType.ORGANISATION, teamName: P.string }, () => (
|
||||
<Trans>
|
||||
{teamName} has invited you to {_(actionVerb).toLowerCase()}
|
||||
<br />"{documentName}"
|
||||
|
||||
@ -2,6 +2,7 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import type { RecipientRole } from '@prisma/client';
|
||||
import { OrganisationType } from '@prisma/client';
|
||||
|
||||
import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles';
|
||||
|
||||
@ -15,10 +16,10 @@ export type DocumentInviteEmailTemplateProps = Partial<TemplateDocumentInvitePro
|
||||
customBody?: string;
|
||||
role: RecipientRole;
|
||||
selfSigner?: boolean;
|
||||
isTeamInvite?: boolean;
|
||||
teamName?: string;
|
||||
teamEmail?: string;
|
||||
includeSenderDetails?: boolean;
|
||||
organisationType?: OrganisationType;
|
||||
};
|
||||
|
||||
export const DocumentInviteEmailTemplate = ({
|
||||
@ -30,9 +31,9 @@ export const DocumentInviteEmailTemplate = ({
|
||||
customBody,
|
||||
role,
|
||||
selfSigner = false,
|
||||
isTeamInvite = false,
|
||||
teamName = '',
|
||||
includeSenderDetails,
|
||||
organisationType,
|
||||
}: DocumentInviteEmailTemplateProps) => {
|
||||
const { _ } = useLingui();
|
||||
const branding = useBranding();
|
||||
@ -41,7 +42,7 @@ export const DocumentInviteEmailTemplate = ({
|
||||
|
||||
let previewText = msg`${inviterName} has invited you to ${action} ${documentName}`;
|
||||
|
||||
if (isTeamInvite) {
|
||||
if (organisationType === OrganisationType.ORGANISATION) {
|
||||
previewText = includeSenderDetails
|
||||
? msg`${inviterName} on behalf of "${teamName}" has invited you to ${action} ${documentName}`
|
||||
: msg`${teamName} has invited you to ${action} ${documentName}`;
|
||||
@ -82,7 +83,7 @@ export const DocumentInviteEmailTemplate = ({
|
||||
assetBaseUrl={assetBaseUrl}
|
||||
role={role}
|
||||
selfSigner={selfSigner}
|
||||
isTeamInvite={isTeamInvite}
|
||||
organisationType={organisationType}
|
||||
teamName={teamName}
|
||||
includeSenderDetails={includeSenderDetails}
|
||||
/>
|
||||
@ -91,7 +92,7 @@ export const DocumentInviteEmailTemplate = ({
|
||||
|
||||
<Container className="mx-auto mt-12 max-w-xl">
|
||||
<Section>
|
||||
{!isTeamInvite && (
|
||||
{organisationType === OrganisationType.PERSONAL && (
|
||||
<Text className="my-4 text-base font-semibold">
|
||||
<Trans>
|
||||
{inviterName}{' '}
|
||||
|
||||
@ -2,8 +2,6 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { formatTeamUrl } from '@documenso/lib/utils/teams';
|
||||
|
||||
import {
|
||||
Body,
|
||||
Button,
|
||||
@ -20,27 +18,25 @@ import { useBranding } from '../providers/branding';
|
||||
import { TemplateFooter } from '../template-components/template-footer';
|
||||
import TemplateImage from '../template-components/template-image';
|
||||
|
||||
export type TeamInviteEmailProps = {
|
||||
export type OrganisationInviteEmailProps = {
|
||||
assetBaseUrl: string;
|
||||
baseUrl: string;
|
||||
senderName: string;
|
||||
teamName: string;
|
||||
teamUrl: string;
|
||||
organisationName: string;
|
||||
token: string;
|
||||
};
|
||||
|
||||
export const TeamInviteEmailTemplate = ({
|
||||
export const OrganisationInviteEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
senderName = 'John Doe',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
organisationName = 'Organisation Name',
|
||||
token = '',
|
||||
}: TeamInviteEmailProps) => {
|
||||
}: OrganisationInviteEmailProps) => {
|
||||
const { _ } = useLingui();
|
||||
const branding = useBranding();
|
||||
|
||||
const previewText = msg`Accept invitation to join a team on Documenso`;
|
||||
const previewText = msg`Accept invitation to join an organisation on Documenso`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
@ -70,15 +66,15 @@ export const TeamInviteEmailTemplate = ({
|
||||
|
||||
<Section className="p-2 text-slate-500">
|
||||
<Text className="text-center text-lg font-medium text-black">
|
||||
<Trans>Join {teamName} on Documenso</Trans>
|
||||
<Trans>Join {organisationName} on Documenso</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="my-1 text-center text-base">
|
||||
<Trans>You have been invited to join the following team</Trans>
|
||||
<Trans>You have been invited to join the following organisation</Trans>
|
||||
</Text>
|
||||
|
||||
<div className="mx-auto my-2 w-fit rounded-lg bg-gray-50 px-4 py-2 text-base font-medium text-slate-600">
|
||||
{formatTeamUrl(teamUrl, baseUrl)}
|
||||
{organisationName}
|
||||
</div>
|
||||
|
||||
<Text className="my-1 text-center text-base">
|
||||
@ -90,13 +86,13 @@ export const TeamInviteEmailTemplate = ({
|
||||
<Section className="mb-6 mt-6 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={`${baseUrl}/team/invite/${token}`}
|
||||
href={`${baseUrl}/organisation/invite/${token}`}
|
||||
>
|
||||
<Trans>Accept</Trans>
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-4 inline-flex items-center justify-center rounded-lg bg-gray-50 px-6 py-3 text-center text-sm font-medium text-slate-600 no-underline"
|
||||
href={`${baseUrl}/team/decline/${token}`}
|
||||
href={`${baseUrl}/organisation/decline/${token}`}
|
||||
>
|
||||
<Trans>Decline</Trans>
|
||||
</Button>
|
||||
@ -115,4 +111,4 @@ export const TeamInviteEmailTemplate = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamInviteEmailTemplate;
|
||||
export default OrganisationInviteEmailTemplate;
|
||||
@ -2,34 +2,32 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { formatTeamUrl } from '@documenso/lib/utils/teams';
|
||||
|
||||
import { Body, Container, Head, Hr, Html, Img, Preview, Section, Text } from '../components';
|
||||
import { useBranding } from '../providers/branding';
|
||||
import { TemplateFooter } from '../template-components/template-footer';
|
||||
import TemplateImage from '../template-components/template-image';
|
||||
|
||||
export type TeamJoinEmailProps = {
|
||||
export type OrganisationJoinEmailProps = {
|
||||
assetBaseUrl: string;
|
||||
baseUrl: string;
|
||||
memberName: string;
|
||||
memberEmail: string;
|
||||
teamName: string;
|
||||
teamUrl: string;
|
||||
organisationName: string;
|
||||
organisationUrl: string;
|
||||
};
|
||||
|
||||
export const TeamJoinEmailTemplate = ({
|
||||
export const OrganisationJoinEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
memberName = 'John Doe',
|
||||
memberEmail = 'johndoe@documenso.com',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
}: TeamJoinEmailProps) => {
|
||||
organisationName = 'Organisation Name',
|
||||
organisationUrl = 'demo',
|
||||
}: OrganisationJoinEmailProps) => {
|
||||
const { _ } = useLingui();
|
||||
const branding = useBranding();
|
||||
|
||||
const previewText = msg`A team member has joined a team on Documenso`;
|
||||
const previewText = msg`A member has joined your organisation on Documenso`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
@ -59,17 +57,11 @@ export const TeamJoinEmailTemplate = ({
|
||||
|
||||
<Section className="p-2 text-slate-500">
|
||||
<Text className="text-center text-lg font-medium text-black">
|
||||
<Trans>
|
||||
{memberName || memberEmail} joined the team {teamName} on Documenso
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="my-1 text-center text-base">
|
||||
<Trans>{memberEmail} joined the following team</Trans>
|
||||
<Trans>A new member has joined your organisation {organisationName}</Trans>
|
||||
</Text>
|
||||
|
||||
<div className="mx-auto my-2 w-fit rounded-lg bg-gray-50 px-4 py-2 text-base font-medium text-slate-600">
|
||||
{formatTeamUrl(teamUrl, baseUrl)}
|
||||
{memberName || memberEmail}
|
||||
</div>
|
||||
</Section>
|
||||
</Container>
|
||||
@ -85,4 +77,4 @@ export const TeamJoinEmailTemplate = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamJoinEmailTemplate;
|
||||
export default OrganisationJoinEmailTemplate;
|
||||
@ -2,34 +2,32 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { formatTeamUrl } from '@documenso/lib/utils/teams';
|
||||
|
||||
import { Body, Container, Head, Hr, Html, Img, Preview, Section, Text } from '../components';
|
||||
import { useBranding } from '../providers/branding';
|
||||
import { TemplateFooter } from '../template-components/template-footer';
|
||||
import TemplateImage from '../template-components/template-image';
|
||||
|
||||
export type TeamLeaveEmailProps = {
|
||||
export type OrganisationLeaveEmailProps = {
|
||||
assetBaseUrl: string;
|
||||
baseUrl: string;
|
||||
memberName: string;
|
||||
memberEmail: string;
|
||||
teamName: string;
|
||||
teamUrl: string;
|
||||
organisationName: string;
|
||||
organisationUrl: string;
|
||||
};
|
||||
|
||||
export const TeamLeaveEmailTemplate = ({
|
||||
export const OrganisationLeaveEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
memberName = 'John Doe',
|
||||
memberEmail = 'johndoe@documenso.com',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
}: TeamLeaveEmailProps) => {
|
||||
organisationName = 'Organisation Name',
|
||||
organisationUrl = 'demo',
|
||||
}: OrganisationLeaveEmailProps) => {
|
||||
const { _ } = useLingui();
|
||||
const branding = useBranding();
|
||||
|
||||
const previewText = msg`A team member has left a team on Documenso`;
|
||||
const previewText = msg`A member has left your organisation on Documenso`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
@ -59,17 +57,11 @@ export const TeamLeaveEmailTemplate = ({
|
||||
|
||||
<Section className="p-2 text-slate-500">
|
||||
<Text className="text-center text-lg font-medium text-black">
|
||||
<Trans>
|
||||
{memberName || memberEmail} left the team {teamName} on Documenso
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="my-1 text-center text-base">
|
||||
<Trans>{memberEmail} left the following team</Trans>
|
||||
<Trans>A member has left your organisation {organisationName}</Trans>
|
||||
</Text>
|
||||
|
||||
<div className="mx-auto my-2 w-fit rounded-lg bg-gray-50 px-4 py-2 text-base font-medium text-slate-600">
|
||||
{formatTeamUrl(teamUrl, baseUrl)}
|
||||
{memberName || memberEmail}
|
||||
</div>
|
||||
</Section>
|
||||
</Container>
|
||||
@ -85,4 +77,4 @@ export const TeamLeaveEmailTemplate = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamLeaveEmailTemplate;
|
||||
export default OrganisationLeaveEmailTemplate;
|
||||
@ -12,29 +12,21 @@ export type TeamDeleteEmailProps = {
|
||||
assetBaseUrl: string;
|
||||
baseUrl: string;
|
||||
teamUrl: string;
|
||||
isOwner: boolean;
|
||||
};
|
||||
|
||||
export const TeamDeleteEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
teamUrl = 'demo',
|
||||
isOwner = false,
|
||||
}: TeamDeleteEmailProps) => {
|
||||
const { _ } = useLingui();
|
||||
const branding = useBranding();
|
||||
|
||||
const previewText = isOwner
|
||||
? msg`Your team has been deleted`
|
||||
: msg`A team you were a part of has been deleted`;
|
||||
const previewText = msg`A team you were a part of has been deleted`;
|
||||
|
||||
const title = isOwner
|
||||
? msg`Your team has been deleted`
|
||||
: msg`A team you were a part of has been deleted`;
|
||||
const title = msg`A team you were a part of has been deleted`;
|
||||
|
||||
const description = isOwner
|
||||
? msg`The following team has been deleted by you`
|
||||
: msg`The following team has been deleted by its owner. You will no longer be able to access this team and its documents`;
|
||||
const description = msg`The following team has been deleted. You will no longer be able to access this team and its documents`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { formatTeamUrl } from '@documenso/lib/utils/teams';
|
||||
|
||||
import { Body, Button, Container, Head, Hr, Html, Preview, Section, Text } from '../components';
|
||||
import { TemplateFooter } from '../template-components/template-footer';
|
||||
import TemplateImage from '../template-components/template-image';
|
||||
|
||||
export type TeamTransferRequestTemplateProps = {
|
||||
assetBaseUrl: string;
|
||||
baseUrl: string;
|
||||
senderName: string;
|
||||
teamName: string;
|
||||
teamUrl: string;
|
||||
token: string;
|
||||
};
|
||||
|
||||
export const TeamTransferRequestTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
senderName = 'John Doe',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
token = '',
|
||||
}: TeamTransferRequestTemplateProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const previewText = msg`Accept team transfer request on Documenso`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Preview>{_(previewText)}</Preview>
|
||||
|
||||
<Body className="mx-auto my-auto font-sans">
|
||||
<Section className="bg-white text-slate-500">
|
||||
<Container className="mx-auto mb-2 mt-8 max-w-xl rounded-lg border border-solid border-slate-200 px-2 pt-2 backdrop-blur-sm">
|
||||
<TemplateImage
|
||||
assetBaseUrl={assetBaseUrl}
|
||||
className="mb-4 h-6 p-2"
|
||||
staticAsset="logo.png"
|
||||
/>
|
||||
|
||||
<Section>
|
||||
<TemplateImage
|
||||
className="mx-auto"
|
||||
assetBaseUrl={assetBaseUrl}
|
||||
staticAsset="add-user.png"
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section className="p-2 text-slate-500">
|
||||
<Text className="text-center text-lg font-medium text-black">
|
||||
<Trans>{teamName} ownership transfer request</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="my-1 text-center text-base">
|
||||
<Trans>
|
||||
<span className="font-bold">{senderName}</span> has requested that you take
|
||||
ownership of the following team
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<div className="mx-auto my-2 w-fit rounded-lg bg-gray-50 px-4 py-2 text-base font-medium text-slate-600">
|
||||
{formatTeamUrl(teamUrl, baseUrl)}
|
||||
</div>
|
||||
|
||||
<Text className="text-center text-sm">
|
||||
<Trans>
|
||||
By accepting this request, you will take responsibility for any billing items
|
||||
associated with this team.
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Section className="mb-6 mt-6 text-center">
|
||||
<Button
|
||||
className="bg-documenso-500 ml-2 inline-flex items-center justify-center rounded-lg px-6 py-3 text-center text-sm font-medium text-black no-underline"
|
||||
href={`${baseUrl}/team/verify/transfer/${token}`}
|
||||
>
|
||||
<Trans>Accept</Trans>
|
||||
</Button>
|
||||
</Section>
|
||||
</Section>
|
||||
|
||||
<Text className="text-center text-xs">
|
||||
<Trans>Link expires in 1 hour.</Trans>
|
||||
</Text>
|
||||
</Container>
|
||||
|
||||
<Hr className="mx-auto mt-12 max-w-xl" />
|
||||
|
||||
<Container className="mx-auto max-w-xl">
|
||||
<TemplateFooter isDocument={false} />
|
||||
</Container>
|
||||
</Section>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamTransferRequestTemplate;
|
||||
Reference in New Issue
Block a user