diff --git a/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts b/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts index 8ad92badd..b7dc37aa3 100644 --- a/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts +++ b/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<3c8b528580116deec511c979e209cfc3>> + * @generated SignedSource<<849144f476ae613437242fe09259fc68>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; export type SnapshotBannerQuery$variables = { snapshotId: string; }; diff --git a/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts b/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts index a6873648f..edd19d312 100644 --- a/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts +++ b/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<32724438ee7e1d53f9c53938a8129e4b>> + * @generated SignedSource<<4856a36194f867773166e9420b403d0b>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; import { FragmentRefs } from "relay-runtime"; export type LinkedSnapshotsCardFragment$data = { readonly createdAt: any; diff --git a/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts b/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts index ac3f00441..61b3217f2 100644 --- a/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts +++ b/apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<1348b159bfe8d53aa1b080efc63bd1b4>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; import { FragmentRefs } from "relay-runtime"; export type LinkedSnapshotsDialogFragment$data = { readonly id: string; diff --git a/apps/console/src/hooks/graph/ContinualImprovementRegistryGraph.ts b/apps/console/src/hooks/graph/ContinualImprovementRegistryGraph.ts index 0ba0077ba..72dfe58ad 100644 --- a/apps/console/src/hooks/graph/ContinualImprovementRegistryGraph.ts +++ b/apps/console/src/hooks/graph/ContinualImprovementRegistryGraph.ts @@ -8,10 +8,10 @@ import { useMutationWithToasts } from "../useMutationWithToasts"; export const ContinualImprovementRegistriesConnectionKey = "ContinualImprovementRegistriesPage_continualImprovementRegistries"; export const continualImprovementRegistriesQuery = graphql` - query ContinualImprovementRegistryGraphListQuery($organizationId: ID!) { + query ContinualImprovementRegistryGraphListQuery($organizationId: ID!, $snapshotId: ID) { node(id: $organizationId) { ... on Organization { - ...ContinualImprovementRegistriesPageFragment + ...ContinualImprovementRegistriesPageFragment @arguments(snapshotId: $snapshotId) } } } @@ -22,6 +22,8 @@ export const continualImprovementRegistryNodeQuery = graphql` node(id: $continualImprovementRegistryId) { ... on ContinualImprovementRegistry { id + snapshotId + sourceId referenceId description source diff --git a/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphListQuery.graphql.ts index 41460a86c..24eb398cb 100644 --- a/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<09a183f301bdb0deae825495f9fdd438>> + * @generated SignedSource<<95ba9ae06f433c92486e63832eb9166d>> * @lightSyntaxTransform * @nogrep */ @@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type ContinualImprovementRegistryGraphListQuery$variables = { organizationId: string; + snapshotId?: string | null | undefined; }; export type ContinualImprovementRegistryGraphListQuery$data = { readonly node: { @@ -29,6 +30,11 @@ var v0 = [ "defaultValue": null, "kind": "LocalArgument", "name": "organizationId" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "snapshotId" } ], v1 = [ @@ -38,21 +44,33 @@ v1 = [ "variableName": "organizationId" } ], -v2 = { +v2 = [ + { + "kind": "Variable", + "name": "snapshotId", + "variableName": "snapshotId" + } +], +v3 = { "alias": null, "args": null, "kind": "ScalarField", "name": "__typename", "storageKey": null }, -v3 = { +v4 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null }, -v4 = [ +v5 = [ + { + "fields": (v2/*: any*/), + "kind": "ObjectValue", + "name": "filter" + }, { "kind": "Literal", "name": "first", @@ -78,7 +96,7 @@ return { "kind": "InlineFragment", "selections": [ { - "args": null, + "args": (v2/*: any*/), "kind": "FragmentSpread", "name": "ContinualImprovementRegistriesPageFragment" } @@ -107,14 +125,14 @@ return { "name": "node", "plural": false, "selections": [ - (v2/*: any*/), (v3/*: any*/), + (v4/*: any*/), { "kind": "InlineFragment", "selections": [ { "alias": null, - "args": (v4/*: any*/), + "args": (v5/*: any*/), "concreteType": "ContinualImprovementRegistryConnection", "kind": "LinkedField", "name": "continualImprovementRegistries", @@ -143,7 +161,21 @@ return { "name": "node", "plural": false, "selections": [ - (v3/*: any*/), + (v4/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "snapshotId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "sourceId", + "storageKey": null + }, { "alias": null, "args": null, @@ -194,7 +226,7 @@ return { "name": "owner", "plural": false, "selections": [ - (v3/*: any*/), + (v4/*: any*/), { "alias": null, "args": null, @@ -219,7 +251,7 @@ return { "name": "updatedAt", "storageKey": null }, - (v2/*: any*/) + (v3/*: any*/) ], "storageKey": null }, @@ -271,12 +303,14 @@ return { ] } ], - "storageKey": "continualImprovementRegistries(first:10)" + "storageKey": null }, { "alias": null, - "args": (v4/*: any*/), - "filters": null, + "args": (v5/*: any*/), + "filters": [ + "filter" + ], "handle": "connection", "key": "ContinualImprovementRegistriesPage_continualImprovementRegistries", "kind": "LinkedHandle", @@ -292,16 +326,16 @@ return { ] }, "params": { - "cacheID": "248942c6d0d46f56e8c55fd3eb1e8888", + "cacheID": "b629619a1e2a00d3e58ae908977124b0", "id": null, "metadata": {}, "name": "ContinualImprovementRegistryGraphListQuery", "operationKind": "query", - "text": "query ContinualImprovementRegistryGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ContinualImprovementRegistriesPageFragment\n }\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment on Organization {\n id\n continualImprovementRegistries(first: 10) {\n totalCount\n edges {\n node {\n id\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" + "text": "query ContinualImprovementRegistryGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ContinualImprovementRegistriesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment_3iomuz on Organization {\n id\n continualImprovementRegistries(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" } }; })(); -(node as any).hash = "1098fc11629892073fbe6d7561b229e3"; +(node as any).hash = "46857b16d3bdb52307eacf7c4e607d2f"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphNodeQuery.graphql.ts index 805661e1a..6591aa907 100644 --- a/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/ContinualImprovementRegistryGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<9992eeb0b74e7015c5f4d3520a87a402>> * @lightSyntaxTransform * @nogrep */ @@ -29,7 +29,9 @@ export type ContinualImprovementRegistryGraphNodeQuery$data = { }; readonly priority?: ContinualImprovementRegistriesPriority; readonly referenceId?: string; + readonly snapshotId?: string | null | undefined; readonly source?: string | null | undefined; + readonly sourceId?: string | null | undefined; readonly status?: ContinualImprovementRegistriesStatus; readonly targetDate?: any | null | undefined; readonly updatedAt?: any; @@ -66,45 +68,59 @@ v3 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "referenceId", + "name": "snapshotId", "storageKey": null }, v4 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "description", + "name": "sourceId", "storageKey": null }, v5 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "source", + "name": "referenceId", "storageKey": null }, v6 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "targetDate", + "name": "description", "storageKey": null }, v7 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "status", + "name": "source", "storageKey": null }, v8 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "priority", + "name": "targetDate", "storageKey": null }, v9 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null +}, +v10 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "priority", + "storageKey": null +}, +v11 = { "alias": null, "args": null, "concreteType": "People", @@ -123,7 +139,7 @@ v9 = { ], "storageKey": null }, -v10 = { +v12 = { "alias": null, "args": null, "concreteType": "Organization", @@ -142,14 +158,14 @@ v10 = { ], "storageKey": null }, -v11 = { +v13 = { "alias": null, "args": null, "kind": "ScalarField", "name": "createdAt", "storageKey": null }, -v12 = { +v14 = { "alias": null, "args": null, "kind": "ScalarField", @@ -184,7 +200,9 @@ return { (v9/*: any*/), (v10/*: any*/), (v11/*: any*/), - (v12/*: any*/) + (v12/*: any*/), + (v13/*: any*/), + (v14/*: any*/) ], "type": "ContinualImprovementRegistry", "abstractKey": null @@ -230,7 +248,9 @@ return { (v9/*: any*/), (v10/*: any*/), (v11/*: any*/), - (v12/*: any*/) + (v12/*: any*/), + (v13/*: any*/), + (v14/*: any*/) ], "type": "ContinualImprovementRegistry", "abstractKey": null @@ -241,16 +261,16 @@ return { ] }, "params": { - "cacheID": "cdf6a776528b7eb148caaa696e7c348c", + "cacheID": "dc67877ad1fe94bfeb50490a9ca6692b", "id": null, "metadata": {}, "name": "ContinualImprovementRegistryGraphNodeQuery", "operationKind": "query", - "text": "query ContinualImprovementRegistryGraphNodeQuery(\n $continualImprovementRegistryId: ID!\n) {\n node(id: $continualImprovementRegistryId) {\n __typename\n ... on ContinualImprovementRegistry {\n id\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" + "text": "query ContinualImprovementRegistryGraphNodeQuery(\n $continualImprovementRegistryId: ID!\n) {\n node(id: $continualImprovementRegistryId) {\n __typename\n ... on ContinualImprovementRegistry {\n id\n snapshotId\n sourceId\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "1b5811e2cd314786117ef60841743dc5"; +(node as any).hash = "659dd712ecf01765f6d5ef0f9d7d2a08"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/SnapshotGraphCreateMutation.graphql.ts b/apps/console/src/hooks/graph/__generated__/SnapshotGraphCreateMutation.graphql.ts index b9af1ffef..8129f2ad6 100644 --- a/apps/console/src/hooks/graph/__generated__/SnapshotGraphCreateMutation.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/SnapshotGraphCreateMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<9f17487d2517912ef9f93b0026eaa555>> + * @generated SignedSource<<0b691997398fc5779891f6ce551192ae>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; export type CreateSnapshotInput = { description?: string | null | undefined; name: string; diff --git a/apps/console/src/hooks/graph/__generated__/SnapshotGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/SnapshotGraphNodeQuery.graphql.ts index 1fcf75c00..d7367d6db 100644 --- a/apps/console/src/hooks/graph/__generated__/SnapshotGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/SnapshotGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<202fa0acc16dc4343e193fb3f6784f3c>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; export type SnapshotGraphNodeQuery$variables = { snapshotId: string; }; diff --git a/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage.tsx b/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage.tsx index c04c3f2d4..444f0bd34 100644 --- a/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage.tsx +++ b/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage.tsx @@ -26,9 +26,11 @@ import { type PreloadedQuery, } from "react-relay"; import { useOrganizationId } from "/hooks/useOrganizationId"; +import { useParams } from "react-router"; import { CreateContinualImprovementRegistryDialog } from "./dialogs/CreateContinualImprovementRegistryDialog"; import { deleteContinualImprovementRegistryMutation, ContinualImprovementRegistriesConnectionKey } from "../../../hooks/graph/ContinualImprovementRegistryGraph"; import { sprintf, promisifyMutation, getStatusVariant, getStatusLabel } from "@probo/helpers"; +import { SnapshotBanner } from "/components/SnapshotBanner"; import type { NodeOf } from "/types"; import type { ContinualImprovementRegistriesPageQuery } from "./__generated__/ContinualImprovementRegistriesPageQuery.graphql"; import type { @@ -46,15 +48,22 @@ const continualImprovementRegistriesPageFragment = graphql` @argumentDefinitions( first: { type: "Int", defaultValue: 10 } after: { type: "CursorKey" } + snapshotId: { type: "ID", defaultValue: null } ) { id - continualImprovementRegistries(first: $first, after: $after) - @connection(key: "ContinualImprovementRegistriesPage_continualImprovementRegistries") { + continualImprovementRegistries( + first: $first + after: $after + filter: { snapshotId: $snapshotId } + ) + @connection(key: "ContinualImprovementRegistriesPage_continualImprovementRegistries", filters: ["filter"]) { __id totalCount edges { node { id + snapshotId + sourceId referenceId description source @@ -80,15 +89,17 @@ const continualImprovementRegistriesPageFragment = graphql` export default function ContinualImprovementRegistriesPage({ queryRef }: ContinualImprovementRegistriesPageProps) { const { __ } = useTranslate(); const organizationId = useOrganizationId(); + const { snapshotId } = useParams<{ snapshotId?: string }>(); + const isSnapshotMode = Boolean(snapshotId); usePageTitle(__("Continual Improvement Registries")); const organization = usePreloadedQuery( graphql` - query ContinualImprovementRegistriesPageQuery($organizationId: ID!) { + query ContinualImprovementRegistriesPageQuery($organizationId: ID!, $snapshotId: ID) { node(id: $organizationId) { ... on Organization { - ...ContinualImprovementRegistriesPageFragment + ...ContinualImprovementRegistriesPageFragment @arguments(snapshotId: $snapshotId) } } } @@ -111,21 +122,27 @@ export default function ContinualImprovementRegistriesPage({ queryRef }: Continu const connectionId = ConnectionHandler.getConnectionID( organizationId, - ContinualImprovementRegistriesConnectionKey + ContinualImprovementRegistriesConnectionKey, + { filter: { snapshotId: snapshotId || null } } ); const registries = data?.continualImprovementRegistries?.edges?.map((edge) => edge.node) ?? []; return (
+ {isSnapshotMode && snapshotId && ( + + )} - - - + {!isSnapshotMode && ( + + + + )} {registries.length > 0 ? ( @@ -139,7 +156,7 @@ export default function ContinualImprovementRegistriesPage({ queryRef }: Continu {__("Priority")} {__("Owner")} {__("Target Date")} - {__("Actions")} + {!isSnapshotMode && {__("Actions")}} @@ -148,6 +165,7 @@ export default function ContinualImprovementRegistriesPage({ queryRef }: Continu key={registry.id} registry={registry} connectionId={connectionId} + snapshotId={snapshotId} /> ))} @@ -184,14 +202,17 @@ export default function ContinualImprovementRegistriesPage({ queryRef }: Continu function RegistryRow({ registry, connectionId, + snapshotId, }: { registry: NodeOf>; connectionId: string; + snapshotId?: string; }) { const organizationId = useOrganizationId(); const { __ } = useTranslate(); const [deleteRegistry] = useMutation(deleteContinualImprovementRegistryMutation); const confirm = useConfirm(); + const isSnapshotMode = Boolean(snapshotId); const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString(); @@ -219,8 +240,12 @@ function RegistryRow({ ); }; + const detailsUrl = isSnapshotMode + ? `/organizations/${organizationId}/snapshots/${snapshotId}/continual-improvement-registries/${registry.id}` + : `/organizations/${organizationId}/continual-improvement-registries/${registry.id}`; + return ( - + {registry.referenceId} @@ -245,17 +270,19 @@ function RegistryRow({ {__("No target date")} )} - - - - {__("Delete")} - - - + {!isSnapshotMode && ( + + + + {__("Delete")} + + + + )} ); } diff --git a/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage.tsx b/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage.tsx index 21dd3d849..baf0dbbc7 100644 --- a/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage.tsx +++ b/apps/console/src/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage.tsx @@ -25,12 +25,14 @@ import { Label, } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; +import { useParams } from "react-router"; import { useOrganizationId } from "/hooks/useOrganizationId"; import { PeopleSelectField } from "/components/form/PeopleSelectField"; import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { Controller } from "react-hook-form"; import z from "zod"; -import { getStatusVariant, getStatusLabel, formatDatetime } from "@probo/helpers"; +import { getStatusVariant, getStatusLabel, formatDatetime, validateSnapshotConsistency } from "@probo/helpers"; +import { SnapshotBanner } from "/components/SnapshotBanner"; import type { ContinualImprovementRegistryGraphNodeQuery } from "/hooks/graph/__generated__/ContinualImprovementRegistryGraphNodeQuery.graphql"; const updateRegistrySchema = z.object({ @@ -53,16 +55,21 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { const { __ } = useTranslate(); const { toast } = useToast(); const organizationId = useOrganizationId(); + const { snapshotId } = useParams<{ snapshotId?: string }>(); + const isSnapshotMode = Boolean(snapshotId); if (!registry) { return
{__("Continual improvement registry entry not found")}
; } + validateSnapshotConsistency(registry, snapshotId); + const updateRegistry = useUpdateContinualImprovementRegistry(); const connectionId = ConnectionHandler.getConnectionID( organizationId, - ContinualImprovementRegistriesConnectionKey + ContinualImprovementRegistriesConnectionKey, + { filter: { snapshotId: snapshotId || null } } ); const deleteRegistry = useDeleteContinualImprovementRegistry({ id: registry.id!, referenceId: registry.referenceId! }, connectionId); @@ -124,20 +131,29 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { { value: "HIGH", label: __("High") }, ]; + const breadcrumbRegistriesUrl = isSnapshotMode + ? `/organizations/${organizationId}/snapshots/${snapshotId}/continual-improvement-registries` + : `/organizations/${organizationId}/continual-improvement-registries`; + return (
+ {isSnapshotMode && snapshotId && ( + + )}
- - - {__("Delete")} - - + {!isSnapshotMode && ( + + + {__("Delete")} + + + )}
@@ -159,6 +175,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { label={__("Reference ID")} {...register("referenceId")} error={formState.errors.referenceId?.message} + readOnly={isSnapshotMode} required /> @@ -170,6 +187,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { {...register("description")} placeholder={__("Enter description")} rows={3} + readOnly={isSnapshotMode} /> {formState.errors.description?.message && (
@@ -183,6 +201,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { label={__("Source")} {...register("source")} error={formState.errors.source?.message} + readOnly={isSnapshotMode} />
@@ -190,6 +209,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { {formState.errors.targetDate?.message && (
@@ -205,6 +225,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { name="ownerId" label={__("Owner")} error={formState.errors.ownerId?.message} + disabled={isSnapshotMode} required /> @@ -218,6 +239,7 @@ export default function ContinualImprovementRegistryDetailsPage(props: Props) { {priorityOptions.map((option) => (
-
- -
+ {!isSnapshotMode && ( +
+ +
+ )}
diff --git a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageFragment.graphql.ts b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageFragment.graphql.ts index a2bde990b..7523a074e 100644 --- a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageFragment.graphql.ts +++ b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -26,7 +26,9 @@ export type ContinualImprovementRegistriesPageFragment$data = { }; readonly priority: ContinualImprovementRegistriesPriority; readonly referenceId: string; + readonly snapshotId: string | null | undefined; readonly source: string | null | undefined; + readonly sourceId: string | null | undefined; readonly status: ContinualImprovementRegistriesStatus; readonly targetDate: any | null | undefined; readonly updatedAt: any; @@ -70,6 +72,11 @@ return { "defaultValue": 10, "kind": "LocalArgument", "name": "first" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "snapshotId" } ], "kind": "Fragment", @@ -106,7 +113,19 @@ return { (v1/*: any*/), { "alias": "continualImprovementRegistries", - "args": null, + "args": [ + { + "fields": [ + { + "kind": "Variable", + "name": "snapshotId", + "variableName": "snapshotId" + } + ], + "kind": "ObjectValue", + "name": "filter" + } + ], "concreteType": "ContinualImprovementRegistryConnection", "kind": "LinkedField", "name": "__ContinualImprovementRegistriesPage_continualImprovementRegistries_connection", @@ -136,6 +155,20 @@ return { "plural": false, "selections": [ (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "snapshotId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "sourceId", + "storageKey": null + }, { "alias": null, "args": null, @@ -277,6 +310,6 @@ return { }; })(); -(node as any).hash = "1532ac43a0b47d9cd63980861eaa7306"; +(node as any).hash = "9e11628f65527ac1ff8974faa1855280"; export default node; diff --git a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageQuery.graphql.ts b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageQuery.graphql.ts index 06e23b112..609ed8d2f 100644 --- a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageQuery.graphql.ts +++ b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<32acc7b83177d41eb30081c290ba1393>> * @lightSyntaxTransform * @nogrep */ @@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type ContinualImprovementRegistriesPageQuery$variables = { organizationId: string; + snapshotId?: string | null | undefined; }; export type ContinualImprovementRegistriesPageQuery$data = { readonly node: { @@ -29,6 +30,11 @@ var v0 = [ "defaultValue": null, "kind": "LocalArgument", "name": "organizationId" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "snapshotId" } ], v1 = [ @@ -38,21 +44,33 @@ v1 = [ "variableName": "organizationId" } ], -v2 = { +v2 = [ + { + "kind": "Variable", + "name": "snapshotId", + "variableName": "snapshotId" + } +], +v3 = { "alias": null, "args": null, "kind": "ScalarField", "name": "__typename", "storageKey": null }, -v3 = { +v4 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null }, -v4 = [ +v5 = [ + { + "fields": (v2/*: any*/), + "kind": "ObjectValue", + "name": "filter" + }, { "kind": "Literal", "name": "first", @@ -78,7 +96,7 @@ return { "kind": "InlineFragment", "selections": [ { - "args": null, + "args": (v2/*: any*/), "kind": "FragmentSpread", "name": "ContinualImprovementRegistriesPageFragment" } @@ -107,14 +125,14 @@ return { "name": "node", "plural": false, "selections": [ - (v2/*: any*/), (v3/*: any*/), + (v4/*: any*/), { "kind": "InlineFragment", "selections": [ { "alias": null, - "args": (v4/*: any*/), + "args": (v5/*: any*/), "concreteType": "ContinualImprovementRegistryConnection", "kind": "LinkedField", "name": "continualImprovementRegistries", @@ -143,7 +161,21 @@ return { "name": "node", "plural": false, "selections": [ - (v3/*: any*/), + (v4/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "snapshotId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "sourceId", + "storageKey": null + }, { "alias": null, "args": null, @@ -194,7 +226,7 @@ return { "name": "owner", "plural": false, "selections": [ - (v3/*: any*/), + (v4/*: any*/), { "alias": null, "args": null, @@ -219,7 +251,7 @@ return { "name": "updatedAt", "storageKey": null }, - (v2/*: any*/) + (v3/*: any*/) ], "storageKey": null }, @@ -271,12 +303,14 @@ return { ] } ], - "storageKey": "continualImprovementRegistries(first:10)" + "storageKey": null }, { "alias": null, - "args": (v4/*: any*/), - "filters": null, + "args": (v5/*: any*/), + "filters": [ + "filter" + ], "handle": "connection", "key": "ContinualImprovementRegistriesPage_continualImprovementRegistries", "kind": "LinkedHandle", @@ -292,16 +326,16 @@ return { ] }, "params": { - "cacheID": "aefda1aa296696b978edb452106544c5", + "cacheID": "8cf92f4e9c75b4a42350503ae2d30cae", "id": null, "metadata": {}, "name": "ContinualImprovementRegistriesPageQuery", "operationKind": "query", - "text": "query ContinualImprovementRegistriesPageQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ContinualImprovementRegistriesPageFragment\n }\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment on Organization {\n id\n continualImprovementRegistries(first: 10) {\n totalCount\n edges {\n node {\n id\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" + "text": "query ContinualImprovementRegistriesPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ContinualImprovementRegistriesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment_3iomuz on Organization {\n id\n continualImprovementRegistries(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" } }; })(); -(node as any).hash = "fcece87ab1695d20b6b5f31379e67f1d"; +(node as any).hash = "506a807c01116d1b5622ac2624d5bf1b"; export default node; diff --git a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageRefetchQuery.graphql.ts b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageRefetchQuery.graphql.ts index aad7f7f68..ce0d3662e 100644 --- a/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageRefetchQuery.graphql.ts +++ b/apps/console/src/pages/organizations/continualImprovementRegistries/__generated__/ContinualImprovementRegistriesPageRefetchQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<105f0362fe12b8fd084e076e760d51f2>> + * @generated SignedSource<<7edb3bd39c98d7799e4b5eabccb36175>> * @lightSyntaxTransform * @nogrep */ @@ -14,6 +14,7 @@ export type ContinualImprovementRegistriesPageRefetchQuery$variables = { after?: any | null | undefined; first?: number | null | undefined; id: string; + snapshotId?: string | null | undefined; }; export type ContinualImprovementRegistriesPageRefetchQuery$data = { readonly node: { @@ -26,73 +27,99 @@ export type ContinualImprovementRegistriesPageRefetchQuery = { }; const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "after" - }, - { - "defaultValue": 10, - "kind": "LocalArgument", - "name": "first" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "id" - } -], -v1 = [ +var v0 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" +}, +v1 = { + "defaultValue": 10, + "kind": "LocalArgument", + "name": "first" +}, +v2 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "id" +}, +v3 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "snapshotId" +}, +v4 = [ { "kind": "Variable", "name": "id", "variableName": "id" } ], -v2 = [ - { - "kind": "Variable", - "name": "after", - "variableName": "after" - }, - { - "kind": "Variable", - "name": "first", - "variableName": "first" - } -], -v3 = { +v5 = { + "kind": "Variable", + "name": "after", + "variableName": "after" +}, +v6 = { + "kind": "Variable", + "name": "first", + "variableName": "first" +}, +v7 = { + "kind": "Variable", + "name": "snapshotId", + "variableName": "snapshotId" +}, +v8 = { "alias": null, "args": null, "kind": "ScalarField", "name": "__typename", "storageKey": null }, -v4 = { +v9 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null -}; +}, +v10 = [ + (v5/*: any*/), + { + "fields": [ + (v7/*: any*/) + ], + "kind": "ObjectValue", + "name": "filter" + }, + (v6/*: any*/) +]; return { "fragment": { - "argumentDefinitions": (v0/*: any*/), + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/), + (v3/*: any*/) + ], "kind": "Fragment", "metadata": null, "name": "ContinualImprovementRegistriesPageRefetchQuery", "selections": [ { "alias": null, - "args": (v1/*: any*/), + "args": (v4/*: any*/), "concreteType": null, "kind": "LinkedField", "name": "node", "plural": false, "selections": [ { - "args": (v2/*: any*/), + "args": [ + (v5/*: any*/), + (v6/*: any*/), + (v7/*: any*/) + ], "kind": "FragmentSpread", "name": "ContinualImprovementRegistriesPageFragment" } @@ -105,26 +132,31 @@ return { }, "kind": "Request", "operation": { - "argumentDefinitions": (v0/*: any*/), + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v3/*: any*/), + (v2/*: any*/) + ], "kind": "Operation", "name": "ContinualImprovementRegistriesPageRefetchQuery", "selections": [ { "alias": null, - "args": (v1/*: any*/), + "args": (v4/*: any*/), "concreteType": null, "kind": "LinkedField", "name": "node", "plural": false, "selections": [ - (v3/*: any*/), - (v4/*: any*/), + (v8/*: any*/), + (v9/*: any*/), { "kind": "InlineFragment", "selections": [ { "alias": null, - "args": (v2/*: any*/), + "args": (v10/*: any*/), "concreteType": "ContinualImprovementRegistryConnection", "kind": "LinkedField", "name": "continualImprovementRegistries", @@ -153,7 +185,21 @@ return { "name": "node", "plural": false, "selections": [ - (v4/*: any*/), + (v9/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "snapshotId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "sourceId", + "storageKey": null + }, { "alias": null, "args": null, @@ -204,7 +250,7 @@ return { "name": "owner", "plural": false, "selections": [ - (v4/*: any*/), + (v9/*: any*/), { "alias": null, "args": null, @@ -229,7 +275,7 @@ return { "name": "updatedAt", "storageKey": null }, - (v3/*: any*/) + (v8/*: any*/) ], "storageKey": null }, @@ -285,8 +331,10 @@ return { }, { "alias": null, - "args": (v2/*: any*/), - "filters": null, + "args": (v10/*: any*/), + "filters": [ + "filter" + ], "handle": "connection", "key": "ContinualImprovementRegistriesPage_continualImprovementRegistries", "kind": "LinkedHandle", @@ -302,16 +350,16 @@ return { ] }, "params": { - "cacheID": "2e8a89e4ba6d6811f415617a559381b1", + "cacheID": "eb4f60205ab9cae8aeb307e2fc1a8b68", "id": null, "metadata": {}, "name": "ContinualImprovementRegistriesPageRefetchQuery", "operationKind": "query", - "text": "query ContinualImprovementRegistriesPageRefetchQuery(\n $after: CursorKey\n $first: Int = 10\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ContinualImprovementRegistriesPageFragment_2HEEH6\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment_2HEEH6 on Organization {\n id\n continualImprovementRegistries(first: $first, after: $after) {\n totalCount\n edges {\n node {\n id\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" + "text": "query ContinualImprovementRegistriesPageRefetchQuery(\n $after: CursorKey\n $first: Int = 10\n $snapshotId: ID = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ContinualImprovementRegistriesPageFragment_35e0S5\n id\n }\n}\n\nfragment ContinualImprovementRegistriesPageFragment_35e0S5 on Organization {\n id\n continualImprovementRegistries(first: $first, after: $after, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" } }; })(); -(node as any).hash = "1532ac43a0b47d9cd63980861eaa7306"; +(node as any).hash = "9e11628f65527ac1ff8974faa1855280"; export default node; diff --git a/apps/console/src/pages/organizations/snapshots/__generated__/SnapshotsPageFragment.graphql.ts b/apps/console/src/pages/organizations/snapshots/__generated__/SnapshotsPageFragment.graphql.ts index 08c9df7e7..73ceab525 100644 --- a/apps/console/src/pages/organizations/snapshots/__generated__/SnapshotsPageFragment.graphql.ts +++ b/apps/console/src/pages/organizations/snapshots/__generated__/SnapshotsPageFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<515e309ba0b61b3cacd37ebd567203c4>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; import { FragmentRefs } from "relay-runtime"; export type SnapshotsPageFragment$data = { readonly snapshots: { diff --git a/apps/console/src/pages/organizations/snapshots/dialog/__generated__/SnapshotFormDialogCreateMutation.graphql.ts b/apps/console/src/pages/organizations/snapshots/dialog/__generated__/SnapshotFormDialogCreateMutation.graphql.ts index 2b3a23c21..55f67a407 100644 --- a/apps/console/src/pages/organizations/snapshots/dialog/__generated__/SnapshotFormDialogCreateMutation.graphql.ts +++ b/apps/console/src/pages/organizations/snapshots/dialog/__generated__/SnapshotFormDialogCreateMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<8e3f14794ab1cbd6c2e67ab4eb8ac373>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "CONTINUAL_IMPROVEMENT_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; export type CreateSnapshotInput = { description?: string | null | undefined; name: string; diff --git a/apps/console/src/routes/continualImprovementRegistryRoutes.ts b/apps/console/src/routes/continualImprovementRegistryRoutes.ts index bab19f060..f8eb3080e 100644 --- a/apps/console/src/routes/continualImprovementRegistryRoutes.ts +++ b/apps/console/src/routes/continualImprovementRegistryRoutes.ts @@ -9,8 +9,23 @@ export const continualImprovementRegistryRoutes = [ { path: "continual-improvement-registries", fallback: PageSkeleton, - queryLoader: ({ organizationId }: { organizationId: string }) => - loadQuery(relayEnvironment, continualImprovementRegistriesQuery, { organizationId }), + queryLoader: (params: Record) => + loadQuery(relayEnvironment, continualImprovementRegistriesQuery, { + organizationId: params.organizationId, + snapshotId: null + }), + Component: lazy( + () => import("/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage") + ), + }, + { + path: "snapshots/:snapshotId/continual-improvement-registries", + fallback: PageSkeleton, + queryLoader: (params: Record) => + loadQuery(relayEnvironment, continualImprovementRegistriesQuery, { + organizationId: params.organizationId, + snapshotId: params.snapshotId + }), Component: lazy( () => import("/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistriesPage") ), @@ -26,4 +41,15 @@ export const continualImprovementRegistryRoutes = [ () => import("/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage") ), }, + { + path: "snapshots/:snapshotId/continual-improvement-registries/:registryId", + fallback: PageSkeleton, + queryLoader: (params: Record) => + loadQuery(relayEnvironment, continualImprovementRegistryNodeQuery, { + continualImprovementRegistryId: params.registryId + }), + Component: lazy( + () => import("/pages/organizations/continualImprovementRegistries/ContinualImprovementRegistryDetailsPage") + ), + }, ] satisfies AppRoute[]; diff --git a/packages/helpers/src/snapshots.ts b/packages/helpers/src/snapshots.ts index 6bd016110..a42b3e429 100644 --- a/packages/helpers/src/snapshots.ts +++ b/packages/helpers/src/snapshots.ts @@ -4,6 +4,7 @@ export const snapshotTypes = [ "DATA", "NONCONFORMITY_REGISTRIES", "COMPLIANCE_REGISTRIES", + "CONTINUAL_IMPROVEMENT_REGISTRIES", ] as const; export function getSnapshotTypeLabel(__: Translator, type: string | null | undefined) { @@ -24,6 +25,8 @@ export function getSnapshotTypeLabel(__: Translator, type: string | null | undef return __("Nonconformity Registries"); case "COMPLIANCE_REGISTRIES": return __("Compliance Registries"); + case "CONTINUAL_IMPROVEMENT_REGISTRIES": + return __("Continual Improvement Registries"); default: return __("Unknown"); } @@ -37,6 +40,8 @@ export function getSnapshotTypeUrlPath(type?: string): string { return "/nonconformity-registries"; case "COMPLIANCE_REGISTRIES": return "/compliance-registries"; + case "CONTINUAL_IMPROVEMENT_REGISTRIES": + return "/continual-improvement-registries"; default: return ""; } diff --git a/pkg/coredata/continual_improvement_registries.go b/pkg/coredata/continual_improvement_registries.go index 64594bff5..8dc2cd53e 100644 --- a/pkg/coredata/continual_improvement_registries.go +++ b/pkg/coredata/continual_improvement_registries.go @@ -37,6 +37,8 @@ type ( TargetDate *time.Time `db:"target_date"` Status ContinualImprovementRegistriesStatus `db:"status"` Priority ContinualImprovementRegistriesPriority `db:"priority"` + SnapshotID *gid.GID `db:"snapshot_id"` + SourceID *gid.GID `db:"source_id"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } @@ -78,6 +80,8 @@ SELECT target_date, status, priority, + snapshot_id, + source_id, created_at, updated_at FROM @@ -113,6 +117,7 @@ func (cirs *ContinualImprovementRegistries) CountByOrganizationID( conn pg.Conn, scope Scoper, organizationID gid.GID, + filter *ContinualImprovementRegistryFilter, ) (int, error) { q := ` SELECT @@ -122,12 +127,14 @@ FROM WHERE %s AND organization_id = @organization_id + AND %s ` - q = fmt.Sprintf(q, scope.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment()) args := pgx.StrictNamedArgs{"organization_id": organizationID} maps.Copy(args, scope.SQLArguments()) + maps.Copy(args, filter.SQLArguments()) row := conn.QueryRow(ctx, q, args) @@ -146,6 +153,7 @@ func (cirs *ContinualImprovementRegistries) LoadByOrganizationID( scope Scoper, organizationID gid.GID, cursor *page.Cursor[ContinualImprovementRegistriesOrderField], + filter *ContinualImprovementRegistryFilter, ) error { q := ` SELECT @@ -158,6 +166,8 @@ SELECT target_date, status, priority, + snapshot_id, + source_id, created_at, updated_at FROM @@ -166,12 +176,14 @@ WHERE %s AND organization_id = @organization_id AND %s + AND %s ` - q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment()) args := pgx.StrictNamedArgs{"organization_id": organizationID} maps.Copy(args, scope.SQLArguments()) + maps.Copy(args, filter.SQLArguments()) maps.Copy(args, cursor.SQLArguments()) rows, err := conn.Query(ctx, q, args) @@ -314,3 +326,58 @@ WHERE return nil } + +func (cirs ContinualImprovementRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error { + query := ` +INSERT INTO continual_improvement_registries ( + id, + tenant_id, + snapshot_id, + source_id, + organization_id, + reference_id, + description, + source, + owner_id, + target_date, + status, + priority, + created_at, + updated_at +) +SELECT + generate_gid(decode_base64_unpadded(@tenant_id), @continual_improvement_registry_entity_type), + @tenant_id, + @snapshot_id, + r.id, + r.organization_id, + r.reference_id, + r.description, + r.source, + r.owner_id, + r.target_date, + r.status, + r.priority, + r.created_at, + r.updated_at +FROM continual_improvement_registries r +WHERE %s AND r.organization_id = @organization_id AND r.snapshot_id IS NULL + ` + + query = fmt.Sprintf(query, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "tenant_id": scope.GetTenantID(), + "snapshot_id": snapshotID, + "organization_id": organizationID, + "continual_improvement_registry_entity_type": ContinualImprovementRegistryEntityType, + } + maps.Copy(args, scope.SQLArguments()) + + _, err := conn.Exec(ctx, query, args) + if err != nil { + return fmt.Errorf("cannot insert continual improvement registry snapshots: %w", err) + } + + return nil +} diff --git a/pkg/coredata/continual_improvement_registry_filter.go b/pkg/coredata/continual_improvement_registry_filter.go new file mode 100644 index 000000000..6a01a5180 --- /dev/null +++ b/pkg/coredata/continual_improvement_registry_filter.go @@ -0,0 +1,54 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "github.com/getprobo/probo/pkg/gid" + "github.com/jackc/pgx/v5" +) + +type ( + ContinualImprovementRegistryFilter struct { + snapshotID **gid.GID + } +) + +func NewContinualImprovementRegistryFilter(snapshotID **gid.GID) *ContinualImprovementRegistryFilter { + return &ContinualImprovementRegistryFilter{ + snapshotID: snapshotID, + } +} + +func (f *ContinualImprovementRegistryFilter) SQLArguments() pgx.NamedArgs { + args := pgx.NamedArgs{} + + if f.snapshotID != nil && *f.snapshotID != nil { + args["filter_snapshot_id"] = **f.snapshotID + } + + return args +} + +func (f *ContinualImprovementRegistryFilter) SQLFragment() string { + if f.snapshotID == nil { + return "TRUE" + } + + if *f.snapshotID == nil { + return "snapshot_id IS NULL" + } else { + return "snapshot_id = @filter_snapshot_id" + } +} diff --git a/pkg/coredata/migrations/20250829T123035Z.sql b/pkg/coredata/migrations/20250829T123035Z.sql new file mode 100644 index 000000000..e41509e21 --- /dev/null +++ b/pkg/coredata/migrations/20250829T123035Z.sql @@ -0,0 +1,13 @@ +ALTER TYPE snapshots_type ADD VALUE 'CONTINUAL_IMPROVEMENT_REGISTRIES'; + +ALTER TABLE continual_improvement_registries ADD COLUMN snapshot_id TEXT; +ALTER TABLE continual_improvement_registries ADD COLUMN source_id TEXT; + +ALTER TABLE continual_improvement_registries ADD CONSTRAINT continual_improvement_registries_snapshot_id_fkey + FOREIGN KEY (snapshot_id) + REFERENCES snapshots(id) + ON UPDATE CASCADE + ON DELETE CASCADE; + +ALTER TABLE continual_improvement_registries ADD CONSTRAINT continual_improvement_registries_source_id_snapshot_id_key + UNIQUE (source_id, snapshot_id); diff --git a/pkg/coredata/snapshots_type.go b/pkg/coredata/snapshots_type.go index 7550f762d..84c61d67d 100644 --- a/pkg/coredata/snapshots_type.go +++ b/pkg/coredata/snapshots_type.go @@ -24,12 +24,13 @@ type ( ) const ( - SnapshotsTypeRisks SnapshotsType = "RISKS" - SnapshotsTypeVendors SnapshotsType = "VENDORS" - SnapshotsTypeAssets SnapshotsType = "ASSETS" - SnapshotsTypeData SnapshotsType = "DATA" - SnapshotsTypeNonConformityRegistries SnapshotsType = "NONCONFORMITY_REGISTRIES" - SnapshotsTypeComplianceRegistries SnapshotsType = "COMPLIANCE_REGISTRIES" + SnapshotsTypeRisks SnapshotsType = "RISKS" + SnapshotsTypeVendors SnapshotsType = "VENDORS" + SnapshotsTypeAssets SnapshotsType = "ASSETS" + SnapshotsTypeData SnapshotsType = "DATA" + SnapshotsTypeNonConformityRegistries SnapshotsType = "NONCONFORMITY_REGISTRIES" + SnapshotsTypeComplianceRegistries SnapshotsType = "COMPLIANCE_REGISTRIES" + SnapshotsTypeContinualImprovementRegistries SnapshotsType = "CONTINUAL_IMPROVEMENT_REGISTRIES" ) func (st SnapshotsType) String() string { @@ -60,6 +61,8 @@ func (st *SnapshotsType) Scan(value any) error { *st = SnapshotsTypeNonConformityRegistries case SnapshotsTypeComplianceRegistries.String(): *st = SnapshotsTypeComplianceRegistries + case SnapshotsTypeContinualImprovementRegistries.String(): + *st = SnapshotsTypeContinualImprovementRegistries default: return fmt.Errorf("invalid SnapshotsType value: %q", s) } diff --git a/pkg/coredata/snapshottable.go b/pkg/coredata/snapshottable.go index 7e4802c62..517e68a35 100644 --- a/pkg/coredata/snapshottable.go +++ b/pkg/coredata/snapshottable.go @@ -34,6 +34,8 @@ func GetSnapshottable(snapshotType SnapshotsType) (Snapshottable, error) { return NonconformityRegistries{}, nil case SnapshotsTypeComplianceRegistries: return ComplianceRegistries{}, nil + case SnapshotsTypeContinualImprovementRegistries: + return ContinualImprovementRegistries{}, nil default: return nil, fmt.Errorf("unsupported snapshot type: %s", snapshotType) } diff --git a/pkg/probo/continual_improvement_registries_service.go b/pkg/probo/continual_improvement_registries_service.go index c65803622..c711ccd05 100644 --- a/pkg/probo/continual_improvement_registries_service.go +++ b/pkg/probo/continual_improvement_registries_service.go @@ -213,6 +213,7 @@ func (s *ContinualImprovementRegistriesService) Delete( func (s ContinualImprovementRegistriesService) CountByOrganizationID( ctx context.Context, organizationID gid.GID, + filter *coredata.ContinualImprovementRegistryFilter, ) (int, error) { var count int @@ -220,7 +221,7 @@ func (s ContinualImprovementRegistriesService) CountByOrganizationID( ctx, func(conn pg.Conn) (err error) { registries := coredata.ContinualImprovementRegistries{} - count, err = registries.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID) + count, err = registries.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, filter) if err != nil { return fmt.Errorf("cannot count continual improvement registries: %w", err) } @@ -240,13 +241,14 @@ func (s ContinualImprovementRegistriesService) ListForOrganizationID( ctx context.Context, organizationID gid.GID, cursor *page.Cursor[coredata.ContinualImprovementRegistriesOrderField], + filter *coredata.ContinualImprovementRegistryFilter, ) (*page.Page[*coredata.ContinualImprovementRegistry, coredata.ContinualImprovementRegistriesOrderField], error) { var registries coredata.ContinualImprovementRegistries err := s.svc.pg.WithConn( ctx, func(conn pg.Conn) error { - err := registries.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID, cursor) + err := registries.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID, cursor, filter) if err != nil { return fmt.Errorf("cannot load continual improvement registries: %w", err) } diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index fd2e2f655..01983568b 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -876,6 +876,10 @@ enum SnapshotsType @goEnum( value: "github.com/getprobo/probo/pkg/coredata.SnapshotsTypeComplianceRegistries" ) + CONTINUAL_IMPROVEMENT_REGISTRIES + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.SnapshotsTypeContinualImprovementRegistries" + ) } enum SnapshotOrderField @@ -1114,6 +1118,10 @@ input ComplianceRegistryFilter { snapshotId: ID } +input ContinualImprovementRegistryFilter { + snapshotId: ID +} + # Core Types type TrustCenter implements Node { id: ID! @@ -1271,6 +1279,7 @@ type Organization implements Node { last: Int before: CursorKey orderBy: ContinualImprovementRegistriesOrder + filter: ContinualImprovementRegistryFilter ): ContinualImprovementRegistryConnection! @goField(forceResolver: true) processingActivityRegistries( @@ -1745,6 +1754,8 @@ type ComplianceRegistry implements Node { type ContinualImprovementRegistry implements Node { id: ID! + snapshotId: ID + sourceId: ID organization: Organization! @goField(forceResolver: true) referenceId: String! description: String diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 75270a20e..af50be9ed 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -231,7 +231,9 @@ type ComplexityRoot struct { Owner func(childComplexity int) int Priority func(childComplexity int) int ReferenceID func(childComplexity int) int + SnapshotID func(childComplexity int) int Source func(childComplexity int) int + SourceID func(childComplexity int) int Status func(childComplexity int) int TargetDate func(childComplexity int) int UpdatedAt func(childComplexity int) int @@ -875,7 +877,7 @@ type ComplexityRoot struct { Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) int ComplianceRegistries func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ComplianceRegistryOrderBy, filter *types.ComplianceRegistryFilter) int Connectors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ConnectorOrder) int - ContinualImprovementRegistries func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy) int + ContinualImprovementRegistries func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy, filter *types.ContinualImprovementRegistryFilter) int Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) int CreatedAt func(childComplexity int) int Data func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DatumOrderBy, filter *types.DatumFilter) int @@ -1672,7 +1674,7 @@ type OrganizationResolver interface { Audits(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) (*types.AuditConnection, error) NonconformityRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.NonconformityRegistryOrderBy, filter *types.NonconformityRegistryFilter) (*types.NonconformityRegistryConnection, error) ComplianceRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ComplianceRegistryOrderBy, filter *types.ComplianceRegistryFilter) (*types.ComplianceRegistryConnection, error) - ContinualImprovementRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy) (*types.ContinualImprovementRegistryConnection, error) + ContinualImprovementRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy, filter *types.ContinualImprovementRegistryFilter) (*types.ContinualImprovementRegistryConnection, error) ProcessingActivityRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProcessingActivityRegistryOrderBy) (*types.ProcessingActivityRegistryConnection, error) Snapshots(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) (*types.SnapshotConnection, error) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) @@ -2346,6 +2348,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.ContinualImprovementRegistry.ReferenceID(childComplexity), true + case "ContinualImprovementRegistry.snapshotId": + if e.complexity.ContinualImprovementRegistry.SnapshotID == nil { + break + } + + return e.complexity.ContinualImprovementRegistry.SnapshotID(childComplexity), true + case "ContinualImprovementRegistry.source": if e.complexity.ContinualImprovementRegistry.Source == nil { break @@ -2353,6 +2362,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.ContinualImprovementRegistry.Source(childComplexity), true + case "ContinualImprovementRegistry.sourceId": + if e.complexity.ContinualImprovementRegistry.SourceID == nil { + break + } + + return e.complexity.ContinualImprovementRegistry.SourceID(childComplexity), true + case "ContinualImprovementRegistry.status": if e.complexity.ContinualImprovementRegistry.Status == nil { break @@ -5410,7 +5426,7 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return 0, false } - return e.complexity.Organization.ContinualImprovementRegistries(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ContinualImprovementRegistriesOrderBy)), true + return e.complexity.Organization.ContinualImprovementRegistries(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ContinualImprovementRegistriesOrderBy), args["filter"].(*types.ContinualImprovementRegistryFilter)), true case "Organization.controls": if e.complexity.Organization.Controls == nil { @@ -7676,6 +7692,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputConfirmEmailInput, ec.unmarshalInputConnectorOrder, ec.unmarshalInputContinualImprovementRegistriesOrder, + ec.unmarshalInputContinualImprovementRegistryFilter, ec.unmarshalInputControlFilter, ec.unmarshalInputControlOrder, ec.unmarshalInputCreateAssetInput, @@ -8785,6 +8802,10 @@ enum SnapshotsType @goEnum( value: "github.com/getprobo/probo/pkg/coredata.SnapshotsTypeComplianceRegistries" ) + CONTINUAL_IMPROVEMENT_REGISTRIES + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.SnapshotsTypeContinualImprovementRegistries" + ) } enum SnapshotOrderField @@ -9023,6 +9044,10 @@ input ComplianceRegistryFilter { snapshotId: ID } +input ContinualImprovementRegistryFilter { + snapshotId: ID +} + # Core Types type TrustCenter implements Node { id: ID! @@ -9180,6 +9205,7 @@ type Organization implements Node { last: Int before: CursorKey orderBy: ContinualImprovementRegistriesOrder + filter: ContinualImprovementRegistryFilter ): ContinualImprovementRegistryConnection! @goField(forceResolver: true) processingActivityRegistries( @@ -9654,6 +9680,8 @@ type ComplianceRegistry implements Node { type ContinualImprovementRegistry implements Node { id: ID! + snapshotId: ID + sourceId: ID organization: Organization! @goField(forceResolver: true) referenceId: String! description: String @@ -16225,6 +16253,11 @@ func (ec *executionContext) field_Organization_continualImprovementRegistries_ar return nil, err } args["orderBy"] = arg4 + arg5, err := ec.field_Organization_continualImprovementRegistries_argsFilter(ctx, rawArgs) + if err != nil { + return nil, err + } + args["filter"] = arg5 return args, nil } func (ec *executionContext) field_Organization_continualImprovementRegistries_argsFirst( @@ -16292,6 +16325,19 @@ func (ec *executionContext) field_Organization_continualImprovementRegistries_ar return zeroVal, nil } +func (ec *executionContext) field_Organization_continualImprovementRegistries_argsFilter( + ctx context.Context, + rawArgs map[string]any, +) (*types.ContinualImprovementRegistryFilter, error) { + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + if tmp, ok := rawArgs["filter"]; ok { + return ec.unmarshalOContinualImprovementRegistryFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐContinualImprovementRegistryFilter(ctx, tmp) + } + + var zeroVal *types.ContinualImprovementRegistryFilter + return zeroVal, nil +} + func (ec *executionContext) field_Organization_controls_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -22615,6 +22661,88 @@ func (ec *executionContext) fieldContext_ContinualImprovementRegistry_id(_ conte return fc, nil } +func (ec *executionContext) _ContinualImprovementRegistry_snapshotId(ctx context.Context, field graphql.CollectedField, obj *types.ContinualImprovementRegistry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ContinualImprovementRegistry_snapshotId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SnapshotID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*gid.GID) + fc.Result = res + return ec.marshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ContinualImprovementRegistry_snapshotId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ContinualImprovementRegistry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ContinualImprovementRegistry_sourceId(ctx context.Context, field graphql.CollectedField, obj *types.ContinualImprovementRegistry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ContinualImprovementRegistry_sourceId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SourceID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*gid.GID) + fc.Result = res + return ec.marshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ContinualImprovementRegistry_sourceId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ContinualImprovementRegistry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _ContinualImprovementRegistry_organization(ctx context.Context, field graphql.CollectedField, obj *types.ContinualImprovementRegistry) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ContinualImprovementRegistry_organization(ctx, field) if err != nil { @@ -23351,6 +23479,10 @@ func (ec *executionContext) fieldContext_ContinualImprovementRegistryEdge_node(_ switch field.Name { case "id": return ec.fieldContext_ContinualImprovementRegistry_id(ctx, field) + case "snapshotId": + return ec.fieldContext_ContinualImprovementRegistry_snapshotId(ctx, field) + case "sourceId": + return ec.fieldContext_ContinualImprovementRegistry_sourceId(ctx, field) case "organization": return ec.fieldContext_ContinualImprovementRegistry_organization(ctx, field) case "referenceId": @@ -42136,7 +42268,7 @@ func (ec *executionContext) _Organization_continualImprovementRegistries(ctx con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Organization().ContinualImprovementRegistries(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ContinualImprovementRegistriesOrderBy)) + return ec.resolvers.Organization().ContinualImprovementRegistries(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ContinualImprovementRegistriesOrderBy), fc.Args["filter"].(*types.ContinualImprovementRegistryFilter)) }) if err != nil { ec.Error(ctx, err) @@ -49836,6 +49968,10 @@ func (ec *executionContext) fieldContext_UpdateContinualImprovementRegistryPaylo switch field.Name { case "id": return ec.fieldContext_ContinualImprovementRegistry_id(ctx, field) + case "snapshotId": + return ec.fieldContext_ContinualImprovementRegistry_snapshotId(ctx, field) + case "sourceId": + return ec.fieldContext_ContinualImprovementRegistry_sourceId(ctx, field) case "organization": return ec.fieldContext_ContinualImprovementRegistry_organization(ctx, field) case "referenceId": @@ -59722,6 +59858,33 @@ func (ec *executionContext) unmarshalInputContinualImprovementRegistriesOrder(ct return it, nil } +func (ec *executionContext) unmarshalInputContinualImprovementRegistryFilter(ctx context.Context, obj any) (types.ContinualImprovementRegistryFilter, error) { + var it types.ContinualImprovementRegistryFilter + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"snapshotId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "snapshotId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("snapshotId")) + data, err := ec.unmarshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.SnapshotID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputControlFilter(ctx context.Context, obj any) (types.ControlFilter, error) { var it types.ControlFilter asMap := map[string]any{} @@ -67291,6 +67454,10 @@ func (ec *executionContext) _ContinualImprovementRegistry(ctx context.Context, s if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "snapshotId": + out.Values[i] = ec._ContinualImprovementRegistry_snapshotId(ctx, field, obj) + case "sourceId": + out.Values[i] = ec._ContinualImprovementRegistry_sourceId(ctx, field, obj) case "organization": field := field @@ -84804,20 +84971,22 @@ func (ec *executionContext) marshalNSnapshotsType2githubᚗcomᚋgetproboᚋprob var ( unmarshalNSnapshotsType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐSnapshotsType = map[string]coredata.SnapshotsType{ - "RISKS": coredata.SnapshotsTypeRisks, - "VENDORS": coredata.SnapshotsTypeVendors, - "ASSETS": coredata.SnapshotsTypeAssets, - "DATA": coredata.SnapshotsTypeData, - "NONCONFORMITY_REGISTRIES": coredata.SnapshotsTypeNonConformityRegistries, - "COMPLIANCE_REGISTRIES": coredata.SnapshotsTypeComplianceRegistries, + "RISKS": coredata.SnapshotsTypeRisks, + "VENDORS": coredata.SnapshotsTypeVendors, + "ASSETS": coredata.SnapshotsTypeAssets, + "DATA": coredata.SnapshotsTypeData, + "NONCONFORMITY_REGISTRIES": coredata.SnapshotsTypeNonConformityRegistries, + "COMPLIANCE_REGISTRIES": coredata.SnapshotsTypeComplianceRegistries, + "CONTINUAL_IMPROVEMENT_REGISTRIES": coredata.SnapshotsTypeContinualImprovementRegistries, } marshalNSnapshotsType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐSnapshotsType = map[coredata.SnapshotsType]string{ - coredata.SnapshotsTypeRisks: "RISKS", - coredata.SnapshotsTypeVendors: "VENDORS", - coredata.SnapshotsTypeAssets: "ASSETS", - coredata.SnapshotsTypeData: "DATA", - coredata.SnapshotsTypeNonConformityRegistries: "NONCONFORMITY_REGISTRIES", - coredata.SnapshotsTypeComplianceRegistries: "COMPLIANCE_REGISTRIES", + coredata.SnapshotsTypeRisks: "RISKS", + coredata.SnapshotsTypeVendors: "VENDORS", + coredata.SnapshotsTypeAssets: "ASSETS", + coredata.SnapshotsTypeData: "DATA", + coredata.SnapshotsTypeNonConformityRegistries: "NONCONFORMITY_REGISTRIES", + coredata.SnapshotsTypeComplianceRegistries: "COMPLIANCE_REGISTRIES", + coredata.SnapshotsTypeContinualImprovementRegistries: "CONTINUAL_IMPROVEMENT_REGISTRIES", } ) @@ -86983,6 +87152,14 @@ var ( } ) +func (ec *executionContext) unmarshalOContinualImprovementRegistryFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐContinualImprovementRegistryFilter(ctx context.Context, v any) (*types.ContinualImprovementRegistryFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputContinualImprovementRegistryFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOControlFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐControlFilter(ctx context.Context, v any) (*types.ControlFilter, error) { if v == nil { return nil, nil diff --git a/pkg/server/api/console/v1/types/continual_improvement_registry.go b/pkg/server/api/console/v1/types/continual_improvement_registry.go index f2ca50cc5..a14868ad9 100644 --- a/pkg/server/api/console/v1/types/continual_improvement_registry.go +++ b/pkg/server/api/console/v1/types/continual_improvement_registry.go @@ -30,6 +30,7 @@ type ( Resolver any ParentID gid.GID + Filter *ContinualImprovementRegistryFilter } ) @@ -37,6 +38,7 @@ func NewContinualImprovementRegistryConnection( p *page.Page[*coredata.ContinualImprovementRegistry, coredata.ContinualImprovementRegistriesOrderField], parentType any, parentID gid.GID, + filter *ContinualImprovementRegistryFilter, ) *ContinualImprovementRegistryConnection { edges := make([]*ContinualImprovementRegistryEdge, len(p.Data)) for i, registry := range p.Data { @@ -49,12 +51,15 @@ func NewContinualImprovementRegistryConnection( Resolver: parentType, ParentID: parentID, + Filter: filter, } } func NewContinualImprovementRegistry(cir *coredata.ContinualImprovementRegistry) *ContinualImprovementRegistry { return &ContinualImprovementRegistry{ ID: cir.ID, + SnapshotID: cir.SnapshotID, + SourceID: cir.SourceID, ReferenceID: cir.ReferenceID, Description: cir.Description, Source: cir.Source, diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index 0736c9c83..a2a4eea5e 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -174,6 +174,8 @@ type ConnectorOrder struct { type ContinualImprovementRegistry struct { ID gid.GID `json:"id"` + SnapshotID *gid.GID `json:"snapshotId,omitempty"` + SourceID *gid.GID `json:"sourceId,omitempty"` Organization *Organization `json:"organization"` ReferenceID string `json:"referenceId"` Description *string `json:"description,omitempty"` @@ -194,6 +196,10 @@ type ContinualImprovementRegistryEdge struct { Node *ContinualImprovementRegistry `json:"node"` } +type ContinualImprovementRegistryFilter struct { + SnapshotID *gid.GID `json:"snapshotId,omitempty"` +} + type Control struct { ID gid.GID `json:"id"` SectionTitle string `json:"sectionTitle"` diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index c2edcacdd..43fedf7a1 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -315,7 +315,12 @@ func (r *continualImprovementRegistryConnectionResolver) TotalCount(ctx context. switch obj.Resolver.(type) { case *organizationResolver: - count, err := prb.ContinualImprovementRegistries.CountByOrganizationID(ctx, obj.ParentID) + continualImprovementRegistryFilter := coredata.NewContinualImprovementRegistryFilter(nil) + if obj.Filter != nil { + continualImprovementRegistryFilter = coredata.NewContinualImprovementRegistryFilter(&obj.Filter.SnapshotID) + } + + count, err := prb.ContinualImprovementRegistries.CountByOrganizationID(ctx, obj.ParentID, continualImprovementRegistryFilter) if err != nil { panic(fmt.Errorf("cannot count continual improvement registries: %w", err)) } @@ -3756,7 +3761,7 @@ func (r *organizationResolver) ComplianceRegistries(ctx context.Context, obj *ty } // ContinualImprovementRegistries is the resolver for the continualImprovementRegistries field. -func (r *organizationResolver) ContinualImprovementRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy) (*types.ContinualImprovementRegistryConnection, error) { +func (r *organizationResolver) ContinualImprovementRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementRegistriesOrderBy, filter *types.ContinualImprovementRegistryFilter) (*types.ContinualImprovementRegistryConnection, error) { prb := r.ProboService(ctx, obj.ID.TenantID()) pageOrderBy := page.OrderBy[coredata.ContinualImprovementRegistriesOrderField]{ @@ -3773,12 +3778,17 @@ func (r *organizationResolver) ContinualImprovementRegistries(ctx context.Contex cursor := types.NewCursor(first, after, last, before, pageOrderBy) - page, err := prb.ContinualImprovementRegistries.ListForOrganizationID(ctx, obj.ID, cursor) + continualImprovementRegistryFilter := coredata.NewContinualImprovementRegistryFilter(nil) + if filter != nil { + continualImprovementRegistryFilter = coredata.NewContinualImprovementRegistryFilter(&filter.SnapshotID) + } + + page, err := prb.ContinualImprovementRegistries.ListForOrganizationID(ctx, obj.ID, cursor, continualImprovementRegistryFilter) if err != nil { panic(fmt.Errorf("cannot list organization continual improvement registries: %w", err)) } - return types.NewContinualImprovementRegistryConnection(page, r, obj.ID), nil + return types.NewContinualImprovementRegistryConnection(page, r, obj.ID, filter), nil } // ProcessingActivityRegistries is the resolver for the processingActivityRegistries field.