Move document type from document to document version
Follow the same pattern used for classification: document type now lives exclusively on DocumentVersion. A migration copies existing values from documents to their versions. The document filter uses a subquery on the latest version. All three API surfaces (GraphQL, MCP, CLI), resolvers, frontend, and e2e tests are updated accordingly. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -44,11 +44,11 @@ const linkedDocumentFragment = graphql`
|
|||||||
fragment LinkedDocumentsCardFragment on Document {
|
fragment LinkedDocumentsCardFragment on Document {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
documentType
|
|
||||||
versions(first: 1) {
|
versions(first: 1) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
|
documentType
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ function DocumentRow(props: {
|
|||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<DocumentTypeBadge type={document.documentType} />
|
<DocumentTypeBadge type={document.versions.edges[0].node.documentType} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<DocumentVersionBadge state={document.versions.edges[0].node.status} />
|
<DocumentVersionBadge state={document.versions.edges[0].node.status} />
|
||||||
|
|||||||
@@ -72,11 +72,17 @@ const documentsFragment = graphql`
|
|||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
versions(first: 1, orderBy: { field: CREATED_AT, direction: DESC }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
documentType
|
documentType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -187,7 +193,7 @@ function DocumentRow(props: RowProps) {
|
|||||||
onClick={() => onClick(props.document.id)}
|
onClick={() => onClick(props.document.id)}
|
||||||
>
|
>
|
||||||
{props.document.title}
|
{props.document.title}
|
||||||
<DocumentTypeBadge type={props.document.documentType} />
|
<DocumentTypeBadge type={props.document.versions.edges[0].node.documentType} />
|
||||||
<Button
|
<Button
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
className="ml-auto"
|
className="ml-auto"
|
||||||
|
|||||||
@@ -13,10 +13,7 @@
|
|||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
import type { TrustCenterDocumentAccessStatus } from "@probo/coredata";
|
import type { TrustCenterDocumentAccessStatus } from "@probo/coredata";
|
||||||
import {
|
import type { TrustCenterDocumentAccessInfo } from "@probo/helpers";
|
||||||
getTrustCenterDocumentAccessInfo,
|
|
||||||
type TrustCenterDocumentAccessInfo,
|
|
||||||
} from "@probo/helpers";
|
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -31,8 +28,9 @@ import {
|
|||||||
usePreloadedQuery,
|
usePreloadedQuery,
|
||||||
useQueryLoader,
|
useQueryLoader,
|
||||||
} from "react-relay";
|
} from "react-relay";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql, readInlineData } from "relay-runtime";
|
||||||
|
|
||||||
|
import type { CompliancePageAccessEditDialogDocumentAccessFragment$data, CompliancePageAccessEditDialogDocumentAccessFragment$key } from "#/__generated__/core/CompliancePageAccessEditDialogDocumentAccessFragment.graphql";
|
||||||
import type { CompliancePageAccessEditDialogQuery as CompliancePageAccessEditDialogQueryType } from "#/__generated__/core/CompliancePageAccessEditDialogQuery.graphql";
|
import type { CompliancePageAccessEditDialogQuery as CompliancePageAccessEditDialogQueryType } from "#/__generated__/core/CompliancePageAccessEditDialogQuery.graphql";
|
||||||
import type { CompliancePageAccessEditDialogUpdateMutation } from "#/__generated__/core/CompliancePageAccessEditDialogUpdateMutation.graphql";
|
import type { CompliancePageAccessEditDialogUpdateMutation } from "#/__generated__/core/CompliancePageAccessEditDialogUpdateMutation.graphql";
|
||||||
import type { CompliancePageAccessListItemFragment$data } from "#/__generated__/core/CompliancePageAccessListItemFragment.graphql";
|
import type { CompliancePageAccessListItemFragment$data } from "#/__generated__/core/CompliancePageAccessListItemFragment.graphql";
|
||||||
@@ -40,6 +38,90 @@ import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
|
|||||||
import { CompliancePageDocumentAccessList } from "#/pages/organizations/compliance-page/access/_components/CompliancePageDocumentAccessList";
|
import { CompliancePageDocumentAccessList } from "#/pages/organizations/compliance-page/access/_components/CompliancePageDocumentAccessList";
|
||||||
import { ElectronicSignatureSection } from "#/pages/organizations/compliance-page/access/_components/ElectronicSignatureSection";
|
import { ElectronicSignatureSection } from "#/pages/organizations/compliance-page/access/_components/ElectronicSignatureSection";
|
||||||
|
|
||||||
|
const documentAccessFragment = graphql`
|
||||||
|
fragment CompliancePageAccessEditDialogDocumentAccessFragment on TrustCenterDocumentAccess @inline {
|
||||||
|
id
|
||||||
|
status
|
||||||
|
document {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
versions(first: 1, orderBy: { field: CREATED_AT, direction: DESC }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
documentType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report {
|
||||||
|
id
|
||||||
|
filename
|
||||||
|
audit {
|
||||||
|
id
|
||||||
|
framework {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trustCenterFile {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
function getTrustCenterDocumentAccessInfo(
|
||||||
|
fragmentRef: CompliancePageAccessEditDialogDocumentAccessFragment$key,
|
||||||
|
__: (key: string) => string,
|
||||||
|
): TrustCenterDocumentAccessInfo {
|
||||||
|
const node = readInlineData(documentAccessFragment, fragmentRef);
|
||||||
|
return toDocumentAccessInfo(node, __);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toDocumentAccessInfo(
|
||||||
|
node: CompliancePageAccessEditDialogDocumentAccessFragment$data,
|
||||||
|
__: (key: string) => string,
|
||||||
|
): TrustCenterDocumentAccessInfo {
|
||||||
|
if (node.document) {
|
||||||
|
return {
|
||||||
|
persisted: node.id !== node.document.id,
|
||||||
|
variant: "info",
|
||||||
|
name: node.document.title,
|
||||||
|
type: "document",
|
||||||
|
typeLabel: __("Document"),
|
||||||
|
category: node.document.versions?.edges[0]?.node.documentType ?? "",
|
||||||
|
id: node.document.id,
|
||||||
|
status: node.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (node.report) {
|
||||||
|
return {
|
||||||
|
persisted: node.id !== node.report.id,
|
||||||
|
variant: "success",
|
||||||
|
name: node.report.filename,
|
||||||
|
type: "report",
|
||||||
|
typeLabel: __("Report"),
|
||||||
|
category: node.report.audit?.framework?.name ?? "",
|
||||||
|
id: node.report.id,
|
||||||
|
status: node.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (node.trustCenterFile) {
|
||||||
|
return {
|
||||||
|
persisted: node.id !== node.trustCenterFile.id,
|
||||||
|
variant: "highlight",
|
||||||
|
name: node.trustCenterFile.name,
|
||||||
|
type: "file",
|
||||||
|
typeLabel: __("File"),
|
||||||
|
category: node.trustCenterFile.category,
|
||||||
|
id: node.trustCenterFile.id,
|
||||||
|
status: node.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error("Unknown trust center access document type");
|
||||||
|
}
|
||||||
|
|
||||||
const compliancePageAccessEditDialogQuery = graphql`
|
const compliancePageAccessEditDialogQuery = graphql`
|
||||||
query CompliancePageAccessEditDialogQuery($accessId: ID!) {
|
query CompliancePageAccessEditDialogQuery($accessId: ID!) {
|
||||||
node(id: $accessId) {
|
node(id: $accessId) {
|
||||||
@@ -54,38 +136,7 @@ const compliancePageAccessEditDialogQuery = graphql`
|
|||||||
) {
|
) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...CompliancePageAccessEditDialogDocumentAccessFragment
|
||||||
status
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
document {
|
|
||||||
id
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
title
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
documentType
|
|
||||||
}
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
report {
|
|
||||||
id
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
filename
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
audit {
|
|
||||||
id
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
framework {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
trustCenterFile {
|
|
||||||
id
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
name
|
|
||||||
# eslint-disable-next-line relay/unused-fields
|
|
||||||
category
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ const compliancePageFragment = graphql`
|
|||||||
const documentFragment = graphql`
|
const documentFragment = graphql`
|
||||||
fragment CompliancePageDocumentListItem_documentFragment on Document {
|
fragment CompliancePageDocumentListItem_documentFragment on Document {
|
||||||
id
|
id
|
||||||
documentType
|
|
||||||
trustCenterVisibility
|
trustCenterVisibility
|
||||||
latestPublishedVersion: versions(
|
latestPublishedVersion: versions(
|
||||||
first: 1
|
first: 1
|
||||||
@@ -43,6 +42,7 @@ const documentFragment = graphql`
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
title
|
title
|
||||||
|
documentType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,8 @@ export function CompliancePageDocumentListItem(props: {
|
|||||||
[document.id, updateDocumentVisibility],
|
[document.id, updateDocumentVisibility],
|
||||||
);
|
);
|
||||||
|
|
||||||
const versionTitle = document.latestPublishedVersion.edges[0]?.node.title;
|
const latestVersion = document.latestPublishedVersion.edges[0]?.node;
|
||||||
|
const versionTitle = latestVersion?.title;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr to={`/organizations/${organizationId}/documents/${document.id}`}>
|
<Tr to={`/organizations/${organizationId}/documents/${document.id}`}>
|
||||||
@@ -110,7 +111,7 @@ export function CompliancePageDocumentListItem(props: {
|
|||||||
<div className="flex gap-4 items-center">{versionTitle}</div>
|
<div className="flex gap-4 items-center">{versionTitle}</div>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<DocumentTypeBadge type={document.documentType} />
|
{latestVersion && <DocumentTypeBadge type={latestVersion.documentType} />}
|
||||||
</Td>
|
</Td>
|
||||||
<Td noLink width={130} className="pr-0">
|
<Td noLink width={130} className="pr-0">
|
||||||
<Field
|
<Field
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import { documentClassifications, documentTypes, formatDate, getDocumentClassificationLabel, getDocumentTypeLabel } from "@probo/helpers";
|
import { documentClassifications, documentTypes, formatDate, getDocumentClassificationLabel, getDocumentTypeLabel } from "@probo/helpers";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { Badge, Button, Drawer, IconCheckmark1, IconCrossLargeX, IconPencil, PropertyRow } from "@probo/ui";
|
import { Badge, Button, Drawer, IconCheckmark1, IconCrossLargeX, IconPencil, PropertyRow, useToast } from "@probo/ui";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useFragment, useMutation } from "react-relay";
|
import { useFragment, useMutation } from "react-relay";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
@@ -31,7 +31,6 @@ import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
|||||||
const documentFragment = graphql`
|
const documentFragment = graphql`
|
||||||
fragment DocumentLayoutDrawer_documentFragment on Document {
|
fragment DocumentLayoutDrawer_documentFragment on Document {
|
||||||
id
|
id
|
||||||
documentType
|
|
||||||
status
|
status
|
||||||
archivedAt
|
archivedAt
|
||||||
canUpdate: permission(action: "core:document:update")
|
canUpdate: permission(action: "core:document:update")
|
||||||
@@ -41,6 +40,7 @@ const documentFragment = graphql`
|
|||||||
const versionFragment = graphql`
|
const versionFragment = graphql`
|
||||||
fragment DocumentLayoutDrawer_versionFragment on DocumentVersion {
|
fragment DocumentLayoutDrawer_versionFragment on DocumentVersion {
|
||||||
id
|
id
|
||||||
|
documentType
|
||||||
classification
|
classification
|
||||||
major
|
major
|
||||||
minor
|
minor
|
||||||
@@ -50,10 +50,10 @@ const versionFragment = graphql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const updateDocumentMutation = graphql`
|
const updateDocumentTypeMutation = graphql`
|
||||||
mutation DocumentLayoutDrawerMutation($input: UpdateDocumentInput!) {
|
mutation DocumentLayoutDrawerMutation($input: UpdateDocumentVersionInput!) {
|
||||||
updateDocument(input: $input) {
|
updateDocumentVersion(input: $input) {
|
||||||
document {
|
documentVersion {
|
||||||
id
|
id
|
||||||
documentType
|
documentType
|
||||||
}
|
}
|
||||||
@@ -91,6 +91,7 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
const [isEditingType, setIsEditingType] = useState(false);
|
const [isEditingType, setIsEditingType] = useState(false);
|
||||||
const [isEditingClassification, setIsEditingClassification] = useState(false);
|
const [isEditingClassification, setIsEditingClassification] = useState(false);
|
||||||
|
|
||||||
|
const { toast } = useToast();
|
||||||
const document = useFragment<DocumentLayoutDrawer_documentFragment$key>(documentFragment, documentFragmentRef);
|
const document = useFragment<DocumentLayoutDrawer_documentFragment$key>(documentFragment, documentFragmentRef);
|
||||||
const version = useFragment<DocumentLayoutDrawer_versionFragment$key>(versionFragment, versionFragmentRef);
|
const version = useFragment<DocumentLayoutDrawer_versionFragment$key>(versionFragment, versionFragmentRef);
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
schema,
|
schema,
|
||||||
{
|
{
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
documentType: document.documentType,
|
documentType: version.documentType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -119,8 +120,8 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [updateDocument, isUpdatingDocument]
|
const [updateDocumentType, isUpdatingDocumentType]
|
||||||
= useMutation<DocumentLayoutDrawerMutation>(updateDocumentMutation);
|
= useMutation<DocumentLayoutDrawerMutation>(updateDocumentTypeMutation);
|
||||||
|
|
||||||
const [updateClassification, isUpdatingClassification]
|
const [updateClassification, isUpdatingClassification]
|
||||||
= useMutation<DocumentLayoutDrawer_updateClassificationMutation>(updateClassificationMutation);
|
= useMutation<DocumentLayoutDrawer_updateClassificationMutation>(updateClassificationMutation);
|
||||||
@@ -128,15 +129,27 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
const handleUpdateDocumentType = (data: {
|
const handleUpdateDocumentType = (data: {
|
||||||
documentType: (typeof documentTypes)[number];
|
documentType: (typeof documentTypes)[number];
|
||||||
}) => {
|
}) => {
|
||||||
updateDocument({
|
updateDocumentType({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
id: document.id,
|
documentVersionId: version.id,
|
||||||
documentType: data.documentType,
|
documentType: data.documentType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
setIsEditingType(false);
|
setIsEditingType(false);
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Document type updated successfully"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: __("Failed to update document type"),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -153,6 +166,18 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
},
|
},
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
setIsEditingClassification(false);
|
setIsEditingClassification(false);
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Document classification updated successfully"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: __("Failed to update document classification"),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -171,7 +196,7 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
setIsEditingType(false);
|
setIsEditingType(false);
|
||||||
reset();
|
reset();
|
||||||
}}
|
}}
|
||||||
disabled={isUpdatingDocument}
|
disabled={isUpdatingDocumentType}
|
||||||
>
|
>
|
||||||
<ControlledField
|
<ControlledField
|
||||||
name="documentType"
|
name="documentType"
|
||||||
@@ -185,10 +210,10 @@ export function DocumentLayoutDrawer(props: {
|
|||||||
: (
|
: (
|
||||||
<ReadOnlyPropertyContent
|
<ReadOnlyPropertyContent
|
||||||
onEdit={() => setIsEditingType(true)}
|
onEdit={() => setIsEditingType(true)}
|
||||||
canEdit={canEdit}
|
canEdit={canEdit && isDraft}
|
||||||
>
|
>
|
||||||
<div className="text-sm text-txt-secondary">
|
<div className="text-sm text-txt-secondary">
|
||||||
{getDocumentTypeLabel(__, document.documentType)}
|
{getDocumentTypeLabel(__, version.documentType)}
|
||||||
</div>
|
</div>
|
||||||
</ReadOnlyPropertyContent>
|
</ReadOnlyPropertyContent>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ const fragment = graphql`
|
|||||||
fragment DocumentListItemFragment on Document {
|
fragment DocumentListItemFragment on Document {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
documentType
|
|
||||||
updatedAt
|
updatedAt
|
||||||
canDelete: permission(action: "core:document:delete")
|
canDelete: permission(action: "core:document:delete")
|
||||||
recentVersions: versions(first: 2 orderBy: { field: CREATED_AT direction: DESC }) {
|
recentVersions: versions(first: 2 orderBy: { field: CREATED_AT direction: DESC }) {
|
||||||
@@ -36,6 +35,7 @@ const fragment = graphql`
|
|||||||
status
|
status
|
||||||
major
|
major
|
||||||
minor
|
minor
|
||||||
|
documentType
|
||||||
classification
|
classification
|
||||||
approvalQuorums(first: 1, orderBy: { field: CREATED_AT, direction: DESC }) {
|
approvalQuorums(first: 1, orderBy: { field: CREATED_AT, direction: DESC }) {
|
||||||
edges {
|
edges {
|
||||||
@@ -165,7 +165,7 @@ export function DocumentListItem(props: {
|
|||||||
{lastVersion.minor}
|
{lastVersion.minor}
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="w-28">
|
<Td className="w-28">
|
||||||
{getDocumentTypeLabel(__, document.documentType)}
|
{getDocumentTypeLabel(__, lastVersion.documentType)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="w-32">
|
<Td className="w-32">
|
||||||
{getDocumentClassificationLabel(__, lastVersion.classification)}
|
{getDocumentClassificationLabel(__, lastVersion.classification)}
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ const fragment = graphql`
|
|||||||
fragment ApprovableDocumentRowFragment on EmployeeDocument {
|
fragment ApprovableDocumentRowFragment on EmployeeDocument {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
documentType
|
|
||||||
approvalState
|
approvalState
|
||||||
updatedAt
|
updatedAt
|
||||||
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT direction: DESC }) {
|
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT direction: DESC }) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
|
documentType
|
||||||
classification
|
classification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ export function ApprovableDocumentRow({
|
|||||||
<Tr to={`/organizations/${organizationId}/employee/approvals/${document.id}`}>
|
<Tr to={`/organizations/${organizationId}/employee/approvals/${document.id}`}>
|
||||||
<Td>{document.title}</Td>
|
<Td>{document.title}</Td>
|
||||||
<Td className="w-48">
|
<Td className="w-48">
|
||||||
{getDocumentTypeLabel(__, document.documentType)}
|
{getDocumentTypeLabel(__, lastVersion.documentType)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="w-36">
|
<Td className="w-36">
|
||||||
<Badge variant="neutral">
|
<Badge variant="neutral">
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ const fragment = graphql`
|
|||||||
fragment DocumentRowFragment on EmployeeDocument {
|
fragment DocumentRowFragment on EmployeeDocument {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
documentType
|
|
||||||
signed
|
signed
|
||||||
updatedAt
|
updatedAt
|
||||||
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT direction: DESC }) {
|
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT direction: DESC }) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
|
documentType
|
||||||
classification
|
classification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ export function DocumentRow({
|
|||||||
<Tr to={`/organizations/${organizationId}/employee/signatures/${document.id}`}>
|
<Tr to={`/organizations/${organizationId}/employee/signatures/${document.id}`}>
|
||||||
<Td>{document.title}</Td>
|
<Td>{document.title}</Td>
|
||||||
<Td className="w-48">
|
<Td className="w-48">
|
||||||
{getDocumentTypeLabel(__, document.documentType)}
|
{getDocumentTypeLabel(__, lastVersion.documentType)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="w-36">
|
<Td className="w-36">
|
||||||
<Badge variant="neutral">
|
<Badge variant="neutral">
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ const overviewFragment = graphql`
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
...DocumentRowFragment
|
|
||||||
documentType
|
documentType
|
||||||
|
...DocumentRowFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,11 @@ func TestDocument_Create(t *testing.T) {
|
|||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
documentVersionEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
documentType
|
documentType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,9 +126,14 @@ func TestDocument_Create(t *testing.T) {
|
|||||||
Node struct {
|
Node struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
DocumentType string `json:"documentType"`
|
|
||||||
} `json:"node"`
|
} `json:"node"`
|
||||||
} `json:"documentEdge"`
|
} `json:"documentEdge"`
|
||||||
|
DocumentVersionEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
DocumentType string `json:"documentType"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"documentVersionEdge"`
|
||||||
} `json:"createDocument"`
|
} `json:"createDocument"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +143,13 @@ func TestDocument_Create(t *testing.T) {
|
|||||||
node := result.CreateDocument.DocumentEdge.Node
|
node := result.CreateDocument.DocumentEdge.Node
|
||||||
assert.NotEmpty(t, node.ID)
|
assert.NotEmpty(t, node.ID)
|
||||||
|
|
||||||
|
versionNode := result.CreateDocument.DocumentVersionEdge.Node
|
||||||
|
|
||||||
switch tt.assertField {
|
switch tt.assertField {
|
||||||
case "title":
|
case "title":
|
||||||
assert.Equal(t, tt.assertValue, node.Title)
|
assert.Equal(t, tt.assertValue, node.Title)
|
||||||
case "documentType":
|
case "documentType":
|
||||||
assert.Equal(t, tt.assertValue, node.DocumentType)
|
assert.Equal(t, tt.assertValue, versionNode.DocumentType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -277,48 +289,14 @@ func TestDocument_Update(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
owner := testutil.NewClient(t, testutil.RoleOwner)
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
tests := []struct {
|
t.Run(
|
||||||
name string
|
"update title",
|
||||||
setup func() string
|
func(t *testing.T) {
|
||||||
input func(id string) map[string]any
|
t.Parallel()
|
||||||
assertField string
|
|
||||||
assertValue string
|
documentID := factory.NewDocument(owner).
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "update title",
|
|
||||||
setup: func() string {
|
|
||||||
return factory.NewDocument(owner).
|
|
||||||
WithTitle("Document to Update").
|
WithTitle("Document to Update").
|
||||||
Create()
|
Create()
|
||||||
},
|
|
||||||
input: func(id string) map[string]any {
|
|
||||||
return map[string]any{
|
|
||||||
"id": id,
|
|
||||||
"title": "Updated Document Title",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
assertField: "title",
|
|
||||||
assertValue: "Updated Document Title",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "update document type",
|
|
||||||
setup: func() string {
|
|
||||||
return factory.NewDocument(owner).
|
|
||||||
WithTitle("Type Test").
|
|
||||||
WithDocumentType("POLICY").
|
|
||||||
Create()
|
|
||||||
},
|
|
||||||
input: func(id string) map[string]any {
|
|
||||||
return map[string]any{"id": id, "documentType": "PROCEDURE"}
|
|
||||||
},
|
|
||||||
assertField: "documentType",
|
|
||||||
assertValue: "PROCEDURE",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
documentID := tt.setup()
|
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
mutation UpdateDocument($input: UpdateDocumentInput!) {
|
mutation UpdateDocument($input: UpdateDocumentInput!) {
|
||||||
@@ -326,7 +304,6 @@ func TestDocument_Update(t *testing.T) {
|
|||||||
document {
|
document {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
documentType
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,23 +314,20 @@ func TestDocument_Update(t *testing.T) {
|
|||||||
Document struct {
|
Document struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
DocumentType string `json:"documentType"`
|
|
||||||
} `json:"document"`
|
} `json:"document"`
|
||||||
} `json:"updateDocument"`
|
} `json:"updateDocument"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := owner.Execute(query, map[string]any{"input": tt.input(documentID)}, &result)
|
err := owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"id": documentID,
|
||||||
|
"title": "Updated Document Title",
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "Updated Document Title", result.UpdateDocument.Document.Title)
|
||||||
doc := result.UpdateDocument.Document
|
},
|
||||||
switch tt.assertField {
|
)
|
||||||
case "title":
|
|
||||||
assert.Equal(t, tt.assertValue, doc.Title)
|
|
||||||
case "documentType":
|
|
||||||
assert.Equal(t, tt.assertValue, doc.DocumentType)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_Update_Validation(t *testing.T) {
|
func TestDocument_Update_Validation(t *testing.T) {
|
||||||
|
|||||||
@@ -20,28 +20,3 @@ export const trustCenterDocumentAccessStatus = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type TrustCenterDocumentAccessStatus = (typeof trustCenterDocumentAccessStatus)[keyof typeof trustCenterDocumentAccessStatus];
|
export type TrustCenterDocumentAccessStatus = (typeof trustCenterDocumentAccessStatus)[keyof typeof trustCenterDocumentAccessStatus];
|
||||||
|
|
||||||
export type TrustCenterDocumentAccess = {
|
|
||||||
id: string;
|
|
||||||
status: TrustCenterDocumentAccessStatus;
|
|
||||||
document?: {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
documentType: string;
|
|
||||||
} | null;
|
|
||||||
report?: {
|
|
||||||
id: string;
|
|
||||||
filename: string;
|
|
||||||
audit?: {
|
|
||||||
id: string;
|
|
||||||
framework?: {
|
|
||||||
name: string;
|
|
||||||
} | null;
|
|
||||||
} | null;
|
|
||||||
} | null;
|
|
||||||
trustCenterFile?: {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
category: string;
|
|
||||||
} | null;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -13,6 +13,5 @@
|
|||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
TrustCenterDocumentAccess,
|
|
||||||
TrustCenterDocumentAccessStatus,
|
TrustCenterDocumentAccessStatus,
|
||||||
} from "./TrustCenterDocumentAccess";
|
} from "./TrustCenterDocumentAccess";
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ export { detectSocialName } from "./socialUrl";
|
|||||||
export { formatError, type GraphQLError } from "./error";
|
export { formatError, type GraphQLError } from "./error";
|
||||||
export { Role, roles, getAssignableRoles } from "./roles";
|
export { Role, roles, getAssignableRoles } from "./roles";
|
||||||
export {
|
export {
|
||||||
getTrustCenterDocumentAccessInfo,
|
|
||||||
getTrustCenterDocumentAccessStatusBadgeVariant,
|
getTrustCenterDocumentAccessStatusBadgeVariant,
|
||||||
getTrustCenterDocumentAccessStatusLabel,
|
getTrustCenterDocumentAccessStatusLabel,
|
||||||
type TrustCenterDocumentAccessInfo,
|
type TrustCenterDocumentAccessInfo,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
import type { TrustCenterDocumentAccess, TrustCenterDocumentAccessStatus } from "@probo/coredata";
|
import type { TrustCenterDocumentAccessStatus } from "@probo/coredata";
|
||||||
|
|
||||||
export function getTrustCenterDocumentAccessStatusBadgeVariant(status: TrustCenterDocumentAccessStatus) {
|
export function getTrustCenterDocumentAccessStatusBadgeVariant(status: TrustCenterDocumentAccessStatus) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -63,46 +63,3 @@ export type TrustCenterDocumentAccessInfo = ITrustCenterDocumentAccessInfo & (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
export function getTrustCenterDocumentAccessInfo(
|
|
||||||
docAccess: TrustCenterDocumentAccess,
|
|
||||||
__: (key: string) => string
|
|
||||||
): TrustCenterDocumentAccessInfo {
|
|
||||||
if (docAccess.document) {
|
|
||||||
return {
|
|
||||||
persisted: docAccess.id !== docAccess.document.id,
|
|
||||||
variant: "info" as const,
|
|
||||||
name: docAccess.document.title,
|
|
||||||
type: "document",
|
|
||||||
typeLabel: __("Document"),
|
|
||||||
category: docAccess.document.documentType,
|
|
||||||
id: docAccess.document.id,
|
|
||||||
status: docAccess.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (docAccess.report) {
|
|
||||||
return {
|
|
||||||
persisted: docAccess.id !== docAccess.report.id,
|
|
||||||
variant: "success" as const,
|
|
||||||
name: docAccess.report.filename,
|
|
||||||
type: "report",
|
|
||||||
typeLabel: __("Report"),
|
|
||||||
category: docAccess.report.audit?.framework?.name ?? "",
|
|
||||||
id: docAccess.report.id,
|
|
||||||
status: docAccess.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (docAccess.trustCenterFile) {
|
|
||||||
return {
|
|
||||||
persisted: docAccess.id !== docAccess.trustCenterFile.id,
|
|
||||||
variant: "highlight" as const,
|
|
||||||
name: docAccess.trustCenterFile.name,
|
|
||||||
type: "file",
|
|
||||||
typeLabel: __("File"),
|
|
||||||
category: docAccess.trustCenterFile.category,
|
|
||||||
id: docAccess.trustCenterFile.id,
|
|
||||||
status: docAccess.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Unknown trust center access document type");
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ type (
|
|||||||
ID gid.GID `db:"id"`
|
ID gid.GID `db:"id"`
|
||||||
OrganizationID gid.GID `db:"organization_id"`
|
OrganizationID gid.GID `db:"organization_id"`
|
||||||
Title string `db:"title"`
|
Title string `db:"title"`
|
||||||
DocumentType DocumentType `db:"document_type"`
|
|
||||||
CurrentPublishedMajor *int `db:"current_published_major"`
|
CurrentPublishedMajor *int `db:"current_published_major"`
|
||||||
CurrentPublishedMinor *int `db:"current_published_minor"`
|
CurrentPublishedMinor *int `db:"current_published_minor"`
|
||||||
TrustCenterVisibility TrustCenterVisibility `db:"trust_center_visibility"`
|
TrustCenterVisibility TrustCenterVisibility `db:"trust_center_visibility"`
|
||||||
@@ -41,6 +40,9 @@ type (
|
|||||||
ArchivedAt *time.Time `db:"archived_at"`
|
ArchivedAt *time.Time `db:"archived_at"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
|
|
||||||
|
// ordering only
|
||||||
|
DocumentType DocumentType `db:"document_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
Documents []*Document
|
Documents []*Document
|
||||||
@@ -122,24 +124,30 @@ func (p *Document) LoadByID(
|
|||||||
documentID gid.GID,
|
documentID gid.GID,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
title,
|
documents.title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
documents
|
documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND deleted_at IS NULL
|
AND documents.deleted_at IS NULL
|
||||||
AND id = @document_id
|
AND documents.id = @document_id
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -175,24 +183,30 @@ func (p *Document) LoadByIDWithFilter(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
title,
|
documents.title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
documents
|
documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND deleted_at IS NULL
|
AND documents.deleted_at IS NULL
|
||||||
AND id = @document_id
|
AND documents.id = @document_id
|
||||||
AND %s
|
AND %s
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
`
|
`
|
||||||
@@ -229,24 +243,30 @@ func (p *Documents) LoadByIDs(
|
|||||||
documentIDs []gid.GID,
|
documentIDs []gid.GID,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
title,
|
documents.title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
documents
|
documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND deleted_at IS NULL
|
AND documents.deleted_at IS NULL
|
||||||
AND id = ANY(@document_ids)
|
AND documents.id = ANY(@document_ids)
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -312,24 +332,30 @@ func (p *Documents) LoadByOrganizationID(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
title,
|
documents.title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
documents
|
documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND deleted_at IS NULL
|
AND documents.deleted_at IS NULL
|
||||||
AND organization_id = @organization_id
|
AND documents.organization_id = @organization_id
|
||||||
AND %s
|
AND %s
|
||||||
AND %s
|
AND %s
|
||||||
`
|
`
|
||||||
@@ -364,24 +390,30 @@ func (p *Documents) LoadAllByOrganizationID(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
title,
|
documents.title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
documents
|
documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND deleted_at IS NULL
|
AND documents.deleted_at IS NULL
|
||||||
AND organization_id = @organization_id
|
AND documents.organization_id = @organization_id
|
||||||
AND %s
|
AND %s
|
||||||
ORDER BY title ASC
|
ORDER BY title ASC
|
||||||
`
|
`
|
||||||
@@ -416,7 +448,12 @@ func (p *Documents) LoadPublishedByOrganizationID(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
WITH published_documents AS (
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
),
|
||||||
|
published_documents AS (
|
||||||
SELECT
|
SELECT
|
||||||
d.*,
|
d.*,
|
||||||
dv.title AS published_title
|
dv.title AS published_title
|
||||||
@@ -431,19 +468,20 @@ WITH published_documents AS (
|
|||||||
AND d.organization_id = @organization_id
|
AND d.organization_id = @organization_id
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
documents.id,
|
||||||
organization_id,
|
documents.organization_id,
|
||||||
COALESCE(published_title, title) AS title,
|
COALESCE(documents.published_title, documents.title) AS title,
|
||||||
document_type,
|
documents.current_published_major,
|
||||||
current_published_major,
|
documents.current_published_minor,
|
||||||
current_published_minor,
|
documents.trust_center_visibility,
|
||||||
trust_center_visibility,
|
documents.status,
|
||||||
status,
|
documents.archived_at,
|
||||||
archived_at,
|
documents.created_at,
|
||||||
created_at,
|
documents.updated_at,
|
||||||
updated_at
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM
|
FROM
|
||||||
published_documents documents
|
published_documents documents
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND %s
|
AND %s
|
||||||
@@ -483,7 +521,6 @@ INSERT INTO
|
|||||||
id,
|
id,
|
||||||
organization_id,
|
organization_id,
|
||||||
title,
|
title,
|
||||||
document_type,
|
|
||||||
current_published_major,
|
current_published_major,
|
||||||
current_published_minor,
|
current_published_minor,
|
||||||
trust_center_visibility,
|
trust_center_visibility,
|
||||||
@@ -497,7 +534,6 @@ VALUES (
|
|||||||
@document_id,
|
@document_id,
|
||||||
@organization_id,
|
@organization_id,
|
||||||
@title,
|
@title,
|
||||||
@document_type,
|
|
||||||
@current_published_major,
|
@current_published_major,
|
||||||
@current_published_minor,
|
@current_published_minor,
|
||||||
@trust_center_visibility,
|
@trust_center_visibility,
|
||||||
@@ -513,7 +549,6 @@ VALUES (
|
|||||||
"document_id": p.ID,
|
"document_id": p.ID,
|
||||||
"organization_id": p.OrganizationID,
|
"organization_id": p.OrganizationID,
|
||||||
"title": p.Title,
|
"title": p.Title,
|
||||||
"document_type": p.DocumentType,
|
|
||||||
"current_published_major": p.CurrentPublishedMajor,
|
"current_published_major": p.CurrentPublishedMajor,
|
||||||
"current_published_minor": p.CurrentPublishedMinor,
|
"current_published_minor": p.CurrentPublishedMinor,
|
||||||
"trust_center_visibility": p.TrustCenterVisibility,
|
"trust_center_visibility": p.TrustCenterVisibility,
|
||||||
@@ -575,7 +610,6 @@ SET
|
|||||||
title = @title,
|
title = @title,
|
||||||
current_published_major = @current_published_major,
|
current_published_major = @current_published_major,
|
||||||
current_published_minor = @current_published_minor,
|
current_published_minor = @current_published_minor,
|
||||||
document_type = @document_type,
|
|
||||||
trust_center_visibility = @trust_center_visibility,
|
trust_center_visibility = @trust_center_visibility,
|
||||||
status = @status,
|
status = @status,
|
||||||
archived_at = @archived_at,
|
archived_at = @archived_at,
|
||||||
@@ -593,7 +627,6 @@ WHERE
|
|||||||
"title": p.Title,
|
"title": p.Title,
|
||||||
"current_published_major": p.CurrentPublishedMajor,
|
"current_published_major": p.CurrentPublishedMajor,
|
||||||
"current_published_minor": p.CurrentPublishedMinor,
|
"current_published_minor": p.CurrentPublishedMinor,
|
||||||
"document_type": p.DocumentType,
|
|
||||||
"trust_center_visibility": p.TrustCenterVisibility,
|
"trust_center_visibility": p.TrustCenterVisibility,
|
||||||
"status": p.Status,
|
"status": p.Status,
|
||||||
"archived_at": p.ArchivedAt,
|
"archived_at": p.ArchivedAt,
|
||||||
@@ -653,7 +686,12 @@ func (p *Documents) LoadByControlID(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
WITH scoped_documents AS (
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
),
|
||||||
|
scoped_documents AS (
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM documents
|
FROM documents
|
||||||
WHERE %s
|
WHERE %s
|
||||||
@@ -665,16 +703,17 @@ SELECT
|
|||||||
scoped_documents.id,
|
scoped_documents.id,
|
||||||
scoped_documents.organization_id,
|
scoped_documents.organization_id,
|
||||||
scoped_documents.title,
|
scoped_documents.title,
|
||||||
scoped_documents.document_type,
|
|
||||||
scoped_documents.current_published_major,
|
scoped_documents.current_published_major,
|
||||||
scoped_documents.current_published_minor,
|
scoped_documents.current_published_minor,
|
||||||
scoped_documents.trust_center_visibility,
|
scoped_documents.trust_center_visibility,
|
||||||
scoped_documents.status,
|
scoped_documents.status,
|
||||||
scoped_documents.archived_at,
|
scoped_documents.archived_at,
|
||||||
scoped_documents.created_at,
|
scoped_documents.created_at,
|
||||||
scoped_documents.updated_at
|
scoped_documents.updated_at,
|
||||||
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM scoped_documents
|
FROM scoped_documents
|
||||||
INNER JOIN controls_documents cp ON scoped_documents.id = cp.document_id
|
INNER JOIN controls_documents cp ON scoped_documents.id = cp.document_id
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = scoped_documents.id
|
||||||
WHERE cp.control_id = @control_id
|
WHERE cp.control_id = @control_id
|
||||||
`
|
`
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||||
@@ -744,7 +783,12 @@ func (p *Documents) LoadByRiskID(
|
|||||||
filter *DocumentFilter,
|
filter *DocumentFilter,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
WITH scoped_documents AS (
|
WITH latest_versions AS (
|
||||||
|
SELECT DISTINCT ON (document_id) document_id, document_type
|
||||||
|
FROM document_versions
|
||||||
|
ORDER BY document_id, major DESC, minor DESC
|
||||||
|
),
|
||||||
|
scoped_documents AS (
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM documents
|
FROM documents
|
||||||
WHERE %s
|
WHERE %s
|
||||||
@@ -756,16 +800,17 @@ SELECT
|
|||||||
scoped_documents.id,
|
scoped_documents.id,
|
||||||
scoped_documents.organization_id,
|
scoped_documents.organization_id,
|
||||||
scoped_documents.title,
|
scoped_documents.title,
|
||||||
scoped_documents.document_type,
|
|
||||||
scoped_documents.current_published_major,
|
scoped_documents.current_published_major,
|
||||||
scoped_documents.current_published_minor,
|
scoped_documents.current_published_minor,
|
||||||
scoped_documents.trust_center_visibility,
|
scoped_documents.trust_center_visibility,
|
||||||
scoped_documents.status,
|
scoped_documents.status,
|
||||||
scoped_documents.archived_at,
|
scoped_documents.archived_at,
|
||||||
scoped_documents.created_at,
|
scoped_documents.created_at,
|
||||||
scoped_documents.updated_at
|
scoped_documents.updated_at,
|
||||||
|
COALESCE(lv.document_type, 'OTHER') AS document_type
|
||||||
FROM scoped_documents
|
FROM scoped_documents
|
||||||
INNER JOIN risks_documents rp ON scoped_documents.id = rp.document_id
|
INNER JOIN risks_documents rp ON scoped_documents.id = rp.document_id
|
||||||
|
LEFT JOIN latest_versions lv ON lv.document_id = scoped_documents.id
|
||||||
WHERE rp.risk_id = @risk_id
|
WHERE rp.risk_id = @risk_id
|
||||||
`
|
`
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||||
|
|||||||
@@ -180,7 +180,13 @@ func (f *DocumentFilter) SQLFragment() string {
|
|||||||
AND
|
AND
|
||||||
CASE
|
CASE
|
||||||
WHEN @document_types::document_type[] IS NOT NULL THEN
|
WHEN @document_types::document_type[] IS NOT NULL THEN
|
||||||
document_type = ANY(@document_types::document_type[])
|
(
|
||||||
|
SELECT dv.document_type
|
||||||
|
FROM document_versions dv
|
||||||
|
WHERE dv.document_id = documents.id
|
||||||
|
ORDER BY dv.major DESC, dv.minor DESC
|
||||||
|
LIMIT 1
|
||||||
|
) = ANY(@document_types::document_type[])
|
||||||
ELSE TRUE
|
ELSE TRUE
|
||||||
END
|
END
|
||||||
AND
|
AND
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
package coredata
|
package coredata
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
DocumentOrderField string
|
DocumentOrderField string
|
||||||
)
|
)
|
||||||
@@ -25,7 +27,25 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p DocumentOrderField) Column() string {
|
func (p DocumentOrderField) Column() string {
|
||||||
return string(p)
|
switch p {
|
||||||
|
case DocumentOrderFieldCreatedAt:
|
||||||
|
return "created_at"
|
||||||
|
case DocumentOrderFieldTitle:
|
||||||
|
return "title"
|
||||||
|
case DocumentOrderFieldDocumentType:
|
||||||
|
return "document_type"
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("unsupported order by: %s", p))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p DocumentOrderField) IsValid() bool {
|
||||||
|
switch p {
|
||||||
|
case DocumentOrderFieldCreatedAt,
|
||||||
|
DocumentOrderFieldTitle,
|
||||||
|
DocumentOrderFieldDocumentType:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p DocumentOrderField) String() string {
|
func (p DocumentOrderField) String() string {
|
||||||
@@ -38,5 +58,8 @@ func (p DocumentOrderField) MarshalText() ([]byte, error) {
|
|||||||
|
|
||||||
func (p *DocumentOrderField) UnmarshalText(text []byte) error {
|
func (p *DocumentOrderField) UnmarshalText(text []byte) error {
|
||||||
*p = DocumentOrderField(text)
|
*p = DocumentOrderField(text)
|
||||||
|
if !p.IsValid() {
|
||||||
|
return fmt.Errorf("%s is not a valid DocumentOrderField", string(text))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type (
|
|||||||
Major int `db:"major"`
|
Major int `db:"major"`
|
||||||
Minor int `db:"minor"`
|
Minor int `db:"minor"`
|
||||||
Classification DocumentClassification `db:"classification"`
|
Classification DocumentClassification `db:"classification"`
|
||||||
|
DocumentType DocumentType `db:"document_type"`
|
||||||
Content string `db:"content"`
|
Content string `db:"content"`
|
||||||
Changelog string `db:"changelog"`
|
Changelog string `db:"changelog"`
|
||||||
Status DocumentVersionStatus `db:"status"`
|
Status DocumentVersionStatus `db:"status"`
|
||||||
@@ -120,6 +121,7 @@ SELECT
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -182,6 +184,7 @@ SELECT
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -233,6 +236,7 @@ INSERT INTO document_versions (
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -248,6 +252,7 @@ VALUES (
|
|||||||
@major,
|
@major,
|
||||||
@minor,
|
@minor,
|
||||||
@classification,
|
@classification,
|
||||||
|
@document_type,
|
||||||
@content,
|
@content,
|
||||||
@changelog,
|
@changelog,
|
||||||
@status,
|
@status,
|
||||||
@@ -264,6 +269,7 @@ VALUES (
|
|||||||
"major": dv.Major,
|
"major": dv.Major,
|
||||||
"minor": dv.Minor,
|
"minor": dv.Minor,
|
||||||
"classification": dv.Classification,
|
"classification": dv.Classification,
|
||||||
|
"document_type": dv.DocumentType,
|
||||||
"content": dv.Content,
|
"content": dv.Content,
|
||||||
"changelog": dv.Changelog,
|
"changelog": dv.Changelog,
|
||||||
"status": dv.Status,
|
"status": dv.Status,
|
||||||
@@ -304,6 +310,7 @@ SELECT
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -359,6 +366,7 @@ SELECT
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -410,6 +418,7 @@ SELECT
|
|||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
classification,
|
classification,
|
||||||
|
document_type,
|
||||||
content,
|
content,
|
||||||
changelog,
|
changelog,
|
||||||
status,
|
status,
|
||||||
@@ -463,6 +472,7 @@ UPDATE document_versions SET
|
|||||||
content = @content,
|
content = @content,
|
||||||
published_at = @published_at,
|
published_at = @published_at,
|
||||||
classification = @classification,
|
classification = @classification,
|
||||||
|
document_type = @document_type,
|
||||||
updated_at = @updated_at
|
updated_at = @updated_at
|
||||||
WHERE %s
|
WHERE %s
|
||||||
AND id = @document_version_id
|
AND id = @document_version_id
|
||||||
@@ -480,6 +490,7 @@ WHERE %s
|
|||||||
"content": dv.Content,
|
"content": dv.Content,
|
||||||
"published_at": dv.PublishedAt,
|
"published_at": dv.PublishedAt,
|
||||||
"classification": dv.Classification,
|
"classification": dv.Classification,
|
||||||
|
"document_type": dv.DocumentType,
|
||||||
"updated_at": dv.UpdatedAt,
|
"updated_at": dv.UpdatedAt,
|
||||||
}
|
}
|
||||||
maps.Copy(args, scope.SQLArguments())
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|||||||
12
pkg/coredata/migrations/20260331T120000Z.sql
Normal file
12
pkg/coredata/migrations/20260331T120000Z.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- Add document_type column to document_versions, copying from parent document.
|
||||||
|
ALTER TABLE document_versions ADD COLUMN document_type document_type NOT NULL DEFAULT 'OTHER';
|
||||||
|
|
||||||
|
UPDATE document_versions dv
|
||||||
|
SET document_type = d.document_type
|
||||||
|
FROM documents d
|
||||||
|
WHERE dv.document_id = d.id;
|
||||||
|
|
||||||
|
ALTER TABLE document_versions ALTER COLUMN document_type DROP DEFAULT;
|
||||||
|
|
||||||
|
-- TODO: drop the document_type column from documents.
|
||||||
|
ALTER TABLE documents ALTER COLUMN document_type SET DEFAULT 'OTHER';
|
||||||
@@ -290,7 +290,7 @@ func (s *DocumentApprovalService) Approve(
|
|||||||
tx,
|
tx,
|
||||||
&esign.CreateAndAcceptSignatureRequest{
|
&esign.CreateAndAcceptSignatureRequest{
|
||||||
OrganizationID: documentVersion.OrganizationID,
|
OrganizationID: documentVersion.OrganizationID,
|
||||||
DocumentType: coredata.ElectronicSignatureDocumentTypeFromDocumentType(document.DocumentType),
|
DocumentType: coredata.ElectronicSignatureDocumentTypeFromDocumentType(documentVersion.DocumentType),
|
||||||
DocumentName: &document.Title,
|
DocumentName: &document.Title,
|
||||||
FileID: fileRecord.ID,
|
FileID: fileRecord.ID,
|
||||||
SignerEmail: req.SignerEmail,
|
SignerEmail: req.SignerEmail,
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ type (
|
|||||||
UpdateDocumentRequest struct {
|
UpdateDocumentRequest struct {
|
||||||
DocumentID gid.GID
|
DocumentID gid.GID
|
||||||
Title *string
|
Title *string
|
||||||
DocumentType *coredata.DocumentType
|
|
||||||
TrustCenterVisibility *coredata.TrustCenterVisibility
|
TrustCenterVisibility *coredata.TrustCenterVisibility
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +93,7 @@ type (
|
|||||||
ID gid.GID
|
ID gid.GID
|
||||||
Content *string
|
Content *string
|
||||||
Classification *coredata.DocumentClassification
|
Classification *coredata.DocumentClassification
|
||||||
|
DocumentType *coredata.DocumentType
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSignatureRequest struct {
|
RequestSignatureRequest struct {
|
||||||
@@ -139,7 +139,6 @@ func (udr *UpdateDocumentRequest) Validate() error {
|
|||||||
|
|
||||||
v.Check(udr.DocumentID, "document_id", validator.Required(), validator.GID(coredata.DocumentEntityType))
|
v.Check(udr.DocumentID, "document_id", validator.Required(), validator.GID(coredata.DocumentEntityType))
|
||||||
v.Check(udr.Title, "title", validator.SafeTextNoNewLine(TitleMaxLength))
|
v.Check(udr.Title, "title", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||||
v.Check(udr.DocumentType, "document_type", validator.OneOfSlice(coredata.DocumentTypes()))
|
|
||||||
v.Check(udr.TrustCenterVisibility, "trust_center_visibility", validator.OneOfSlice(coredata.TrustCenterVisibilities()))
|
v.Check(udr.TrustCenterVisibility, "trust_center_visibility", validator.OneOfSlice(coredata.TrustCenterVisibilities()))
|
||||||
|
|
||||||
return v.Error()
|
return v.Error()
|
||||||
@@ -156,6 +155,7 @@ func (udvr *UpdateDocumentVersionRequest) Validate() error {
|
|||||||
validator.MaxLen(documentMaxLength),
|
validator.MaxLen(documentMaxLength),
|
||||||
validator.ProseMirrorDocumentContent(),
|
validator.ProseMirrorDocumentContent(),
|
||||||
)
|
)
|
||||||
|
v.Check(udvr.DocumentType, "document_type", validator.OneOfSlice(coredata.DocumentTypes()))
|
||||||
|
|
||||||
return v.Error()
|
return v.Error()
|
||||||
}
|
}
|
||||||
@@ -518,7 +518,6 @@ func (s *DocumentService) Create(
|
|||||||
document := &coredata.Document{
|
document := &coredata.Document{
|
||||||
ID: documentID,
|
ID: documentID,
|
||||||
Title: req.Title,
|
Title: req.Title,
|
||||||
DocumentType: req.DocumentType,
|
|
||||||
TrustCenterVisibility: coredata.TrustCenterVisibilityNone,
|
TrustCenterVisibility: coredata.TrustCenterVisibilityNone,
|
||||||
Status: coredata.DocumentStatusActive,
|
Status: coredata.DocumentStatusActive,
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
@@ -547,6 +546,7 @@ func (s *DocumentService) Create(
|
|||||||
Content: content,
|
Content: content,
|
||||||
Status: coredata.DocumentVersionStatusDraft,
|
Status: coredata.DocumentVersionStatusDraft,
|
||||||
Classification: req.Classification,
|
Classification: req.Classification,
|
||||||
|
DocumentType: req.DocumentType,
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
@@ -793,6 +793,9 @@ func (s *DocumentService) UpdateVersion(
|
|||||||
if req.Classification != nil {
|
if req.Classification != nil {
|
||||||
documentVersion.Classification = *req.Classification
|
documentVersion.Classification = *req.Classification
|
||||||
}
|
}
|
||||||
|
if req.DocumentType != nil {
|
||||||
|
documentVersion.DocumentType = *req.DocumentType
|
||||||
|
}
|
||||||
documentVersion.UpdatedAt = time.Now()
|
documentVersion.UpdatedAt = time.Now()
|
||||||
|
|
||||||
if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil {
|
if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil {
|
||||||
@@ -1031,6 +1034,7 @@ func (s *DocumentService) CreateDraft(
|
|||||||
draftVersion.Major = latestVersion.Major
|
draftVersion.Major = latestVersion.Major
|
||||||
draftVersion.Minor = latestVersion.Minor + 1
|
draftVersion.Minor = latestVersion.Minor + 1
|
||||||
draftVersion.Classification = latestVersion.Classification
|
draftVersion.Classification = latestVersion.Classification
|
||||||
|
draftVersion.DocumentType = latestVersion.DocumentType
|
||||||
draftVersion.Content = latestVersion.Content
|
draftVersion.Content = latestVersion.Content
|
||||||
draftVersion.Status = coredata.DocumentVersionStatusDraft
|
draftVersion.Status = coredata.DocumentVersionStatusDraft
|
||||||
draftVersion.CreatedAt = now
|
draftVersion.CreatedAt = now
|
||||||
@@ -1561,14 +1565,6 @@ func (s *DocumentService) Update(
|
|||||||
document.Title = *req.Title
|
document.Title = *req.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.DocumentType != nil {
|
|
||||||
document.DocumentType = *req.DocumentType
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.DocumentType != nil {
|
|
||||||
document.DocumentType = *req.DocumentType
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.TrustCenterVisibility != nil {
|
if req.TrustCenterVisibility != nil {
|
||||||
document.TrustCenterVisibility = *req.TrustCenterVisibility
|
document.TrustCenterVisibility = *req.TrustCenterVisibility
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2543,7 +2543,6 @@ type Document implements Node {
|
|||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
description: String
|
description: String
|
||||||
documentType: DocumentType!
|
|
||||||
currentPublishedMajor: Int
|
currentPublishedMajor: Int
|
||||||
currentPublishedMinor: Int
|
currentPublishedMinor: Int
|
||||||
trustCenterVisibility: TrustCenterVisibility!
|
trustCenterVisibility: TrustCenterVisibility!
|
||||||
@@ -2583,7 +2582,6 @@ type EmployeeDocument
|
|||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
description: String
|
description: String
|
||||||
documentType: DocumentType!
|
|
||||||
signed: Boolean @goField(forceResolver: true)
|
signed: Boolean @goField(forceResolver: true)
|
||||||
approvalState: DocumentVersionApprovalDecisionState @goField(forceResolver: true)
|
approvalState: DocumentVersionApprovalDecisionState @goField(forceResolver: true)
|
||||||
|
|
||||||
@@ -2608,6 +2606,7 @@ type EmployeeDocumentVersion
|
|||||||
minor: Int!
|
minor: Int!
|
||||||
status: DocumentVersionStatus!
|
status: DocumentVersionStatus!
|
||||||
classification: DocumentClassification!
|
classification: DocumentClassification!
|
||||||
|
documentType: DocumentType!
|
||||||
signed: Boolean! @goField(forceResolver: true)
|
signed: Boolean! @goField(forceResolver: true)
|
||||||
approvalDecision: DocumentVersionApprovalDecision @goField(forceResolver: true)
|
approvalDecision: DocumentVersionApprovalDecision @goField(forceResolver: true)
|
||||||
publishedAt: Datetime
|
publishedAt: Datetime
|
||||||
@@ -4642,7 +4641,6 @@ input UpdateDocumentInput {
|
|||||||
id: ID!
|
id: ID!
|
||||||
title: String
|
title: String
|
||||||
content: String
|
content: String
|
||||||
documentType: DocumentType
|
|
||||||
trustCenterVisibility: TrustCenterVisibility
|
trustCenterVisibility: TrustCenterVisibility
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5529,6 +5527,7 @@ type DocumentVersion implements Node {
|
|||||||
changelog: String!
|
changelog: String!
|
||||||
title: String!
|
title: String!
|
||||||
classification: DocumentClassification!
|
classification: DocumentClassification!
|
||||||
|
documentType: DocumentType!
|
||||||
approvers(
|
approvers(
|
||||||
first: Int
|
first: Int
|
||||||
after: CursorKey
|
after: CursorKey
|
||||||
@@ -5900,6 +5899,7 @@ input UpdateDocumentVersionInput {
|
|||||||
documentVersionId: ID!
|
documentVersionId: ID!
|
||||||
content: String
|
content: String
|
||||||
classification: DocumentClassification
|
classification: DocumentClassification
|
||||||
|
documentType: DocumentType
|
||||||
}
|
}
|
||||||
|
|
||||||
input CancelSignatureRequestInput {
|
input CancelSignatureRequestInput {
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ func NewDocument(document *coredata.Document) *Document {
|
|||||||
Organization: &Organization{
|
Organization: &Organization{
|
||||||
ID: document.OrganizationID,
|
ID: document.OrganizationID,
|
||||||
},
|
},
|
||||||
DocumentType: document.DocumentType,
|
|
||||||
CurrentPublishedMajor: document.CurrentPublishedMajor,
|
CurrentPublishedMajor: document.CurrentPublishedMajor,
|
||||||
CurrentPublishedMinor: document.CurrentPublishedMinor,
|
CurrentPublishedMinor: document.CurrentPublishedMinor,
|
||||||
TrustCenterVisibility: document.TrustCenterVisibility,
|
TrustCenterVisibility: document.TrustCenterVisibility,
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ func NewDocumentVersion(documentVersion *coredata.DocumentVersion) *DocumentVers
|
|||||||
Content: documentVersion.Content,
|
Content: documentVersion.Content,
|
||||||
Status: documentVersion.Status,
|
Status: documentVersion.Status,
|
||||||
Classification: documentVersion.Classification,
|
Classification: documentVersion.Classification,
|
||||||
|
DocumentType: documentVersion.DocumentType,
|
||||||
PublishedAt: documentVersion.PublishedAt,
|
PublishedAt: documentVersion.PublishedAt,
|
||||||
Changelog: documentVersion.Changelog,
|
Changelog: documentVersion.Changelog,
|
||||||
CreatedAt: documentVersion.CreatedAt,
|
CreatedAt: documentVersion.CreatedAt,
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ type (
|
|||||||
Minor int
|
Minor int
|
||||||
Status coredata.DocumentVersionStatus
|
Status coredata.DocumentVersionStatus
|
||||||
Classification coredata.DocumentClassification
|
Classification coredata.DocumentClassification
|
||||||
|
DocumentType coredata.DocumentType
|
||||||
PublishedAt *time.Time
|
PublishedAt *time.Time
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
|
|||||||
@@ -2168,6 +2168,7 @@ func (r *employeeDocumentResolver) Versions(ctx context.Context, obj *types.Empl
|
|||||||
Minor: v.Minor,
|
Minor: v.Minor,
|
||||||
Status: v.Status,
|
Status: v.Status,
|
||||||
Classification: v.Classification,
|
Classification: v.Classification,
|
||||||
|
DocumentType: v.DocumentType,
|
||||||
PublishedAt: v.PublishedAt,
|
PublishedAt: v.PublishedAt,
|
||||||
CreatedAt: v.CreatedAt,
|
CreatedAt: v.CreatedAt,
|
||||||
UpdatedAt: v.UpdatedAt,
|
UpdatedAt: v.UpdatedAt,
|
||||||
@@ -5142,10 +5143,10 @@ func (r *mutationResolver) CreateDocument(ctx context.Context, input types.Creat
|
|||||||
ctx,
|
ctx,
|
||||||
probo.CreateDocumentRequest{
|
probo.CreateDocumentRequest{
|
||||||
OrganizationID: input.OrganizationID,
|
OrganizationID: input.OrganizationID,
|
||||||
DocumentType: input.DocumentType,
|
|
||||||
Title: input.Title,
|
Title: input.Title,
|
||||||
Content: content,
|
Content: content,
|
||||||
Classification: input.Classification,
|
Classification: input.Classification,
|
||||||
|
DocumentType: input.DocumentType,
|
||||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -5180,7 +5181,6 @@ func (r *mutationResolver) UpdateDocument(ctx context.Context, input types.Updat
|
|||||||
probo.UpdateDocumentRequest{
|
probo.UpdateDocumentRequest{
|
||||||
DocumentID: input.ID,
|
DocumentID: input.ID,
|
||||||
Title: input.Title,
|
Title: input.Title,
|
||||||
DocumentType: input.DocumentType,
|
|
||||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -5923,6 +5923,7 @@ func (r *mutationResolver) UpdateDocumentVersion(ctx context.Context, input type
|
|||||||
ID: input.DocumentVersionID,
|
ID: input.DocumentVersionID,
|
||||||
Content: input.Content,
|
Content: input.Content,
|
||||||
Classification: input.Classification,
|
Classification: input.Classification,
|
||||||
|
DocumentType: input.DocumentType,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2095,7 +2095,6 @@ func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequ
|
|||||||
probo.UpdateDocumentRequest{
|
probo.UpdateDocumentRequest{
|
||||||
DocumentID: input.ID,
|
DocumentID: input.ID,
|
||||||
Title: input.Title,
|
Title: input.Title,
|
||||||
DocumentType: input.DocumentType,
|
|
||||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -2201,6 +2200,7 @@ func (r *Resolver) UpdateDocumentVersionTool(ctx context.Context, req *mcp.CallT
|
|||||||
ID: input.DocumentVersionID,
|
ID: input.DocumentVersionID,
|
||||||
Content: content,
|
Content: content,
|
||||||
Classification: input.Classification,
|
Classification: input.Classification,
|
||||||
|
DocumentType: input.DocumentType,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5207,7 +5207,6 @@ components:
|
|||||||
- id
|
- id
|
||||||
- organization_id
|
- organization_id
|
||||||
- title
|
- title
|
||||||
- document_type
|
|
||||||
- trust_center_visibility
|
- trust_center_visibility
|
||||||
- status
|
- status
|
||||||
- created_at
|
- created_at
|
||||||
@@ -5222,9 +5221,6 @@ components:
|
|||||||
title:
|
title:
|
||||||
type: string
|
type: string
|
||||||
description: Document title
|
description: Document title
|
||||||
document_type:
|
|
||||||
$ref: "#/components/schemas/DocumentType"
|
|
||||||
description: Document type
|
|
||||||
current_published_major:
|
current_published_major:
|
||||||
type:
|
type:
|
||||||
- integer
|
- integer
|
||||||
@@ -5266,6 +5262,7 @@ components:
|
|||||||
- major
|
- major
|
||||||
- minor
|
- minor
|
||||||
- classification
|
- classification
|
||||||
|
- document_type
|
||||||
- content
|
- content
|
||||||
- changelog
|
- changelog
|
||||||
- status
|
- status
|
||||||
@@ -5293,6 +5290,9 @@ components:
|
|||||||
classification:
|
classification:
|
||||||
$ref: "#/components/schemas/DocumentClassification"
|
$ref: "#/components/schemas/DocumentClassification"
|
||||||
description: Document classification
|
description: Document classification
|
||||||
|
document_type:
|
||||||
|
$ref: "#/components/schemas/DocumentType"
|
||||||
|
description: Document type
|
||||||
content:
|
content:
|
||||||
type: string
|
type: string
|
||||||
description: Document content
|
description: Document content
|
||||||
@@ -5482,9 +5482,6 @@ components:
|
|||||||
title:
|
title:
|
||||||
type: string
|
type: string
|
||||||
description: Document title
|
description: Document title
|
||||||
document_type:
|
|
||||||
$ref: "#/components/schemas/DocumentType"
|
|
||||||
description: Document type
|
|
||||||
trust_center_visibility:
|
trust_center_visibility:
|
||||||
$ref: "#/components/schemas/TrustCenterVisibility"
|
$ref: "#/components/schemas/TrustCenterVisibility"
|
||||||
description: Trust center visibility
|
description: Trust center visibility
|
||||||
@@ -5613,6 +5610,9 @@ components:
|
|||||||
classification:
|
classification:
|
||||||
$ref: "#/components/schemas/DocumentClassification"
|
$ref: "#/components/schemas/DocumentClassification"
|
||||||
description: Document classification
|
description: Document classification
|
||||||
|
document_type:
|
||||||
|
$ref: "#/components/schemas/DocumentType"
|
||||||
|
description: Document type
|
||||||
|
|
||||||
UpdateDocumentVersionOutput:
|
UpdateDocumentVersionOutput:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ func NewDocument(d *coredata.Document) *Document {
|
|||||||
ID: d.ID,
|
ID: d.ID,
|
||||||
OrganizationID: d.OrganizationID,
|
OrganizationID: d.OrganizationID,
|
||||||
Title: d.Title,
|
Title: d.Title,
|
||||||
DocumentType: d.DocumentType,
|
|
||||||
CurrentPublishedMajor: d.CurrentPublishedMajor,
|
CurrentPublishedMajor: d.CurrentPublishedMajor,
|
||||||
CurrentPublishedMinor: d.CurrentPublishedMinor,
|
CurrentPublishedMinor: d.CurrentPublishedMinor,
|
||||||
TrustCenterVisibility: d.TrustCenterVisibility,
|
TrustCenterVisibility: d.TrustCenterVisibility,
|
||||||
@@ -87,6 +86,7 @@ func NewDocumentVersion(dv *coredata.DocumentVersion) *DocumentVersion {
|
|||||||
Major: dv.Major,
|
Major: dv.Major,
|
||||||
Minor: dv.Minor,
|
Minor: dv.Minor,
|
||||||
Classification: dv.Classification,
|
Classification: dv.Classification,
|
||||||
|
DocumentType: dv.DocumentType,
|
||||||
Content: dv.Content,
|
Content: dv.Content,
|
||||||
Changelog: dv.Changelog,
|
Changelog: dv.Changelog,
|
||||||
Status: dv.Status,
|
Status: dv.Status,
|
||||||
|
|||||||
Reference in New Issue
Block a user