feat: add teams (#848)

## Description

Add support for teams which will allow users to collaborate on
documents.

Teams features allows users to:

- Create, manage and transfer teams
- Manage team members
- Manage team emails
- Manage a shared team inbox and documents

These changes do NOT include the following, which are planned for a
future release:

- Team templates
- Team API
- Search menu integration

## Testing Performed

- Added E2E tests for general team management
- Added E2E tests to validate document counts

## Checklist

- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [ ] I have updated the documentation to reflect these changes, if
applicable.
- [X] I have followed the project's coding style guidelines.
This commit is contained in:
David Nguyen
2024-02-06 16:16:10 +11:00
committed by GitHub
parent c6457e75e0
commit 0c339b78b6
200 changed files with 12916 additions and 968 deletions

View File

@ -10,6 +10,7 @@ import * as z from 'zod';
import { getRecipientType } from '@documenso/lib/client-only/recipient-type';
import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter';
import type { Team } from '@documenso/prisma/client';
import { type Document, type Recipient, SigningStatus } from '@documenso/prisma/client';
import { trpc as trpcReact } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
@ -39,8 +40,11 @@ import { StackAvatar } from '~/components/(dashboard)/avatar/stack-avatar';
const FORM_ID = 'resend-email';
export type ResendDocumentActionItemProps = {
document: Document;
document: Document & {
team: Pick<Team, 'id' | 'url'> | null;
};
recipients: Recipient[];
team?: Pick<Team, 'id' | 'url'>;
};
export const ZResendDocumentFormSchema = z.object({
@ -54,15 +58,17 @@ export type TResendDocumentFormSchema = z.infer<typeof ZResendDocumentFormSchema
export const ResendDocumentActionItem = ({
document,
recipients,
team,
}: ResendDocumentActionItemProps) => {
const { data: session } = useSession();
const { toast } = useToast();
const [isOpen, setIsOpen] = useState(false);
const isOwner = document.userId === session?.user?.id;
const isCurrentTeamDocument = team && document.team?.url === team.url;
const isDisabled =
!isOwner ||
(!isOwner && !isCurrentTeamDocument) ||
document.status !== 'PENDING' ||
!recipients.some((r) => r.signingStatus === SigningStatus.NOT_SIGNED);
@ -82,7 +88,7 @@ export const ResendDocumentActionItem = ({
const onFormSubmit = async ({ recipients }: TResendDocumentFormSchema) => {
try {
await resendDocument({ documentId: document.id, recipients });
await resendDocument({ documentId: document.id, recipients, teamId: team?.id });
toast({
title: 'Document re-sent',