Add changelog dialog when bulk publishing
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
committed by
Sacha Al Himdani
parent
75656b1ae1
commit
8fd8319ad4
@@ -41,6 +41,7 @@ import type { DocumentsPageRowFragment$key } from "./__generated__/DocumentsPage
|
||||
import { SortableTable, SortableTh } from "/components/SortableTable";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts.ts";
|
||||
import { usePeople } from "/hooks/graph/PeopleGraph.ts";
|
||||
import { PublishDocumentsDialog } from "./dialogs/PublishDocumentsDialog.tsx";
|
||||
|
||||
const documentsFragment = graphql`
|
||||
fragment DocumentsPageListFragment on Organization
|
||||
@@ -73,25 +74,8 @@ const documentsFragment = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
const documentsPublishMutation = graphql`
|
||||
mutation DocumentsPagePublishMutation(
|
||||
$input: BulkPublishDocumentVersionsInput!
|
||||
) {
|
||||
bulkPublishDocumentVersions(input: $input) {
|
||||
documentEdges {
|
||||
node {
|
||||
id
|
||||
...DocumentsPageRowFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const documentsSignatureMutation = graphql`
|
||||
mutation DocumentsPageSignatureMutation(
|
||||
$input: BulkRequestSignaturesInput!
|
||||
) {
|
||||
mutation DocumentsPageSignatureMutation($input: BulkRequestSignaturesInput!) {
|
||||
bulkRequestSignatures(input: $input) {
|
||||
documentVersionSignatureEdges {
|
||||
node {
|
||||
@@ -112,11 +96,11 @@ export default function DocumentsPage(props: Props) {
|
||||
|
||||
const organization = usePreloadedQuery(
|
||||
documentsQuery,
|
||||
props.queryRef,
|
||||
props.queryRef
|
||||
).organization;
|
||||
const pagination = usePaginationFragment(
|
||||
documentsFragment,
|
||||
organization as DocumentsPageListFragment$key,
|
||||
organization as DocumentsPageListFragment$key
|
||||
);
|
||||
|
||||
const documents = pagination.data.documents.edges.map((edge) => edge.node);
|
||||
@@ -124,15 +108,13 @@ export default function DocumentsPage(props: Props) {
|
||||
const [sendSigningNotifications] = useSendSigningNotificationsMutation();
|
||||
const { list: selection, toggle, clear, reset } = useList<string>([]);
|
||||
|
||||
const [publishMutation, isPublishing] = useMutationWithToasts(documentsPublishMutation, {
|
||||
successMessage: sprintf(__("%s documents published"), selection.length),
|
||||
errorMessage: sprintf(__("Failed to publish %s documents"), selection.length),
|
||||
})
|
||||
|
||||
const [signatureMutation, isSigning] = useMutationWithToasts(documentsSignatureMutation, {
|
||||
successMessage: __("Signature request send successfully"),
|
||||
errorMessage: __("Failed to send signature requests"),
|
||||
})
|
||||
const [signatureMutation, isSigning] = useMutationWithToasts(
|
||||
documentsSignatureMutation,
|
||||
{
|
||||
successMessage: __("Signature request send successfully"),
|
||||
errorMessage: __("Failed to send signature requests"),
|
||||
}
|
||||
);
|
||||
const people = usePeople(organization.id);
|
||||
usePageTitle(__("Documents"));
|
||||
|
||||
@@ -144,29 +126,17 @@ export default function DocumentsPage(props: Props) {
|
||||
});
|
||||
};
|
||||
|
||||
const publish = async () => {
|
||||
await publishMutation({
|
||||
variables: {
|
||||
input: {
|
||||
documentIds: selection,
|
||||
changelog: '',
|
||||
}
|
||||
}
|
||||
})
|
||||
clear();
|
||||
}
|
||||
|
||||
const requestSignatures = async () => {
|
||||
await signatureMutation({
|
||||
variables: {
|
||||
input: {
|
||||
documentIds: selection,
|
||||
signatoryIds: people.map(p => p.id),
|
||||
}
|
||||
}
|
||||
})
|
||||
signatoryIds: people.map((p) => p.id),
|
||||
},
|
||||
},
|
||||
});
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -221,8 +191,18 @@ export default function DocumentsPage(props: Props) {
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button icon={IconCheckmark1} onClick={publish} disabled={isPublishing}>{__("Publish")}</Button>
|
||||
<Button variant="secondary" icon={IconSignature} onClick={requestSignatures} disabled={isSigning}>
|
||||
<PublishDocumentsDialog
|
||||
documentIds={selection}
|
||||
onSave={clear}
|
||||
>
|
||||
<Button icon={IconCheckmark1}>{__("Publish")}</Button>
|
||||
</PublishDocumentsDialog>
|
||||
<Button
|
||||
variant="secondary"
|
||||
icon={IconSignature}
|
||||
onClick={requestSignatures}
|
||||
disabled={isSigning}
|
||||
>
|
||||
{__("Request signature")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -293,14 +273,14 @@ function DocumentRow({
|
||||
}) {
|
||||
const document = useFragment<DocumentsPageRowFragment$key>(
|
||||
rowFragment,
|
||||
documentKey,
|
||||
documentKey
|
||||
);
|
||||
const lastVersion = document.versions.edges[0].node;
|
||||
const isDraft = lastVersion.status === "DRAFT";
|
||||
const { __, dateFormat } = useTranslate();
|
||||
const signatures = lastVersion.signatures.edges.map((edge) => edge.node);
|
||||
const signedCount = signatures.filter(
|
||||
(signature) => signature.state === "SIGNED",
|
||||
(signature) => signature.state === "SIGNED"
|
||||
).length;
|
||||
const [deleteDocument] = useDeleteDocumentMutation();
|
||||
const confirm = useConfirm();
|
||||
@@ -317,11 +297,11 @@ function DocumentRow({
|
||||
{
|
||||
message: sprintf(
|
||||
__(
|
||||
'This will permanently delete the document "%s". This action cannot be undone.',
|
||||
'This will permanently delete the document "%s". This action cannot be undone.'
|
||||
),
|
||||
document.title,
|
||||
document.title
|
||||
),
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
Field,
|
||||
useDialogRef,
|
||||
Breadcrumb,
|
||||
} from "@probo/ui";
|
||||
import { type ReactNode } from "react";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import z from "zod";
|
||||
import { useFormWithSchema } from "/hooks/useFormWithSchema.ts";
|
||||
import { graphql } from "relay-runtime";
|
||||
import { sprintf } from "@probo/helpers";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts.ts";
|
||||
|
||||
type Props = {
|
||||
documentIds: string[];
|
||||
children: ReactNode;
|
||||
onSave: () => void;
|
||||
};
|
||||
|
||||
const documentsPublishMutation = graphql`
|
||||
mutation PublishDocumentsDialogMutation(
|
||||
$input: BulkPublishDocumentVersionsInput!
|
||||
) {
|
||||
bulkPublishDocumentVersions(input: $input) {
|
||||
documentEdges {
|
||||
node {
|
||||
id
|
||||
...DocumentsPageRowFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const schema = z.object({
|
||||
changelog: z.string().min(1, "Changelog is required"),
|
||||
});
|
||||
|
||||
export function PublishDocumentsDialog({
|
||||
documentIds,
|
||||
children,
|
||||
onSave,
|
||||
}: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const dialogRef = useDialogRef();
|
||||
const {
|
||||
handleSubmit,
|
||||
register,
|
||||
formState: { isSubmitting, errors },
|
||||
} = useFormWithSchema(schema, {
|
||||
defaultValues: {
|
||||
changelog: "",
|
||||
},
|
||||
});
|
||||
const onSubmit = handleSubmit(async (data) => {
|
||||
await publishMutation({
|
||||
variables: {
|
||||
input: {
|
||||
documentIds,
|
||||
changelog: data.changelog,
|
||||
},
|
||||
},
|
||||
});
|
||||
dialogRef.current?.close();
|
||||
onSave();
|
||||
});
|
||||
|
||||
const [publishMutation] = useMutationWithToasts(documentsPublishMutation, {
|
||||
successMessage: sprintf(__("%s documents published"), documentIds.length),
|
||||
errorMessage: sprintf(
|
||||
__("Failed to publish %s documents"),
|
||||
documentIds.length
|
||||
),
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
className="max-w-xl"
|
||||
ref={dialogRef}
|
||||
trigger={children}
|
||||
title={<Breadcrumb items={[__("Documents"), __("Publish documents")]} />}
|
||||
>
|
||||
<form onSubmit={onSubmit}>
|
||||
<DialogContent padded>
|
||||
<Field
|
||||
id="changelog"
|
||||
aria-label={__("Changelog")}
|
||||
required
|
||||
variant="title"
|
||||
placeholder={__("Changelog")}
|
||||
{...register("changelog")}
|
||||
error={errors.changelog?.message}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{sprintf(__("Publish %s documents"), documentIds.length)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<ceff42181ddc76c55b97c976cfb1b697>>
|
||||
* @generated SignedSource<<2961ff4f50f912f350acab5b0a341042>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,10 +14,10 @@ export type BulkPublishDocumentVersionsInput = {
|
||||
changelog: string;
|
||||
documentIds: ReadonlyArray<string>;
|
||||
};
|
||||
export type DocumentsPagePublishMutation$variables = {
|
||||
export type PublishDocumentsDialogMutation$variables = {
|
||||
input: BulkPublishDocumentVersionsInput;
|
||||
};
|
||||
export type DocumentsPagePublishMutation$data = {
|
||||
export type PublishDocumentsDialogMutation$data = {
|
||||
readonly bulkPublishDocumentVersions: {
|
||||
readonly documentEdges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
@@ -27,9 +27,9 @@ export type DocumentsPagePublishMutation$data = {
|
||||
}>;
|
||||
};
|
||||
};
|
||||
export type DocumentsPagePublishMutation = {
|
||||
response: DocumentsPagePublishMutation$data;
|
||||
variables: DocumentsPagePublishMutation$variables;
|
||||
export type PublishDocumentsDialogMutation = {
|
||||
response: PublishDocumentsDialogMutation$data;
|
||||
variables: PublishDocumentsDialogMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
@@ -59,7 +59,7 @@ return {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentsPagePublishMutation",
|
||||
"name": "PublishDocumentsDialogMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
@@ -108,7 +108,7 @@ return {
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "DocumentsPagePublishMutation",
|
||||
"name": "PublishDocumentsDialogMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
@@ -288,16 +288,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "7cd29425535c6d30017201fee219447b",
|
||||
"cacheID": "bcc8589071b241670107f00c127f70d0",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentsPagePublishMutation",
|
||||
"name": "PublishDocumentsDialogMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation DocumentsPagePublishMutation(\n $input: BulkPublishDocumentVersionsInput!\n) {\n bulkPublishDocumentVersions(input: $input) {\n documentEdges {\n node {\n id\n ...DocumentsPageRowFragment\n }\n }\n }\n}\n\nfragment DocumentsPageRowFragment on Document {\n id\n title\n description\n documentType\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n}\n"
|
||||
"text": "mutation PublishDocumentsDialogMutation(\n $input: BulkPublishDocumentVersionsInput!\n) {\n bulkPublishDocumentVersions(input: $input) {\n documentEdges {\n node {\n id\n ...DocumentsPageRowFragment\n }\n }\n }\n}\n\nfragment DocumentsPageRowFragment on Document {\n id\n title\n description\n documentType\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "baea3e7dce61a42bf5bf2caefda998ea";
|
||||
(node as any).hash = "c9d699258bb8638d5474ab5e6b5e4585";
|
||||
|
||||
export default node;
|
||||
Reference in New Issue
Block a user