+ );
+}
diff --git a/apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx b/apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx
index 99630e57c..83aa0fa5a 100644
--- a/apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx
+++ b/apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx
@@ -113,10 +113,11 @@ export const DeleteTeamDialog = ({ trigger, teamId, teamName }: DeleteTeamDialog
- Delete team
+ Are you sure you wish to delete this team?
- Are you sure? This is irreversable.
+ Please note that you will lose access to all documents associated with this team & all
+ the members will be removed and notified
diff --git a/apps/web/src/components/(teams)/dialogs/remove-team-email-dialog.tsx b/apps/web/src/components/(teams)/dialogs/remove-team-email-dialog.tsx
new file mode 100644
index 000000000..04fd46d33
--- /dev/null
+++ b/apps/web/src/components/(teams)/dialogs/remove-team-email-dialog.tsx
@@ -0,0 +1,153 @@
+'use client';
+
+import { useState } from 'react';
+
+import { useRouter } from 'next/navigation';
+
+import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
+import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
+import type { Prisma } from '@documenso/prisma/client';
+import { trpc } from '@documenso/trpc/react';
+import { Alert } from '@documenso/ui/primitives/alert';
+import { AvatarWithText } from '@documenso/ui/primitives/avatar';
+import { Button } from '@documenso/ui/primitives/button';
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from '@documenso/ui/primitives/dialog';
+import { useToast } from '@documenso/ui/primitives/use-toast';
+
+export type RemoveTeamEmailDialogProps = {
+ trigger?: React.ReactNode;
+ teamName: string;
+ team: Prisma.TeamGetPayload<{
+ include: {
+ teamEmail: true;
+ emailVerification: {
+ select: {
+ expiresAt: true;
+ name: true;
+ email: true;
+ };
+ };
+ };
+ }>;
+};
+
+export const RemoveTeamEmailDialog = ({ trigger, teamName, team }: RemoveTeamEmailDialogProps) => {
+ const [open, setOpen] = useState(false);
+
+ const { toast } = useToast();
+ const router = useRouter();
+
+ const { mutateAsync: deleteTeamEmail, isLoading: isDeletingTeamEmail } =
+ trpc.team.deleteTeamEmail.useMutation({
+ onSuccess: () => {
+ toast({
+ title: 'Success',
+ description: 'Team email has been removed',
+ duration: 5000,
+ });
+ },
+ onError: () => {
+ toast({
+ title: 'Something went wrong',
+ variant: 'destructive',
+ duration: 10000,
+ description: 'Unable to remove team email at this time. Please try again.',
+ });
+ },
+ });
+
+ const { mutateAsync: deleteTeamEmailVerification, isLoading: isDeletingTeamEmailVerification } =
+ trpc.team.deleteTeamEmailVerification.useMutation({
+ onSuccess: () => {
+ toast({
+ title: 'Success',
+ description: 'Email verification has been removed',
+ duration: 5000,
+ });
+ },
+ onError: () => {
+ toast({
+ title: 'Something went wrong',
+ variant: 'destructive',
+ duration: 10000,
+ description: 'Unable to remove email verification at this time. Please try again.',
+ });
+ },
+ });
+
+ const onRemove = async () => {
+ if (team.teamEmail) {
+ await deleteTeamEmail({ teamId: team.id });
+ }
+
+ if (team.emailVerification) {
+ await deleteTeamEmailVerification({ teamId: team.id });
+ }
+
+ router.refresh();
+ };
+
+ return (
+
+ );
+};
diff --git a/packages/app-tests/e2e/document-auth/access-auth.spec.ts b/packages/app-tests/e2e/document-auth/access-auth.spec.ts
index b57969b50..8fb4afc04 100644
--- a/packages/app-tests/e2e/document-auth/access-auth.spec.ts
+++ b/packages/app-tests/e2e/document-auth/access-auth.spec.ts
@@ -3,7 +3,7 @@ import { expect, test } from '@playwright/test';
import { createDocumentAuthOptions } from '@documenso/lib/utils/document-auth';
import { prisma } from '@documenso/prisma';
import { seedPendingDocument } from '@documenso/prisma/seed/documents';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -31,8 +31,6 @@ test('[DOCUMENT_AUTH]: should grant access when not required', async ({ page })
await page.goto(`/sign/${token}`);
await expect(page.getByRole('heading', { name: 'Sign Document' })).toBeVisible();
}
-
- await unseedUser(user.id);
});
test('[DOCUMENT_AUTH]: should allow or deny access when required', async ({ page }) => {
@@ -90,7 +88,4 @@ test('[DOCUMENT_AUTH]: should allow or deny access when required', async ({ page
await expect(page.getByRole('paragraph')).toContainText(email);
}
}
-
- await unseedUser(user.id);
- await unseedUser(recipientWithAccount.id);
});
diff --git a/packages/app-tests/e2e/document-auth/action-auth.spec.ts b/packages/app-tests/e2e/document-auth/action-auth.spec.ts
index 5a29f287c..7a30d585d 100644
--- a/packages/app-tests/e2e/document-auth/action-auth.spec.ts
+++ b/packages/app-tests/e2e/document-auth/action-auth.spec.ts
@@ -10,7 +10,7 @@ import {
seedPendingDocumentNoFields,
seedPendingDocumentWithFullFields,
} from '@documenso/prisma/seed/documents';
-import { seedTestEmail, seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedTestEmail, seedUser } from '@documenso/prisma/seed/users';
import { apiSignin, apiSignout } from '../fixtures/authentication';
@@ -60,9 +60,6 @@ test('[DOCUMENT_AUTH]: should allow signing when no auth setup', async ({ page }
await page.getByRole('button', { name: 'Sign' }).click();
await page.waitForURL(`${signUrl}/complete`);
}
-
- await unseedUser(user.id);
- await unseedUser(recipientWithAccount.id);
});
test('[DOCUMENT_AUTH]: should allow signing with valid global auth', async ({ page }) => {
@@ -119,9 +116,6 @@ test('[DOCUMENT_AUTH]: should allow signing with valid global auth', async ({ pa
await page.getByRole('button', { name: 'Complete' }).click();
await page.getByRole('button', { name: 'Sign' }).click();
await page.waitForURL(`${signUrl}/complete`);
-
- await unseedUser(user.id);
- await unseedUser(recipientWithAccount.id);
});
// Currently document auth for signing/approving/viewing is not required.
@@ -154,9 +148,6 @@ test.skip('[DOCUMENT_AUTH]: should deny signing document when required for globa
await expect(page.getByRole('paragraph')).toContainText(
'Reauthentication is required to sign the document',
);
-
- await unseedUser(user.id);
- await unseedUser(recipientWithAccount.id);
});
test('[DOCUMENT_AUTH]: should deny signing fields when required for global auth', async ({
@@ -196,9 +187,6 @@ test('[DOCUMENT_AUTH]: should deny signing fields when required for global auth'
await page.getByRole('button', { name: 'Cancel' }).click();
}
}
-
- await unseedUser(user.id);
- await unseedUser(recipientWithAccount.id);
});
test('[DOCUMENT_AUTH]: should allow field signing when required for recipient auth', async ({
diff --git a/packages/app-tests/e2e/document-flow/settings-step.spec.ts b/packages/app-tests/e2e/document-flow/settings-step.spec.ts
index cef428a24..49d8de1f5 100644
--- a/packages/app-tests/e2e/document-flow/settings-step.spec.ts
+++ b/packages/app-tests/e2e/document-flow/settings-step.spec.ts
@@ -6,8 +6,8 @@ import {
seedPendingDocument,
} from '@documenso/prisma/seed/documents';
import { seedUserSubscription } from '@documenso/prisma/seed/subscriptions';
-import { seedTeam, unseedTeam } from '@documenso/prisma/seed/teams';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedTeam } from '@documenso/prisma/seed/teams';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -53,8 +53,6 @@ test.describe('[EE_ONLY]', () => {
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
await expect(page.getByTestId('documentActionSelectValue')).toContainText('Require passkey');
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW] enterprise team member can add action auth settings', async ({ page }) => {
@@ -94,8 +92,6 @@ test.describe('[EE_ONLY]', () => {
// Advanced settings should be visible.
await expect(page.getByLabel('Show advanced settings')).toBeVisible();
-
- await unseedTeam(team.url);
});
test('[DOCUMENT_FLOW] enterprise team member should not have access to enterprise on personal account', async ({
@@ -130,8 +126,6 @@ test.describe('[EE_ONLY]', () => {
// Advanced settings should not be visible.
await expect(page.getByLabel('Show advanced settings')).not.toBeVisible();
-
- await unseedTeam(team.url);
});
});
@@ -166,8 +160,6 @@ test('[DOCUMENT_FLOW]: add settings', async ({ page }) => {
await expect(page.getByLabel('Title')).toHaveValue('New Title');
await expect(page.getByTestId('documentAccessSelectValue')).toContainText('Require account');
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: title should be disabled depending on document status', async ({ page }) => {
@@ -188,6 +180,4 @@ test('[DOCUMENT_FLOW]: title should be disabled depending on document status', a
// Should be enabled for draft documents.
await page.goto(`/documents/${draftDocument.id}/edit`);
await expect(page.getByLabel('Title')).toBeEnabled();
-
- await unseedUser(user.id);
});
diff --git a/packages/app-tests/e2e/document-flow/signers-step.spec.ts b/packages/app-tests/e2e/document-flow/signers-step.spec.ts
index a832c69a6..a29066c03 100644
--- a/packages/app-tests/e2e/document-flow/signers-step.spec.ts
+++ b/packages/app-tests/e2e/document-flow/signers-step.spec.ts
@@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test';
import { seedBlankDocument } from '@documenso/prisma/seed/documents';
import { seedUserSubscription } from '@documenso/prisma/seed/subscriptions';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -57,8 +57,6 @@ test.describe('[EE_ONLY]', () => {
await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible();
// Todo: Fix stepper component back issue before finishing test.
-
- await unseedUser(user.id);
});
});
@@ -91,6 +89,4 @@ test('[DOCUMENT_FLOW]: add signers', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible();
await page.getByRole('button', { name: 'Go Back' }).click();
await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible();
-
- await unseedUser(user.id);
});
diff --git a/packages/app-tests/e2e/document-flow/stepper-component.spec.ts b/packages/app-tests/e2e/document-flow/stepper-component.spec.ts
index 327e0ab74..c35ad759d 100644
--- a/packages/app-tests/e2e/document-flow/stepper-component.spec.ts
+++ b/packages/app-tests/e2e/document-flow/stepper-component.spec.ts
@@ -9,7 +9,7 @@ import {
seedBlankDocument,
seedPendingDocumentWithFullFields,
} from '@documenso/prisma/seed/documents';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -107,8 +107,6 @@ test('[DOCUMENT_FLOW]: should be able to create a document', async ({ page }) =>
// Assert document was created
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipients', async ({
@@ -192,8 +190,6 @@ test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipie
// Assert document was created
await expect(page.getByRole('link', { name: documentTitle })).toBeVisible();
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipients with different roles', async ({
@@ -291,8 +287,6 @@ test('[DOCUMENT_FLOW]: should be able to create a document with multiple recipie
// Assert document was created
await expect(page.getByRole('link', { name: 'Test Title' })).toBeVisible();
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should not be able to create a document without signatures', async ({
@@ -331,8 +325,6 @@ test('[DOCUMENT_FLOW]: should not be able to create a document without signature
await expect(
page.getByRole('dialog').getByText('No signature field found').first(),
).toBeVisible();
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should be able to approve a document', async ({ page }) => {
@@ -388,8 +380,6 @@ test('[DOCUMENT_FLOW]: should be able to approve a document', async ({ page }) =
.click();
await page.waitForURL(`${signUrl}/complete`);
}
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should be able to create, send with redirect url, sign a document and redirect to redirect url', async ({
@@ -462,8 +452,6 @@ test('[DOCUMENT_FLOW]: should be able to create, send with redirect url, sign a
// Check if document has been signed
const { status: completedStatus } = await getDocumentByToken(token);
expect(completedStatus).toBe(DocumentStatus.COMPLETED);
-
- await unseedUser(user.id);
});
test('[DOCUMENT_FLOW]: should be able to sign a document with custom date', async ({ page }) => {
@@ -505,6 +493,4 @@ test('[DOCUMENT_FLOW]: should be able to sign a document with custom date', asyn
// Check if document has been signed
const { status: completedStatus } = await getDocumentByToken(token);
expect(completedStatus).toBe(DocumentStatus.COMPLETED);
-
- await unseedUser(user.id);
});
diff --git a/packages/app-tests/e2e/teams/manage-team.spec.ts b/packages/app-tests/e2e/teams/manage-team.spec.ts
index 7403ab9c9..3d0fb0ace 100644
--- a/packages/app-tests/e2e/teams/manage-team.spec.ts
+++ b/packages/app-tests/e2e/teams/manage-team.spec.ts
@@ -1,7 +1,7 @@
import { test } from '@playwright/test';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
-import { seedTeam, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam } from '@documenso/prisma/seed/teams';
import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -33,8 +33,6 @@ test('[TEAMS]: create team', async ({ page }) => {
// Goto new team settings page.
await page.getByRole('row').filter({ hasText: teamId }).getByRole('link').nth(1).click();
-
- await unseedTeam(teamId);
});
test('[TEAMS]: delete team', async ({ page }) => {
@@ -84,6 +82,4 @@ test('[TEAMS]: update team', async ({ page }) => {
// Check we have been redirected to the new team URL and the name is updated.
await page.waitForURL(`${WEBAPP_BASE_URL}/t/${updatedTeamId}/settings`);
-
- await unseedTeam(updatedTeamId);
});
diff --git a/packages/app-tests/e2e/teams/team-documents.spec.ts b/packages/app-tests/e2e/teams/team-documents.spec.ts
index 6cea6445d..b40f6d376 100644
--- a/packages/app-tests/e2e/teams/team-documents.spec.ts
+++ b/packages/app-tests/e2e/teams/team-documents.spec.ts
@@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test';
import { DocumentStatus } from '@documenso/prisma/client';
import { seedDocuments, seedTeamDocuments } from '@documenso/prisma/seed/documents';
-import { seedTeamEmail, unseedTeam, unseedTeamEmail } from '@documenso/prisma/seed/teams';
+import { seedTeamEmail } from '@documenso/prisma/seed/teams';
import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin, apiSignout } from '../fixtures/authentication';
@@ -42,8 +42,6 @@ test('[TEAMS]: check team documents count', async ({ page }) => {
await apiSignout({ page });
}
-
- await unseedTeam(team.url);
});
test('[TEAMS]: check team documents count with internal team email', async ({ page }) => {
@@ -138,9 +136,6 @@ test('[TEAMS]: check team documents count with internal team email', async ({ pa
await apiSignout({ page });
}
-
- await unseedTeamEmail({ teamId: team.id });
- await unseedTeam(team.url);
});
test('[TEAMS]: check team documents count with external team email', async ({ page }) => {
@@ -225,9 +220,6 @@ test('[TEAMS]: check team documents count with external team email', async ({ pa
await checkDocumentTabCount(page, 'Completed', 0);
await checkDocumentTabCount(page, 'Draft', 1);
await checkDocumentTabCount(page, 'All', 3);
-
- await unseedTeamEmail({ teamId: team.id });
- await unseedTeam(team.url);
});
test('[TEAMS]: resend pending team document', async ({ page }) => {
@@ -284,8 +276,6 @@ test('[TEAMS]: delete draft team document', async ({ page }) => {
await apiSignout({ page });
}
-
- await unseedTeam(team.url);
});
test('[TEAMS]: delete pending team document', async ({ page }) => {
@@ -325,8 +315,6 @@ test('[TEAMS]: delete pending team document', async ({ page }) => {
await apiSignout({ page });
}
-
- await unseedTeam(team.url);
});
test('[TEAMS]: delete completed team document', async ({ page }) => {
@@ -366,6 +354,4 @@ test('[TEAMS]: delete completed team document', async ({ page }) => {
await apiSignout({ page });
}
-
- await unseedTeam(team.url);
});
diff --git a/packages/app-tests/e2e/teams/team-email.spec.ts b/packages/app-tests/e2e/teams/team-email.spec.ts
index 6ae820f59..7becb2418 100644
--- a/packages/app-tests/e2e/teams/team-email.spec.ts
+++ b/packages/app-tests/e2e/teams/team-email.spec.ts
@@ -1,8 +1,8 @@
import { expect, test } from '@playwright/test';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
-import { seedTeam, seedTeamEmailVerification, unseedTeam } from '@documenso/prisma/seed/teams';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedTeam, seedTeamEmailVerification } from '@documenso/prisma/seed/teams';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -31,8 +31,6 @@ test('[TEAMS]: send team email request', async ({ page }) => {
.filter({ hasText: 'We have sent a confirmation email for verification.' })
.first(),
).toBeVisible();
-
- await unseedTeam(team.url);
});
test('[TEAMS]: accept team email request', async ({ page }) => {
@@ -41,14 +39,12 @@ test('[TEAMS]: accept team email request', async ({ page }) => {
});
const teamEmailVerification = await seedTeamEmailVerification({
- email: 'team-email-verification@test.documenso.com',
+ email: `team-email-verification--${team.url}@test.documenso.com`,
teamId: team.id,
});
await page.goto(`${WEBAPP_BASE_URL}/team/verify/email/${teamEmailVerification.token}`);
await expect(page.getByRole('heading')).toContainText('Team email verified!');
-
- await unseedTeam(team.url);
});
test('[TEAMS]: delete team email', async ({ page }) => {
@@ -66,10 +62,9 @@ test('[TEAMS]: delete team email', async ({ page }) => {
await page.locator('section div').filter({ hasText: 'Team email' }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Remove' }).click();
+ await page.getByRole('button', { name: 'Remove' }).click();
await expect(page.getByText('Team email has been removed').first()).toBeVisible();
-
- await unseedTeam(team.url);
});
test('[TEAMS]: team email owner removes access', async ({ page }) => {
@@ -96,7 +91,4 @@ test('[TEAMS]: team email owner removes access', async ({ page }) => {
await page.getByRole('button', { name: 'Revoke' }).click();
await expect(page.getByText('You have successfully revoked').first()).toBeVisible();
-
- await unseedTeam(team.url);
- await unseedUser(teamEmailOwner.id);
});
diff --git a/packages/app-tests/e2e/teams/team-members.spec.ts b/packages/app-tests/e2e/teams/team-members.spec.ts
index c85717729..0e5f828ed 100644
--- a/packages/app-tests/e2e/teams/team-members.spec.ts
+++ b/packages/app-tests/e2e/teams/team-members.spec.ts
@@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
-import { seedTeam, seedTeamInvite, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam, seedTeamInvite } from '@documenso/prisma/seed/teams';
import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -35,8 +35,6 @@ test('[TEAMS]: update team member role', async ({ page }) => {
await expect(
page.getByRole('row').filter({ hasText: teamMemberToUpdate.user.email }),
).toContainText('Manager');
-
- await unseedTeam(team.url);
});
test('[TEAMS]: accept team invitation without account', async ({ page }) => {
@@ -49,8 +47,6 @@ test('[TEAMS]: accept team invitation without account', async ({ page }) => {
await page.goto(`${WEBAPP_BASE_URL}/team/invite/${teamInvite.token}`);
await expect(page.getByRole('heading')).toContainText('Team invitation');
-
- await unseedTeam(team.url);
});
test('[TEAMS]: accept team invitation with account', async ({ page }) => {
@@ -64,8 +60,6 @@ test('[TEAMS]: accept team invitation with account', async ({ page }) => {
await page.goto(`${WEBAPP_BASE_URL}/team/invite/${teamInvite.token}`);
await expect(page.getByRole('heading')).toContainText('Invitation accepted!');
-
- await unseedTeam(team.url);
});
test('[TEAMS]: member can leave team', async ({ page }) => {
@@ -88,8 +82,6 @@ test('[TEAMS]: member can leave team', async ({ page }) => {
await expect(page.getByRole('status').first()).toContainText(
'You have successfully left this team.',
);
-
- await unseedTeam(team.url);
});
test('[TEAMS]: owner cannot leave team', async ({ page }) => {
@@ -105,6 +97,4 @@ test('[TEAMS]: owner cannot leave team', async ({ page }) => {
});
await expect(page.getByRole('button').getByText('Leave')).toBeDisabled();
-
- await unseedTeam(team.url);
});
diff --git a/packages/app-tests/e2e/teams/transfer-team.spec.ts b/packages/app-tests/e2e/teams/transfer-team.spec.ts
index c8460baf8..d34525160 100644
--- a/packages/app-tests/e2e/teams/transfer-team.spec.ts
+++ b/packages/app-tests/e2e/teams/transfer-team.spec.ts
@@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
-import { seedTeam, seedTeamTransfer, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam, seedTeamTransfer } from '@documenso/prisma/seed/teams';
import { apiSignin } from '../fixtures/authentication';
@@ -43,8 +43,6 @@ test('[TEAMS]: initiate and cancel team transfer', async ({ page }) => {
await expect(page.getByRole('status').first()).toContainText(
'The team transfer invitation has been successfully deleted.',
);
-
- await unseedTeam(team.url);
});
/**
@@ -64,6 +62,4 @@ test.skip('[TEAMS]: accept team transfer', async ({ page }) => {
await page.goto(`${WEBAPP_BASE_URL}/team/verify/transfer/${teamTransferRequest.token}`);
await expect(page.getByRole('heading')).toContainText('Team ownership transferred!');
-
- await unseedTeam(team.url);
});
diff --git a/packages/app-tests/e2e/templates-flow/template-settings-step.spec.ts b/packages/app-tests/e2e/templates-flow/template-settings-step.spec.ts
index 517a3f093..4061b0046 100644
--- a/packages/app-tests/e2e/templates-flow/template-settings-step.spec.ts
+++ b/packages/app-tests/e2e/templates-flow/template-settings-step.spec.ts
@@ -1,9 +1,9 @@
import { expect, test } from '@playwright/test';
import { seedUserSubscription } from '@documenso/prisma/seed/subscriptions';
-import { seedTeam, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam } from '@documenso/prisma/seed/teams';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -49,8 +49,6 @@ test.describe('[EE_ONLY]', () => {
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
await expect(page.getByTestId('documentActionSelectValue')).toContainText('Require passkey');
-
- await unseedUser(user.id);
});
test('[TEMPLATE_FLOW] enterprise team member can add action auth settings', async ({ page }) => {
@@ -90,8 +88,6 @@ test.describe('[EE_ONLY]', () => {
// Advanced settings should be visible.
await expect(page.getByLabel('Show advanced settings')).toBeVisible();
-
- await unseedTeam(team.url);
});
test('[TEMPLATE_FLOW] enterprise team member should not have access to enterprise on personal account', async ({
@@ -126,8 +122,6 @@ test.describe('[EE_ONLY]', () => {
// Advanced settings should not be visible.
await expect(page.getByLabel('Show advanced settings')).not.toBeVisible();
-
- await unseedTeam(team.url);
});
});
@@ -162,6 +156,4 @@ test('[TEMPLATE_FLOW]: add settings', async ({ page }) => {
await expect(page.getByLabel('Title')).toHaveValue('New Title');
await expect(page.getByTestId('documentAccessSelectValue')).toContainText('Require account');
-
- await unseedUser(user.id);
});
diff --git a/packages/app-tests/e2e/templates-flow/template-signers-step.spec.ts b/packages/app-tests/e2e/templates-flow/template-signers-step.spec.ts
index 37b58f53b..dd9dfa9a5 100644
--- a/packages/app-tests/e2e/templates-flow/template-signers-step.spec.ts
+++ b/packages/app-tests/e2e/templates-flow/template-signers-step.spec.ts
@@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test';
import { seedUserSubscription } from '@documenso/prisma/seed/subscriptions';
import { seedBlankTemplate } from '@documenso/prisma/seed/templates';
-import { seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
@@ -73,8 +73,6 @@ test.describe('[EE_ONLY]', () => {
// Expect that the advanced settings is visible, and the checkbox is hidden. Since advanced
// settings were applied.
await expect(page.getByLabel('Show advanced settings')).toBeHidden();
-
- await unseedUser(user.id);
});
});
@@ -101,6 +99,4 @@ test('[TEMPLATE_FLOW]: add placeholder', async ({ page }) => {
// Advanced settings should not be visible for non EE users.
await expect(page.getByLabel('Show advanced settings')).toBeHidden();
-
- await unseedUser(user.id);
});
diff --git a/packages/app-tests/e2e/templates/direct-templates.spec.ts b/packages/app-tests/e2e/templates/direct-templates.spec.ts
index 518dc28c0..5b822dbcf 100644
--- a/packages/app-tests/e2e/templates/direct-templates.spec.ts
+++ b/packages/app-tests/e2e/templates/direct-templates.spec.ts
@@ -9,9 +9,9 @@ import {
import { createDocumentAuthOptions } from '@documenso/lib/utils/document-auth';
import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams';
import { formatDirectTemplatePath } from '@documenso/lib/utils/templates';
-import { seedTeam, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam } from '@documenso/prisma/seed/teams';
import { seedDirectTemplate, seedTemplate } from '@documenso/prisma/seed/templates';
-import { seedTestEmail, seedUser, unseedUser } from '@documenso/prisma/seed/users';
+import { seedTestEmail, seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
import { checkDocumentTabCount } from '../fixtures/documents';
@@ -67,8 +67,6 @@ test('[DIRECT_TEMPLATES]: create direct link for template', async ({ page }) =>
// Expect badge to appear.
await expect(page.getByRole('button', { name: 'direct link' })).toHaveCount(2);
}
-
- await unseedTeam(team.url);
});
test('[DIRECT_TEMPLATES]: toggle direct template link', async ({ page }) => {
@@ -115,8 +113,6 @@ test('[DIRECT_TEMPLATES]: toggle direct template link', async ({ page }) => {
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
await expect(page.getByText('Template not found')).toBeVisible();
}
-
- await unseedTeam(team.url);
});
test('[DIRECT_TEMPLATES]: delete direct template link', async ({ page }) => {
@@ -162,8 +158,6 @@ test('[DIRECT_TEMPLATES]: delete direct template link', async ({ page }) => {
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
await expect(page.getByText('Template not found')).toBeVisible();
}
-
- await unseedTeam(team.url);
});
test('[DIRECT_TEMPLATES]: direct template link auth access', async ({ page }) => {
@@ -197,8 +191,6 @@ test('[DIRECT_TEMPLATES]: direct template link auth access', async ({ page }) =>
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
await expect(page.getByLabel('Email')).toBeDisabled();
-
- await unseedUser(user.id);
});
test('[DIRECT_TEMPLATES]: use direct template link with 1 recipient', async ({ page }) => {
@@ -248,8 +240,6 @@ test('[DIRECT_TEMPLATES]: use direct template link with 1 recipient', async ({ p
// Check that the document is in the 'All' tab.
await checkDocumentTabCount(page, 'Completed', 1);
}
-
- await unseedTeam(team.url);
});
test('[DIRECT_TEMPLATES]: use direct template link with 2 recipients', async ({ page }) => {
@@ -333,7 +323,4 @@ test('[DIRECT_TEMPLATES]: use direct template link with 2 recipients', async ({
await checkDocumentTabCount(page, 'All', 2);
await checkDocumentTabCount(page, 'Inbox', 2);
-
- await unseedTeam(team.url);
- await unseedUser(secondRecipient.id);
});
diff --git a/packages/app-tests/e2e/templates/manage-templates.spec.ts b/packages/app-tests/e2e/templates/manage-templates.spec.ts
index 7d75c4f65..135ab96f1 100644
--- a/packages/app-tests/e2e/templates/manage-templates.spec.ts
+++ b/packages/app-tests/e2e/templates/manage-templates.spec.ts
@@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
-import { seedTeam, unseedTeam } from '@documenso/prisma/seed/teams';
+import { seedTeam } from '@documenso/prisma/seed/teams';
import { seedTemplate } from '@documenso/prisma/seed/templates';
import { apiSignin } from '../fixtures/authentication';
@@ -49,8 +49,6 @@ test('[TEMPLATES]: view templates', async ({ page }) => {
// Only should only see their personal template.
await page.goto(`${WEBAPP_BASE_URL}/templates`);
await expect(page.getByRole('main')).toContainText('Showing 1 result');
-
- await unseedTeam(team.url);
});
test('[TEMPLATES]: delete template', async ({ page }) => {
@@ -110,8 +108,6 @@ test('[TEMPLATES]: delete template', async ({ page }) => {
await page.reload();
}
-
- await unseedTeam(team.url);
});
test('[TEMPLATES]: duplicate template', async ({ page }) => {
@@ -156,8 +152,6 @@ test('[TEMPLATES]: duplicate template', async ({ page }) => {
await page.getByRole('button', { name: 'Duplicate' }).click();
await expect(page.getByText('Template duplicated').first()).toBeVisible();
await expect(page.getByRole('main')).toContainText('Showing 2 results');
-
- await unseedTeam(team.url);
});
test('[TEMPLATES]: use template', async ({ page }) => {
@@ -219,6 +213,4 @@ test('[TEMPLATES]: use template', async ({ page }) => {
await page.getByRole('main').getByRole('link', { name: 'Documents' }).click();
await page.waitForURL(`/t/${team.url}/documents`);
await expect(page.getByRole('main')).toContainText('Showing 1 result');
-
- await unseedTeam(team.url);
});
diff --git a/packages/app-tests/e2e/user/auth-flow.spec.ts b/packages/app-tests/e2e/user/auth-flow.spec.ts
index 94338ec21..e1d311530 100644
--- a/packages/app-tests/e2e/user/auth-flow.spec.ts
+++ b/packages/app-tests/e2e/user/auth-flow.spec.ts
@@ -4,8 +4,6 @@ import {
extractUserVerificationToken,
seedTestEmail,
seedUser,
- unseedUser,
- unseedUserByEmail,
} from '@documenso/prisma/seed/users';
test.use({ storageState: { cookies: [], origins: [] } });
@@ -48,7 +46,6 @@ test('[USER] can sign up with email and password', async ({ page }: { page: Page
await page.waitForURL('/documents');
await expect(page).toHaveURL('/documents');
- await unseedUserByEmail(email);
});
test('[USER] can sign in using email and password', async ({ page }: { page: Page }) => {
@@ -61,6 +58,4 @@ test('[USER] can sign in using email and password', async ({ page }: { page: Pag
await page.waitForURL('/documents');
await expect(page).toHaveURL('/documents');
-
- await unseedUser(user.id);
});
diff --git a/packages/email/static/delete-team.png b/packages/email/static/delete-team.png
new file mode 100644
index 000000000..cc6cca3d7
Binary files /dev/null and b/packages/email/static/delete-team.png differ
diff --git a/packages/email/static/delete-user.png b/packages/email/static/delete-user.png
new file mode 100644
index 000000000..34e15e6b9
Binary files /dev/null and b/packages/email/static/delete-user.png differ
diff --git a/packages/email/templates/team-delete.tsx b/packages/email/templates/team-delete.tsx
new file mode 100644
index 000000000..240757338
--- /dev/null
+++ b/packages/email/templates/team-delete.tsx
@@ -0,0 +1,86 @@
+import { formatTeamUrl } from '@documenso/lib/utils/teams';
+import config from '@documenso/tailwind-config';
+
+import { Body, Container, Head, Hr, Html, Preview, Section, Tailwind, Text } from '../components';
+import { TemplateFooter } from '../template-components/template-footer';
+import TemplateImage from '../template-components/template-image';
+
+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 previewText = isOwner
+ ? 'Your team has been deleted'
+ : 'A team you were a part of has been deleted';
+
+ const title = isOwner
+ ? 'Your team has been deleted'
+ : 'A team you were a part of has been deleted';
+
+ const description = isOwner
+ ? 'The following team has been deleted by you'
+ : 'The following team has been deleted by its owner. You will no longer be able to access this team and its documents';
+
+ return (
+
+
+ {previewText}
+
+
+
+
+
+
+
+
+
+
+
+ {title}
+
+ {description}
+
+
+ {formatTeamUrl(teamUrl, baseUrl)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default TeamDeleteEmailTemplate;
diff --git a/packages/email/templates/team-invite.tsx b/packages/email/templates/team-invite.tsx
index 4602b7382..3c062c4c8 100644
--- a/packages/email/templates/team-invite.tsx
+++ b/packages/email/templates/team-invite.tsx
@@ -89,6 +89,12 @@ export const TeamInviteEmailTemplate = ({
>
Accept
+
diff --git a/packages/email/templates/team-join.tsx b/packages/email/templates/team-join.tsx
new file mode 100644
index 000000000..b3c1efc2f
--- /dev/null
+++ b/packages/email/templates/team-join.tsx
@@ -0,0 +1,84 @@
+import { formatTeamUrl } from '@documenso/lib/utils/teams';
+import config from '@documenso/tailwind-config';
+
+import { Body, Container, Head, Hr, Html, Preview, Section, Tailwind, Text } from '../components';
+import { TemplateFooter } from '../template-components/template-footer';
+import TemplateImage from '../template-components/template-image';
+
+export type TeamJoinEmailProps = {
+ assetBaseUrl: string;
+ baseUrl: string;
+ memberName: string;
+ memberEmail: string;
+ teamName: string;
+ teamUrl: string;
+};
+
+export const TeamJoinEmailTemplate = ({
+ assetBaseUrl = 'http://localhost:3002',
+ baseUrl = 'https://documenso.com',
+ memberName = 'John Doe',
+ memberEmail = 'johndoe@documenso.com',
+ teamName = 'Team Name',
+ teamUrl = 'demo',
+}: TeamJoinEmailProps) => {
+ const previewText = 'A team member has joined a team on Documenso';
+
+ return (
+
+
+ {previewText}
+
+
+
+
+
+
+
+
+
+
+
+
+ {memberName || memberEmail} joined the team {teamName} on Documenso
+
+
+
+ {memberEmail} joined the following team
+
+
+
+ {formatTeamUrl(teamUrl, baseUrl)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default TeamJoinEmailTemplate;
diff --git a/packages/email/templates/team-leave.tsx b/packages/email/templates/team-leave.tsx
new file mode 100644
index 000000000..51b9aaab1
--- /dev/null
+++ b/packages/email/templates/team-leave.tsx
@@ -0,0 +1,84 @@
+import { formatTeamUrl } from '@documenso/lib/utils/teams';
+import config from '@documenso/tailwind-config';
+
+import { Body, Container, Head, Hr, Html, Preview, Section, Tailwind, Text } from '../components';
+import { TemplateFooter } from '../template-components/template-footer';
+import TemplateImage from '../template-components/template-image';
+
+export type TeamLeaveEmailProps = {
+ assetBaseUrl: string;
+ baseUrl: string;
+ memberName: string;
+ memberEmail: string;
+ teamName: string;
+ teamUrl: string;
+};
+
+export const TeamLeaveEmailTemplate = ({
+ assetBaseUrl = 'http://localhost:3002',
+ baseUrl = 'https://documenso.com',
+ memberName = 'John Doe',
+ memberEmail = 'johndoe@documenso.com',
+ teamName = 'Team Name',
+ teamUrl = 'demo',
+}: TeamLeaveEmailProps) => {
+ const previewText = 'A team member has left a team on Documenso';
+
+ return (
+
+