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 { SortableTable, SortableTh } from "/components/SortableTable";
|
||||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts.ts";
|
import { useMutationWithToasts } from "/hooks/useMutationWithToasts.ts";
|
||||||
import { usePeople } from "/hooks/graph/PeopleGraph.ts";
|
import { usePeople } from "/hooks/graph/PeopleGraph.ts";
|
||||||
|
import { PublishDocumentsDialog } from "./dialogs/PublishDocumentsDialog.tsx";
|
||||||
|
|
||||||
const documentsFragment = graphql`
|
const documentsFragment = graphql`
|
||||||
fragment DocumentsPageListFragment on Organization
|
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`
|
const documentsSignatureMutation = graphql`
|
||||||
mutation DocumentsPageSignatureMutation(
|
mutation DocumentsPageSignatureMutation($input: BulkRequestSignaturesInput!) {
|
||||||
$input: BulkRequestSignaturesInput!
|
|
||||||
) {
|
|
||||||
bulkRequestSignatures(input: $input) {
|
bulkRequestSignatures(input: $input) {
|
||||||
documentVersionSignatureEdges {
|
documentVersionSignatureEdges {
|
||||||
node {
|
node {
|
||||||
@@ -112,11 +96,11 @@ export default function DocumentsPage(props: Props) {
|
|||||||
|
|
||||||
const organization = usePreloadedQuery(
|
const organization = usePreloadedQuery(
|
||||||
documentsQuery,
|
documentsQuery,
|
||||||
props.queryRef,
|
props.queryRef
|
||||||
).organization;
|
).organization;
|
||||||
const pagination = usePaginationFragment(
|
const pagination = usePaginationFragment(
|
||||||
documentsFragment,
|
documentsFragment,
|
||||||
organization as DocumentsPageListFragment$key,
|
organization as DocumentsPageListFragment$key
|
||||||
);
|
);
|
||||||
|
|
||||||
const documents = pagination.data.documents.edges.map((edge) => edge.node);
|
const documents = pagination.data.documents.edges.map((edge) => edge.node);
|
||||||
@@ -124,15 +108,13 @@ export default function DocumentsPage(props: Props) {
|
|||||||
const [sendSigningNotifications] = useSendSigningNotificationsMutation();
|
const [sendSigningNotifications] = useSendSigningNotificationsMutation();
|
||||||
const { list: selection, toggle, clear, reset } = useList<string>([]);
|
const { list: selection, toggle, clear, reset } = useList<string>([]);
|
||||||
|
|
||||||
const [publishMutation, isPublishing] = useMutationWithToasts(documentsPublishMutation, {
|
const [signatureMutation, isSigning] = useMutationWithToasts(
|
||||||
successMessage: sprintf(__("%s documents published"), selection.length),
|
documentsSignatureMutation,
|
||||||
errorMessage: sprintf(__("Failed to publish %s documents"), selection.length),
|
{
|
||||||
})
|
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);
|
const people = usePeople(organization.id);
|
||||||
usePageTitle(__("Documents"));
|
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 () => {
|
const requestSignatures = async () => {
|
||||||
await signatureMutation({
|
await signatureMutation({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
documentIds: selection,
|
documentIds: selection,
|
||||||
signatoryIds: people.map(p => p.id),
|
signatoryIds: people.map((p) => p.id),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
clear();
|
clear();
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
@@ -221,8 +191,18 @@ export default function DocumentsPage(props: Props) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button icon={IconCheckmark1} onClick={publish} disabled={isPublishing}>{__("Publish")}</Button>
|
<PublishDocumentsDialog
|
||||||
<Button variant="secondary" icon={IconSignature} onClick={requestSignatures} disabled={isSigning}>
|
documentIds={selection}
|
||||||
|
onSave={clear}
|
||||||
|
>
|
||||||
|
<Button icon={IconCheckmark1}>{__("Publish")}</Button>
|
||||||
|
</PublishDocumentsDialog>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
icon={IconSignature}
|
||||||
|
onClick={requestSignatures}
|
||||||
|
disabled={isSigning}
|
||||||
|
>
|
||||||
{__("Request signature")}
|
{__("Request signature")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -293,14 +273,14 @@ function DocumentRow({
|
|||||||
}) {
|
}) {
|
||||||
const document = useFragment<DocumentsPageRowFragment$key>(
|
const document = useFragment<DocumentsPageRowFragment$key>(
|
||||||
rowFragment,
|
rowFragment,
|
||||||
documentKey,
|
documentKey
|
||||||
);
|
);
|
||||||
const lastVersion = document.versions.edges[0].node;
|
const lastVersion = document.versions.edges[0].node;
|
||||||
const isDraft = lastVersion.status === "DRAFT";
|
const isDraft = lastVersion.status === "DRAFT";
|
||||||
const { __, dateFormat } = useTranslate();
|
const { __, dateFormat } = useTranslate();
|
||||||
const signatures = lastVersion.signatures.edges.map((edge) => edge.node);
|
const signatures = lastVersion.signatures.edges.map((edge) => edge.node);
|
||||||
const signedCount = signatures.filter(
|
const signedCount = signatures.filter(
|
||||||
(signature) => signature.state === "SIGNED",
|
(signature) => signature.state === "SIGNED"
|
||||||
).length;
|
).length;
|
||||||
const [deleteDocument] = useDeleteDocumentMutation();
|
const [deleteDocument] = useDeleteDocumentMutation();
|
||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
@@ -317,11 +297,11 @@ function DocumentRow({
|
|||||||
{
|
{
|
||||||
message: sprintf(
|
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
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -14,10 +14,10 @@ export type BulkPublishDocumentVersionsInput = {
|
|||||||
changelog: string;
|
changelog: string;
|
||||||
documentIds: ReadonlyArray<string>;
|
documentIds: ReadonlyArray<string>;
|
||||||
};
|
};
|
||||||
export type DocumentsPagePublishMutation$variables = {
|
export type PublishDocumentsDialogMutation$variables = {
|
||||||
input: BulkPublishDocumentVersionsInput;
|
input: BulkPublishDocumentVersionsInput;
|
||||||
};
|
};
|
||||||
export type DocumentsPagePublishMutation$data = {
|
export type PublishDocumentsDialogMutation$data = {
|
||||||
readonly bulkPublishDocumentVersions: {
|
readonly bulkPublishDocumentVersions: {
|
||||||
readonly documentEdges: ReadonlyArray<{
|
readonly documentEdges: ReadonlyArray<{
|
||||||
readonly node: {
|
readonly node: {
|
||||||
@@ -27,9 +27,9 @@ export type DocumentsPagePublishMutation$data = {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type DocumentsPagePublishMutation = {
|
export type PublishDocumentsDialogMutation = {
|
||||||
response: DocumentsPagePublishMutation$data;
|
response: PublishDocumentsDialogMutation$data;
|
||||||
variables: DocumentsPagePublishMutation$variables;
|
variables: PublishDocumentsDialogMutation$variables;
|
||||||
};
|
};
|
||||||
|
|
||||||
const node: ConcreteRequest = (function(){
|
const node: ConcreteRequest = (function(){
|
||||||
@@ -59,7 +59,7 @@ return {
|
|||||||
"argumentDefinitions": (v0/*: any*/),
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
"kind": "Fragment",
|
"kind": "Fragment",
|
||||||
"metadata": null,
|
"metadata": null,
|
||||||
"name": "DocumentsPagePublishMutation",
|
"name": "PublishDocumentsDialogMutation",
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
@@ -108,7 +108,7 @@ return {
|
|||||||
"operation": {
|
"operation": {
|
||||||
"argumentDefinitions": (v0/*: any*/),
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
"kind": "Operation",
|
"kind": "Operation",
|
||||||
"name": "DocumentsPagePublishMutation",
|
"name": "PublishDocumentsDialogMutation",
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
@@ -288,16 +288,16 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "7cd29425535c6d30017201fee219447b",
|
"cacheID": "bcc8589071b241670107f00c127f70d0",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "DocumentsPagePublishMutation",
|
"name": "PublishDocumentsDialogMutation",
|
||||||
"operationKind": "mutation",
|
"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;
|
export default node;
|
||||||
Reference in New Issue
Block a user