Allow edition of some document fields
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
17
apps/console/src/components/form/DocumentTypeOptions.tsx
Normal file
17
apps/console/src/components/form/DocumentTypeOptions.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { Option } from "@probo/ui";
|
||||
import { documentTypes, getDocumentTypeLabel } from "@probo/helpers";
|
||||
|
||||
export function DocumentTypeOptions() {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
return (
|
||||
<>
|
||||
{documentTypes.map((type) => (
|
||||
<Option key={type} value={type}>
|
||||
{getDocumentTypeLabel(__, type)}
|
||||
</Option>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<92803a3585816e3db509c46a86d083e9>>
|
||||
* @generated SignedSource<<2a5e6cd48ca8a8fd7fe448c3a6190ccc>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,6 +9,7 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type AuditState = "COMPLETED" | "IN_PROGRESS" | "NOT_STARTED" | "OUTDATED" | "REJECTED";
|
||||
export type UpdateAuditInput = {
|
||||
id: string;
|
||||
@@ -25,6 +26,7 @@ export type TrustCenterAuditGraphUpdateMutation$data = {
|
||||
readonly audit: {
|
||||
readonly id: string;
|
||||
readonly showOnTrustCenter: boolean;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterAuditsCardFragment">;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -43,55 +45,62 @@ var v0 = [
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UpdateAuditPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateAudit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Audit",
|
||||
"kind": "LinkedField",
|
||||
"name": "audit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "showOnTrustCenter",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
];
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "showOnTrustCenter",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "TrustCenterAuditGraphUpdateMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": "UpdateAuditPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateAudit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Audit",
|
||||
"kind": "LinkedField",
|
||||
"name": "audit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "TrustCenterAuditsCardFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
@@ -100,19 +109,91 @@ return {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "TrustCenterAuditGraphUpdateMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": "UpdateAuditPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateAudit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Audit",
|
||||
"kind": "LinkedField",
|
||||
"name": "audit",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "validFrom",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "validUntil",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "state",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "1ecc930abe6daebb184b1e55ccebc65c",
|
||||
"cacheID": "9cb78f25506e1a67b5f29d4f742f8773",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterAuditGraphUpdateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterAuditGraphUpdateMutation(\n $input: UpdateAuditInput!\n) {\n updateAudit(input: $input) {\n audit {\n id\n showOnTrustCenter\n }\n }\n}\n"
|
||||
"text": "mutation TrustCenterAuditGraphUpdateMutation(\n $input: UpdateAuditInput!\n) {\n updateAudit(input: $input) {\n audit {\n id\n showOnTrustCenter\n ...TrustCenterAuditsCardFragment\n }\n }\n}\n\nfragment TrustCenterAuditsCardFragment on Audit {\n id\n framework {\n name\n id\n }\n validFrom\n validUntil\n state\n showOnTrustCenter\n createdAt\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "ebf90264b72bb993d60f48d1d3fc4fb7";
|
||||
(node as any).hash = "1e92374989ecf8f439d069eb003e4e4e";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<012c4e605372a38efef4780c63d40888>>
|
||||
* @generated SignedSource<<be30aebdf9a7304cd154284fa9f6b207>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,6 +9,7 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type VendorCategory = "ANALYTICS" | "CLOUD_MONITORING" | "CLOUD_PROVIDER" | "COLLABORATION" | "CUSTOMER_SUPPORT" | "DATA_STORAGE_AND_PROCESSING" | "DOCUMENT_MANAGEMENT" | "EMPLOYEE_MANAGEMENT" | "ENGINEERING" | "FINANCE" | "IDENTITY_PROVIDER" | "IT" | "MARKETING" | "OFFICE_OPERATIONS" | "OTHER" | "PASSWORD_MANAGEMENT" | "PRODUCT_AND_DESIGN" | "PROFESSIONAL_SERVICES" | "RECRUITING" | "SALES" | "SECURITY" | "VERSION_CONTROL";
|
||||
export type UpdateVendorInput = {
|
||||
businessAssociateAgreementUrl?: string | null | undefined;
|
||||
@@ -40,6 +41,7 @@ export type TrustCenterVendorGraphUpdateMutation$data = {
|
||||
readonly vendor: {
|
||||
readonly id: string;
|
||||
readonly showOnTrustCenter: boolean;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterVendorsCardFragment">;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -58,55 +60,62 @@ var v0 = [
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UpdateVendorPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateVendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Vendor",
|
||||
"kind": "LinkedField",
|
||||
"name": "vendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "showOnTrustCenter",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
];
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "showOnTrustCenter",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "TrustCenterVendorGraphUpdateMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": "UpdateVendorPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateVendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Vendor",
|
||||
"kind": "LinkedField",
|
||||
"name": "vendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "TrustCenterVendorsCardFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
@@ -115,19 +124,72 @@ return {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "TrustCenterVendorGraphUpdateMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": "UpdateVendorPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateVendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Vendor",
|
||||
"kind": "LinkedField",
|
||||
"name": "vendor",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "category",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "44e483af96833ea9efb1567fa5983282",
|
||||
"cacheID": "92823eef2e21ea731d8f37dbf9cd5da3",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterVendorGraphUpdateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterVendorGraphUpdateMutation(\n $input: UpdateVendorInput!\n) {\n updateVendor(input: $input) {\n vendor {\n id\n showOnTrustCenter\n }\n }\n}\n"
|
||||
"text": "mutation TrustCenterVendorGraphUpdateMutation(\n $input: UpdateVendorInput!\n) {\n updateVendor(input: $input) {\n vendor {\n id\n showOnTrustCenter\n ...TrustCenterVendorsCardFragment\n }\n }\n}\n\nfragment TrustCenterVendorsCardFragment on Vendor {\n id\n name\n category\n description\n showOnTrustCenter\n createdAt\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "e561918e67c08f1e3fae85dfb04591d1";
|
||||
(node as any).hash = "2b4395821fcfbd30bb06448db5429289";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -18,6 +18,7 @@ import type {
|
||||
DocumentDetailPageDocumentFragment$key,
|
||||
} from "./__generated__/DocumentDetailPageDocumentFragment.graphql";
|
||||
import type { DocumentDetailPageExportPDFMutation } from "./__generated__/DocumentDetailPageExportPDFMutation.graphql";
|
||||
import type { DocumentDetailPageUpdateMutation } from "./__generated__/DocumentDetailPageUpdateMutation.graphql";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import {
|
||||
ActionDropdown,
|
||||
@@ -34,6 +35,8 @@ import {
|
||||
IconClock,
|
||||
IconPencil,
|
||||
IconTrashCan,
|
||||
IconCrossLargeX,
|
||||
Input,
|
||||
PageHeader,
|
||||
PropertyRow,
|
||||
TabBadge,
|
||||
@@ -43,7 +46,7 @@ import {
|
||||
} from "@probo/ui";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { getDocumentTypeLabel, sprintf } from "@probo/helpers";
|
||||
import { getDocumentTypeLabel, sprintf, documentTypes } from "@probo/helpers";
|
||||
import {
|
||||
Link,
|
||||
Outlet,
|
||||
@@ -52,9 +55,14 @@ import {
|
||||
useParams,
|
||||
} from "react-router";
|
||||
import UpdateVersionDialog from "./dialogs/UpdateVersionDialog";
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import type { NodeOf } from "/types.ts";
|
||||
import clsx from "clsx";
|
||||
import { PeopleSelectField } from "/components/form/PeopleSelectField";
|
||||
import { ControlledField } from "/components/form/ControlledField";
|
||||
import { DocumentTypeOptions } from "/components/form/DocumentTypeOptions";
|
||||
import { z } from "zod";
|
||||
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<DocumentGraphNodeQuery>;
|
||||
@@ -128,6 +136,28 @@ const exportDocumentVersionPDFMutation = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
const updateDocumentMutation = graphql`
|
||||
mutation DocumentDetailPageUpdateMutation($input: UpdateDocumentInput!) {
|
||||
updateDocument(input: $input) {
|
||||
document {
|
||||
id
|
||||
title
|
||||
documentType
|
||||
owner {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const documentUpdateSchema = z.object({
|
||||
title: z.string().min(1, "Title is required").max(255),
|
||||
ownerId: z.string().min(1, "Owner is required"),
|
||||
documentType: z.enum(documentTypes),
|
||||
});
|
||||
|
||||
export default function DocumentDetailPage(props: Props) {
|
||||
const { versionId } = useParams<{ versionId?: string }>();
|
||||
const node = usePreloadedQuery(documentNodeQuery, props.queryRef).node;
|
||||
@@ -138,6 +168,10 @@ export default function DocumentDetailPage(props: Props) {
|
||||
const { __, dateFormat } = useTranslate();
|
||||
const organizationId = useOrganizationId();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isEditingTitle, setIsEditingTitle] = useState(false);
|
||||
const [isEditingOwner, setIsEditingOwner] = useState(false);
|
||||
const [isEditingType, setIsEditingType] = useState(false);
|
||||
const versions = document.versions.edges.map((edge) => edge.node);
|
||||
const currentVersion =
|
||||
document.versions.edges.find((v) => v.node.id === versionId)?.node ??
|
||||
@@ -161,10 +195,73 @@ export default function DocumentDetailPage(props: Props) {
|
||||
errorMessage: __("Failed to generate PDF. Please try again."),
|
||||
}
|
||||
);
|
||||
const [updateDocument, isUpdatingDocument] = useMutationWithToasts<DocumentDetailPageUpdateMutation>(
|
||||
updateDocumentMutation,
|
||||
{
|
||||
successMessage: __("Document updated successfully."),
|
||||
errorMessage: __("Failed to update document. Please try again."),
|
||||
}
|
||||
);
|
||||
const versionConnectionId = document.versions.__id;
|
||||
|
||||
const { register, control, handleSubmit, reset } = useFormWithSchema(documentUpdateSchema, {
|
||||
defaultValues: {
|
||||
title: document.title,
|
||||
ownerId: document.owner?.id || "",
|
||||
documentType: document.documentType,
|
||||
},
|
||||
});
|
||||
|
||||
usePageTitle(document.title);
|
||||
|
||||
const handleUpdateTitle = (data: { title: string }) => {
|
||||
updateDocument({
|
||||
variables: {
|
||||
input: {
|
||||
id: document.id,
|
||||
title: data.title,
|
||||
},
|
||||
},
|
||||
onSuccess: () => {
|
||||
setIsEditingTitle(false);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdateOwner = (data: { ownerId: string }) => {
|
||||
updateDocument({
|
||||
variables: {
|
||||
input: {
|
||||
id: document.id,
|
||||
ownerId: data.ownerId,
|
||||
},
|
||||
},
|
||||
onSuccess: () => {
|
||||
setIsEditingOwner(false);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdateDocumentType = (data: { documentType: typeof documentTypes[number] }) => {
|
||||
updateDocument({
|
||||
variables: {
|
||||
input: {
|
||||
id: document.id,
|
||||
documentType: data.documentType,
|
||||
},
|
||||
},
|
||||
onSuccess: () => {
|
||||
setIsEditingType(false);
|
||||
loadQuery(
|
||||
props.queryRef.environment,
|
||||
documentNodeQuery,
|
||||
props.queryRef.variables,
|
||||
{ fetchPolicy: "network-only" }
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handlePublish = () => {
|
||||
publishDocumentVersion({
|
||||
variables: {
|
||||
@@ -313,7 +410,52 @@ export default function DocumentDetailPage(props: Props) {
|
||||
</ActionDropdown>
|
||||
</div>
|
||||
</div>
|
||||
<PageHeader title={document.title} />
|
||||
<PageHeader
|
||||
title={
|
||||
isEditingTitle ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
{...register("title")}
|
||||
variant="title"
|
||||
className="flex-1"
|
||||
autoFocus
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Escape") {
|
||||
setIsEditingTitle(false);
|
||||
reset();
|
||||
}
|
||||
if (e.key === "Enter") {
|
||||
handleSubmit(handleUpdateTitle)();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconCheckmark1}
|
||||
onClick={handleSubmit(handleUpdateTitle)}
|
||||
disabled={isUpdatingDocument}
|
||||
/>
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconCrossLargeX}
|
||||
onClick={() => {
|
||||
setIsEditingTitle(false);
|
||||
reset();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{document.title}</span>
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconPencil}
|
||||
onClick={() => setIsEditingTitle(true)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<Tabs>
|
||||
<TabLink to={`${urlPrefix}/description`}>{__("Description")}</TabLink>
|
||||
@@ -336,15 +478,55 @@ export default function DocumentDetailPage(props: Props) {
|
||||
{__("Properties")}
|
||||
</div>
|
||||
<PropertyRow label={__("Owner")}>
|
||||
<Badge variant="highlight" size="md" className="gap-2">
|
||||
<Avatar name={document.owner?.fullName ?? ""} />
|
||||
{document.owner?.fullName}
|
||||
</Badge>
|
||||
{isEditingOwner ? (
|
||||
<EditablePropertyContent
|
||||
onSave={handleSubmit(handleUpdateOwner)}
|
||||
onCancel={() => {
|
||||
setIsEditingOwner(false);
|
||||
reset();
|
||||
}}
|
||||
disabled={isUpdatingDocument}
|
||||
>
|
||||
<PeopleSelectField
|
||||
name="ownerId"
|
||||
control={control}
|
||||
organizationId={organizationId}
|
||||
/>
|
||||
</EditablePropertyContent>
|
||||
) : (
|
||||
<ReadOnlyPropertyContent onEdit={() => setIsEditingOwner(true)}>
|
||||
<Badge variant="highlight" size="md" className="gap-2">
|
||||
<Avatar name={document.owner?.fullName ?? ""} />
|
||||
{document.owner?.fullName}
|
||||
</Badge>
|
||||
</ReadOnlyPropertyContent>
|
||||
)}
|
||||
</PropertyRow>
|
||||
<PropertyRow label={__("Type")}>
|
||||
<div className="text-sm text-txt-secondary">
|
||||
{getDocumentTypeLabel(__, document.documentType)}
|
||||
</div>
|
||||
{isEditingType ? (
|
||||
<EditablePropertyContent
|
||||
onSave={handleSubmit(handleUpdateDocumentType)}
|
||||
onCancel={() => {
|
||||
setIsEditingType(false);
|
||||
reset();
|
||||
}}
|
||||
disabled={isUpdatingDocument}
|
||||
>
|
||||
<ControlledField
|
||||
name="documentType"
|
||||
control={control}
|
||||
type="select"
|
||||
>
|
||||
<DocumentTypeOptions />
|
||||
</ControlledField>
|
||||
</EditablePropertyContent>
|
||||
) : (
|
||||
<ReadOnlyPropertyContent onEdit={() => setIsEditingType(true)}>
|
||||
<div className="text-sm text-txt-secondary">
|
||||
{getDocumentTypeLabel(__, document.documentType)}
|
||||
</div>
|
||||
</ReadOnlyPropertyContent>
|
||||
)}
|
||||
</PropertyRow>
|
||||
<PropertyRow label={__("Status")}>
|
||||
<Badge
|
||||
@@ -379,6 +561,54 @@ export default function DocumentDetailPage(props: Props) {
|
||||
|
||||
type Version = NodeOf<DocumentDetailPageDocumentFragment$data["versions"]>;
|
||||
|
||||
function EditablePropertyContent({
|
||||
children,
|
||||
onSave,
|
||||
onCancel,
|
||||
disabled,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
onSave: () => void;
|
||||
onCancel: () => void;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1">{children}</div>
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconCheckmark1}
|
||||
onClick={onSave}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconCrossLargeX}
|
||||
onClick={onCancel}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ReadOnlyPropertyContent({
|
||||
children,
|
||||
onEdit,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
onEdit: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
{children}
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconPencil}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function VersionItem({
|
||||
document,
|
||||
version,
|
||||
|
||||
144
apps/console/src/pages/organizations/documents/__generated__/DocumentDetailPageUpdateMutation.graphql.ts
generated
Normal file
144
apps/console/src/pages/organizations/documents/__generated__/DocumentDetailPageUpdateMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @generated SignedSource<<78eb861601ac1babc8f02dc877d9e1cf>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY";
|
||||
export type UpdateDocumentInput = {
|
||||
content?: string | null | undefined;
|
||||
createdBy?: string | null | undefined;
|
||||
documentType?: DocumentType | null | undefined;
|
||||
id: string;
|
||||
ownerId?: string | null | undefined;
|
||||
showOnTrustCenter?: boolean | null | undefined;
|
||||
title?: string | null | undefined;
|
||||
};
|
||||
export type DocumentDetailPageUpdateMutation$variables = {
|
||||
input: UpdateDocumentInput;
|
||||
};
|
||||
export type DocumentDetailPageUpdateMutation$data = {
|
||||
readonly updateDocument: {
|
||||
readonly document: {
|
||||
readonly id: string;
|
||||
readonly owner: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
readonly title: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type DocumentDetailPageUpdateMutation = {
|
||||
response: DocumentDetailPageUpdateMutation$data;
|
||||
variables: DocumentDetailPageUpdateMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v2 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UpdateDocumentPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateDocument",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Document",
|
||||
"kind": "LinkedField",
|
||||
"name": "document",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "title",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "People",
|
||||
"kind": "LinkedField",
|
||||
"name": "owner",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentDetailPageUpdateMutation",
|
||||
"selections": (v2/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "DocumentDetailPageUpdateMutation",
|
||||
"selections": (v2/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "bb375479bf3446cccb49753a27fb6bcb",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentDetailPageUpdateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation DocumentDetailPageUpdateMutation(\n $input: UpdateDocumentInput!\n) {\n updateDocument(input: $input) {\n document {\n id\n title\n owner {\n id\n fullName\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "9d204fe6a01448bd05d68699c06d18f9";
|
||||
|
||||
export default node;
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
PropertyRow,
|
||||
Textarea,
|
||||
useDialogRef,
|
||||
Option,
|
||||
} from "@probo/ui";
|
||||
import { type ReactNode } from "react";
|
||||
import { graphql } from "relay-runtime";
|
||||
@@ -21,6 +20,7 @@ import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { PeopleSelectField } from "/components/form/PeopleSelectField";
|
||||
import type { CreateDocumentDialogMutation } from "./__generated__/CreateDocumentDialogMutation.graphql";
|
||||
import { ControlledField } from "/components/form/ControlledField";
|
||||
import { DocumentTypeOptions } from "/components/form/DocumentTypeOptions";
|
||||
|
||||
type Props = {
|
||||
trigger?: ReactNode;
|
||||
@@ -121,15 +121,7 @@ export function CreateDocumentDialog({ trigger, connection }: Props) {
|
||||
name="documentType"
|
||||
type="select"
|
||||
>
|
||||
<Option value="POLICY">
|
||||
{__("Policy")}
|
||||
</Option>
|
||||
<Option value="ISMS">
|
||||
{__("ISMS")}
|
||||
</Option>
|
||||
<Option value="OTHER">
|
||||
{__("Other")}
|
||||
</Option>
|
||||
<DocumentTypeOptions />
|
||||
</ControlledField>
|
||||
</PropertyRow>
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @generated SignedSource<<5b79ea2de8e0c11b167b479ef72558c6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY";
|
||||
export type UpdateDocumentInput = {
|
||||
content?: string | null | undefined;
|
||||
createdBy?: string | null | undefined;
|
||||
documentType?: DocumentType | null | undefined;
|
||||
id: string;
|
||||
ownerId?: string | null | undefined;
|
||||
showOnTrustCenter?: boolean | null | undefined;
|
||||
title?: string | null | undefined;
|
||||
};
|
||||
export type UpdateDocumentDialogMutation$variables = {
|
||||
input: UpdateDocumentInput;
|
||||
};
|
||||
export type UpdateDocumentDialogMutation$data = {
|
||||
readonly updateDocument: {
|
||||
readonly document: {
|
||||
readonly id: string;
|
||||
readonly owner: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
readonly title: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type UpdateDocumentDialogMutation = {
|
||||
response: UpdateDocumentDialogMutation$data;
|
||||
variables: UpdateDocumentDialogMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v2 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UpdateDocumentPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateDocument",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Document",
|
||||
"kind": "LinkedField",
|
||||
"name": "document",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "title",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "People",
|
||||
"kind": "LinkedField",
|
||||
"name": "owner",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "UpdateDocumentDialogMutation",
|
||||
"selections": (v2/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "UpdateDocumentDialogMutation",
|
||||
"selections": (v2/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "27831214e4f4c0a988553abccf99d547",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "UpdateDocumentDialogMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation UpdateDocumentDialogMutation(\n $input: UpdateDocumentInput!\n) {\n updateDocument(input: $input) {\n document {\n id\n title\n owner {\n id\n fullName\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "ea3902438d59438b49c5d34edadbe5e4";
|
||||
|
||||
export default node;
|
||||
Reference in New Issue
Block a user