mirror of
https://github.com/documenso/documenso.git
synced 2025-11-17 02:01:33 +10:00
feat: expiry links
This commit is contained in:
@ -198,6 +198,8 @@ export const DocumentEditForm = ({
|
||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||
expiryAmount: data.meta.expiryAmount,
|
||||
expiryUnit: data.meta.expiryUnit,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -158,6 +158,14 @@ export const DocumentPageViewRecipients = ({
|
||||
</PopoverHover>
|
||||
)}
|
||||
|
||||
{document.status !== DocumentStatus.DRAFT &&
|
||||
recipient.signingStatus === SigningStatus.EXPIRED && (
|
||||
<Badge variant="warning">
|
||||
<Clock className="mr-1 h-3 w-3" />
|
||||
<Trans>Expired</Trans>
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{document.status === DocumentStatus.PENDING &&
|
||||
recipient.signingStatus === SigningStatus.NOT_SIGNED &&
|
||||
recipient.role !== RecipientRole.CC && (
|
||||
|
||||
@ -41,6 +41,9 @@ export const StackAvatar = ({ first, zIndex, fallbackText = '', type }: StackAva
|
||||
case RecipientStatusType.REJECTED:
|
||||
classes = 'bg-red-200 text-red-800';
|
||||
break;
|
||||
case RecipientStatusType.EXPIRED:
|
||||
classes = 'bg-orange-200 text-orange-800';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -48,13 +48,20 @@ export const StackAvatarsWithTooltip = ({
|
||||
(recipient) => getRecipientType(recipient) === RecipientStatusType.REJECTED,
|
||||
);
|
||||
|
||||
const expiredRecipients = recipients.filter(
|
||||
(recipient) => getRecipientType(recipient) === RecipientStatusType.EXPIRED,
|
||||
);
|
||||
|
||||
const sortedRecipients = useMemo(() => {
|
||||
const otherRecipients = recipients.filter(
|
||||
(recipient) => getRecipientType(recipient) !== RecipientStatusType.REJECTED,
|
||||
(recipient) =>
|
||||
getRecipientType(recipient) !== RecipientStatusType.REJECTED &&
|
||||
getRecipientType(recipient) !== RecipientStatusType.EXPIRED,
|
||||
);
|
||||
|
||||
return [
|
||||
...rejectedRecipients.sort((a, b) => a.id - b.id),
|
||||
...expiredRecipients.sort((a, b) => a.id - b.id),
|
||||
...otherRecipients.sort((a, b) => {
|
||||
return a.id - b.id;
|
||||
}),
|
||||
@ -117,6 +124,30 @@ export const StackAvatarsWithTooltip = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{expiredRecipients.length > 0 && (
|
||||
<div>
|
||||
<h1 className="text-base font-medium">
|
||||
<Trans>Expired</Trans>
|
||||
</h1>
|
||||
{expiredRecipients.map((recipient: Recipient) => (
|
||||
<div key={recipient.id} className="my-1 flex items-center gap-2">
|
||||
<StackAvatar
|
||||
first={true}
|
||||
key={recipient.id}
|
||||
type={getRecipientType(recipient)}
|
||||
fallbackText={recipientAbbreviation(recipient)}
|
||||
/>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">{recipient.email}</p>
|
||||
<p className="text-muted-foreground/70 text-xs">
|
||||
{_(RECIPIENT_ROLES_DESCRIPTION[recipient.role].roleName)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{waitingRecipients.length > 0 && (
|
||||
<div>
|
||||
<h1 className="text-base font-medium">
|
||||
|
||||
@ -2,7 +2,7 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { DocumentStatus, RecipientRole, SigningStatus } from '@prisma/client';
|
||||
import { CheckCircle, Download, Edit, EyeIcon, Pencil } from 'lucide-react';
|
||||
import { CheckCircle, Clock, Download, Edit, EyeIcon, Pencil } from 'lucide-react';
|
||||
import { Link } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
@ -36,6 +36,7 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr
|
||||
const isPending = row.status === DocumentStatus.PENDING;
|
||||
const isComplete = isDocumentCompleted(row.status);
|
||||
const isSigned = recipient?.signingStatus === SigningStatus.SIGNED;
|
||||
const isExpired = recipient?.signingStatus === SigningStatus.EXPIRED;
|
||||
const role = recipient?.role;
|
||||
const isCurrentTeamDocument = team && row.team?.url === team.url;
|
||||
|
||||
@ -87,8 +88,15 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr
|
||||
isPending,
|
||||
isComplete,
|
||||
isSigned,
|
||||
isExpired,
|
||||
isCurrentTeamDocument,
|
||||
})
|
||||
.with({ isRecipient: true, isExpired: true }, () => (
|
||||
<Button className="w-32 bg-orange-100 text-orange-600 hover:bg-orange-200" disabled={true}>
|
||||
<Clock className="-ml-1 mr-2 h-4 w-4" />
|
||||
<Trans>Expired</Trans>
|
||||
</Button>
|
||||
))
|
||||
.with(
|
||||
isOwner ? { isDraft: true, isOwner: true } : { isDraft: true, isCurrentTeamDocument: true },
|
||||
() => (
|
||||
|
||||
@ -5,7 +5,7 @@ import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { DocumentStatus as DocumentStatusEnum } from '@prisma/client';
|
||||
import { RecipientRole, SigningStatus } from '@prisma/client';
|
||||
import { CheckCircleIcon, DownloadIcon, EyeIcon, Loader, PencilIcon } from 'lucide-react';
|
||||
import { CheckCircleIcon, Clock, DownloadIcon, EyeIcon, Loader, PencilIcon } from 'lucide-react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
@ -194,6 +194,7 @@ export const InboxTableActionButton = ({ row }: InboxTableActionButtonProps) =>
|
||||
const isPending = row.status === DocumentStatusEnum.PENDING;
|
||||
const isComplete = isDocumentCompleted(row.status);
|
||||
const isSigned = recipient?.signingStatus === SigningStatus.SIGNED;
|
||||
const isExpired = recipient?.signingStatus === SigningStatus.EXPIRED;
|
||||
const role = recipient?.role;
|
||||
|
||||
if (!recipient) {
|
||||
@ -231,7 +232,14 @@ export const InboxTableActionButton = ({ row }: InboxTableActionButtonProps) =>
|
||||
isPending,
|
||||
isComplete,
|
||||
isSigned,
|
||||
isExpired,
|
||||
})
|
||||
.with({ isExpired: true }, () => (
|
||||
<Button className="w-32 bg-orange-100 text-orange-600 hover:bg-orange-200" disabled={true}>
|
||||
<Clock className="-ml-1 mr-2 h-4 w-4" />
|
||||
<Trans>Expired</Trans>
|
||||
</Button>
|
||||
))
|
||||
.with({ isPending: true, isSigned: false }, () => (
|
||||
<Button className="w-32" asChild>
|
||||
<Link to={`/sign/${recipient?.token}`}>
|
||||
|
||||
Reference in New Issue
Block a user