import { useSession } from '@documenso/lib/client-only/providers/session'; import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document'; import { isDocumentCompleted } from '@documenso/lib/utils/document'; import { getEnvelopeItemPermissions } from '@documenso/lib/utils/envelope'; import { findRecipientByEmail } from '@documenso/lib/utils/recipients'; import { formatDocumentsPath, isMemberManagerOrAbove } from '@documenso/lib/utils/teams'; import { trpc as trpcReact } from '@documenso/trpc/react'; import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger, } from '@documenso/ui/primitives/dropdown-menu'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { DocumentStatus, EnvelopeType, RecipientRole } from '@prisma/client'; import { CheckCircle, Copy, Download, Edit, EyeIcon, FileOutputIcon, FolderInput, History, Loader, MoreHorizontal, Pencil, Share, Trash2, XCircle, } from 'lucide-react'; import { useState } from 'react'; import { Link } from 'react-router'; import { EnvelopeCancelDialog } from '~/components/dialogs/envelope-cancel-dialog'; import { EnvelopeDeleteDialog } from '~/components/dialogs/envelope-delete-dialog'; import { EnvelopeDuplicateDialog } from '~/components/dialogs/envelope-duplicate-dialog'; import { EnvelopeRedistributeDialog } from '~/components/dialogs/envelope-redistribute-dialog'; import { EnvelopeSaveAsTemplateDialog } from '~/components/dialogs/envelope-save-as-template-dialog'; import { DocumentRecipientLinkCopyDialog } from '~/components/general/document/document-recipient-link-copy-dialog'; import { useCurrentTeam } from '~/providers/team'; import { EnvelopeDownloadDialog } from '../dialogs/envelope-download-dialog'; import { EnvelopeRenameDialog } from '../dialogs/envelope-rename-dialog'; export type DocumentsTableActionDropdownProps = { row: TDocumentRow; onMoveDocument?: () => void; }; export const DocumentsTableActionDropdown = ({ row, onMoveDocument }: DocumentsTableActionDropdownProps) => { const { user } = useSession(); const team = useCurrentTeam(); const { _ } = useLingui(); const trpcUtils = trpcReact.useUtils(); const [isRenameDialogOpen, setRenameDialogOpen] = useState(false); const [isSaveAsTemplateDialogOpen, setSaveAsTemplateDialogOpen] = useState(false); const recipient = findRecipientByEmail({ recipients: row.recipients, userEmail: user.email, teamEmail: team.teamEmail?.email, }); const isOwner = row.user.id === user.id; // const isRecipient = !!recipient; const isDraft = row.status === DocumentStatus.DRAFT; const isPending = row.status === DocumentStatus.PENDING; const isComplete = isDocumentCompleted(row.status); // const isSigned = recipient?.signingStatus === SigningStatus.SIGNED; const isCurrentTeamDocument = team && row.team?.url === team.url; const canManageDocument = Boolean(isOwner || isCurrentTeamDocument); // Cancelling a document is restricted server-side to the document owner or a // privileged team member (ADMIN/MANAGER). Mirror that here so plain MEMBERs // don't see a Cancel action that would fail on the server. const isPrivilegedTeamMember = isMemberManagerOrAbove(team.currentTeamRole); const canCancelDocument = isOwner || isPrivilegedTeamMember; const { canTitleBeChanged } = getEnvelopeItemPermissions( { completedAt: row.completedAt, deletedAt: row.deletedAt, type: EnvelopeType.DOCUMENT, status: row.status, }, [], ); const documentsPath = formatDocumentsPath(team.url); const formatPath = `${documentsPath}/${row.envelopeId}/edit`; return ( Action {!isDraft && recipient && recipient?.role !== RecipientRole.CC && recipient?.role !== RecipientRole.ASSISTANT && ( {recipient?.role === RecipientRole.VIEWER && ( <> View )} {recipient?.role === RecipientRole.SIGNER && ( <> Sign )} {recipient?.role === RecipientRole.APPROVER && ( <> Approve )} )} Edit {canManageDocument && canTitleBeChanged && ( setRenameDialogOpen(true)}> Rename )} e.preventDefault()}>
Download
} /> e.preventDefault()}>
Duplicate
} /> setSaveAsTemplateDialogOpen(true)}> Save as Template {onMoveDocument && canManageDocument && ( e.preventDefault()}> Move to Folder )} {canCancelDocument && isPending && ( { await trpcUtils.document.findDocumentsInternal.invalidate(); }} trigger={ e.preventDefault()}>
Cancel
} /> )} e.preventDefault()}>
{canManageDocument ? _(msg`Delete`) : _(msg`Hide`)}
} /> Share {canManageDocument && ( e.preventDefault()}>
Signing Links
} /> )} {canManageDocument && ( e.preventDefault()}>
Resend
} /> )} ( e.preventDefault()}>
{loading ? : } Share Signing Card
)} />
{ await trpcUtils.document.findDocumentsInternal.invalidate(); }} />
); };