Add compliance registry snapshots

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-08-29 11:05:01 +02:00
parent 828895a436
commit 16c94c4cca
25 changed files with 781 additions and 199 deletions

View File

@@ -8,10 +8,10 @@ import { useMutationWithToasts } from "../useMutationWithToasts";
export const ComplianceRegistriesConnectionKey = "ComplianceRegistriesPage_complianceRegistries";
export const complianceRegistriesQuery = graphql`
query ComplianceRegistryGraphListQuery($organizationId: ID!) {
query ComplianceRegistryGraphListQuery($organizationId: ID!, $snapshotId: ID) {
node(id: $organizationId) {
... on Organization {
...ComplianceRegistriesPageFragment
...ComplianceRegistriesPageFragment @arguments(snapshotId: $snapshotId)
}
}
}
@@ -22,6 +22,8 @@ export const complianceRegistryNodeQuery = graphql`
node(id: $complianceRegistryId) {
... on ComplianceRegistry {
id
snapshotId
sourceId
referenceId
area
source

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<fa68dc3f1afe9ab6d98e189eff649e04>>
* @generated SignedSource<<41975a1dcc769268a6255ea703ff26fe>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type ComplianceRegistryGraphListQuery$variables = {
organizationId: string;
snapshotId?: string | null | undefined;
};
export type ComplianceRegistryGraphListQuery$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": "ComplianceRegistriesPageFragment"
}
@@ -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": "ComplianceRegistryConnection",
"kind": "LinkedField",
"name": "complianceRegistries",
@@ -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,
@@ -215,7 +247,7 @@ return {
"name": "owner",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
@@ -240,7 +272,7 @@ return {
"name": "updatedAt",
"storageKey": null
},
(v2/*: any*/)
(v3/*: any*/)
],
"storageKey": null
},
@@ -292,12 +324,14 @@ return {
]
}
],
"storageKey": "complianceRegistries(first:10)"
"storageKey": null
},
{
"alias": null,
"args": (v4/*: any*/),
"filters": null,
"args": (v5/*: any*/),
"filters": [
"filter"
],
"handle": "connection",
"key": "ComplianceRegistriesPage_complianceRegistries",
"kind": "LinkedHandle",
@@ -313,16 +347,16 @@ return {
]
},
"params": {
"cacheID": "2852dc9732086326e7770650cbd00ad1",
"cacheID": "d578089841a93f60ae9ba5bc6e9175b0",
"id": null,
"metadata": {},
"name": "ComplianceRegistryGraphListQuery",
"operationKind": "query",
"text": "query ComplianceRegistryGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ComplianceRegistriesPageFragment\n }\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment on Organization {\n id\n complianceRegistries(first: 10) {\n totalCount\n edges {\n node {\n id\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 ComplianceRegistryGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ComplianceRegistriesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment_3iomuz on Organization {\n id\n complianceRegistries(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 = "363434c78eb3e27ac52b6da13c7432a1";
(node as any).hash = "2c50dd58eb2d72e49bce300726f35a34";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<f3d37c53737c5f0f3bd062eb2b682898>>
* @generated SignedSource<<ec60b0715df426d6819f03f6e1597fef>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -32,7 +32,9 @@ export type ComplianceRegistryGraphNodeQuery$data = {
readonly referenceId?: string;
readonly regulator?: string | null | undefined;
readonly requirement?: string | null | undefined;
readonly snapshotId?: string | null | undefined;
readonly source?: string | null | undefined;
readonly sourceId?: string | null | undefined;
readonly status?: ComplianceRegistryStatus;
readonly updatedAt?: any;
};
@@ -68,66 +70,80 @@ v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "referenceId",
"name": "snapshotId",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "area",
"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": "requirement",
"name": "area",
"storageKey": null
},
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "actionsToBeImplemented",
"name": "source",
"storageKey": null
},
v8 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "regulator",
"name": "requirement",
"storageKey": null
},
v9 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "lastReviewDate",
"name": "actionsToBeImplemented",
"storageKey": null
},
v10 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "dueDate",
"name": "regulator",
"storageKey": null
},
v11 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"name": "lastReviewDate",
"storageKey": null
},
v12 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "dueDate",
"storageKey": null
},
v13 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
},
v14 = {
"alias": null,
"args": null,
"concreteType": "People",
@@ -146,7 +162,7 @@ v12 = {
],
"storageKey": null
},
v13 = {
v15 = {
"alias": null,
"args": null,
"concreteType": "Organization",
@@ -165,14 +181,14 @@ v13 = {
],
"storageKey": null
},
v14 = {
v16 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
v15 = {
v17 = {
"alias": null,
"args": null,
"kind": "ScalarField",
@@ -210,7 +226,9 @@ return {
(v12/*: any*/),
(v13/*: any*/),
(v14/*: any*/),
(v15/*: any*/)
(v15/*: any*/),
(v16/*: any*/),
(v17/*: any*/)
],
"type": "ComplianceRegistry",
"abstractKey": null
@@ -259,7 +277,9 @@ return {
(v12/*: any*/),
(v13/*: any*/),
(v14/*: any*/),
(v15/*: any*/)
(v15/*: any*/),
(v16/*: any*/),
(v17/*: any*/)
],
"type": "ComplianceRegistry",
"abstractKey": null
@@ -270,16 +290,16 @@ return {
]
},
"params": {
"cacheID": "4b91258de0711b2821a26bef89b60b02",
"cacheID": "2c4649d3258530fd79420bc2ed8fd14a",
"id": null,
"metadata": {},
"name": "ComplianceRegistryGraphNodeQuery",
"operationKind": "query",
"text": "query ComplianceRegistryGraphNodeQuery(\n $complianceRegistryId: ID!\n) {\n node(id: $complianceRegistryId) {\n __typename\n ... on ComplianceRegistry {\n id\n referenceId\n area\n source\n requirement\n actionsToBeImplemented\n regulator\n lastReviewDate\n dueDate\n status\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 ComplianceRegistryGraphNodeQuery(\n $complianceRegistryId: ID!\n) {\n node(id: $complianceRegistryId) {\n __typename\n ... on ComplianceRegistry {\n id\n snapshotId\n sourceId\n referenceId\n area\n source\n requirement\n actionsToBeImplemented\n regulator\n lastReviewDate\n dueDate\n status\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 = "1b3352776a5b514b7545111aeb780148";
(node as any).hash = "b290ce12f57b586e64bac227777bc294";
export default node;

View File

@@ -24,10 +24,12 @@ import {
useMutation,
type PreloadedQuery,
} from "react-relay";
import { useParams } from "react-router";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { CreateComplianceRegistryDialog } from "./dialogs/CreateComplianceRegistryDialog";
import { deleteComplianceRegistryMutation } from "../../../hooks/graph/ComplianceRegistryGraph";
import { sprintf, promisifyMutation, getStatusVariant, getStatusLabel } from "@probo/helpers";
import { SnapshotBanner } from "/components/SnapshotBanner";
import type { ComplianceRegistriesPageQuery } from "./__generated__/ComplianceRegistriesPageQuery.graphql";
import type {
ComplianceRegistriesPageFragment$key,
@@ -46,15 +48,22 @@ const complianceRegistriesPageFragment = graphql`
@argumentDefinitions(
first: { type: "Int", defaultValue: 10 }
after: { type: "CursorKey" }
snapshotId: { type: "ID", defaultValue: null }
) {
id
complianceRegistries(first: $first, after: $after)
@connection(key: "ComplianceRegistriesPage_complianceRegistries") {
complianceRegistries(
first: $first
after: $after
filter: { snapshotId: $snapshotId }
)
@connection(key: "ComplianceRegistriesPage_complianceRegistries", filters: ["filter"]) {
__id
totalCount
edges {
node {
id
snapshotId
sourceId
referenceId
area
source
@@ -83,15 +92,17 @@ const complianceRegistriesPageFragment = graphql`
export default function ComplianceRegistriesPage({ queryRef }: ComplianceRegistriesPageProps) {
const { __ } = useTranslate();
const organizationId = useOrganizationId();
const { snapshotId } = useParams<{ snapshotId?: string }>();
const isSnapshotMode = Boolean(snapshotId);
usePageTitle(__("Compliance Registries"));
const organization = usePreloadedQuery(
graphql`
query ComplianceRegistriesPageQuery($organizationId: ID!) {
query ComplianceRegistriesPageQuery($organizationId: ID!, $snapshotId: ID) {
node(id: $organizationId) {
... on Organization {
...ComplianceRegistriesPageFragment
...ComplianceRegistriesPageFragment @arguments(snapshotId: $snapshotId)
}
}
}
@@ -109,15 +120,20 @@ export default function ComplianceRegistriesPage({ queryRef }: ComplianceRegistr
return (
<div className="space-y-6">
{isSnapshotMode && snapshotId && (
<SnapshotBanner snapshotId={snapshotId} />
)}
<PageHeader
title={__("Compliance Registries")}
description={__(
"Manage your organization's compliance registry entries."
)}
>
<CreateComplianceRegistryDialog organizationId={organizationId} connection={connectionId}>
<Button icon={IconPlusLarge}>{__("Add compliance registry")}</Button>
</CreateComplianceRegistryDialog>
{!snapshotId && (
<CreateComplianceRegistryDialog organizationId={organizationId} connection={connectionId}>
<Button icon={IconPlusLarge}>{__("Add compliance registry")}</Button>
</CreateComplianceRegistryDialog>
)}
</PageHeader>
{registries.length === 0 ? (
@@ -151,6 +167,7 @@ export default function ComplianceRegistriesPage({ queryRef }: ComplianceRegistr
key={registry.id}
registry={registry}
connectionId={connectionId}
snapshotId={snapshotId}
/>
))}
</Tbody>
@@ -176,14 +193,17 @@ export default function ComplianceRegistriesPage({ queryRef }: ComplianceRegistr
function RegistryRow({
registry,
connectionId,
snapshotId,
}: {
registry: ComplianceRegistry;
connectionId: string;
snapshotId?: string;
}) {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [deleteRegistry] = useMutation(deleteComplianceRegistryMutation);
const confirm = useConfirm();
const isSnapshotMode = Boolean(snapshotId);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString();
@@ -211,8 +231,12 @@ function RegistryRow({
);
};
const detailsUrl = isSnapshotMode
? `/organizations/${organizationId}/snapshots/${snapshotId}/compliance-registries/${registry.id}`
: `/organizations/${organizationId}/compliance-registries/${registry.id}`;
return (
<Tr to={`/organizations/${organizationId}/compliance-registries/${registry.id}`}>
<Tr to={detailsUrl}>
<Td>
<span className="font-mono text-sm">{registry.referenceId}</span>
</Td>
@@ -234,15 +258,17 @@ function RegistryRow({
)}
</Td>
<Td noLink width={50} className="text-end">
<ActionDropdown>
<DropdownItem
icon={IconTrashCan}
variant="danger"
onSelect={handleDelete}
>
{__("Delete")}
</DropdownItem>
</ActionDropdown>
{!isSnapshotMode && (
<ActionDropdown>
<DropdownItem
icon={IconTrashCan}
variant="danger"
onSelect={handleDelete}
>
{__("Delete")}
</DropdownItem>
</ActionDropdown>
)}
</Td>
</Tr>
);

View File

@@ -25,12 +25,14 @@ import {
Select,
} 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, getComplianceRegistryStatusOptions } from "@probo/helpers";
import { getStatusVariant, getStatusLabel, formatDatetime, getComplianceRegistryStatusOptions, validateSnapshotConsistency } from "@probo/helpers";
import { SnapshotBanner } from "/components/SnapshotBanner";
import type { ComplianceRegistryGraphNodeQuery } from "/hooks/graph/__generated__/ComplianceRegistryGraphNodeQuery.graphql";
const updateRegistrySchema = z.object({
@@ -56,11 +58,15 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
const { __ } = useTranslate();
const { toast } = useToast();
const organizationId = useOrganizationId();
const { snapshotId } = useParams<{ snapshotId?: string }>();
const isSnapshotMode = Boolean(snapshotId);
if (!registry) {
return <div>{__("Compliance registry entry not found")}</div>;
}
validateSnapshotConsistency(registry, snapshotId);
const updateRegistry = useUpdateComplianceRegistry();
const statusOptions = getComplianceRegistryStatusOptions(__);
@@ -124,29 +130,38 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
}
});
const breadcrumbComplianceRegistriesUrl = isSnapshotMode
? `/organizations/${organizationId}/snapshots/${snapshotId}/compliance-registries`
: `/organizations/${organizationId}/compliance-registries`;
return (
<div className="space-y-6">
{isSnapshotMode && snapshotId && (
<SnapshotBanner snapshotId={snapshotId} />
)}
<div className="flex justify-between items-start">
<div>
<Breadcrumb
items={[
{ label: __("Compliance Registries"), to: "../compliance-registries" },
{ label: registry.referenceId! },
]}
/>
<div className="flex items-center gap-3 mt-2">
<h1 className="text-2xl font-bold">{registry.referenceId}</h1>
<Badge variant={getStatusVariant(registry.status || "OPEN")}>
{getStatusLabel(registry.status || "OPEN")}
</Badge>
</div>
<Breadcrumb
items={[
{ label: __("Compliance Registries"), to: breadcrumbComplianceRegistriesUrl },
{ label: registry.referenceId! },
]}
/>
<div className="flex items-center gap-3 mt-2">
<h1 className="text-2xl font-bold">{registry.referenceId}</h1>
<Badge variant={getStatusVariant(registry.status || "OPEN")}>
{getStatusLabel(registry.status || "OPEN")}
</Badge>
</div>
</div>
<ActionDropdown>
<DropdownItem icon={IconTrashCan} onClick={deleteRegistry}>
{__("Delete")}
</DropdownItem>
</ActionDropdown>
{!isSnapshotMode && (
<ActionDropdown>
<DropdownItem icon={IconTrashCan} onClick={deleteRegistry}>
{__("Delete")}
</DropdownItem>
</ActionDropdown>
)}
</div>
<Card padded>
@@ -159,6 +174,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("referenceId")}
placeholder={__("Enter reference ID")}
disabled={isSnapshotMode}
/>
</Field>
@@ -172,6 +188,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("area")}
placeholder={__("Enter area")}
disabled={isSnapshotMode}
/>
</Field>
@@ -182,6 +199,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("source")}
placeholder={__("Enter source")}
disabled={isSnapshotMode}
/>
</Field>
</div>
@@ -198,6 +216,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
onValueChange={field.onChange}
value={field.value}
className="w-full"
disabled={isSnapshotMode}
>
{statusOptions.map((option) => (
<Option key={option.value} value={option.value}>
@@ -223,6 +242,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
label={__("Owner")}
error={formState.errors.ownerId?.message}
required
disabled={isSnapshotMode}
/>
)}
/>
@@ -236,6 +256,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("regulator")}
placeholder={__("Enter regulator")}
disabled={isSnapshotMode}
/>
</Field>
</div>
@@ -248,6 +269,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("lastReviewDate")}
type="date"
disabled={isSnapshotMode}
/>
</Field>
@@ -258,6 +280,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
<Input
{...register("dueDate")}
type="date"
disabled={isSnapshotMode}
/>
</Field>
</div>
@@ -270,6 +293,7 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
{...register("requirement")}
placeholder={__("Enter requirement")}
rows={4}
disabled={isSnapshotMode}
/>
</Field>
@@ -281,17 +305,20 @@ export default function ComplianceRegistryDetailsPage(props: Props) {
{...register("actionsToBeImplemented")}
placeholder={__("Enter actions to be implemented")}
rows={4}
disabled={isSnapshotMode}
/>
</Field>
<div className="flex justify-end">
<Button
type="submit"
disabled={formState.isSubmitting}
>
{formState.isSubmitting ? __("Saving...") : __("Save Changes")}
</Button>
</div>
{!isSnapshotMode && (
<div className="flex justify-end">
<Button
type="submit"
disabled={formState.isSubmitting}
>
{formState.isSubmitting ? __("Saving...") : __("Save Changes")}
</Button>
</div>
)}
</form>
</Card>
</div>

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<312905201e0a72d96dd29afeed17dee1>>
* @generated SignedSource<<db8b4530d56ae89fa8e332555a85eb33>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -29,7 +29,9 @@ export type ComplianceRegistriesPageFragment$data = {
readonly referenceId: string;
readonly regulator: string | null | undefined;
readonly requirement: string | null | undefined;
readonly snapshotId: string | null | undefined;
readonly source: string | null | undefined;
readonly sourceId: string | null | undefined;
readonly status: ComplianceRegistryStatus;
readonly updatedAt: any;
};
@@ -72,6 +74,11 @@ return {
"defaultValue": 10,
"kind": "LocalArgument",
"name": "first"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "snapshotId"
}
],
"kind": "Fragment",
@@ -108,7 +115,19 @@ return {
(v1/*: any*/),
{
"alias": "complianceRegistries",
"args": null,
"args": [
{
"fields": [
{
"kind": "Variable",
"name": "snapshotId",
"variableName": "snapshotId"
}
],
"kind": "ObjectValue",
"name": "filter"
}
],
"concreteType": "ComplianceRegistryConnection",
"kind": "LinkedField",
"name": "__ComplianceRegistriesPage_complianceRegistries_connection",
@@ -138,6 +157,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,
@@ -300,6 +333,6 @@ return {
};
})();
(node as any).hash = "b6b97d09ba132cbc1ffb006c23a33589";
(node as any).hash = "b22ac157b9ba89ab14fe8363e56957ef";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c6faaadb8a0f7d2b70fed9a5801f3580>>
* @generated SignedSource<<794221c1dbbf8fd2d1808863d55d2c05>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type ComplianceRegistriesPageQuery$variables = {
organizationId: string;
snapshotId?: string | null | undefined;
};
export type ComplianceRegistriesPageQuery$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": "ComplianceRegistriesPageFragment"
}
@@ -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": "ComplianceRegistryConnection",
"kind": "LinkedField",
"name": "complianceRegistries",
@@ -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,
@@ -215,7 +247,7 @@ return {
"name": "owner",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
@@ -240,7 +272,7 @@ return {
"name": "updatedAt",
"storageKey": null
},
(v2/*: any*/)
(v3/*: any*/)
],
"storageKey": null
},
@@ -292,12 +324,14 @@ return {
]
}
],
"storageKey": "complianceRegistries(first:10)"
"storageKey": null
},
{
"alias": null,
"args": (v4/*: any*/),
"filters": null,
"args": (v5/*: any*/),
"filters": [
"filter"
],
"handle": "connection",
"key": "ComplianceRegistriesPage_complianceRegistries",
"kind": "LinkedHandle",
@@ -313,16 +347,16 @@ return {
]
},
"params": {
"cacheID": "e4fba5ed79a8d19c72d2814f1adf38c3",
"cacheID": "b63e74cea7f47c7e4f735ad2b52e1765",
"id": null,
"metadata": {},
"name": "ComplianceRegistriesPageQuery",
"operationKind": "query",
"text": "query ComplianceRegistriesPageQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ComplianceRegistriesPageFragment\n }\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment on Organization {\n id\n complianceRegistries(first: 10) {\n totalCount\n edges {\n node {\n id\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 ComplianceRegistriesPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ComplianceRegistriesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment_3iomuz on Organization {\n id\n complianceRegistries(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 = "3e8551eebdf52ee84fb3910ee77cfe15";
(node as any).hash = "f0064c0d6d6e628923be30edb4b249db";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<25a63f42437f72ee5aea5f2c6e324d4a>>
* @generated SignedSource<<af4b3139bff8ab757fa1876aa4be4bb1>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -14,6 +14,7 @@ export type ComplianceRegistriesPageRefetchQuery$variables = {
after?: any | null | undefined;
first?: number | null | undefined;
id: string;
snapshotId?: string | null | undefined;
};
export type ComplianceRegistriesPageRefetchQuery$data = {
readonly node: {
@@ -26,73 +27,99 @@ export type ComplianceRegistriesPageRefetchQuery = {
};
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": "ComplianceRegistriesPageRefetchQuery",
"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": "ComplianceRegistriesPageFragment"
}
@@ -105,26 +132,31 @@ return {
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/),
(v3/*: any*/),
(v2/*: any*/)
],
"kind": "Operation",
"name": "ComplianceRegistriesPageRefetchQuery",
"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": "ComplianceRegistryConnection",
"kind": "LinkedField",
"name": "complianceRegistries",
@@ -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,
@@ -225,7 +271,7 @@ return {
"name": "owner",
"plural": false,
"selections": [
(v4/*: any*/),
(v9/*: any*/),
{
"alias": null,
"args": null,
@@ -250,7 +296,7 @@ return {
"name": "updatedAt",
"storageKey": null
},
(v3/*: any*/)
(v8/*: any*/)
],
"storageKey": null
},
@@ -306,8 +352,10 @@ return {
},
{
"alias": null,
"args": (v2/*: any*/),
"filters": null,
"args": (v10/*: any*/),
"filters": [
"filter"
],
"handle": "connection",
"key": "ComplianceRegistriesPage_complianceRegistries",
"kind": "LinkedHandle",
@@ -323,16 +371,16 @@ return {
]
},
"params": {
"cacheID": "2b10e1f8598c007ee1e3e93e39b51b0d",
"cacheID": "d14ed4a195ca3b570ad5ecd255cf17e8",
"id": null,
"metadata": {},
"name": "ComplianceRegistriesPageRefetchQuery",
"operationKind": "query",
"text": "query ComplianceRegistriesPageRefetchQuery(\n $after: CursorKey\n $first: Int = 10\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ComplianceRegistriesPageFragment_2HEEH6\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment_2HEEH6 on Organization {\n id\n complianceRegistries(first: $first, after: $after) {\n totalCount\n edges {\n node {\n id\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 ComplianceRegistriesPageRefetchQuery(\n $after: CursorKey\n $first: Int = 10\n $snapshotId: ID = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ComplianceRegistriesPageFragment_35e0S5\n id\n }\n}\n\nfragment ComplianceRegistriesPageFragment_35e0S5 on Organization {\n id\n complianceRegistries(first: $first, after: $after, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\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 = "b6b97d09ba132cbc1ffb006c23a33589";
(node as any).hash = "b22ac157b9ba89ab14fe8363e56957ef";
export default node;

View File

@@ -19,6 +19,7 @@ import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { ControlledField } from "/components/form/ControlledField";
import { SnapshotTypeOptions } from "/components/form/SnapshotTypeOptions";
import { snapshotTypes } from "@probo/helpers";
const snapshotCreateMutation = graphql`
mutation SnapshotFormDialogCreateMutation(
@@ -42,7 +43,7 @@ const snapshotCreateMutation = graphql`
const snapshotSchema = z.object({
name: z.string().min(2, { message: "Name is required" }),
description: z.string().optional(),
type: z.enum(["DATA", "NONCONFORMITY_REGISTRIES"]),
type: z.enum(snapshotTypes),
});
type Props = {

View File

@@ -9,8 +9,23 @@ export const complianceRegistryRoutes = [
{
path: "compliance-registries",
fallback: PageSkeleton,
queryLoader: ({ organizationId }: { organizationId: string }) =>
loadQuery(relayEnvironment, complianceRegistriesQuery, { organizationId }),
queryLoader: (params: Record<string, string>) =>
loadQuery(relayEnvironment, complianceRegistriesQuery, {
organizationId: params.organizationId,
snapshotId: null
}),
Component: lazy(
() => import("/pages/organizations/complianceRegistries/ComplianceRegistriesPage")
),
},
{
path: "snapshots/:snapshotId/compliance-registries",
fallback: PageSkeleton,
queryLoader: (params: Record<string, string>) =>
loadQuery(relayEnvironment, complianceRegistriesQuery, {
organizationId: params.organizationId,
snapshotId: params.snapshotId
}),
Component: lazy(
() => import("/pages/organizations/complianceRegistries/ComplianceRegistriesPage")
),
@@ -26,4 +41,15 @@ export const complianceRegistryRoutes = [
() => import("/pages/organizations/complianceRegistries/ComplianceRegistryDetailsPage")
),
},
{
path: "snapshots/:snapshotId/compliance-registries/:registryId",
fallback: PageSkeleton,
queryLoader: (params: Record<string, string>) =>
loadQuery(relayEnvironment, complianceRegistryNodeQuery, {
complianceRegistryId: params.registryId
}),
Component: lazy(
() => import("/pages/organizations/complianceRegistries/ComplianceRegistryDetailsPage")
),
},
] satisfies AppRoute[];

View File

@@ -3,6 +3,7 @@ type Translator = (s: string) => string;
export const snapshotTypes = [
"DATA",
"NONCONFORMITY_REGISTRIES",
"COMPLIANCE_REGISTRIES",
] as const;
export function getSnapshotTypeLabel(__: Translator, type: string | null | undefined) {
@@ -34,6 +35,8 @@ export function getSnapshotTypeUrlPath(type?: string): string {
return "/data";
case "NONCONFORMITY_REGISTRIES":
return "/nonconformity-registries";
case "COMPLIANCE_REGISTRIES":
return "/compliance-registries";
default:
return "";
}

View File

@@ -40,6 +40,8 @@ type (
LastReviewDate *time.Time `db:"last_review_date"`
DueDate *time.Time `db:"due_date"`
Status ComplianceRegistryStatus `db:"status"`
SnapshotID *gid.GID `db:"snapshot_id"`
SourceID *gid.GID `db:"source_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
@@ -74,6 +76,8 @@ func (cr *ComplianceRegistry) LoadByID(
SELECT
id,
organization_id,
snapshot_id,
source_id,
reference_id,
area,
source,
@@ -119,6 +123,7 @@ func (crs *ComplianceRegistries) CountByOrganizationID(
conn pg.Conn,
scope Scoper,
organizationID gid.GID,
filter *ComplianceRegistryFilter,
) (int, error) {
q := `
SELECT
@@ -128,12 +133,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)
@@ -152,6 +159,7 @@ func (crs *ComplianceRegistries) LoadByOrganizationID(
scope Scoper,
organizationID gid.GID,
cursor *page.Cursor[ComplianceRegistryOrderField],
filter *ComplianceRegistryFilter,
) error {
q := `
SELECT
@@ -167,6 +175,8 @@ SELECT
last_review_date,
due_date,
status,
snapshot_id,
source_id,
created_at,
updated_at
FROM
@@ -175,12 +185,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)
@@ -218,6 +230,8 @@ INSERT INTO compliance_registries (
last_review_date,
due_date,
status,
snapshot_id,
source_id,
created_at,
updated_at
) VALUES (
@@ -234,6 +248,8 @@ INSERT INTO compliance_registries (
@last_review_date,
@due_date,
@status,
@snapshot_id,
@source_id,
@created_at,
@updated_at
)
@@ -253,6 +269,8 @@ INSERT INTO compliance_registries (
"last_review_date": cr.LastReviewDate,
"due_date": cr.DueDate,
"status": cr.Status,
"snapshot_id": cr.SnapshotID,
"source_id": cr.SourceID,
"created_at": cr.CreatedAt,
"updated_at": cr.UpdatedAt,
}
@@ -286,6 +304,7 @@ UPDATE compliance_registries SET
WHERE
%s
AND id = @id
AND snapshot_id IS NULL
`
q = fmt.Sprintf(q, scope.SQLFragment())
@@ -324,6 +343,7 @@ DELETE FROM compliance_registries
WHERE
%s
AND id = @id
AND snapshot_id IS NULL
`
q = fmt.Sprintf(q, scope.SQLFragment())
@@ -338,3 +358,64 @@ WHERE
return nil
}
func (crs ComplianceRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
query := `
INSERT INTO compliance_registries (
id,
tenant_id,
snapshot_id,
source_id,
organization_id,
reference_id,
area,
source,
requirement,
actions_to_be_implemented,
regulator,
owner_id,
last_review_date,
due_date,
status,
created_at,
updated_at
)
SELECT
generate_gid(decode_base64_unpadded(@tenant_id), @compliance_registry_entity_type),
@tenant_id,
@snapshot_id,
r.id,
r.organization_id,
r.reference_id,
r.area,
r.source,
r.requirement,
r.actions_to_be_implemented,
r.regulator,
r.owner_id,
r.last_review_date,
r.due_date,
r.status,
r.created_at,
r.updated_at
FROM compliance_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,
"compliance_registry_entity_type": ComplianceRegistryEntityType,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, query, args)
if err != nil {
return fmt.Errorf("cannot insert compliance registry snapshots: %w", err)
}
return nil
}

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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 (
ComplianceRegistryFilter struct {
snapshotID **gid.GID
}
)
func NewComplianceRegistryFilter(snapshotID **gid.GID) *ComplianceRegistryFilter {
return &ComplianceRegistryFilter{
snapshotID: snapshotID,
}
}
func (f *ComplianceRegistryFilter) SQLArguments() pgx.NamedArgs {
args := pgx.NamedArgs{}
if f.snapshotID != nil && *f.snapshotID != nil {
args["filter_snapshot_id"] = **f.snapshotID
}
return args
}
func (f *ComplianceRegistryFilter) SQLFragment() string {
if f.snapshotID == nil {
return "TRUE"
}
if *f.snapshotID == nil {
return "snapshot_id IS NULL"
} else {
return "snapshot_id = @filter_snapshot_id"
}
}

View File

@@ -25,13 +25,7 @@ type (
}
)
func NewDatumFilter() *DatumFilter {
return &DatumFilter{
snapshotID: nil,
}
}
func NewDatumFilterBySnapshotID(snapshotID **gid.GID) *DatumFilter {
func NewDatumFilter(snapshotID **gid.GID) *DatumFilter {
return &DatumFilter{
snapshotID: snapshotID,
}

View File

@@ -0,0 +1,11 @@
ALTER TABLE compliance_registries ADD COLUMN snapshot_id TEXT;
ALTER TABLE compliance_registries ADD COLUMN source_id TEXT;
ALTER TABLE compliance_registries ADD CONSTRAINT compliance_registries_snapshot_id_fkey
FOREIGN KEY (snapshot_id)
REFERENCES snapshots(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE compliance_registries ADD CONSTRAINT compliance_registries_source_id_snapshot_id_key
UNIQUE (source_id, snapshot_id);

View File

@@ -25,18 +25,12 @@ type (
}
)
func NewNonconformityRegistryFilter() *NonconformityRegistryFilter {
func NewNonconformityRegistryFilter(snapshotID **gid.GID) *NonconformityRegistryFilter {
return &NonconformityRegistryFilter{
snapshotID: nil,
}
}
func NewNonconformityRegistryFilterBySnapshotID(snapshotID **gid.GID) *NonconformityRegistryFilter {
return &NonconformityRegistryFilter{
snapshotID: snapshotID,
}
}
func (f *NonconformityRegistryFilter) SQLArguments() pgx.NamedArgs {
args := pgx.NamedArgs{}

View File

@@ -32,6 +32,8 @@ func GetSnapshottable(snapshotType SnapshotsType) (Snapshottable, error) {
return Data{}, nil
case SnapshotsTypeNonConformityRegistries:
return NonconformityRegistries{}, nil
case SnapshotsTypeComplianceRegistries:
return ComplianceRegistries{}, nil
default:
return nil, fmt.Errorf("unsupported snapshot type: %s", snapshotType)
}

View File

@@ -26,20 +26,10 @@ type (
}
)
func NewVendorFilter() *VendorFilter {
return &VendorFilter{}
}
func NewVendorTrustCenterFilter() *VendorFilter {
showOnTrustCenter := true
func NewVendorFilter(snapshotID **gid.GID, showOnTrustCenter *bool) *VendorFilter {
return &VendorFilter{
showOnTrustCenter: &showOnTrustCenter,
}
}
func NewVendorFilterBySnapshotID(snapshotID **gid.GID) *VendorFilter {
return &VendorFilter{
snapshotID: snapshotID,
snapshotID: snapshotID,
showOnTrustCenter: showOnTrustCenter,
}
}

View File

@@ -231,9 +231,10 @@ func (s *ComplianceRegistryService) Delete(
return err
}
func (s ComplianceRegistryService) CountByOrganizationID(
func (s ComplianceRegistryService) CountForOrganizationID(
ctx context.Context,
organizationID gid.GID,
filter *coredata.ComplianceRegistryFilter,
) (int, error) {
var count int
@@ -241,7 +242,7 @@ func (s ComplianceRegistryService) CountByOrganizationID(
ctx,
func(conn pg.Conn) (err error) {
registries := coredata.ComplianceRegistries{}
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 compliance registries: %w", err)
}
@@ -261,13 +262,14 @@ func (s ComplianceRegistryService) ListForOrganizationID(
ctx context.Context,
organizationID gid.GID,
cursor *page.Cursor[coredata.ComplianceRegistryOrderField],
filter *coredata.ComplianceRegistryFilter,
) (*page.Page[*coredata.ComplianceRegistry, coredata.ComplianceRegistryOrderField], error) {
var registries coredata.ComplianceRegistries
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 compliance registries: %w", err)
}

View File

@@ -1110,6 +1110,10 @@ input NonconformityRegistryFilter {
snapshotId: ID
}
input ComplianceRegistryFilter {
snapshotId: ID
}
# Core Types
type TrustCenter implements Node {
id: ID!
@@ -1258,6 +1262,7 @@ type Organization implements Node {
last: Int
before: CursorKey
orderBy: ComplianceRegistryOrder
filter: ComplianceRegistryFilter
): ComplianceRegistryConnection! @goField(forceResolver: true)
continualImprovementRegistries(
@@ -1721,6 +1726,8 @@ type NonconformityRegistry implements Node {
type ComplianceRegistry implements Node {
id: ID!
snapshotId: ID
sourceId: ID
organization: Organization! @goField(forceResolver: true)
referenceId: String!
area: String

View File

@@ -183,7 +183,9 @@ type ComplexityRoot struct {
ReferenceID func(childComplexity int) int
Regulator func(childComplexity int) int
Requirement func(childComplexity int) int
SnapshotID func(childComplexity int) int
Source func(childComplexity int) int
SourceID func(childComplexity int) int
Status func(childComplexity int) int
UpdatedAt func(childComplexity int) int
}
@@ -871,7 +873,7 @@ type ComplexityRoot struct {
Organization struct {
Assets func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AssetOrderBy) int
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) 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
Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) int
@@ -1669,7 +1671,7 @@ type OrganizationResolver interface {
Data(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DatumOrderBy, filter *types.DatumFilter) (*types.DatumConnection, error)
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) (*types.ComplianceRegistryConnection, 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)
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)
@@ -2155,6 +2157,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.ComplianceRegistry.Requirement(childComplexity), true
case "ComplianceRegistry.snapshotId":
if e.complexity.ComplianceRegistry.SnapshotID == nil {
break
}
return e.complexity.ComplianceRegistry.SnapshotID(childComplexity), true
case "ComplianceRegistry.source":
if e.complexity.ComplianceRegistry.Source == nil {
break
@@ -2162,6 +2171,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.ComplianceRegistry.Source(childComplexity), true
case "ComplianceRegistry.sourceId":
if e.complexity.ComplianceRegistry.SourceID == nil {
break
}
return e.complexity.ComplianceRegistry.SourceID(childComplexity), true
case "ComplianceRegistry.status":
if e.complexity.ComplianceRegistry.Status == nil {
break
@@ -5370,7 +5386,7 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return 0, false
}
return e.complexity.Organization.ComplianceRegistries(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ComplianceRegistryOrderBy)), true
return e.complexity.Organization.ComplianceRegistries(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ComplianceRegistryOrderBy), args["filter"].(*types.ComplianceRegistryFilter)), true
case "Organization.connectors":
if e.complexity.Organization.Connectors == nil {
@@ -7655,6 +7671,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputBulkPublishDocumentVersionsInput,
ec.unmarshalInputBulkRequestSignaturesInput,
ec.unmarshalInputCancelSignatureRequestInput,
ec.unmarshalInputComplianceRegistryFilter,
ec.unmarshalInputComplianceRegistryOrder,
ec.unmarshalInputConfirmEmailInput,
ec.unmarshalInputConnectorOrder,
@@ -9002,6 +9019,10 @@ input NonconformityRegistryFilter {
snapshotId: ID
}
input ComplianceRegistryFilter {
snapshotId: ID
}
# Core Types
type TrustCenter implements Node {
id: ID!
@@ -9150,6 +9171,7 @@ type Organization implements Node {
last: Int
before: CursorKey
orderBy: ComplianceRegistryOrder
filter: ComplianceRegistryFilter
): ComplianceRegistryConnection! @goField(forceResolver: true)
continualImprovementRegistries(
@@ -9613,6 +9635,8 @@ type NonconformityRegistry implements Node {
type ComplianceRegistry implements Node {
id: ID!
snapshotId: ID
sourceId: ID
organization: Organization! @goField(forceResolver: true)
referenceId: String!
area: String
@@ -15993,6 +16017,11 @@ func (ec *executionContext) field_Organization_complianceRegistries_args(ctx con
return nil, err
}
args["orderBy"] = arg4
arg5, err := ec.field_Organization_complianceRegistries_argsFilter(ctx, rawArgs)
if err != nil {
return nil, err
}
args["filter"] = arg5
return args, nil
}
func (ec *executionContext) field_Organization_complianceRegistries_argsFirst(
@@ -16060,6 +16089,19 @@ func (ec *executionContext) field_Organization_complianceRegistries_argsOrderBy(
return zeroVal, nil
}
func (ec *executionContext) field_Organization_complianceRegistries_argsFilter(
ctx context.Context,
rawArgs map[string]any,
) (*types.ComplianceRegistryFilter, error) {
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
if tmp, ok := rawArgs["filter"]; ok {
return ec.unmarshalOComplianceRegistryFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐComplianceRegistryFilter(ctx, tmp)
}
var zeroVal *types.ComplianceRegistryFilter
return zeroVal, nil
}
func (ec *executionContext) field_Organization_connectors_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -21086,6 +21128,88 @@ func (ec *executionContext) fieldContext_ComplianceRegistry_id(_ context.Context
return fc, nil
}
func (ec *executionContext) _ComplianceRegistry_snapshotId(ctx context.Context, field graphql.CollectedField, obj *types.ComplianceRegistry) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ComplianceRegistry_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_ComplianceRegistry_snapshotId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ComplianceRegistry",
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) _ComplianceRegistry_sourceId(ctx context.Context, field graphql.CollectedField, obj *types.ComplianceRegistry) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ComplianceRegistry_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_ComplianceRegistry_sourceId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ComplianceRegistry",
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) _ComplianceRegistry_organization(ctx context.Context, field graphql.CollectedField, obj *types.ComplianceRegistry) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ComplianceRegistry_organization(ctx, field)
if err != nil {
@@ -21942,6 +22066,10 @@ func (ec *executionContext) fieldContext_ComplianceRegistryEdge_node(_ context.C
switch field.Name {
case "id":
return ec.fieldContext_ComplianceRegistry_id(ctx, field)
case "snapshotId":
return ec.fieldContext_ComplianceRegistry_snapshotId(ctx, field)
case "sourceId":
return ec.fieldContext_ComplianceRegistry_sourceId(ctx, field)
case "organization":
return ec.fieldContext_ComplianceRegistry_organization(ctx, field)
case "referenceId":
@@ -41945,7 +42073,7 @@ func (ec *executionContext) _Organization_complianceRegistries(ctx context.Conte
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Organization().ComplianceRegistries(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ComplianceRegistryOrderBy))
return ec.resolvers.Organization().ComplianceRegistries(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ComplianceRegistryOrderBy), fc.Args["filter"].(*types.ComplianceRegistryFilter))
})
if err != nil {
ec.Error(ctx, err)
@@ -49630,6 +49758,10 @@ func (ec *executionContext) fieldContext_UpdateComplianceRegistryPayload_complia
switch field.Name {
case "id":
return ec.fieldContext_ComplianceRegistry_id(ctx, field)
case "snapshotId":
return ec.fieldContext_ComplianceRegistry_snapshotId(ctx, field)
case "sourceId":
return ec.fieldContext_ComplianceRegistry_sourceId(ctx, field)
case "organization":
return ec.fieldContext_ComplianceRegistry_organization(ctx, field)
case "referenceId":
@@ -59434,6 +59566,33 @@ func (ec *executionContext) unmarshalInputCancelSignatureRequestInput(ctx contex
return it, nil
}
func (ec *executionContext) unmarshalInputComplianceRegistryFilter(ctx context.Context, obj any) (types.ComplianceRegistryFilter, error) {
var it types.ComplianceRegistryFilter
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) unmarshalInputComplianceRegistryOrder(ctx context.Context, obj any) (types.ComplianceRegistryOrderBy, error) {
var it types.ComplianceRegistryOrderBy
asMap := map[string]any{}
@@ -66673,6 +66832,10 @@ func (ec *executionContext) _ComplianceRegistry(ctx context.Context, sel ast.Sel
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "snapshotId":
out.Values[i] = ec._ComplianceRegistry_snapshotId(ctx, field, obj)
case "sourceId":
out.Values[i] = ec._ComplianceRegistry_sourceId(ctx, field, obj)
case "organization":
field := field
@@ -86692,6 +86855,14 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
return res
}
func (ec *executionContext) unmarshalOComplianceRegistryFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐComplianceRegistryFilter(ctx context.Context, v any) (*types.ComplianceRegistryFilter, error) {
if v == nil {
return nil, nil
}
res, err := ec.unmarshalInputComplianceRegistryFilter(ctx, v)
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalOComplianceRegistryOrder2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐComplianceRegistryOrderBy(ctx context.Context, v any) (*types.ComplianceRegistryOrderBy, error) {
if v == nil {
return nil, nil

View File

@@ -30,6 +30,7 @@ type (
Resolver any
ParentID gid.GID
Filter *ComplianceRegistryFilter
}
)
@@ -37,6 +38,7 @@ func NewComplianceRegistryConnection(
p *page.Page[*coredata.ComplianceRegistry, coredata.ComplianceRegistryOrderField],
parentType any,
parentID gid.GID,
filter *ComplianceRegistryFilter,
) *ComplianceRegistryConnection {
edges := make([]*ComplianceRegistryEdge, len(p.Data))
for i, registry := range p.Data {
@@ -49,12 +51,15 @@ func NewComplianceRegistryConnection(
Resolver: parentType,
ParentID: parentID,
Filter: filter,
}
}
func NewComplianceRegistry(cr *coredata.ComplianceRegistry) *ComplianceRegistry {
return &ComplianceRegistry{
ID: cr.ID,
SnapshotID: cr.SnapshotID,
SourceID: cr.SourceID,
ReferenceID: cr.ReferenceID,
Area: cr.Area,
Source: cr.Source,

View File

@@ -109,6 +109,8 @@ type CancelSignatureRequestPayload struct {
type ComplianceRegistry 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"`
Area *string `json:"area,omitempty"`
@@ -132,6 +134,10 @@ type ComplianceRegistryEdge struct {
Node *ComplianceRegistry `json:"node"`
}
type ComplianceRegistryFilter struct {
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
}
type ConfirmEmailInput struct {
Token string `json:"token"`
}

View File

@@ -260,7 +260,12 @@ func (r *complianceRegistryConnectionResolver) TotalCount(ctx context.Context, o
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.ComplianceRegistries.CountByOrganizationID(ctx, obj.ParentID)
complianceRegistryFilter := coredata.NewComplianceRegistryFilter(nil)
if obj.Filter != nil {
complianceRegistryFilter = coredata.NewComplianceRegistryFilter(&obj.Filter.SnapshotID)
}
count, err := prb.ComplianceRegistries.CountForOrganizationID(ctx, obj.ParentID, complianceRegistryFilter)
if err != nil {
panic(fmt.Errorf("cannot count compliance registries: %w", err))
}
@@ -3313,9 +3318,9 @@ func (r *nonconformityRegistryConnectionResolver) TotalCount(ctx context.Context
switch obj.Resolver.(type) {
case *organizationResolver:
nonconformityRegistryFilter := coredata.NewNonconformityRegistryFilterBySnapshotID(nil)
nonconformityRegistryFilter := coredata.NewNonconformityRegistryFilter(nil)
if obj.Filter != nil {
nonconformityRegistryFilter = coredata.NewNonconformityRegistryFilterBySnapshotID(&obj.Filter.SnapshotID)
nonconformityRegistryFilter = coredata.NewNonconformityRegistryFilter(&obj.Filter.SnapshotID)
}
count, err := prb.NonconformityRegistries.CountForOrganizationID(ctx, obj.ParentID, nonconformityRegistryFilter)
@@ -3455,7 +3460,7 @@ func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organizat
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var nilSnapshotID *gid.GID = nil
vendorFilter := coredata.NewVendorFilterBySnapshotID(&nilSnapshotID)
vendorFilter := coredata.NewVendorFilter(&nilSnapshotID, nil)
page, err := prb.Vendors.ListForOrganizationID(ctx, obj.ID, cursor, vendorFilter)
if err != nil {
@@ -3652,9 +3657,9 @@ func (r *organizationResolver) Data(ctx context.Context, obj *types.Organization
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
datumFilter := coredata.NewDatumFilterBySnapshotID(nil)
datumFilter := coredata.NewDatumFilter(nil)
if filter != nil {
datumFilter = coredata.NewDatumFilterBySnapshotID(&filter.SnapshotID)
datumFilter = coredata.NewDatumFilter(&filter.SnapshotID)
}
page, err := prb.Data.ListForOrganizationID(ctx, obj.ID, cursor, datumFilter)
@@ -3707,9 +3712,9 @@ func (r *organizationResolver) NonconformityRegistries(ctx context.Context, obj
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
nonconformityRegistryFilter := coredata.NewNonconformityRegistryFilterBySnapshotID(nil)
nonconformityRegistryFilter := coredata.NewNonconformityRegistryFilter(nil)
if filter != nil {
nonconformityRegistryFilter = coredata.NewNonconformityRegistryFilterBySnapshotID(&filter.SnapshotID)
nonconformityRegistryFilter = coredata.NewNonconformityRegistryFilter(&filter.SnapshotID)
}
page, err := prb.NonconformityRegistries.ListForOrganizationID(ctx, obj.ID, cursor, nonconformityRegistryFilter)
@@ -3721,7 +3726,7 @@ func (r *organizationResolver) NonconformityRegistries(ctx context.Context, obj
}
// ComplianceRegistries is the resolver for the complianceRegistries field.
func (r *organizationResolver) ComplianceRegistries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ComplianceRegistryOrderBy) (*types.ComplianceRegistryConnection, error) {
func (r *organizationResolver) 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) {
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ComplianceRegistryOrderField]{
@@ -3737,12 +3742,17 @@ func (r *organizationResolver) ComplianceRegistries(ctx context.Context, obj *ty
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.ComplianceRegistries.ListForOrganizationID(ctx, obj.ID, cursor)
complianceRegistryFilter := coredata.NewComplianceRegistryFilter(nil)
if filter != nil {
complianceRegistryFilter = coredata.NewComplianceRegistryFilter(&filter.SnapshotID)
}
page, err := prb.ComplianceRegistries.ListForOrganizationID(ctx, obj.ID, cursor, complianceRegistryFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization compliance registries: %w", err))
}
return types.NewComplianceRegistryConnection(page, r, obj.ID), nil
return types.NewComplianceRegistryConnection(page, r, obj.ID, filter), nil
}
// ContinualImprovementRegistries is the resolver for the continualImprovementRegistries field.

View File

@@ -63,7 +63,8 @@ func (s VendorService) ListForOrganizationId(
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
filter := coredata.NewVendorTrustCenterFilter()
showOnTrustCenter := true
filter := coredata.NewVendorFilter(nil, &showOnTrustCenter)
err := vendors.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID, cursor, filter)
if err != nil {
return fmt.Errorf("cannot load vendors: %w", err)