mirror of
https://github.com/documenso/documenso.git
synced 2026-08-25 15:52:29 +10:00
feat: add cancellable document status (#2992)
Adds a CANCELLED envelope status that privileged members (owner or team admin/manager) can move a pending document into. Sending recipient notifications via a background job while retaining the document in the dashboard as proof of distribution. Includes a dedicated Cancelled tab, single and bulk cancel actions, the ENVELOPE_CANCELLED mutability guard, and e2e coverage for permissions and visibility.
This commit is contained in:
@@ -224,6 +224,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
{match(envelope.status)
|
||||
.with(DocumentStatus.COMPLETED, () => <Trans>This document has been signed by all recipients</Trans>)
|
||||
.with(DocumentStatus.REJECTED, () => <Trans>This document has been rejected by a recipient</Trans>)
|
||||
.with(DocumentStatus.CANCELLED, () => <Trans>This document has been cancelled</Trans>)
|
||||
.with(DocumentStatus.DRAFT, () => (
|
||||
<Trans>This document is currently a draft and has not been sent</Trans>
|
||||
))
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Link, useParams, useSearchParams } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { DocumentMoveToFolderDialog } from '~/components/dialogs/document-move-to-folder-dialog';
|
||||
import { EnvelopesBulkCancelDialog } from '~/components/dialogs/envelopes-bulk-cancel-dialog';
|
||||
import { EnvelopesBulkDeleteDialog } from '~/components/dialogs/envelopes-bulk-delete-dialog';
|
||||
import { EnvelopesBulkMoveDialog } from '~/components/dialogs/envelopes-bulk-move-dialog';
|
||||
import { DocumentSearch } from '~/components/general/document/document-search';
|
||||
@@ -61,6 +62,7 @@ export default function DocumentsPage() {
|
||||
const [rowSelection, setRowSelection] = useSessionStorage<RowSelectionState>('documents-bulk-selection', {});
|
||||
const [isBulkMoveDialogOpen, setIsBulkMoveDialogOpen] = useState(false);
|
||||
const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false);
|
||||
const [isBulkCancelDialogOpen, setIsBulkCancelDialogOpen] = useState(false);
|
||||
|
||||
const selectedEnvelopeIds = useMemo(() => {
|
||||
return Object.keys(rowSelection).filter((id) => rowSelection[id]);
|
||||
@@ -71,6 +73,7 @@ export default function DocumentsPage() {
|
||||
[ExtendedDocumentStatus.PENDING]: 0,
|
||||
[ExtendedDocumentStatus.COMPLETED]: 0,
|
||||
[ExtendedDocumentStatus.REJECTED]: 0,
|
||||
[ExtendedDocumentStatus.CANCELLED]: 0,
|
||||
[ExtendedDocumentStatus.INBOX]: 0,
|
||||
[ExtendedDocumentStatus.ALL]: 0,
|
||||
});
|
||||
@@ -150,6 +153,7 @@ export default function DocumentsPage() {
|
||||
ExtendedDocumentStatus.INBOX,
|
||||
ExtendedDocumentStatus.PENDING,
|
||||
ExtendedDocumentStatus.COMPLETED,
|
||||
ExtendedDocumentStatus.CANCELLED,
|
||||
ExtendedDocumentStatus.DRAFT,
|
||||
ExtendedDocumentStatus.ALL,
|
||||
]
|
||||
@@ -227,6 +231,7 @@ export default function DocumentsPage() {
|
||||
selectedCount={selectedEnvelopeIds.length}
|
||||
onMoveClick={() => setIsBulkMoveDialogOpen(true)}
|
||||
onDeleteClick={() => setIsBulkDeleteDialogOpen(true)}
|
||||
onCancelClick={() => setIsBulkCancelDialogOpen(true)}
|
||||
onClearSelection={() => setRowSelection({})}
|
||||
/>
|
||||
|
||||
@@ -246,6 +251,13 @@ export default function DocumentsPage() {
|
||||
onOpenChange={setIsBulkDeleteDialogOpen}
|
||||
onSuccess={() => setRowSelection({})}
|
||||
/>
|
||||
|
||||
<EnvelopesBulkCancelDialog
|
||||
envelopeIds={selectedEnvelopeIds}
|
||||
open={isBulkCancelDialogOpen}
|
||||
onOpenChange={setIsBulkCancelDialogOpen}
|
||||
onSuccess={() => setRowSelection({})}
|
||||
/>
|
||||
</div>
|
||||
</EnvelopeDropZoneWrapper>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user