diff --git a/apps/console/src/pages/organizations/documents/tabs/DocumentSignaturesTab.tsx b/apps/console/src/pages/organizations/documents/tabs/DocumentSignaturesTab.tsx index 7f61fd7b7..ccd14a9ff 100644 --- a/apps/console/src/pages/organizations/documents/tabs/DocumentSignaturesTab.tsx +++ b/apps/console/src/pages/organizations/documents/tabs/DocumentSignaturesTab.tsx @@ -8,7 +8,7 @@ import { Spinner, } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; -import { Suspense, useState, useEffect } from "react"; +import { Suspense, useState, useEffect, useRef } from "react"; import type { ItemOf, NodeOf } from "/types"; import { graphql, useFragment, useRefetchableFragment } from "react-relay"; import { usePeople } from "/hooks/graph/PeopleGraph.ts"; @@ -19,6 +19,7 @@ import type { DocumentDetailPageDocumentFragment$data } from "../__generated__/D import { useOutletContext } from "react-router"; import type { DocumentSignaturesTab_signature$key } from "/pages/organizations/documents/tabs/__generated__/DocumentSignaturesTab_signature.graphql.ts"; import type { DocumentSignaturesTab_version$key } from "/pages/organizations/documents/tabs/__generated__/DocumentSignaturesTab_version.graphql.ts"; +import type { DocumentSignaturesTabRefetchQuery } from "./__generated__/DocumentSignaturesTabRefetchQuery.graphql"; type Version = NodeOf; @@ -33,7 +34,10 @@ const versionFragment = graphql` id status signatures(first: $count, after: $cursor, filter: $signatureFilter) - @connection(key: "DocumentSignaturesTab_signatures", filters: ["filter"]) { + @connection( + key: "DocumentSignaturesTab_signatures" + filters: ["filter"] + ) { __id edges { node { @@ -54,7 +58,9 @@ const versionFragment = graphql` type SignatureState = "REQUESTED" | "SIGNED"; export default function DocumentSignaturesTab() { - const { version: versionFromContext } = useOutletContext<{ version: Version }>(); + const { version: versionFromContext } = useOutletContext<{ + version: Version; + }>(); const [selectedStates, setSelectedStates] = useState([]); const { __ } = useTranslate(); @@ -64,9 +70,7 @@ export default function DocumentSignaturesTab() { const toggleState = (state: SignatureState) => { setSelectedStates((prev) => - prev.includes(state) - ? prev.filter((s) => s !== state) - : [...prev, state] + prev.includes(state) ? prev.filter((s) => s !== state) : [...prev, state] ); }; @@ -102,29 +106,40 @@ export default function DocumentSignaturesTab() { }> - + ); } -function SignatureList(props: { version: Version; selectedStates: SignatureState[] }) { - const [version, refetch] = useRefetchableFragment( - versionFragment, - props.version - ); +function SignatureList(props: { + version: Version; + selectedStates: SignatureState[]; +}) { + const [version, refetch] = useRefetchableFragment< + DocumentSignaturesTabRefetchQuery, + DocumentSignaturesTab_version$key + >(versionFragment, props.version); const signatures = version.signatures?.edges?.map((edge) => edge.node) ?? []; const { __ } = useTranslate(); const signatureMap = new Map(signatures.map((s) => [s.signedBy.id, s])); const organizationId = useOrganizationId(); const people = usePeople(organizationId, { excludeContractEnded: true }); const signable = version.status === "PUBLISHED"; + const isFirstRender = useRef(true); - // Refetch when filter changes + // Refetch when filter changes (skip initial render) useEffect(() => { - const filter = props.selectedStates.length > 0 - ? { states: props.selectedStates } - : null; + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + const filter = + props.selectedStates.length > 0 ? { states: props.selectedStates } : null; refetch({ signatureFilter: filter }); }, [JSON.stringify(props.selectedStates), refetch]); @@ -146,9 +161,10 @@ function SignatureList(props: { version: Version; selectedStates: SignatureState } // When a filter is active, only show people who have signatures in the filtered results - const filteredPeople = props.selectedStates.length > 0 - ? people.filter((p) => signatureMap.has(p.id)) - : people; + const filteredPeople = + props.selectedStates.length > 0 + ? people.filter((p) => signatureMap.has(p.id)) + : people; if (filteredPeople.length === 0 && props.selectedStates.length > 0) { return ( @@ -174,9 +190,6 @@ function SignatureList(props: { version: Version; selectedStates: SignatureState ); } -/** - * Fragments - */ const signatureFragment = graphql` fragment DocumentSignaturesTab_signature on DocumentVersionSignature { id @@ -237,14 +250,14 @@ function SignatureItem(props: { { successMessage: __("Signature request sent successfully"), errorMessage: __("Failed to send signature request"), - }, + } ); const [cancelSignature, isCancellingSignature] = useMutationWithToasts( cancelSignatureMutation, { successMessage: __("Request cancelled successfully"), errorMessage: __("Failed to cancel signature request"), - }, + } ); // No signature request for this user @@ -304,8 +317,8 @@ function SignatureItem(props: { {sprintf( label, dateTimeFormat( - isSigned ? signature.signedAt : signature.requestedAt, - ), + isSigned ? signature.signedAt : signature.requestedAt + ) )} diff --git a/pkg/coredata/document_version_signature_state.go b/pkg/coredata/document_version_signature_state.go index 67e835da9..10e07b56b 100644 --- a/pkg/coredata/document_version_signature_state.go +++ b/pkg/coredata/document_version_signature_state.go @@ -78,6 +78,10 @@ func (pvs DocumentVersionSignatureState) Value() (driver.Value, error) { } func (states DocumentVersionSignatureStates) Value() (driver.Value, error) { + if states == nil || len(states) == 0 { + return nil, nil + } + var result strings.Builder result.WriteString("{") for i, state := range states {