Add vendor snapshots
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -89,11 +89,11 @@ export const useDeleteVendor = (
|
|||||||
export const vendorConnectionKey = "VendorsPage_vendors";
|
export const vendorConnectionKey = "VendorsPage_vendors";
|
||||||
|
|
||||||
export const vendorsQuery = graphql`
|
export const vendorsQuery = graphql`
|
||||||
query VendorGraphListQuery($organizationId: ID!) {
|
query VendorGraphListQuery($organizationId: ID!, $snapshotId: ID) {
|
||||||
node(id: $organizationId) {
|
node(id: $organizationId) {
|
||||||
... on Organization {
|
... on Organization {
|
||||||
id
|
id
|
||||||
...VendorGraphPaginatedFragment
|
...VendorGraphPaginatedFragment @arguments(snapshotId: $snapshotId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,6 +108,7 @@ export const paginatedVendorsFragment = graphql`
|
|||||||
after: { type: "CursorKey", defaultValue: null }
|
after: { type: "CursorKey", defaultValue: null }
|
||||||
before: { type: "CursorKey", defaultValue: null }
|
before: { type: "CursorKey", defaultValue: null }
|
||||||
last: { type: "Int", defaultValue: null }
|
last: { type: "Int", defaultValue: null }
|
||||||
|
snapshotId: { type: "ID", defaultValue: null }
|
||||||
) {
|
) {
|
||||||
vendors(
|
vendors(
|
||||||
first: $first
|
first: $first
|
||||||
@@ -115,11 +116,13 @@ export const paginatedVendorsFragment = graphql`
|
|||||||
last: $last
|
last: $last
|
||||||
before: $before
|
before: $before
|
||||||
orderBy: $order
|
orderBy: $order
|
||||||
) @connection(key: "VendorsListQuery_vendors") {
|
filter: { snapshotId: $snapshotId }
|
||||||
|
) @connection(key: "VendorsListQuery_vendors", filters: ["filter"]) {
|
||||||
__id
|
__id
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
|
snapshotId
|
||||||
name
|
name
|
||||||
websiteUrl
|
websiteUrl
|
||||||
updatedAt
|
updatedAt
|
||||||
@@ -148,6 +151,7 @@ export const vendorNodeQuery = graphql`
|
|||||||
node(id: $vendorId) {
|
node(id: $vendorId) {
|
||||||
... on Vendor {
|
... on Vendor {
|
||||||
id
|
id
|
||||||
|
snapshotId
|
||||||
name
|
name
|
||||||
websiteUrl
|
websiteUrl
|
||||||
...useVendorFormFragment
|
...useVendorFormFragment
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<b748739bef19b5c39b7c352f35332865>>
|
* @generated SignedSource<<8b1614888dac560deff871232f91995d>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
|
|||||||
import { FragmentRefs } from "relay-runtime";
|
import { FragmentRefs } from "relay-runtime";
|
||||||
export type VendorGraphListQuery$variables = {
|
export type VendorGraphListQuery$variables = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
|
snapshotId?: string | null | undefined;
|
||||||
};
|
};
|
||||||
export type VendorGraphListQuery$data = {
|
export type VendorGraphListQuery$data = {
|
||||||
readonly node: {
|
readonly node: {
|
||||||
@@ -30,6 +31,11 @@ var v0 = [
|
|||||||
"defaultValue": null,
|
"defaultValue": null,
|
||||||
"kind": "LocalArgument",
|
"kind": "LocalArgument",
|
||||||
"name": "organizationId"
|
"name": "organizationId"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "snapshotId"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
v1 = [
|
v1 = [
|
||||||
@@ -46,14 +52,26 @@ v2 = {
|
|||||||
"name": "id",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v3 = {
|
v3 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"variableName": "snapshotId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v4 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "__typename",
|
"name": "__typename",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v4 = [
|
v5 = [
|
||||||
|
{
|
||||||
|
"fields": (v3/*: any*/),
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "filter"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "Literal",
|
"kind": "Literal",
|
||||||
"name": "first",
|
"name": "first",
|
||||||
@@ -80,7 +98,7 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
(v2/*: any*/),
|
(v2/*: any*/),
|
||||||
{
|
{
|
||||||
"args": null,
|
"args": (v3/*: any*/),
|
||||||
"kind": "FragmentSpread",
|
"kind": "FragmentSpread",
|
||||||
"name": "VendorGraphPaginatedFragment"
|
"name": "VendorGraphPaginatedFragment"
|
||||||
}
|
}
|
||||||
@@ -109,14 +127,14 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v4/*: any*/),
|
||||||
(v2/*: any*/),
|
(v2/*: any*/),
|
||||||
{
|
{
|
||||||
"kind": "InlineFragment",
|
"kind": "InlineFragment",
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v4/*: any*/),
|
"args": (v5/*: any*/),
|
||||||
"concreteType": "VendorConnection",
|
"concreteType": "VendorConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "vendors",
|
"name": "vendors",
|
||||||
@@ -139,6 +157,13 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v2/*: any*/),
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -236,7 +261,7 @@ return {
|
|||||||
],
|
],
|
||||||
"storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})"
|
"storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})"
|
||||||
},
|
},
|
||||||
(v3/*: any*/)
|
(v4/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -302,13 +327,13 @@ return {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": "vendors(first:50)"
|
"storageKey": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v4/*: any*/),
|
"args": (v5/*: any*/),
|
||||||
"filters": [
|
"filters": [
|
||||||
"orderBy"
|
"filter"
|
||||||
],
|
],
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorsListQuery_vendors",
|
"key": "VendorsListQuery_vendors",
|
||||||
@@ -325,16 +350,16 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "e2eade63dcf3d7ea071463a2e5993293",
|
"cacheID": "4b19f6f4be47c38d8b68601ec95315a6",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "VendorGraphListQuery",
|
"name": "VendorGraphListQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query VendorGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...VendorGraphPaginatedFragment\n }\n id\n }\n}\n\nfragment VendorGraphPaginatedFragment on Organization {\n vendors(first: 50) {\n edges {\n node {\n id\n name\n websiteUrl\n updatedAt\n riskAssessments(first: 1, orderBy: {direction: DESC, field: ASSESSED_AT}) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
"text": "query VendorGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...VendorGraphPaginatedFragment_3iomuz\n }\n id\n }\n}\n\nfragment VendorGraphPaginatedFragment_3iomuz on Organization {\n vendors(first: 50, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n websiteUrl\n updatedAt\n riskAssessments(first: 1, orderBy: {direction: DESC, field: ASSESSED_AT}) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "3bb12a4d7a49090154bb56951e69f4aa";
|
(node as any).hash = "3034ee812f89d0596f3f6d3094c1dfc8";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<46bd8a339fe6fd05256df0b1f806e0bd>>
|
* @generated SignedSource<<c3a7e9de9c7f072bbca3ad552e5860cd>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -18,6 +18,7 @@ export type VendorGraphNodeQuery$data = {
|
|||||||
readonly node: {
|
readonly node: {
|
||||||
readonly id?: string;
|
readonly id?: string;
|
||||||
readonly name?: string;
|
readonly name?: string;
|
||||||
|
readonly snapshotId?: string | null | undefined;
|
||||||
readonly websiteUrl?: string | null | undefined;
|
readonly websiteUrl?: string | null | undefined;
|
||||||
readonly " $fragmentSpreads": FragmentRefs<"VendorComplianceTabFragment" | "VendorContactsTabFragment" | "VendorOverviewTabBusinessAssociateAgreementFragment" | "VendorOverviewTabDataPrivacyAgreementFragment" | "VendorRiskAssessmentTabFragment" | "VendorServicesTabFragment" | "useVendorFormFragment">;
|
readonly " $fragmentSpreads": FragmentRefs<"VendorComplianceTabFragment" | "VendorContactsTabFragment" | "VendorOverviewTabBusinessAssociateAgreementFragment" | "VendorOverviewTabDataPrivacyAgreementFragment" | "VendorRiskAssessmentTabFragment" | "VendorServicesTabFragment" | "useVendorFormFragment">;
|
||||||
};
|
};
|
||||||
@@ -63,20 +64,27 @@ v4 = {
|
|||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "name",
|
"name": "snapshotId",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v5 = {
|
v5 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "name",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v6 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "websiteUrl",
|
"name": "websiteUrl",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v6 = [
|
v7 = [
|
||||||
(v3/*: any*/)
|
(v3/*: any*/)
|
||||||
],
|
],
|
||||||
v7 = {
|
v8 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
@@ -89,80 +97,80 @@ v7 = {
|
|||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "people",
|
"name": "people",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v6/*: any*/),
|
"selections": (v7/*: any*/),
|
||||||
"storageKey": null
|
|
||||||
},
|
|
||||||
v8 = {
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "__typename",
|
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v9 = {
|
v9 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v10 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v10 = [
|
v11 = [
|
||||||
{
|
{
|
||||||
"kind": "Literal",
|
"kind": "Literal",
|
||||||
"name": "first",
|
"name": "first",
|
||||||
"value": 50
|
"value": 50
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
v11 = {
|
v12 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "validUntil",
|
"name": "validUntil",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v12 = {
|
v13 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "fileUrl",
|
"name": "fileUrl",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v13 = {
|
v14 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "cursor",
|
"name": "cursor",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v14 = {
|
v15 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "endCursor",
|
"name": "endCursor",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v15 = {
|
v16 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "hasNextPage",
|
"name": "hasNextPage",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v16 = {
|
v17 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "hasPreviousPage",
|
"name": "hasPreviousPage",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v17 = {
|
v18 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "startCursor",
|
"name": "startCursor",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v18 = {
|
v19 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"concreteType": "PageInfo",
|
"concreteType": "PageInfo",
|
||||||
@@ -170,14 +178,14 @@ v18 = {
|
|||||||
"name": "pageInfo",
|
"name": "pageInfo",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v14/*: any*/),
|
|
||||||
(v15/*: any*/),
|
(v15/*: any*/),
|
||||||
(v16/*: any*/),
|
(v16/*: any*/),
|
||||||
(v17/*: any*/)
|
(v17/*: any*/),
|
||||||
|
(v18/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v19 = {
|
v20 = {
|
||||||
"kind": "ClientExtension",
|
"kind": "ClientExtension",
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
@@ -189,31 +197,31 @@ v19 = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
v20 = [
|
v21 = [
|
||||||
"orderBy"
|
"orderBy"
|
||||||
],
|
],
|
||||||
v21 = {
|
v22 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "fullName",
|
"name": "fullName",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v22 = {
|
v23 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "createdAt",
|
"name": "createdAt",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v23 = {
|
v24 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "updatedAt",
|
"name": "updatedAt",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v24 = [
|
v25 = [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
@@ -222,7 +230,7 @@ v24 = [
|
|||||||
"name": "fileName",
|
"name": "fileName",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v12/*: any*/),
|
(v13/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -230,8 +238,8 @@ v24 = [
|
|||||||
"name": "validFrom",
|
"name": "validFrom",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v11/*: any*/),
|
(v12/*: any*/),
|
||||||
(v22/*: any*/)
|
(v23/*: any*/)
|
||||||
];
|
];
|
||||||
return {
|
return {
|
||||||
"fragment": {
|
"fragment": {
|
||||||
@@ -257,6 +265,7 @@ return {
|
|||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v4/*: any*/),
|
(v4/*: any*/),
|
||||||
(v5/*: any*/),
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/),
|
||||||
{
|
{
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "FragmentSpread",
|
"kind": "FragmentSpread",
|
||||||
@@ -315,7 +324,7 @@ return {
|
|||||||
"name": "user",
|
"name": "user",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v7/*: any*/)
|
(v8/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
@@ -343,14 +352,15 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v8/*: any*/),
|
(v9/*: any*/),
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
{
|
{
|
||||||
"kind": "InlineFragment",
|
"kind": "InlineFragment",
|
||||||
"selections": [
|
"selections": [
|
||||||
(v4/*: any*/),
|
(v4/*: any*/),
|
||||||
(v5/*: any*/),
|
(v5/*: any*/),
|
||||||
(v9/*: any*/),
|
(v6/*: any*/),
|
||||||
|
(v10/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -428,7 +438,7 @@ return {
|
|||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "businessOwner",
|
"name": "businessOwner",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v6/*: any*/),
|
"selections": (v7/*: any*/),
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -438,12 +448,12 @@ return {
|
|||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "securityOwner",
|
"name": "securityOwner",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v6/*: any*/),
|
"selections": (v7/*: any*/),
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"concreteType": "VendorComplianceReportConnection",
|
"concreteType": "VendorComplianceReportConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "complianceReports",
|
"name": "complianceReports",
|
||||||
@@ -473,7 +483,7 @@ return {
|
|||||||
"name": "reportDate",
|
"name": "reportDate",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v11/*: any*/),
|
(v12/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -481,7 +491,7 @@ return {
|
|||||||
"name": "reportName",
|
"name": "reportName",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v12/*: any*/),
|
(v13/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -489,23 +499,23 @@ return {
|
|||||||
"name": "fileSize",
|
"name": "fileSize",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v8/*: any*/)
|
(v9/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v13/*: any*/)
|
(v14/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v18/*: any*/),
|
(v19/*: any*/),
|
||||||
(v19/*: any*/)
|
(v20/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": "complianceReports(first:50)"
|
"storageKey": "complianceReports(first:50)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"filters": (v20/*: any*/),
|
"filters": (v21/*: any*/),
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorComplianceTabFragment_complianceReports",
|
"key": "VendorComplianceTabFragment_complianceReports",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
@@ -513,7 +523,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"concreteType": "VendorContactConnection",
|
"concreteType": "VendorContactConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "contacts",
|
"name": "contacts",
|
||||||
@@ -536,7 +546,7 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v21/*: any*/),
|
(v22/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -558,25 +568,25 @@ return {
|
|||||||
"name": "role",
|
"name": "role",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v22/*: any*/),
|
|
||||||
(v23/*: any*/),
|
(v23/*: any*/),
|
||||||
(v8/*: any*/)
|
(v24/*: any*/),
|
||||||
|
(v9/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v13/*: any*/)
|
(v14/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v18/*: any*/),
|
(v19/*: any*/),
|
||||||
(v19/*: any*/)
|
(v20/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": "contacts(first:50)"
|
"storageKey": "contacts(first:50)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"filters": (v20/*: any*/),
|
"filters": (v21/*: any*/),
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorContactsTabFragment_contacts",
|
"key": "VendorContactsTabFragment_contacts",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
@@ -584,7 +594,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"concreteType": "VendorServiceConnection",
|
"concreteType": "VendorServiceConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "services",
|
"name": "services",
|
||||||
@@ -607,27 +617,27 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v4/*: any*/),
|
(v5/*: any*/),
|
||||||
(v9/*: any*/),
|
(v10/*: any*/),
|
||||||
(v22/*: any*/),
|
|
||||||
(v23/*: any*/),
|
(v23/*: any*/),
|
||||||
(v8/*: any*/)
|
(v24/*: any*/),
|
||||||
|
(v9/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v13/*: any*/)
|
(v14/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v18/*: any*/),
|
(v19/*: any*/),
|
||||||
(v19/*: any*/)
|
(v20/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": "services(first:50)"
|
"storageKey": "services(first:50)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"filters": (v20/*: any*/),
|
"filters": (v21/*: any*/),
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorServicesTabFragment_services",
|
"key": "VendorServicesTabFragment_services",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
@@ -635,7 +645,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"concreteType": "VendorRiskAssessmentConnection",
|
"concreteType": "VendorRiskAssessmentConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "riskAssessments",
|
"name": "riskAssessments",
|
||||||
@@ -674,7 +684,7 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v21/*: any*/)
|
(v22/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -706,11 +716,11 @@ return {
|
|||||||
"name": "notes",
|
"name": "notes",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v8/*: any*/)
|
(v9/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v13/*: any*/)
|
(v14/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -722,21 +732,21 @@ return {
|
|||||||
"name": "pageInfo",
|
"name": "pageInfo",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v15/*: any*/),
|
|
||||||
(v14/*: any*/),
|
|
||||||
(v16/*: any*/),
|
(v16/*: any*/),
|
||||||
(v17/*: any*/)
|
(v15/*: any*/),
|
||||||
|
(v17/*: any*/),
|
||||||
|
(v18/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
(v19/*: any*/)
|
(v20/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": "riskAssessments(first:50)"
|
"storageKey": "riskAssessments(first:50)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v10/*: any*/),
|
"args": (v11/*: any*/),
|
||||||
"filters": (v20/*: any*/),
|
"filters": (v21/*: any*/),
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorRiskAssessmentTabFragment_riskAssessments",
|
"key": "VendorRiskAssessmentTabFragment_riskAssessments",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
@@ -749,7 +759,7 @@ return {
|
|||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "businessAssociateAgreement",
|
"name": "businessAssociateAgreement",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v24/*: any*/),
|
"selections": (v25/*: any*/),
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -759,7 +769,7 @@ return {
|
|||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "dataPrivacyAgreement",
|
"name": "dataPrivacyAgreement",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v24/*: any*/),
|
"selections": (v25/*: any*/),
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -785,7 +795,7 @@ return {
|
|||||||
"name": "user",
|
"name": "user",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v7/*: any*/),
|
(v8/*: any*/),
|
||||||
(v3/*: any*/)
|
(v3/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -797,16 +807,16 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "7e1a7455861aea37eee2d799d8385586",
|
"cacheID": "f0b506b57e84959deb0b1e3fa0481897",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "VendorGraphNodeQuery",
|
"name": "VendorGraphNodeQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query VendorGraphNodeQuery(\n $vendorId: ID!\n $organizationId: ID!\n) {\n node(id: $vendorId) {\n __typename\n ... on Vendor {\n id\n name\n websiteUrl\n ...useVendorFormFragment\n ...VendorComplianceTabFragment\n ...VendorContactsTabFragment\n ...VendorServicesTabFragment\n ...VendorRiskAssessmentTabFragment\n ...VendorOverviewTabBusinessAssociateAgreementFragment\n ...VendorOverviewTabDataPrivacyAgreementFragment\n }\n id\n }\n viewer {\n user {\n people(organizationId: $organizationId) {\n id\n }\n id\n }\n id\n }\n}\n\nfragment VendorComplianceTabFragment on Vendor {\n complianceReports(first: 50) {\n edges {\n node {\n id\n ...VendorComplianceTabFragment_report\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorComplianceTabFragment_report on VendorComplianceReport {\n id\n reportDate\n validUntil\n reportName\n fileUrl\n fileSize\n}\n\nfragment VendorContactsTabFragment on Vendor {\n contacts(first: 50) {\n edges {\n node {\n id\n ...VendorContactsTabFragment_contact\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorContactsTabFragment_contact on VendorContact {\n id\n fullName\n email\n phone\n role\n createdAt\n updatedAt\n}\n\nfragment VendorOverviewTabBusinessAssociateAgreementFragment on Vendor {\n businessAssociateAgreement {\n id\n fileName\n fileUrl\n validFrom\n validUntil\n createdAt\n }\n}\n\nfragment VendorOverviewTabDataPrivacyAgreementFragment on Vendor {\n dataPrivacyAgreement {\n id\n fileName\n fileUrl\n validFrom\n validUntil\n createdAt\n }\n}\n\nfragment VendorRiskAssessmentTabFragment on Vendor {\n id\n riskAssessments(first: 50) {\n edges {\n node {\n id\n ...VendorRiskAssessmentTabFragment_assessment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment VendorRiskAssessmentTabFragment_assessment on VendorRiskAssessment {\n id\n assessedAt\n assessedBy {\n id\n fullName\n }\n expiresAt\n dataSensitivity\n businessImpact\n notes\n}\n\nfragment VendorServicesTabFragment on Vendor {\n services(first: 50) {\n edges {\n node {\n id\n ...VendorServicesTabFragment_service\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorServicesTabFragment_service on VendorService {\n id\n name\n description\n createdAt\n updatedAt\n}\n\nfragment useVendorFormFragment on Vendor {\n id\n name\n description\n statusPageUrl\n termsOfServiceUrl\n privacyPolicyUrl\n serviceLevelAgreementUrl\n dataProcessingAgreementUrl\n websiteUrl\n legalName\n headquarterAddress\n certifications\n securityPageUrl\n trustPageUrl\n businessOwner {\n id\n }\n securityOwner {\n id\n }\n}\n"
|
"text": "query VendorGraphNodeQuery(\n $vendorId: ID!\n $organizationId: ID!\n) {\n node(id: $vendorId) {\n __typename\n ... on Vendor {\n id\n snapshotId\n name\n websiteUrl\n ...useVendorFormFragment\n ...VendorComplianceTabFragment\n ...VendorContactsTabFragment\n ...VendorServicesTabFragment\n ...VendorRiskAssessmentTabFragment\n ...VendorOverviewTabBusinessAssociateAgreementFragment\n ...VendorOverviewTabDataPrivacyAgreementFragment\n }\n id\n }\n viewer {\n user {\n people(organizationId: $organizationId) {\n id\n }\n id\n }\n id\n }\n}\n\nfragment VendorComplianceTabFragment on Vendor {\n complianceReports(first: 50) {\n edges {\n node {\n id\n ...VendorComplianceTabFragment_report\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorComplianceTabFragment_report on VendorComplianceReport {\n id\n reportDate\n validUntil\n reportName\n fileUrl\n fileSize\n}\n\nfragment VendorContactsTabFragment on Vendor {\n contacts(first: 50) {\n edges {\n node {\n id\n ...VendorContactsTabFragment_contact\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorContactsTabFragment_contact on VendorContact {\n id\n fullName\n email\n phone\n role\n createdAt\n updatedAt\n}\n\nfragment VendorOverviewTabBusinessAssociateAgreementFragment on Vendor {\n businessAssociateAgreement {\n id\n fileName\n fileUrl\n validFrom\n validUntil\n createdAt\n }\n}\n\nfragment VendorOverviewTabDataPrivacyAgreementFragment on Vendor {\n dataPrivacyAgreement {\n id\n fileName\n fileUrl\n validFrom\n validUntil\n createdAt\n }\n}\n\nfragment VendorRiskAssessmentTabFragment on Vendor {\n id\n riskAssessments(first: 50) {\n edges {\n node {\n id\n ...VendorRiskAssessmentTabFragment_assessment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment VendorRiskAssessmentTabFragment_assessment on VendorRiskAssessment {\n id\n assessedAt\n assessedBy {\n id\n fullName\n }\n expiresAt\n dataSensitivity\n businessImpact\n notes\n}\n\nfragment VendorServicesTabFragment on Vendor {\n services(first: 50) {\n edges {\n node {\n id\n ...VendorServicesTabFragment_service\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment VendorServicesTabFragment_service on VendorService {\n id\n name\n description\n createdAt\n updatedAt\n}\n\nfragment useVendorFormFragment on Vendor {\n id\n name\n description\n statusPageUrl\n termsOfServiceUrl\n privacyPolicyUrl\n serviceLevelAgreementUrl\n dataProcessingAgreementUrl\n websiteUrl\n legalName\n headquarterAddress\n certifications\n securityPageUrl\n trustPageUrl\n businessOwner {\n id\n }\n securityOwner {\n id\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "1eac0bd4bc5eccf51ea024d27f348e14";
|
(node as any).hash = "4af64d92bd85441554a2c6ad8d2ccd77";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<93638f7eeb1634fc19aaaa95cae0c7b8>>
|
* @generated SignedSource<<b6975a3a740bdf7e2c9914fc64770638>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -31,6 +31,7 @@ export type VendorGraphPaginatedFragment$data = {
|
|||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
readonly snapshotId: string | null | undefined;
|
||||||
readonly updatedAt: any;
|
readonly updatedAt: any;
|
||||||
readonly websiteUrl: string | null | undefined;
|
readonly websiteUrl: string | null | undefined;
|
||||||
};
|
};
|
||||||
@@ -82,6 +83,11 @@ return {
|
|||||||
"defaultValue": null,
|
"defaultValue": null,
|
||||||
"kind": "LocalArgument",
|
"kind": "LocalArgument",
|
||||||
"name": "order"
|
"name": "order"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "snapshotId"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"kind": "Fragment",
|
"kind": "Fragment",
|
||||||
@@ -122,9 +128,15 @@ return {
|
|||||||
"alias": "vendors",
|
"alias": "vendors",
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"kind": "Variable",
|
"fields": [
|
||||||
"name": "orderBy",
|
{
|
||||||
"variableName": "order"
|
"kind": "Variable",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"variableName": "snapshotId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "filter"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"concreteType": "VendorConnection",
|
"concreteType": "VendorConnection",
|
||||||
@@ -149,6 +161,13 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v1/*: any*/),
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -327,6 +346,6 @@ return {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "1d2bf7c29e77d60d0a955a62b98c85ab";
|
(node as any).hash = "578772ed7c83ae174d43b0be95a02fd2";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<bfe74e681960002105d6995d91548400>>
|
* @generated SignedSource<<f98b10bd4f5fb03b55b46e2554480590>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -23,6 +23,7 @@ export type VendorsListQuery$variables = {
|
|||||||
id: string;
|
id: string;
|
||||||
last?: number | null | undefined;
|
last?: number | null | undefined;
|
||||||
order?: VendorOrder | null | undefined;
|
order?: VendorOrder | null | undefined;
|
||||||
|
snapshotId?: string | null | undefined;
|
||||||
};
|
};
|
||||||
export type VendorsListQuery$data = {
|
export type VendorsListQuery$data = {
|
||||||
readonly node: {
|
readonly node: {
|
||||||
@@ -65,52 +66,69 @@ v5 = {
|
|||||||
"kind": "LocalArgument",
|
"kind": "LocalArgument",
|
||||||
"name": "order"
|
"name": "order"
|
||||||
},
|
},
|
||||||
v6 = [
|
v6 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "snapshotId"
|
||||||
|
},
|
||||||
|
v7 = [
|
||||||
{
|
{
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"variableName": "id"
|
"variableName": "id"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
v7 = {
|
v8 = {
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "after",
|
"name": "after",
|
||||||
"variableName": "after"
|
"variableName": "after"
|
||||||
},
|
},
|
||||||
v8 = {
|
v9 = {
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "before",
|
"name": "before",
|
||||||
"variableName": "before"
|
"variableName": "before"
|
||||||
},
|
},
|
||||||
v9 = {
|
v10 = {
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "first",
|
"name": "first",
|
||||||
"variableName": "first"
|
"variableName": "first"
|
||||||
},
|
},
|
||||||
v10 = {
|
v11 = {
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "last",
|
"name": "last",
|
||||||
"variableName": "last"
|
"variableName": "last"
|
||||||
},
|
},
|
||||||
v11 = {
|
v12 = {
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"variableName": "snapshotId"
|
||||||
|
},
|
||||||
|
v13 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "__typename",
|
"name": "__typename",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v12 = {
|
v14 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v13 = [
|
v15 = [
|
||||||
(v7/*: any*/),
|
|
||||||
(v8/*: any*/),
|
(v8/*: any*/),
|
||||||
(v9/*: any*/),
|
(v9/*: any*/),
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
(v12/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "filter"
|
||||||
|
},
|
||||||
(v10/*: any*/),
|
(v10/*: any*/),
|
||||||
|
(v11/*: any*/),
|
||||||
{
|
{
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "orderBy",
|
"name": "orderBy",
|
||||||
@@ -125,7 +143,8 @@ return {
|
|||||||
(v2/*: any*/),
|
(v2/*: any*/),
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v4/*: any*/),
|
(v4/*: any*/),
|
||||||
(v5/*: any*/)
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/)
|
||||||
],
|
],
|
||||||
"kind": "Fragment",
|
"kind": "Fragment",
|
||||||
"metadata": null,
|
"metadata": null,
|
||||||
@@ -133,7 +152,7 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v6/*: any*/),
|
"args": (v7/*: any*/),
|
||||||
"concreteType": null,
|
"concreteType": null,
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "node",
|
"name": "node",
|
||||||
@@ -141,15 +160,16 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"args": [
|
"args": [
|
||||||
(v7/*: any*/),
|
|
||||||
(v8/*: any*/),
|
(v8/*: any*/),
|
||||||
(v9/*: any*/),
|
(v9/*: any*/),
|
||||||
(v10/*: any*/),
|
(v10/*: any*/),
|
||||||
|
(v11/*: any*/),
|
||||||
{
|
{
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "order",
|
"name": "order",
|
||||||
"variableName": "order"
|
"variableName": "order"
|
||||||
}
|
},
|
||||||
|
(v12/*: any*/)
|
||||||
],
|
],
|
||||||
"kind": "FragmentSpread",
|
"kind": "FragmentSpread",
|
||||||
"name": "VendorGraphPaginatedFragment"
|
"name": "VendorGraphPaginatedFragment"
|
||||||
@@ -169,6 +189,7 @@ return {
|
|||||||
(v2/*: any*/),
|
(v2/*: any*/),
|
||||||
(v4/*: any*/),
|
(v4/*: any*/),
|
||||||
(v5/*: any*/),
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/),
|
||||||
(v3/*: any*/)
|
(v3/*: any*/)
|
||||||
],
|
],
|
||||||
"kind": "Operation",
|
"kind": "Operation",
|
||||||
@@ -176,20 +197,20 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v6/*: any*/),
|
"args": (v7/*: any*/),
|
||||||
"concreteType": null,
|
"concreteType": null,
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v11/*: any*/),
|
(v13/*: any*/),
|
||||||
(v12/*: any*/),
|
(v14/*: any*/),
|
||||||
{
|
{
|
||||||
"kind": "InlineFragment",
|
"kind": "InlineFragment",
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v13/*: any*/),
|
"args": (v15/*: any*/),
|
||||||
"concreteType": "VendorConnection",
|
"concreteType": "VendorConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "vendors",
|
"name": "vendors",
|
||||||
@@ -211,7 +232,14 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v12/*: any*/),
|
(v14/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "snapshotId",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -271,7 +299,7 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v12/*: any*/),
|
(v14/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -309,7 +337,7 @@ return {
|
|||||||
],
|
],
|
||||||
"storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})"
|
"storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})"
|
||||||
},
|
},
|
||||||
(v11/*: any*/)
|
(v13/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -379,9 +407,9 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v13/*: any*/),
|
"args": (v15/*: any*/),
|
||||||
"filters": [
|
"filters": [
|
||||||
"orderBy"
|
"filter"
|
||||||
],
|
],
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "VendorsListQuery_vendors",
|
"key": "VendorsListQuery_vendors",
|
||||||
@@ -398,16 +426,16 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "70fb3d49e78996ae4cefbaa8f5605c2c",
|
"cacheID": "6570f4601f6dea5b7fe738d851a7f1ba",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "VendorsListQuery",
|
"name": "VendorsListQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query VendorsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: VendorOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...VendorGraphPaginatedFragment_16fISc\n id\n }\n}\n\nfragment VendorGraphPaginatedFragment_16fISc on Organization {\n vendors(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n name\n websiteUrl\n updatedAt\n riskAssessments(first: 1, orderBy: {direction: DESC, field: ASSESSED_AT}) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
"text": "query VendorsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: VendorOrder = null\n $snapshotId: ID = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...VendorGraphPaginatedFragment_25MC8O\n id\n }\n}\n\nfragment VendorGraphPaginatedFragment_25MC8O on Organization {\n vendors(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n websiteUrl\n updatedAt\n riskAssessments(first: 1, orderBy: {direction: DESC, field: ASSESSED_AT}) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "1d2bf7c29e77d60d0a955a62b98c85ab";
|
(node as any).hash = "578772ed7c83ae174d43b0be95a02fd2";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ export default function AssetDetailsPage(props: Props) {
|
|||||||
organizationId={organizationId}
|
organizationId={organizationId}
|
||||||
control={control}
|
control={control}
|
||||||
name="vendorIds"
|
name="vendorIds"
|
||||||
|
selectedVendors={vendors}
|
||||||
label={__("Vendors")}
|
label={__("Vendors")}
|
||||||
disabled={isSnapshotMode}
|
disabled={isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ import {
|
|||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
import { Outlet } from "react-router";
|
import { Outlet, useParams } from "react-router";
|
||||||
import { faviconUrl } from "@probo/helpers";
|
import { faviconUrl, validateSnapshotConsistency } from "@probo/helpers";
|
||||||
import { ImportAssessmentDialog } from "./dialogs/ImportAssessmentDialog";
|
import { ImportAssessmentDialog } from "./dialogs/ImportAssessmentDialog";
|
||||||
import { complianceReportsFragment } from "./tabs/VendorComplianceTab";
|
import { complianceReportsFragment } from "./tabs/VendorComplianceTab";
|
||||||
import type { VendorComplianceTabFragment$key } from "./tabs/__generated__/VendorComplianceTabFragment.graphql";
|
import type { VendorComplianceTabFragment$key } from "./tabs/__generated__/VendorComplianceTabFragment.graphql";
|
||||||
|
import { SnapshotBanner } from "/components/SnapshotBanner";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
queryRef: PreloadedQuery<VendorGraphNodeQuery>;
|
queryRef: PreloadedQuery<VendorGraphNodeQuery>;
|
||||||
@@ -38,6 +39,14 @@ export default function VendorDetailPage(props: Props) {
|
|||||||
const vendor = data.node;
|
const vendor = data.node;
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const organizationId = useOrganizationId();
|
const organizationId = useOrganizationId();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
|
|
||||||
|
if (!vendor) {
|
||||||
|
return <div>{__("Vendor not found")}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateSnapshotConsistency(vendor, snapshotId);
|
||||||
const deleteVendor = useDeleteVendor(
|
const deleteVendor = useDeleteVendor(
|
||||||
vendor,
|
vendor,
|
||||||
ConnectionHandler.getConnectionID(organizationId, vendorConnectionKey)
|
ConnectionHandler.getConnectionID(organizationId, vendorConnectionKey)
|
||||||
@@ -48,13 +57,22 @@ export default function VendorDetailPage(props: Props) {
|
|||||||
vendor as VendorComplianceTabFragment$key
|
vendor as VendorComplianceTabFragment$key
|
||||||
).complianceReports.edges.length;
|
).complianceReports.edges.length;
|
||||||
|
|
||||||
|
const vendorsUrl = isSnapshotMode && snapshotId
|
||||||
|
? `/organizations/${organizationId}/snapshots/${snapshotId}/vendors`
|
||||||
|
: `/organizations/${organizationId}/vendors`;
|
||||||
|
|
||||||
|
const baseVendorUrl = isSnapshotMode && snapshotId
|
||||||
|
? `/organizations/${organizationId}/snapshots/${snapshotId}/vendors/${vendor.id}`
|
||||||
|
: `/organizations/${organizationId}/vendors/${vendor.id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
{snapshotId && <SnapshotBanner snapshotId={snapshotId} />}
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
label: __("Vendors"),
|
label: __("Vendors"),
|
||||||
to: `/organizations/${organizationId}/vendors`,
|
to: vendorsUrl,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: vendor.name ?? "",
|
label: vendor.name ?? "",
|
||||||
@@ -72,54 +90,44 @@ export default function VendorDetailPage(props: Props) {
|
|||||||
)}
|
)}
|
||||||
<div className="text-2xl">{vendor.name}</div>
|
<div className="text-2xl">{vendor.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 items-center">
|
{!isSnapshotMode && (
|
||||||
<ImportAssessmentDialog vendorId={vendor.id!}>
|
<div className="flex gap-2 items-center">
|
||||||
<Button icon={IconPageTextLine} variant="secondary">
|
<ImportAssessmentDialog vendorId={vendor.id!}>
|
||||||
{__("Assessment From Website")}
|
<Button icon={IconPageTextLine} variant="secondary">
|
||||||
</Button>
|
{__("Assessment From Website")}
|
||||||
</ImportAssessmentDialog>
|
</Button>
|
||||||
<ActionDropdown variant="secondary">
|
</ImportAssessmentDialog>
|
||||||
<DropdownItem
|
<ActionDropdown variant="secondary">
|
||||||
variant="danger"
|
<DropdownItem
|
||||||
icon={IconTrashCan}
|
variant="danger"
|
||||||
onClick={deleteVendor}
|
icon={IconTrashCan}
|
||||||
>
|
onClick={deleteVendor}
|
||||||
{__("Delete")}
|
>
|
||||||
</DropdownItem>
|
{__("Delete")}
|
||||||
</ActionDropdown>
|
</DropdownItem>
|
||||||
</div>
|
</ActionDropdown>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/overview`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/overview`}
|
|
||||||
>
|
|
||||||
{__("Overview")}
|
{__("Overview")}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/certifications`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/certifications`}
|
|
||||||
>
|
|
||||||
{__("Certifications")}
|
{__("Certifications")}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/compliance`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/compliance`}
|
|
||||||
>
|
|
||||||
{__("Compliance reports")}
|
{__("Compliance reports")}
|
||||||
{reportsCount > 0 && <TabBadge>{reportsCount}</TabBadge>}
|
{reportsCount > 0 && <TabBadge>{reportsCount}</TabBadge>}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/risks`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/risks`}
|
|
||||||
>
|
|
||||||
{__("Risk Assessment")}
|
{__("Risk Assessment")}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/contacts`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/contacts`}
|
|
||||||
>
|
|
||||||
{__("Contacts")}
|
{__("Contacts")}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
<TabLink
|
<TabLink to={`${baseVendorUrl}/services`}>
|
||||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/services`}
|
|
||||||
>
|
|
||||||
{__("Services")}
|
{__("Services")}
|
||||||
</TabLink>
|
</TabLink>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
type PreloadedQuery,
|
type PreloadedQuery,
|
||||||
} from "react-relay";
|
} from "react-relay";
|
||||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
|
import { useParams } from "react-router";
|
||||||
import { faviconUrl } from "@probo/helpers";
|
import { faviconUrl } from "@probo/helpers";
|
||||||
import type { NodeOf } from "/types";
|
import type { NodeOf } from "/types";
|
||||||
import { CreateVendorDialog } from "./dialogs/CreateVendorDialog";
|
import { CreateVendorDialog } from "./dialogs/CreateVendorDialog";
|
||||||
@@ -35,6 +36,7 @@ import type {
|
|||||||
VendorGraphPaginatedFragment$key,
|
VendorGraphPaginatedFragment$key,
|
||||||
} from "/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql";
|
} from "/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql";
|
||||||
import { SortableTable, SortableTh } from "/components/SortableTable";
|
import { SortableTable, SortableTh } from "/components/SortableTable";
|
||||||
|
import { SnapshotBanner } from "/components/SnapshotBanner";
|
||||||
|
|
||||||
type Vendor = NodeOf<VendorGraphPaginatedFragment$data["vendors"]>;
|
type Vendor = NodeOf<VendorGraphPaginatedFragment$data["vendors"]>;
|
||||||
|
|
||||||
@@ -45,6 +47,8 @@ type Props = {
|
|||||||
export default function VendorsPage(props: Props) {
|
export default function VendorsPage(props: Props) {
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const organizationId = useOrganizationId();
|
const organizationId = useOrganizationId();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
|
|
||||||
const data = usePreloadedQuery(vendorsQuery, props.queryRef);
|
const data = usePreloadedQuery(vendorsQuery, props.queryRef);
|
||||||
const pagination = usePaginationFragment(
|
const pagination = usePaginationFragment(
|
||||||
@@ -59,18 +63,21 @@ export default function VendorsPage(props: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
{snapshotId && <SnapshotBanner snapshotId={snapshotId} />}
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={__("Vendors")}
|
title={__("Vendors")}
|
||||||
description={__(
|
description={__(
|
||||||
"Vendors are third-party services that your company uses. Add them to keep track of their risk and compliance status."
|
"Vendors are third-party services that your company uses. Add them to keep track of their risk and compliance status."
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<CreateVendorDialog
|
{!isSnapshotMode && (
|
||||||
connection={connectionId}
|
<CreateVendorDialog
|
||||||
organizationId={organizationId}
|
connection={connectionId}
|
||||||
>
|
organizationId={organizationId}
|
||||||
<Button icon={IconPlusLarge}>{__("Add vendor")}</Button>
|
>
|
||||||
</CreateVendorDialog>
|
<Button icon={IconPlusLarge}>{__("Add vendor")}</Button>
|
||||||
|
</CreateVendorDialog>
|
||||||
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<SortableTable {...pagination}>
|
<SortableTable {...pagination}>
|
||||||
<Thead>
|
<Thead>
|
||||||
@@ -106,14 +113,20 @@ function VendorRow({
|
|||||||
organizationId: string;
|
organizationId: string;
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
}) {
|
}) {
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
const { __, dateFormat } = useTranslate();
|
const { __, dateFormat } = useTranslate();
|
||||||
const latestAssessment = vendor.riskAssessments?.edges[0]?.node;
|
const latestAssessment = vendor.riskAssessments?.edges[0]?.node;
|
||||||
|
|
||||||
const deleteVendor = useDeleteVendor(vendor, connectionId);
|
const deleteVendor = useDeleteVendor(vendor, connectionId);
|
||||||
|
|
||||||
|
const vendorUrl = isSnapshotMode && snapshotId
|
||||||
|
? `/organizations/${organizationId}/snapshots/${snapshotId}/vendors/${vendor.id}/overview`
|
||||||
|
: `/organizations/${organizationId}/vendors/${vendor.id}/overview`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tr to={`/organizations/${organizationId}/vendors/${vendor.id}/overview`}>
|
<Tr to={vendorUrl}>
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
<Avatar name={vendor.name} src={faviconUrl(vendor.websiteUrl)} />
|
<Avatar name={vendor.name} src={faviconUrl(vendor.websiteUrl)} />
|
||||||
@@ -136,15 +149,17 @@ function VendorRow({
|
|||||||
<RiskBadge level={latestAssessment?.businessImpact ?? "NONE"} />
|
<RiskBadge level={latestAssessment?.businessImpact ?? "NONE"} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td noLink width={50} className="text-end">
|
<Td noLink width={50} className="text-end">
|
||||||
<ActionDropdown>
|
{!isSnapshotMode && (
|
||||||
<DropdownItem
|
<ActionDropdown>
|
||||||
onClick={deleteVendor}
|
<DropdownItem
|
||||||
variant="danger"
|
onClick={deleteVendor}
|
||||||
icon={IconTrashCan}
|
variant="danger"
|
||||||
>
|
icon={IconTrashCan}
|
||||||
{__("Delete")}
|
>
|
||||||
</DropdownItem>
|
{__("Delete")}
|
||||||
</ActionDropdown>
|
</DropdownItem>
|
||||||
|
</ActionDropdown>
|
||||||
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useOutletContext } from "react-router";
|
import { useOutletContext, useParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import type { VendorComplianceTabFragment$key } from "./__generated__/VendorComplianceTabFragment.graphql";
|
import type { VendorComplianceTabFragment$key } from "./__generated__/VendorComplianceTabFragment.graphql";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
@@ -98,6 +98,8 @@ export default function VendorComplianceTab() {
|
|||||||
const connectionId = data.complianceReports.__id;
|
const connectionId = data.complianceReports.__id;
|
||||||
const reports = data.complianceReports.edges.map((edge) => edge.node);
|
const reports = data.complianceReports.edges.map((edge) => edge.node);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
|
|
||||||
usePageTitle(vendor.name + " - " + __("Compliance reports"));
|
usePageTitle(vendor.name + " - " + __("Compliance reports"));
|
||||||
|
|
||||||
@@ -125,15 +127,17 @@ export default function VendorComplianceTab() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<Dropzone
|
{!isSnapshotMode && (
|
||||||
description={__("Only PDF files up to 10MB are allowed")}
|
<Dropzone
|
||||||
isUploading={isMutating}
|
description={__("Only PDF files up to 10MB are allowed")}
|
||||||
onDrop={handleDrop}
|
isUploading={isMutating}
|
||||||
accept={{
|
onDrop={handleDrop}
|
||||||
"application/pdf": [".pdf"],
|
accept={{
|
||||||
}}
|
"application/pdf": [".pdf"],
|
||||||
maxSize={10}
|
}}
|
||||||
/>
|
maxSize={10}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<SortableTable refetch={refetch}>
|
<SortableTable refetch={refetch}>
|
||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
@@ -141,7 +145,7 @@ export default function VendorComplianceTab() {
|
|||||||
<SortableTh field="REPORT_DATE">{__("Report date")}</SortableTh>
|
<SortableTh field="REPORT_DATE">{__("Report date")}</SortableTh>
|
||||||
<Th>{__("Valid until")}</Th>
|
<Th>{__("Valid until")}</Th>
|
||||||
<Th>{__("File size")}</Th>
|
<Th>{__("File size")}</Th>
|
||||||
<Th>{__("Actions")}</Th>
|
{!isSnapshotMode && <Th>{__("Actions")}</Th>}
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@@ -150,6 +154,7 @@ export default function VendorComplianceTab() {
|
|||||||
key={report.id}
|
key={report.id}
|
||||||
reportKey={report}
|
reportKey={report}
|
||||||
connectionId={connectionId}
|
connectionId={connectionId}
|
||||||
|
isSnapshotMode={isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tbody>
|
</Tbody>
|
||||||
@@ -161,6 +166,7 @@ export default function VendorComplianceTab() {
|
|||||||
type ReportRowProps = {
|
type ReportRowProps = {
|
||||||
reportKey: VendorComplianceTabFragment_report$key;
|
reportKey: VendorComplianceTabFragment_report$key;
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
|
isSnapshotMode: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ReportRow(props: ReportRowProps) {
|
function ReportRow(props: ReportRowProps) {
|
||||||
@@ -204,17 +210,19 @@ function ReportRow(props: ReportRowProps) {
|
|||||||
<Td>{dateFormat(report.reportDate)}</Td>
|
<Td>{dateFormat(report.reportDate)}</Td>
|
||||||
<Td>{dateFormat(report.validUntil)}</Td>
|
<Td>{dateFormat(report.validUntil)}</Td>
|
||||||
<Td>{fileSize(__, report.fileSize)}</Td>
|
<Td>{fileSize(__, report.fileSize)}</Td>
|
||||||
<Td width={50} className="text-end">
|
{!props.isSnapshotMode && (
|
||||||
<ActionDropdown>
|
<Td width={50} className="text-end">
|
||||||
<DropdownItem
|
<ActionDropdown>
|
||||||
icon={IconTrashCan}
|
<DropdownItem
|
||||||
onClick={handleDelete}
|
icon={IconTrashCan}
|
||||||
variant="danger"
|
onClick={handleDelete}
|
||||||
>
|
variant="danger"
|
||||||
{__("Delete")}
|
>
|
||||||
</DropdownItem>
|
{__("Delete")}
|
||||||
</ActionDropdown>
|
</DropdownItem>
|
||||||
</Td>
|
</ActionDropdown>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
</Tr>
|
</Tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useOutletContext } from "react-router";
|
import { useOutletContext, useParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import type { VendorContactsTabFragment$key } from "./__generated__/VendorContactsTabFragment.graphql";
|
import type { VendorContactsTabFragment$key } from "./__generated__/VendorContactsTabFragment.graphql";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
@@ -89,6 +89,8 @@ export default function VendorContactsTab() {
|
|||||||
const connectionId = data.contacts.__id;
|
const connectionId = data.contacts.__id;
|
||||||
const contacts = data.contacts.edges.map((edge) => edge.node);
|
const contacts = data.contacts.edges.map((edge) => edge.node);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
const [editingContact, setEditingContact] = useState<{
|
const [editingContact, setEditingContact] = useState<{
|
||||||
id: string;
|
id: string;
|
||||||
fullName?: string | null;
|
fullName?: string | null;
|
||||||
@@ -105,12 +107,14 @@ export default function VendorContactsTab() {
|
|||||||
title={__("Contacts")}
|
title={__("Contacts")}
|
||||||
description={__("Manage vendor contacts and their information.")}
|
description={__("Manage vendor contacts and their information.")}
|
||||||
>
|
>
|
||||||
<CreateContactDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<CreateContactDialog
|
||||||
connectionId={connectionId}
|
vendorId={vendor.id}
|
||||||
>
|
connectionId={connectionId}
|
||||||
<Button icon={IconPlusLarge}>{__("Add contact")}</Button>
|
>
|
||||||
</CreateContactDialog>
|
<Button icon={IconPlusLarge}>{__("Add contact")}</Button>
|
||||||
|
</CreateContactDialog>
|
||||||
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<SortableTable refetch={refetch}>
|
<SortableTable refetch={refetch}>
|
||||||
@@ -120,7 +124,7 @@ export default function VendorContactsTab() {
|
|||||||
<SortableTh field="EMAIL">{__("Email")}</SortableTh>
|
<SortableTh field="EMAIL">{__("Email")}</SortableTh>
|
||||||
<Th>{__("Phone")}</Th>
|
<Th>{__("Phone")}</Th>
|
||||||
<Th>{__("Role")}</Th>
|
<Th>{__("Role")}</Th>
|
||||||
<Th>{__("Actions")}</Th>
|
{!isSnapshotMode && <Th>{__("Actions")}</Th>}
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@@ -130,12 +134,13 @@ export default function VendorContactsTab() {
|
|||||||
contactKey={contact}
|
contactKey={contact}
|
||||||
connectionId={connectionId}
|
connectionId={connectionId}
|
||||||
onEdit={setEditingContact}
|
onEdit={setEditingContact}
|
||||||
|
isSnapshotMode={isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tbody>
|
</Tbody>
|
||||||
</SortableTable>
|
</SortableTable>
|
||||||
|
|
||||||
{editingContact && (
|
{editingContact && !isSnapshotMode && (
|
||||||
<EditContactDialog
|
<EditContactDialog
|
||||||
contactId={editingContact.id}
|
contactId={editingContact.id}
|
||||||
contact={editingContact}
|
contact={editingContact}
|
||||||
@@ -156,6 +161,7 @@ type ContactRowProps = {
|
|||||||
phone?: string | null;
|
phone?: string | null;
|
||||||
role?: string | null;
|
role?: string | null;
|
||||||
}) => void;
|
}) => void;
|
||||||
|
isSnapshotMode: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ContactRow(props: ContactRowProps) {
|
function ContactRow(props: ContactRowProps) {
|
||||||
@@ -220,29 +226,31 @@ function ContactRow(props: ContactRowProps) {
|
|||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>{contact.role || __("—")}</Td>
|
<Td>{contact.role || __("—")}</Td>
|
||||||
<Td width={50} className="text-end">
|
{!props.isSnapshotMode && (
|
||||||
<ActionDropdown>
|
<Td width={50} className="text-end">
|
||||||
<DropdownItem
|
<ActionDropdown>
|
||||||
icon={IconPencil}
|
<DropdownItem
|
||||||
onClick={() => props.onEdit({
|
icon={IconPencil}
|
||||||
id: contact.id,
|
onClick={() => props.onEdit({
|
||||||
fullName: contact.fullName,
|
id: contact.id,
|
||||||
email: contact.email,
|
fullName: contact.fullName,
|
||||||
phone: contact.phone,
|
email: contact.email,
|
||||||
role: contact.role,
|
phone: contact.phone,
|
||||||
})}
|
role: contact.role,
|
||||||
>
|
})}
|
||||||
{__("Edit")}
|
>
|
||||||
</DropdownItem>
|
{__("Edit")}
|
||||||
<DropdownItem
|
</DropdownItem>
|
||||||
icon={IconTrashCan}
|
<DropdownItem
|
||||||
onClick={handleDelete}
|
icon={IconTrashCan}
|
||||||
variant="danger"
|
onClick={handleDelete}
|
||||||
>
|
variant="danger"
|
||||||
{__("Delete")}
|
>
|
||||||
</DropdownItem>
|
{__("Delete")}
|
||||||
</ActionDropdown>
|
</DropdownItem>
|
||||||
</Td>
|
</ActionDropdown>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
</Tr>
|
</Tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { useVendorForm } from "/hooks/forms/useVendorForm";
|
import { useVendorForm } from "/hooks/forms/useVendorForm";
|
||||||
import { useOutletContext } from "react-router";
|
import { useOutletContext, useParams } from "react-router";
|
||||||
import { Button, Card, Field, Input, IconPlusLarge, IconTrashCan, IconPencil } from "@probo/ui";
|
import { Button, Card, Field, Input, IconPlusLarge, IconTrashCan, IconPencil } from "@probo/ui";
|
||||||
import { PeopleSelectField } from "/components/form/PeopleSelectField";
|
import { PeopleSelectField } from "/components/form/PeopleSelectField";
|
||||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
@@ -55,6 +55,8 @@ export default function VendorOverviewTab() {
|
|||||||
|
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const organizationId = useOrganizationId();
|
const organizationId = useOrganizationId();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@@ -98,7 +100,7 @@ export default function VendorOverviewTab() {
|
|||||||
usePageTitle(vendor.name + " - " + __("Overview"));
|
usePageTitle(vendor.name + " - " + __("Overview"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className="space-y-12">
|
<form onSubmit={isSnapshotMode ? undefined : handleSubmit} className="space-y-12">
|
||||||
{/* Vendor Details */}
|
{/* Vendor Details */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h2 className="text-base font-medium">{__("Vendor details")}</h2>
|
<h2 className="text-base font-medium">{__("Vendor details")}</h2>
|
||||||
@@ -108,30 +110,35 @@ export default function VendorOverviewTab() {
|
|||||||
label={__("Name")}
|
label={__("Name")}
|
||||||
type="text"
|
type="text"
|
||||||
error={errors.name?.message}
|
error={errors.name?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
{...register("description")}
|
{...register("description")}
|
||||||
label={__("Description")}
|
label={__("Description")}
|
||||||
type="textarea"
|
type="textarea"
|
||||||
error={errors.description?.message}
|
error={errors.description?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
{...register("legalName")}
|
{...register("legalName")}
|
||||||
label={__("Legal name")}
|
label={__("Legal name")}
|
||||||
type="text"
|
type="text"
|
||||||
error={errors.legalName?.message}
|
error={errors.legalName?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
{...register("headquarterAddress")}
|
{...register("headquarterAddress")}
|
||||||
label={__("Headquarter address")}
|
label={__("Headquarter address")}
|
||||||
type="textarea"
|
type="textarea"
|
||||||
error={errors.headquarterAddress?.message}
|
error={errors.headquarterAddress?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
{...register("websiteUrl")}
|
{...register("websiteUrl")}
|
||||||
label={__("Website URL")}
|
label={__("Website URL")}
|
||||||
type="text"
|
type="text"
|
||||||
error={errors.websiteUrl?.message}
|
error={errors.websiteUrl?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,6 +153,7 @@ export default function VendorOverviewTab() {
|
|||||||
name="businessOwnerId"
|
name="businessOwnerId"
|
||||||
label={__("Business owner")}
|
label={__("Business owner")}
|
||||||
error={errors.businessOwnerId?.message}
|
error={errors.businessOwnerId?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
<PeopleSelectField
|
<PeopleSelectField
|
||||||
organizationId={organizationId}
|
organizationId={organizationId}
|
||||||
@@ -153,6 +161,7 @@ export default function VendorOverviewTab() {
|
|||||||
name="securityOwnerId"
|
name="securityOwnerId"
|
||||||
label={__("Security owner")}
|
label={__("Security owner")}
|
||||||
error={errors.securityOwnerId?.message}
|
error={errors.securityOwnerId?.message}
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
@@ -180,6 +189,7 @@ export default function VendorOverviewTab() {
|
|||||||
type="text"
|
type="text"
|
||||||
placeholder="https://..."
|
placeholder="https://..."
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
disabled={isSubmitting || isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -220,33 +230,39 @@ export default function VendorOverviewTab() {
|
|||||||
>
|
>
|
||||||
{__("Download PDF")}
|
{__("Download PDF")}
|
||||||
</Button>
|
</Button>
|
||||||
<EditBusinessAssociateAgreementDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<>
|
||||||
agreement={{
|
<EditBusinessAssociateAgreementDialog
|
||||||
validFrom: businessAssociateAgreement.validFrom,
|
vendorId={vendor.id}
|
||||||
validUntil: businessAssociateAgreement.validUntil,
|
agreement={{
|
||||||
}}
|
validFrom: businessAssociateAgreement.validFrom,
|
||||||
onSuccess={() => window.location.reload()}
|
validUntil: businessAssociateAgreement.validUntil,
|
||||||
>
|
}}
|
||||||
<Button variant="quaternary" icon={IconPencil} />
|
onSuccess={() => window.location.reload()}
|
||||||
</EditBusinessAssociateAgreementDialog>
|
>
|
||||||
<DeleteBusinessAssociateAgreementDialog
|
<Button variant="quaternary" icon={IconPencil} />
|
||||||
vendorId={vendor.id}
|
</EditBusinessAssociateAgreementDialog>
|
||||||
fileName={businessAssociateAgreement.fileName}
|
<DeleteBusinessAssociateAgreementDialog
|
||||||
onSuccess={() => window.location.reload()}
|
vendorId={vendor.id}
|
||||||
>
|
fileName={businessAssociateAgreement.fileName}
|
||||||
<Button variant="quaternary" icon={IconTrashCan} />
|
onSuccess={() => window.location.reload()}
|
||||||
</DeleteBusinessAssociateAgreementDialog>
|
>
|
||||||
|
<Button variant="quaternary" icon={IconTrashCan} />
|
||||||
|
</DeleteBusinessAssociateAgreementDialog>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<UploadBusinessAssociateAgreementDialog
|
!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<UploadBusinessAssociateAgreementDialog
|
||||||
onSuccess={() => window.location.reload()}
|
vendorId={vendor.id}
|
||||||
>
|
onSuccess={() => window.location.reload()}
|
||||||
<Button variant="secondary" icon={IconPlusLarge}>
|
>
|
||||||
{__("Upload")}
|
<Button variant="secondary" icon={IconPlusLarge}>
|
||||||
</Button>
|
{__("Upload")}
|
||||||
</UploadBusinessAssociateAgreementDialog>
|
</Button>
|
||||||
|
</UploadBusinessAssociateAgreementDialog>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -281,26 +297,30 @@ export default function VendorOverviewTab() {
|
|||||||
>
|
>
|
||||||
{__("Download PDF")}
|
{__("Download PDF")}
|
||||||
</Button>
|
</Button>
|
||||||
<EditDataPrivacyAgreementDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<>
|
||||||
agreement={{
|
<EditDataPrivacyAgreementDialog
|
||||||
validFrom: dataPrivacyAgreement.validFrom,
|
vendorId={vendor.id}
|
||||||
validUntil: dataPrivacyAgreement.validUntil,
|
agreement={{
|
||||||
}}
|
validFrom: dataPrivacyAgreement.validFrom,
|
||||||
onSuccess={() => window.location.reload()}
|
validUntil: dataPrivacyAgreement.validUntil,
|
||||||
>
|
}}
|
||||||
<Button variant="quaternary" icon={IconPencil} />
|
onSuccess={() => window.location.reload()}
|
||||||
</EditDataPrivacyAgreementDialog>
|
>
|
||||||
<DeleteDataPrivacyAgreementDialog
|
<Button variant="quaternary" icon={IconPencil} />
|
||||||
vendorId={vendor.id}
|
</EditDataPrivacyAgreementDialog>
|
||||||
fileName={dataPrivacyAgreement.fileName}
|
<DeleteDataPrivacyAgreementDialog
|
||||||
onSuccess={() => window.location.reload()}
|
vendorId={vendor.id}
|
||||||
>
|
fileName={dataPrivacyAgreement.fileName}
|
||||||
<Button variant="quaternary" icon={IconTrashCan} />
|
onSuccess={() => window.location.reload()}
|
||||||
</DeleteDataPrivacyAgreementDialog>
|
>
|
||||||
|
<Button variant="quaternary" icon={IconTrashCan} />
|
||||||
|
</DeleteDataPrivacyAgreementDialog>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
!isSnapshotMode && (
|
||||||
<UploadDataPrivacyAgreementDialog
|
<UploadDataPrivacyAgreementDialog
|
||||||
vendorId={vendor.id}
|
vendorId={vendor.id}
|
||||||
onSuccess={() => window.location.reload()}
|
onSuccess={() => window.location.reload()}
|
||||||
@@ -309,7 +329,7 @@ export default function VendorOverviewTab() {
|
|||||||
{__("Upload")}
|
{__("Upload")}
|
||||||
</Button>
|
</Button>
|
||||||
</UploadDataPrivacyAgreementDialog>
|
</UploadDataPrivacyAgreementDialog>
|
||||||
</>
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -317,11 +337,13 @@ export default function VendorOverviewTab() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Submit */}
|
{/* Submit */}
|
||||||
<div className="flex justify-end">
|
{!isSnapshotMode && (
|
||||||
<Button type="submit" disabled={isSubmitting}>
|
<div className="flex justify-end">
|
||||||
{__("Update vendor")}
|
<Button type="submit" disabled={isSubmitting}>
|
||||||
</Button>
|
{__("Update vendor")}
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useOutletContext } from "react-router";
|
import { useOutletContext, useParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import type { VendorRiskAssessmentTabFragment$key } from "./__generated__/VendorRiskAssessmentTabFragment.graphql";
|
import type { VendorRiskAssessmentTabFragment$key } from "./__generated__/VendorRiskAssessmentTabFragment.graphql";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
@@ -82,6 +82,8 @@ export default function VendorRiskAssessmentTab() {
|
|||||||
);
|
);
|
||||||
const assessments = data.riskAssessments.edges.map((edge) => edge.node);
|
const assessments = data.riskAssessments.edges.map((edge) => edge.node);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
const [expanded, setExpanded] = useState<string | null>(null);
|
const [expanded, setExpanded] = useState<string | null>(null);
|
||||||
|
|
||||||
usePageTitle(vendor.name + " - " + __("Risk Assessments"));
|
usePageTitle(vendor.name + " - " + __("Risk Assessments"));
|
||||||
@@ -90,15 +92,17 @@ export default function VendorRiskAssessmentTab() {
|
|||||||
return (
|
return (
|
||||||
<div className="text-center text-sm py-6 text-txt-secondary flex flex-col items-center gap-2">
|
<div className="text-center text-sm py-6 text-txt-secondary flex flex-col items-center gap-2">
|
||||||
{__("No risk assessments found")}
|
{__("No risk assessments found")}
|
||||||
<CreateRiskAssessmentDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<CreateRiskAssessmentDialog
|
||||||
connection={data.riskAssessments.__id}
|
vendorId={vendor.id}
|
||||||
peopleId={peopleId}
|
connection={data.riskAssessments.__id}
|
||||||
>
|
peopleId={peopleId}
|
||||||
<Button icon={IconPlusLarge} variant="secondary">
|
>
|
||||||
{__("Add Risk Assessment")}
|
<Button icon={IconPlusLarge} variant="secondary">
|
||||||
</Button>
|
{__("Add Risk Assessment")}
|
||||||
</CreateRiskAssessmentDialog>
|
</Button>
|
||||||
|
</CreateRiskAssessmentDialog>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -117,15 +121,17 @@ export default function VendorRiskAssessmentTab() {
|
|||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
<CreateRiskAssessmentDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<CreateRiskAssessmentDialog
|
||||||
connection={data.riskAssessments.__id}
|
vendorId={vendor.id}
|
||||||
peopleId={peopleId}
|
connection={data.riskAssessments.__id}
|
||||||
>
|
peopleId={peopleId}
|
||||||
<TrButton colspan={5} onClick={() => {}}>
|
>
|
||||||
{__("Add Risk Assessment")}
|
<TrButton colspan={5} onClick={() => {}}>
|
||||||
</TrButton>
|
{__("Add Risk Assessment")}
|
||||||
</CreateRiskAssessmentDialog>
|
</TrButton>
|
||||||
|
</CreateRiskAssessmentDialog>
|
||||||
|
)}
|
||||||
{assessments.map((assessment) => (
|
{assessments.map((assessment) => (
|
||||||
<AssessmentRow
|
<AssessmentRow
|
||||||
key={assessment.id}
|
key={assessment.id}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useOutletContext } from "react-router";
|
import { useOutletContext, useParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import type { VendorServicesTabFragment$key } from "./__generated__/VendorServicesTabFragment.graphql";
|
import type { VendorServicesTabFragment$key } from "./__generated__/VendorServicesTabFragment.graphql";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
@@ -87,6 +87,8 @@ export default function VendorServicesTab() {
|
|||||||
const connectionId = data.services.__id;
|
const connectionId = data.services.__id;
|
||||||
const services = data.services.edges.map((edge) => edge.node);
|
const services = data.services.edges.map((edge) => edge.node);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
const [editingService, setEditingService] = useState<{
|
const [editingService, setEditingService] = useState<{
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -101,12 +103,14 @@ export default function VendorServicesTab() {
|
|||||||
title={__("Services")}
|
title={__("Services")}
|
||||||
description={__("Manage services provided by this vendor.")}
|
description={__("Manage services provided by this vendor.")}
|
||||||
>
|
>
|
||||||
<CreateServiceDialog
|
{!isSnapshotMode && (
|
||||||
vendorId={vendor.id}
|
<CreateServiceDialog
|
||||||
connectionId={connectionId}
|
vendorId={vendor.id}
|
||||||
>
|
connectionId={connectionId}
|
||||||
<Button icon={IconPlusLarge}>{__("Add service")}</Button>
|
>
|
||||||
</CreateServiceDialog>
|
<Button icon={IconPlusLarge}>{__("Add service")}</Button>
|
||||||
|
</CreateServiceDialog>
|
||||||
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<SortableTable refetch={refetch}>
|
<SortableTable refetch={refetch}>
|
||||||
@@ -114,7 +118,7 @@ export default function VendorServicesTab() {
|
|||||||
<Tr>
|
<Tr>
|
||||||
<SortableTh field="NAME">{__("Name")}</SortableTh>
|
<SortableTh field="NAME">{__("Name")}</SortableTh>
|
||||||
<Th>{__("Description")}</Th>
|
<Th>{__("Description")}</Th>
|
||||||
<Th>{__("Actions")}</Th>
|
{!isSnapshotMode && <Th>{__("Actions")}</Th>}
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@@ -124,12 +128,13 @@ export default function VendorServicesTab() {
|
|||||||
serviceKey={service}
|
serviceKey={service}
|
||||||
connectionId={connectionId}
|
connectionId={connectionId}
|
||||||
onEdit={setEditingService}
|
onEdit={setEditingService}
|
||||||
|
isSnapshotMode={isSnapshotMode}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tbody>
|
</Tbody>
|
||||||
</SortableTable>
|
</SortableTable>
|
||||||
|
|
||||||
{editingService && (
|
{editingService && !isSnapshotMode && (
|
||||||
<EditServiceDialog
|
<EditServiceDialog
|
||||||
serviceId={editingService.id}
|
serviceId={editingService.id}
|
||||||
service={editingService}
|
service={editingService}
|
||||||
@@ -148,6 +153,7 @@ type ServiceRowProps = {
|
|||||||
name: string;
|
name: string;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
}) => void;
|
}) => void;
|
||||||
|
isSnapshotMode: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ServiceRow(props: ServiceRowProps) {
|
function ServiceRow(props: ServiceRowProps) {
|
||||||
@@ -188,27 +194,29 @@ function ServiceRow(props: ServiceRowProps) {
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td>{service.name}</Td>
|
<Td>{service.name}</Td>
|
||||||
<Td>{service.description || __("—")}</Td>
|
<Td>{service.description || __("—")}</Td>
|
||||||
<Td width={50} className="text-end">
|
{!props.isSnapshotMode && (
|
||||||
<ActionDropdown>
|
<Td width={50} className="text-end">
|
||||||
<DropdownItem
|
<ActionDropdown>
|
||||||
icon={IconPencil}
|
<DropdownItem
|
||||||
onClick={() => props.onEdit({
|
icon={IconPencil}
|
||||||
id: service.id,
|
onClick={() => props.onEdit({
|
||||||
name: service.name,
|
id: service.id,
|
||||||
description: service.description,
|
name: service.name,
|
||||||
})}
|
description: service.description,
|
||||||
>
|
})}
|
||||||
{__("Edit")}
|
>
|
||||||
</DropdownItem>
|
{__("Edit")}
|
||||||
<DropdownItem
|
</DropdownItem>
|
||||||
icon={IconTrashCan}
|
<DropdownItem
|
||||||
onClick={handleDelete}
|
icon={IconTrashCan}
|
||||||
variant="danger"
|
onClick={handleDelete}
|
||||||
>
|
variant="danger"
|
||||||
{__("Delete")}
|
>
|
||||||
</DropdownItem>
|
{__("Delete")}
|
||||||
</ActionDropdown>
|
</DropdownItem>
|
||||||
</Td>
|
</ActionDropdown>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
</Tr>
|
</Tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,20 @@ export const vendorRoutes = [
|
|||||||
path: "vendors",
|
path: "vendors",
|
||||||
fallback: PageSkeleton,
|
fallback: PageSkeleton,
|
||||||
queryLoader: ({ organizationId }) =>
|
queryLoader: ({ organizationId }) =>
|
||||||
loadQuery(relayEnvironment, vendorsQuery, { organizationId }),
|
loadQuery(relayEnvironment, vendorsQuery, {
|
||||||
|
organizationId,
|
||||||
|
snapshotId: null
|
||||||
|
}),
|
||||||
|
Component: lazy(() => import("/pages/organizations/vendors/VendorsPage")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "snapshots/:snapshotId/vendors",
|
||||||
|
fallback: PageSkeleton,
|
||||||
|
queryLoader: ({ organizationId, snapshotId }) =>
|
||||||
|
loadQuery(relayEnvironment, vendorsQuery, {
|
||||||
|
organizationId,
|
||||||
|
snapshotId
|
||||||
|
}),
|
||||||
Component: lazy(() => import("/pages/organizations/vendors/VendorsPage")),
|
Component: lazy(() => import("/pages/organizations/vendors/VendorsPage")),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -79,4 +92,69 @@ export const vendorRoutes = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "snapshots/:snapshotId/vendors/:vendorId",
|
||||||
|
fallback: PageSkeleton,
|
||||||
|
queryLoader: ({ vendorId, organizationId }) =>
|
||||||
|
loadQuery(relayEnvironment, vendorNodeQuery, {
|
||||||
|
vendorId,
|
||||||
|
organizationId,
|
||||||
|
}),
|
||||||
|
Component: lazy(
|
||||||
|
() => import("../pages/organizations/vendors/VendorDetailPage")
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "overview",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() => import("../pages/organizations/vendors/tabs/VendorOverviewTab")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "certifications",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() =>
|
||||||
|
import(
|
||||||
|
"../pages/organizations/vendors/tabs/VendorCertificationsTab"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "compliance",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() =>
|
||||||
|
import("../pages/organizations/vendors/tabs/VendorComplianceTab")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "risks",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() =>
|
||||||
|
import(
|
||||||
|
"../pages/organizations/vendors/tabs/VendorRiskAssessmentTab"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "contacts",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() =>
|
||||||
|
import("../pages/organizations/vendors/tabs/VendorContactsTab")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "services",
|
||||||
|
fallback: LinkCardSkeleton,
|
||||||
|
Component: lazy(
|
||||||
|
() =>
|
||||||
|
import("../pages/organizations/vendors/tabs/VendorServicesTab")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
] satisfies AppRoute[];
|
] satisfies AppRoute[];
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
type Translator = (s: string) => string;
|
type Translator = (s: string) => string;
|
||||||
|
|
||||||
export const snapshotTypes = [
|
export const snapshotTypes = [
|
||||||
|
"VENDORS",
|
||||||
"ASSETS",
|
"ASSETS",
|
||||||
"DATA",
|
"DATA",
|
||||||
"NONCONFORMITY_REGISTRIES",
|
"NONCONFORMITY_REGISTRIES",
|
||||||
@@ -38,6 +39,8 @@ export function getSnapshotTypeLabel(__: Translator, type: string | null | undef
|
|||||||
|
|
||||||
export function getSnapshotTypeUrlPath(type?: string): string {
|
export function getSnapshotTypeUrlPath(type?: string): string {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "VENDORS":
|
||||||
|
return "/vendors";
|
||||||
case "ASSETS":
|
case "ASSETS":
|
||||||
return "/assets";
|
return "/assets";
|
||||||
case "DATA":
|
case "DATA":
|
||||||
|
|||||||
@@ -135,42 +135,3 @@ VALUES (
|
|||||||
_, err := conn.Exec(ctx, q, args)
|
_, err := conn.Exec(ctx, q, args)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f File) Delete(
|
|
||||||
ctx context.Context,
|
|
||||||
conn pg.Conn,
|
|
||||||
scope Scoper,
|
|
||||||
) error {
|
|
||||||
q := `
|
|
||||||
DELETE FROM files WHERE %s AND id = @file_id
|
|
||||||
`
|
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
|
||||||
|
|
||||||
args := pgx.StrictNamedArgs{"file_id": f.ID}
|
|
||||||
maps.Copy(args, scope.SQLArguments())
|
|
||||||
|
|
||||||
_, err := conn.Exec(ctx, q, args)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f File) SoftDelete(
|
|
||||||
ctx context.Context,
|
|
||||||
conn pg.Conn,
|
|
||||||
scope Scoper,
|
|
||||||
) error {
|
|
||||||
q := `
|
|
||||||
UPDATE files SET deleted_at = @deleted_at, updated_at = @updated_at WHERE %s AND id = @file_id
|
|
||||||
`
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
|
||||||
|
|
||||||
args := pgx.StrictNamedArgs{
|
|
||||||
"file_id": f.ID,
|
|
||||||
"updated_at": time.Now(),
|
|
||||||
"deleted_at": time.Now(),
|
|
||||||
}
|
|
||||||
maps.Copy(args, scope.SQLArguments())
|
|
||||||
|
|
||||||
_, err := conn.Exec(ctx, q, args)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|||||||
84
pkg/coredata/migrations/20250829T165122Z.sql
Normal file
84
pkg/coredata/migrations/20250829T165122Z.sql
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
ALTER TABLE vendor_business_associate_agreements ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_business_associate_agreements ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_business_associate_agreements DROP CONSTRAINT vendor_business_associate_agreements_file_id_unique;
|
||||||
|
ALTER TABLE vendor_business_associate_agreements DROP CONSTRAINT vendor_business_associate_agreements_file_id_fkey;
|
||||||
|
ALTER TABLE vendor_business_associate_agreements ADD CONSTRAINT vendor_business_associate_agreements_file_id_fkey
|
||||||
|
FOREIGN KEY (file_id)
|
||||||
|
REFERENCES files(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE RESTRICT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_business_associate_agreements ADD CONSTRAINT vendor_business_associate_agreements_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_business_associate_agreements ADD CONSTRAINT vendor_business_associate_agreements_source_id_snapshot_id_key
|
||||||
|
UNIQUE (source_id, snapshot_id);
|
||||||
|
|
||||||
|
ALTER TABLE vendor_contacts ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_contacts ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_contacts ADD CONSTRAINT vendor_contacts_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_contacts ADD CONSTRAINT vendor_contacts_source_id_snapshot_id_key
|
||||||
|
UNIQUE (source_id, snapshot_id);
|
||||||
|
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements DROP CONSTRAINT vendor_data_privacy_agreements_file_id_unique;
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements DROP CONSTRAINT vendor_data_privacy_agreements_file_id_fkey;
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements ADD CONSTRAINT vendor_data_privacy_agreements_file_id_fkey
|
||||||
|
FOREIGN KEY (file_id)
|
||||||
|
REFERENCES files(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE RESTRICT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements ADD CONSTRAINT vendor_data_privacy_agreements_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_data_privacy_agreements ADD CONSTRAINT vendor_data_privacy_agreements_source_id_snapshot_id_key
|
||||||
|
UNIQUE (source_id, snapshot_id);
|
||||||
|
|
||||||
|
ALTER TABLE vendor_risk_assessments ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_risk_assessments ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_risk_assessments ADD CONSTRAINT vendor_risk_assessments_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_risk_assessments ADD CONSTRAINT vendor_risk_assessments_source_id_snapshot_id_key
|
||||||
|
UNIQUE (source_id, snapshot_id);
|
||||||
|
|
||||||
|
ALTER TABLE vendor_services ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_services ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_services ADD CONSTRAINT vendor_services_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_services ADD CONSTRAINT vendor_services_source_id_snapshot_id_key
|
||||||
|
UNIQUE (source_id, snapshot_id);
|
||||||
|
|
||||||
|
ALTER TABLE vendor_compliance_reports ADD COLUMN snapshot_id TEXT;
|
||||||
|
ALTER TABLE vendor_compliance_reports ADD COLUMN source_id TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE vendor_compliance_reports ADD CONSTRAINT vendor_compliance_reports_snapshot_id_fkey
|
||||||
|
FOREIGN KEY (snapshot_id)
|
||||||
|
REFERENCES snapshots(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE;
|
||||||
@@ -40,6 +40,8 @@ func GetSnapshottable(snapshotType SnapshotsType) (Snapshottable, error) {
|
|||||||
return ContinualImprovementRegistries{}, nil
|
return ContinualImprovementRegistries{}, nil
|
||||||
case SnapshotsTypeProcessingActivityRegistries:
|
case SnapshotsTypeProcessingActivityRegistries:
|
||||||
return ProcessingActivityRegistries{}, nil
|
return ProcessingActivityRegistries{}, nil
|
||||||
|
case SnapshotsTypeVendors:
|
||||||
|
return Vendors{}, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported snapshot type: %s", snapshotType)
|
return nil, fmt.Errorf("unsupported snapshot type: %s", snapshotType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vendors []*Vendor
|
Vendors []*Vendor
|
||||||
|
|
||||||
|
VendorSnapshotter interface {
|
||||||
|
InsertVendorSnapshots(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v Vendor) CursorKey(orderBy VendorOrderField) page.CursorKey {
|
func (v Vendor) CursorKey(orderBy VendorOrderField) page.CursorKey {
|
||||||
@@ -914,3 +918,106 @@ FROM source_vendors v
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Vendors) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||||
|
for _, snapshotter := range []VendorSnapshotter{
|
||||||
|
Vendors{},
|
||||||
|
VendorServices{},
|
||||||
|
VendorContacts{},
|
||||||
|
VendorRiskAssessments{},
|
||||||
|
VendorComplianceReports{},
|
||||||
|
VendorBusinessAssociateAgreements{},
|
||||||
|
VendorDataPrivacyAgreements{},
|
||||||
|
} {
|
||||||
|
if err := snapshotter.InsertVendorSnapshots(ctx, conn, scope, organizationID, snapshotID); err != nil {
|
||||||
|
return fmt.Errorf("cannot create vendor snapshots: (%T) %w", snapshotter, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vendors) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
INSERT INTO vendors (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
organization_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
category,
|
||||||
|
headquarter_address,
|
||||||
|
legal_name,
|
||||||
|
website_url,
|
||||||
|
privacy_policy_url,
|
||||||
|
service_level_agreement_url,
|
||||||
|
data_processing_agreement_url,
|
||||||
|
business_associate_agreement_url,
|
||||||
|
subprocessors_list_url,
|
||||||
|
certifications,
|
||||||
|
business_owner_id,
|
||||||
|
security_owner_id,
|
||||||
|
status_page_url,
|
||||||
|
terms_of_service_url,
|
||||||
|
security_page_url,
|
||||||
|
trust_page_url,
|
||||||
|
show_on_trust_center,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
v.id,
|
||||||
|
v.organization_id,
|
||||||
|
v.name,
|
||||||
|
v.description,
|
||||||
|
v.category,
|
||||||
|
v.headquarter_address,
|
||||||
|
v.legal_name,
|
||||||
|
v.website_url,
|
||||||
|
v.privacy_policy_url,
|
||||||
|
v.service_level_agreement_url,
|
||||||
|
v.data_processing_agreement_url,
|
||||||
|
v.business_associate_agreement_url,
|
||||||
|
v.subprocessors_list_url,
|
||||||
|
v.certifications,
|
||||||
|
v.business_owner_id,
|
||||||
|
v.security_owner_id,
|
||||||
|
v.status_page_url,
|
||||||
|
v.terms_of_service_url,
|
||||||
|
v.security_page_url,
|
||||||
|
v.trust_page_url,
|
||||||
|
v.show_on_trust_center,
|
||||||
|
v.created_at,
|
||||||
|
v.updated_at
|
||||||
|
FROM vendors v
|
||||||
|
WHERE %s AND organization_id = @organization_id AND snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_entity_type": VendorEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ type (
|
|||||||
ValidFrom *time.Time `db:"valid_from"`
|
ValidFrom *time.Time `db:"valid_from"`
|
||||||
ValidUntil *time.Time `db:"valid_until"`
|
ValidUntil *time.Time `db:"valid_until"`
|
||||||
FileID gid.GID `db:"file_id"`
|
FileID gid.GID `db:"file_id"`
|
||||||
|
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||||
|
SourceID *gid.GID `db:"source_id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
}
|
}
|
||||||
@@ -66,6 +68,8 @@ SELECT
|
|||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -110,6 +114,8 @@ SELECT
|
|||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -156,6 +162,7 @@ SET
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @id
|
AND id = @id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -192,6 +199,8 @@ INSERT INTO
|
|||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
)
|
)
|
||||||
@@ -203,6 +212,8 @@ VALUES (
|
|||||||
@valid_from,
|
@valid_from,
|
||||||
@valid_until,
|
@valid_until,
|
||||||
@file_id,
|
@file_id,
|
||||||
|
@snapshot_id,
|
||||||
|
@source_id,
|
||||||
@created_at,
|
@created_at,
|
||||||
@updated_at
|
@updated_at
|
||||||
)
|
)
|
||||||
@@ -211,6 +222,8 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
|||||||
valid_from = EXCLUDED.valid_from,
|
valid_from = EXCLUDED.valid_from,
|
||||||
valid_until = EXCLUDED.valid_until,
|
valid_until = EXCLUDED.valid_until,
|
||||||
file_id = EXCLUDED.file_id,
|
file_id = EXCLUDED.file_id,
|
||||||
|
snapshot_id = EXCLUDED.snapshot_id,
|
||||||
|
source_id = EXCLUDED.source_id,
|
||||||
updated_at = EXCLUDED.updated_at
|
updated_at = EXCLUDED.updated_at
|
||||||
`
|
`
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
@@ -221,6 +234,8 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
|||||||
"valid_from": vbaa.ValidFrom,
|
"valid_from": vbaa.ValidFrom,
|
||||||
"valid_until": vbaa.ValidUntil,
|
"valid_until": vbaa.ValidUntil,
|
||||||
"file_id": vbaa.FileID,
|
"file_id": vbaa.FileID,
|
||||||
|
"snapshot_id": vbaa.SnapshotID,
|
||||||
|
"source_id": vbaa.SourceID,
|
||||||
"created_at": vbaa.CreatedAt,
|
"created_at": vbaa.CreatedAt,
|
||||||
"updated_at": vbaa.UpdatedAt,
|
"updated_at": vbaa.UpdatedAt,
|
||||||
}
|
}
|
||||||
@@ -241,6 +256,7 @@ FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @id
|
AND id = @id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -265,6 +281,7 @@ FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND vendor_id = @vendor_id
|
AND vendor_id = @vendor_id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -275,3 +292,65 @@ WHERE
|
|||||||
_, err := conn.Exec(ctx, q, args)
|
_, err := conn.Exec(ctx, q, args)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v VendorBusinessAssociateAgreements) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_business_associate_agreements (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
organization_id,
|
||||||
|
vendor_id,
|
||||||
|
valid_from,
|
||||||
|
valid_until,
|
||||||
|
file_id,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_business_associate_agreement_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vbaa.id,
|
||||||
|
vbaa.organization_id,
|
||||||
|
sv.id,
|
||||||
|
vbaa.valid_from,
|
||||||
|
vbaa.valid_until,
|
||||||
|
vbaa.file_id,
|
||||||
|
vbaa.created_at,
|
||||||
|
vbaa.updated_at
|
||||||
|
FROM vendor_business_associate_agreements vbaa
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vbaa.vendor_id
|
||||||
|
WHERE %s AND vbaa.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_business_associate_agreement_entity_type": VendorBusinessAssociateAgreementEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor business associate agreement snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ type (
|
|||||||
ReportName string
|
ReportName string
|
||||||
FileKey string
|
FileKey string
|
||||||
FileSize int
|
FileSize int
|
||||||
|
SnapshotID *gid.GID
|
||||||
|
SourceID *gid.GID
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
@@ -69,6 +71,8 @@ SELECT
|
|||||||
report_name,
|
report_name,
|
||||||
file_key,
|
file_key,
|
||||||
file_size,
|
file_size,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -115,6 +119,8 @@ SELECT
|
|||||||
report_name,
|
report_name,
|
||||||
file_key,
|
file_key,
|
||||||
file_size,
|
file_size,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -206,6 +212,7 @@ FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @id
|
AND id = @id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -216,3 +223,67 @@ WHERE
|
|||||||
_, err := conn.Exec(ctx, q, args)
|
_, err := conn.Exec(ctx, q, args)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vcrs VendorComplianceReports) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_compliance_reports (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
vendor_id,
|
||||||
|
report_date,
|
||||||
|
valid_until,
|
||||||
|
report_name,
|
||||||
|
file_key,
|
||||||
|
file_size,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_compliance_report_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vcr.id,
|
||||||
|
sv.id,
|
||||||
|
vcr.report_date,
|
||||||
|
vcr.valid_until,
|
||||||
|
vcr.report_name,
|
||||||
|
vcr.file_key,
|
||||||
|
vcr.file_size,
|
||||||
|
vcr.created_at,
|
||||||
|
vcr.updated_at
|
||||||
|
FROM vendor_compliance_reports vcr
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vcr.vendor_id
|
||||||
|
WHERE %s AND vcr.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_compliance_report_entity_type": VendorComplianceReportEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor compliance report snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,14 +29,16 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
VendorContact struct {
|
VendorContact struct {
|
||||||
ID gid.GID `db:"id"`
|
ID gid.GID `db:"id"`
|
||||||
VendorID gid.GID `db:"vendor_id"`
|
VendorID gid.GID `db:"vendor_id"`
|
||||||
FullName *string `db:"full_name"`
|
FullName *string `db:"full_name"`
|
||||||
Email *string `db:"email"`
|
Email *string `db:"email"`
|
||||||
Phone *string `db:"phone"`
|
Phone *string `db:"phone"`
|
||||||
Role *string `db:"role"`
|
Role *string `db:"role"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
SourceID *gid.GID `db:"source_id"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
VendorContacts []*VendorContact
|
VendorContacts []*VendorContact
|
||||||
@@ -77,6 +79,8 @@ SELECT
|
|||||||
email,
|
email,
|
||||||
phone,
|
phone,
|
||||||
role,
|
role,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -127,6 +131,8 @@ SELECT
|
|||||||
email,
|
email,
|
||||||
phone,
|
phone,
|
||||||
role,
|
role,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -228,6 +234,7 @@ SET
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @vendor_contact_id
|
AND id = @vendor_contact_id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -261,6 +268,7 @@ DELETE FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @vendor_contact_id
|
AND id = @vendor_contact_id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -275,3 +283,65 @@ WHERE
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vc VendorContacts) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_contacts (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
vendor_id,
|
||||||
|
full_name,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
role,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_contact_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vc.id,
|
||||||
|
sv.id,
|
||||||
|
vc.full_name,
|
||||||
|
vc.email,
|
||||||
|
vc.phone,
|
||||||
|
vc.role,
|
||||||
|
vc.created_at,
|
||||||
|
vc.updated_at
|
||||||
|
FROM vendor_contacts vc
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vc.vendor_id
|
||||||
|
WHERE %s AND vc.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_contact_entity_type": VendorContactEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor contact snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,15 +28,16 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
VendorDataPrivacyAgreement struct {
|
VendorDataPrivacyAgreement struct {
|
||||||
ID gid.GID `db:"id"`
|
ID gid.GID `db:"id"`
|
||||||
TenantID gid.TenantID `db:"tenant_id"`
|
OrganizationID gid.GID `db:"organization_id"`
|
||||||
OrganizationID gid.GID `db:"organization_id"`
|
VendorID gid.GID `db:"vendor_id"`
|
||||||
VendorID gid.GID `db:"vendor_id"`
|
ValidFrom *time.Time `db:"valid_from"`
|
||||||
ValidFrom *time.Time `db:"valid_from"`
|
ValidUntil *time.Time `db:"valid_until"`
|
||||||
ValidUntil *time.Time `db:"valid_until"`
|
FileID gid.GID `db:"file_id"`
|
||||||
FileID gid.GID `db:"file_id"`
|
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
SourceID *gid.GID `db:"source_id"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
VendorDataPrivacyAgreements []*VendorDataPrivacyAgreement
|
VendorDataPrivacyAgreements []*VendorDataPrivacyAgreement
|
||||||
@@ -62,12 +63,13 @@ func (vdpa *VendorDataPrivacyAgreement) LoadByVendorID(
|
|||||||
q := `
|
q := `
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
tenant_id,
|
|
||||||
organization_id,
|
organization_id,
|
||||||
vendor_id,
|
vendor_id,
|
||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -107,12 +109,13 @@ func (vdpa *VendorDataPrivacyAgreement) LoadByID(
|
|||||||
q := `
|
q := `
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
tenant_id,
|
|
||||||
organization_id,
|
organization_id,
|
||||||
vendor_id,
|
vendor_id,
|
||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -159,6 +162,7 @@ SET
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @id
|
AND id = @id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -195,6 +199,8 @@ INSERT INTO
|
|||||||
valid_from,
|
valid_from,
|
||||||
valid_until,
|
valid_until,
|
||||||
file_id,
|
file_id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
)
|
)
|
||||||
@@ -206,6 +212,8 @@ VALUES (
|
|||||||
@valid_from,
|
@valid_from,
|
||||||
@valid_until,
|
@valid_until,
|
||||||
@file_id,
|
@file_id,
|
||||||
|
@snapshot_id,
|
||||||
|
@source_id,
|
||||||
@created_at,
|
@created_at,
|
||||||
@updated_at
|
@updated_at
|
||||||
)
|
)
|
||||||
@@ -214,6 +222,8 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
|||||||
valid_from = EXCLUDED.valid_from,
|
valid_from = EXCLUDED.valid_from,
|
||||||
valid_until = EXCLUDED.valid_until,
|
valid_until = EXCLUDED.valid_until,
|
||||||
file_id = EXCLUDED.file_id,
|
file_id = EXCLUDED.file_id,
|
||||||
|
snapshot_id = EXCLUDED.snapshot_id,
|
||||||
|
source_id = EXCLUDED.source_id,
|
||||||
updated_at = EXCLUDED.updated_at
|
updated_at = EXCLUDED.updated_at
|
||||||
`
|
`
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
@@ -224,6 +234,8 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
|||||||
"valid_from": vdpa.ValidFrom,
|
"valid_from": vdpa.ValidFrom,
|
||||||
"valid_until": vdpa.ValidUntil,
|
"valid_until": vdpa.ValidUntil,
|
||||||
"file_id": vdpa.FileID,
|
"file_id": vdpa.FileID,
|
||||||
|
"snapshot_id": vdpa.SnapshotID,
|
||||||
|
"source_id": vdpa.SourceID,
|
||||||
"created_at": vdpa.CreatedAt,
|
"created_at": vdpa.CreatedAt,
|
||||||
"updated_at": vdpa.UpdatedAt,
|
"updated_at": vdpa.UpdatedAt,
|
||||||
}
|
}
|
||||||
@@ -244,6 +256,7 @@ FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @id
|
AND id = @id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -278,3 +291,65 @@ WHERE
|
|||||||
_, err := conn.Exec(ctx, q, args)
|
_, err := conn.Exec(ctx, q, args)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vdpa VendorDataPrivacyAgreements) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_data_privacy_agreements (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
organization_id,
|
||||||
|
vendor_id,
|
||||||
|
valid_from,
|
||||||
|
valid_until,
|
||||||
|
file_id,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_data_privacy_agreement_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vdpa.id,
|
||||||
|
vdpa.organization_id,
|
||||||
|
sv.id,
|
||||||
|
vdpa.valid_from,
|
||||||
|
vdpa.valid_until,
|
||||||
|
vdpa.file_id,
|
||||||
|
vdpa.created_at,
|
||||||
|
vdpa.updated_at
|
||||||
|
FROM vendor_data_privacy_agreements vdpa
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vdpa.vendor_id
|
||||||
|
WHERE %s AND vdpa.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_data_privacy_agreement_entity_type": VendorDataPrivacyAgreementEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor data privacy agreement snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ type (
|
|||||||
DataSensitivity DataSensitivity `db:"data_sensitivity"`
|
DataSensitivity DataSensitivity `db:"data_sensitivity"`
|
||||||
BusinessImpact BusinessImpact `db:"business_impact"`
|
BusinessImpact BusinessImpact `db:"business_impact"`
|
||||||
Notes *string `db:"notes"`
|
Notes *string `db:"notes"`
|
||||||
|
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||||
|
SourceID *gid.GID `db:"source_id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
}
|
}
|
||||||
@@ -137,6 +139,8 @@ SELECT
|
|||||||
data_sensitivity,
|
data_sensitivity,
|
||||||
business_impact,
|
business_impact,
|
||||||
notes,
|
notes,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -187,6 +191,8 @@ SELECT
|
|||||||
data_sensitivity,
|
data_sensitivity,
|
||||||
business_impact,
|
business_impact,
|
||||||
notes,
|
notes,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -240,6 +246,8 @@ SELECT
|
|||||||
data_sensitivity,
|
data_sensitivity,
|
||||||
business_impact,
|
business_impact,
|
||||||
notes,
|
notes,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -270,3 +278,73 @@ WHERE
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v VendorRiskAssessments) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_risk_assessments (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
vendor_id,
|
||||||
|
assessed_at,
|
||||||
|
assessed_by,
|
||||||
|
approved_by,
|
||||||
|
approved_at,
|
||||||
|
expires_at,
|
||||||
|
data_sensitivity,
|
||||||
|
business_impact,
|
||||||
|
notes,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_risk_assessment_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vra.id,
|
||||||
|
sv.id,
|
||||||
|
vra.assessed_at,
|
||||||
|
vra.assessed_by,
|
||||||
|
vra.approved_by,
|
||||||
|
vra.approved_at,
|
||||||
|
vra.expires_at,
|
||||||
|
vra.data_sensitivity,
|
||||||
|
vra.business_impact,
|
||||||
|
vra.notes,
|
||||||
|
vra.created_at,
|
||||||
|
vra.updated_at
|
||||||
|
FROM vendor_risk_assessments vra
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vra.vendor_id
|
||||||
|
WHERE %s AND vra.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_risk_assessment_entity_type": VendorRiskAssessmentEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor risk assessment snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type (
|
|||||||
VendorID gid.GID `db:"vendor_id"`
|
VendorID gid.GID `db:"vendor_id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Description *string `db:"description"`
|
Description *string `db:"description"`
|
||||||
|
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||||
|
SourceID *gid.GID `db:"source_id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
}
|
}
|
||||||
@@ -71,6 +73,8 @@ SELECT
|
|||||||
vendor_id,
|
vendor_id,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -119,6 +123,8 @@ SELECT
|
|||||||
vendor_id,
|
vendor_id,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -212,6 +218,7 @@ SET
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @vendor_service_id
|
AND id = @vendor_service_id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -243,6 +250,7 @@ DELETE FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND id = @vendor_service_id
|
AND id = @vendor_service_id
|
||||||
|
AND snapshot_id IS NULL
|
||||||
`
|
`
|
||||||
|
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
@@ -257,3 +265,61 @@ WHERE
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vs VendorServices) InsertVendorSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
snapshotID gid.GID,
|
||||||
|
) error {
|
||||||
|
query := `
|
||||||
|
WITH
|
||||||
|
snapshot_vendors AS (
|
||||||
|
SELECT id, source_id
|
||||||
|
FROM vendors
|
||||||
|
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||||
|
)
|
||||||
|
INSERT INTO vendor_services (
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
snapshot_id,
|
||||||
|
source_id,
|
||||||
|
vendor_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@tenant_id,
|
||||||
|
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_service_entity_type),
|
||||||
|
@snapshot_id,
|
||||||
|
vs.id,
|
||||||
|
sv.id,
|
||||||
|
vs.name,
|
||||||
|
vs.description,
|
||||||
|
vs.created_at,
|
||||||
|
vs.updated_at
|
||||||
|
FROM vendor_services vs
|
||||||
|
INNER JOIN snapshot_vendors sv ON sv.source_id = vs.vendor_id
|
||||||
|
WHERE %s AND vs.snapshot_id IS NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"snapshot_id": snapshotID,
|
||||||
|
"organization_id": organizationID,
|
||||||
|
"vendor_service_entity_type": VendorServiceEntityType,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert vendor service snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -302,16 +302,10 @@ func (s VendorBusinessAssociateAgreementService) Delete(
|
|||||||
return fmt.Errorf("cannot load vendor business associate agreement: %w", err)
|
return fmt.Errorf("cannot load vendor business associate agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &coredata.File{ID: vendorBusinessAssociateAgreement.FileID}
|
|
||||||
|
|
||||||
if err := vendorBusinessAssociateAgreement.Delete(ctx, conn, s.svc.scope); err != nil {
|
if err := vendorBusinessAssociateAgreement.Delete(ctx, conn, s.svc.scope); err != nil {
|
||||||
return fmt.Errorf("cannot delete vendor business associate agreement: %w", err)
|
return fmt.Errorf("cannot delete vendor business associate agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := file.SoftDelete(ctx, conn, s.svc.scope); err != nil {
|
|
||||||
return fmt.Errorf("cannot soft delete file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -329,16 +323,10 @@ func (s VendorBusinessAssociateAgreementService) DeleteByVendorID(
|
|||||||
return fmt.Errorf("cannot load vendor business associate agreement: %w", err)
|
return fmt.Errorf("cannot load vendor business associate agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &coredata.File{ID: vendorBusinessAssociateAgreement.FileID}
|
|
||||||
|
|
||||||
if err := vendorBusinessAssociateAgreement.DeleteByVendorID(ctx, conn, s.svc.scope, vendorID); err != nil {
|
if err := vendorBusinessAssociateAgreement.DeleteByVendorID(ctx, conn, s.svc.scope, vendorID); err != nil {
|
||||||
return fmt.Errorf("cannot delete vendor business associate agreement: %w", err)
|
return fmt.Errorf("cannot delete vendor business associate agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := file.SoftDelete(ctx, conn, s.svc.scope); err != nil {
|
|
||||||
return fmt.Errorf("cannot soft delete file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ func (s VendorDataPrivacyAgreementService) Upload(
|
|||||||
|
|
||||||
vendorDataPrivacyAgreement = &coredata.VendorDataPrivacyAgreement{
|
vendorDataPrivacyAgreement = &coredata.VendorDataPrivacyAgreement{
|
||||||
ID: vendorDataPrivacyAgreementID,
|
ID: vendorDataPrivacyAgreementID,
|
||||||
TenantID: s.svc.scope.GetTenantID(),
|
|
||||||
OrganizationID: vendor.OrganizationID,
|
OrganizationID: vendor.OrganizationID,
|
||||||
VendorID: vendorID,
|
VendorID: vendorID,
|
||||||
ValidFrom: req.ValidFrom,
|
ValidFrom: req.ValidFrom,
|
||||||
@@ -303,16 +302,10 @@ func (s VendorDataPrivacyAgreementService) Delete(
|
|||||||
return fmt.Errorf("cannot load vendor data privacy agreement: %w", err)
|
return fmt.Errorf("cannot load vendor data privacy agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &coredata.File{ID: vendorDataPrivacyAgreement.FileID}
|
|
||||||
|
|
||||||
if err := vendorDataPrivacyAgreement.Delete(ctx, conn, s.svc.scope); err != nil {
|
if err := vendorDataPrivacyAgreement.Delete(ctx, conn, s.svc.scope); err != nil {
|
||||||
return fmt.Errorf("cannot delete vendor data privacy agreement: %w", err)
|
return fmt.Errorf("cannot delete vendor data privacy agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := file.SoftDelete(ctx, conn, s.svc.scope); err != nil {
|
|
||||||
return fmt.Errorf("cannot soft delete file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -330,16 +323,10 @@ func (s VendorDataPrivacyAgreementService) DeleteByVendorID(
|
|||||||
return fmt.Errorf("cannot load vendor data privacy agreement: %w", err)
|
return fmt.Errorf("cannot load vendor data privacy agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &coredata.File{ID: vendorDataPrivacyAgreement.FileID}
|
|
||||||
|
|
||||||
if err := vendorDataPrivacyAgreement.DeleteByVendorID(ctx, conn, s.svc.scope, vendorID); err != nil {
|
if err := vendorDataPrivacyAgreement.DeleteByVendorID(ctx, conn, s.svc.scope, vendorID); err != nil {
|
||||||
return fmt.Errorf("cannot delete vendor data privacy agreement: %w", err)
|
return fmt.Errorf("cannot delete vendor data privacy agreement: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := file.SoftDelete(ctx, conn, s.svc.scope); err != nil {
|
|
||||||
return fmt.Errorf("cannot soft delete file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1134,6 +1134,10 @@ input AssetFilter {
|
|||||||
snapshotId: ID
|
snapshotId: ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input VendorFilter {
|
||||||
|
snapshotId: ID
|
||||||
|
}
|
||||||
|
|
||||||
# Core Types
|
# Core Types
|
||||||
type TrustCenter implements Node {
|
type TrustCenter implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
@@ -1196,6 +1200,7 @@ type Organization implements Node {
|
|||||||
last: Int
|
last: Int
|
||||||
before: CursorKey
|
before: CursorKey
|
||||||
orderBy: VendorOrder
|
orderBy: VendorOrder
|
||||||
|
filter: VendorFilter = { snapshotId: null }
|
||||||
): VendorConnection! @goField(forceResolver: true)
|
): VendorConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
peoples(
|
peoples(
|
||||||
@@ -1351,6 +1356,7 @@ type People implements Node {
|
|||||||
|
|
||||||
type Vendor implements Node {
|
type Vendor implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
snapshotId: ID
|
||||||
name: String!
|
name: String!
|
||||||
category: VendorCategory!
|
category: VendorCategory!
|
||||||
description: String
|
description: String
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ type ComplexityRoot struct {
|
|||||||
TrustCenter func(childComplexity int) int
|
TrustCenter func(childComplexity int) int
|
||||||
UpdatedAt func(childComplexity int) int
|
UpdatedAt func(childComplexity int) int
|
||||||
Users func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.UserOrderBy) int
|
Users func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.UserOrderBy) int
|
||||||
Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) int
|
Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy, filter *types.VendorFilter) int
|
||||||
}
|
}
|
||||||
|
|
||||||
OrganizationConnection struct {
|
OrganizationConnection struct {
|
||||||
@@ -1300,6 +1300,7 @@ type ComplexityRoot struct {
|
|||||||
ServiceLevelAgreementURL func(childComplexity int) int
|
ServiceLevelAgreementURL func(childComplexity int) int
|
||||||
Services func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorServiceOrderBy) int
|
Services func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorServiceOrderBy) int
|
||||||
ShowOnTrustCenter func(childComplexity int) int
|
ShowOnTrustCenter func(childComplexity int) int
|
||||||
|
SnapshotID func(childComplexity int) int
|
||||||
StatusPageURL func(childComplexity int) int
|
StatusPageURL func(childComplexity int) int
|
||||||
SubprocessorsListURL func(childComplexity int) int
|
SubprocessorsListURL func(childComplexity int) int
|
||||||
TermsOfServiceURL func(childComplexity int) int
|
TermsOfServiceURL func(childComplexity int) int
|
||||||
@@ -1666,7 +1667,7 @@ type OrganizationResolver interface {
|
|||||||
Connectors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ConnectorOrder) (*types.ConnectorConnection, error)
|
Connectors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ConnectorOrder) (*types.ConnectorConnection, error)
|
||||||
Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FrameworkOrderBy) (*types.FrameworkConnection, error)
|
Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FrameworkOrderBy) (*types.FrameworkConnection, error)
|
||||||
Controls(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error)
|
Controls(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error)
|
||||||
Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) (*types.VendorConnection, error)
|
Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy, filter *types.VendorFilter) (*types.VendorConnection, error)
|
||||||
Peoples(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PeopleOrderBy, filter *types.PeopleFilter) (*types.PeopleConnection, error)
|
Peoples(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PeopleOrderBy, filter *types.PeopleFilter) (*types.PeopleConnection, error)
|
||||||
Documents(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error)
|
Documents(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error)
|
||||||
Measures(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error)
|
Measures(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error)
|
||||||
@@ -5634,7 +5635,7 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.Organization.Vendors(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.VendorOrderBy)), true
|
return e.complexity.Organization.Vendors(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.VendorOrderBy), args["filter"].(*types.VendorFilter)), true
|
||||||
|
|
||||||
case "OrganizationConnection.edges":
|
case "OrganizationConnection.edges":
|
||||||
if e.complexity.OrganizationConnection.Edges == nil {
|
if e.complexity.OrganizationConnection.Edges == nil {
|
||||||
@@ -7124,6 +7125,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.Vendor.ShowOnTrustCenter(childComplexity), true
|
return e.complexity.Vendor.ShowOnTrustCenter(childComplexity), true
|
||||||
|
|
||||||
|
case "Vendor.snapshotId":
|
||||||
|
if e.complexity.Vendor.SnapshotID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Vendor.SnapshotID(childComplexity), true
|
||||||
|
|
||||||
case "Vendor.statusPageUrl":
|
case "Vendor.statusPageUrl":
|
||||||
if e.complexity.Vendor.StatusPageURL == nil {
|
if e.complexity.Vendor.StatusPageURL == nil {
|
||||||
break
|
break
|
||||||
@@ -7850,6 +7858,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||||||
ec.unmarshalInputUserOrder,
|
ec.unmarshalInputUserOrder,
|
||||||
ec.unmarshalInputVendorComplianceReportOrder,
|
ec.unmarshalInputVendorComplianceReportOrder,
|
||||||
ec.unmarshalInputVendorContactOrder,
|
ec.unmarshalInputVendorContactOrder,
|
||||||
|
ec.unmarshalInputVendorFilter,
|
||||||
ec.unmarshalInputVendorOrder,
|
ec.unmarshalInputVendorOrder,
|
||||||
ec.unmarshalInputVendorRiskAssessmentOrder,
|
ec.unmarshalInputVendorRiskAssessmentOrder,
|
||||||
ec.unmarshalInputVendorServiceOrder,
|
ec.unmarshalInputVendorServiceOrder,
|
||||||
@@ -9086,6 +9095,10 @@ input AssetFilter {
|
|||||||
snapshotId: ID
|
snapshotId: ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input VendorFilter {
|
||||||
|
snapshotId: ID
|
||||||
|
}
|
||||||
|
|
||||||
# Core Types
|
# Core Types
|
||||||
type TrustCenter implements Node {
|
type TrustCenter implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
@@ -9148,6 +9161,7 @@ type Organization implements Node {
|
|||||||
last: Int
|
last: Int
|
||||||
before: CursorKey
|
before: CursorKey
|
||||||
orderBy: VendorOrder
|
orderBy: VendorOrder
|
||||||
|
filter: VendorFilter = { snapshotId: null }
|
||||||
): VendorConnection! @goField(forceResolver: true)
|
): VendorConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
peoples(
|
peoples(
|
||||||
@@ -9303,6 +9317,7 @@ type People implements Node {
|
|||||||
|
|
||||||
type Vendor implements Node {
|
type Vendor implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
snapshotId: ID
|
||||||
name: String!
|
name: String!
|
||||||
category: VendorCategory!
|
category: VendorCategory!
|
||||||
description: String
|
description: String
|
||||||
@@ -17711,6 +17726,11 @@ func (ec *executionContext) field_Organization_vendors_args(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
args["orderBy"] = arg4
|
args["orderBy"] = arg4
|
||||||
|
arg5, err := ec.field_Organization_vendors_argsFilter(ctx, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args["filter"] = arg5
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
func (ec *executionContext) field_Organization_vendors_argsFirst(
|
func (ec *executionContext) field_Organization_vendors_argsFirst(
|
||||||
@@ -17778,6 +17798,19 @@ func (ec *executionContext) field_Organization_vendors_argsOrderBy(
|
|||||||
return zeroVal, nil
|
return zeroVal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Organization_vendors_argsFilter(
|
||||||
|
ctx context.Context,
|
||||||
|
rawArgs map[string]any,
|
||||||
|
) (*types.VendorFilter, error) {
|
||||||
|
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
|
||||||
|
if tmp, ok := rawArgs["filter"]; ok {
|
||||||
|
return ec.unmarshalOVendorFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐVendorFilter(ctx, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroVal *types.VendorFilter
|
||||||
|
return zeroVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]any{}
|
args := map[string]any{}
|
||||||
@@ -19123,6 +19156,8 @@ func (ec *executionContext) fieldContext_AssessVendorPayload_vendor(_ context.Co
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -41697,7 +41732,7 @@ func (ec *executionContext) _Organization_vendors(ctx context.Context, field gra
|
|||||||
}()
|
}()
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return ec.resolvers.Organization().Vendors(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.VendorOrderBy))
|
return ec.resolvers.Organization().Vendors(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.VendorOrderBy), fc.Args["filter"].(*types.VendorFilter))
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
@@ -51442,6 +51477,8 @@ func (ec *executionContext) fieldContext_UpdateVendorPayload_vendor(_ context.Co
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -52457,6 +52494,47 @@ func (ec *executionContext) fieldContext_Vendor_id(_ context.Context, field grap
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Vendor_snapshotId(ctx context.Context, field graphql.CollectedField, obj *types.Vendor) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_Vendor_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_Vendor_snapshotId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "Vendor",
|
||||||
|
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) _Vendor_name(ctx context.Context, field graphql.CollectedField, obj *types.Vendor) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Vendor_name(ctx context.Context, field graphql.CollectedField, obj *types.Vendor) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Vendor_name(ctx, field)
|
fc, err := ec.fieldContext_Vendor_name(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -53925,6 +54003,8 @@ func (ec *executionContext) fieldContext_VendorBusinessAssociateAgreement_vendor
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -54375,6 +54455,8 @@ func (ec *executionContext) fieldContext_VendorComplianceReport_vendor(_ context
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -55188,6 +55270,8 @@ func (ec *executionContext) fieldContext_VendorContact_vendor(_ context.Context,
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -55798,6 +55882,8 @@ func (ec *executionContext) fieldContext_VendorDataPrivacyAgreement_vendor(_ con
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -56248,6 +56334,8 @@ func (ec *executionContext) fieldContext_VendorEdge_node(_ context.Context, fiel
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -56396,6 +56484,8 @@ func (ec *executionContext) fieldContext_VendorRiskAssessment_vendor(_ context.C
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -57129,6 +57219,8 @@ func (ec *executionContext) fieldContext_VendorService_vendor(_ context.Context,
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "id":
|
case "id":
|
||||||
return ec.fieldContext_Vendor_id(ctx, field)
|
return ec.fieldContext_Vendor_id(ctx, field)
|
||||||
|
case "snapshotId":
|
||||||
|
return ec.fieldContext_Vendor_snapshotId(ctx, field)
|
||||||
case "name":
|
case "name":
|
||||||
return ec.fieldContext_Vendor_name(ctx, field)
|
return ec.fieldContext_Vendor_name(ctx, field)
|
||||||
case "category":
|
case "category":
|
||||||
@@ -66011,6 +66103,33 @@ func (ec *executionContext) unmarshalInputVendorContactOrder(ctx context.Context
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputVendorFilter(ctx context.Context, obj any) (types.VendorFilter, error) {
|
||||||
|
var it types.VendorFilter
|
||||||
|
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) unmarshalInputVendorOrder(ctx context.Context, obj any) (types.VendorOrderBy, error) {
|
func (ec *executionContext) unmarshalInputVendorOrder(ctx context.Context, obj any) (types.VendorOrderBy, error) {
|
||||||
var it types.VendorOrderBy
|
var it types.VendorOrderBy
|
||||||
asMap := map[string]any{}
|
asMap := map[string]any{}
|
||||||
@@ -78797,6 +78916,8 @@ func (ec *executionContext) _Vendor(ctx context.Context, sel ast.SelectionSet, o
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
atomic.AddUint32(&out.Invalids, 1)
|
atomic.AddUint32(&out.Invalids, 1)
|
||||||
}
|
}
|
||||||
|
case "snapshotId":
|
||||||
|
out.Values[i] = ec._Vendor_snapshotId(ctx, field, obj)
|
||||||
case "name":
|
case "name":
|
||||||
out.Values[i] = ec._Vendor_name(ctx, field, obj)
|
out.Values[i] = ec._Vendor_name(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
@@ -88481,6 +88602,14 @@ func (ec *executionContext) marshalOVendorDataPrivacyAgreement2ᚖgithubᚗcom
|
|||||||
return ec._VendorDataPrivacyAgreement(ctx, sel, v)
|
return ec._VendorDataPrivacyAgreement(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalOVendorFilter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐVendorFilter(ctx context.Context, v any) (*types.VendorFilter, error) {
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
res, err := ec.unmarshalInputVendorFilter(ctx, v)
|
||||||
|
return &res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalOVendorOrder2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐVendorOrderBy(ctx context.Context, v any) (*types.VendorOrderBy, error) {
|
func (ec *executionContext) unmarshalOVendorOrder2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐVendorOrderBy(ctx context.Context, v any) (*types.VendorOrderBy, error) {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@@ -1881,6 +1881,7 @@ type UserEdge struct {
|
|||||||
|
|
||||||
type Vendor struct {
|
type Vendor struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
|
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Category coredata.VendorCategory `json:"category"`
|
Category coredata.VendorCategory `json:"category"`
|
||||||
Description *string `json:"description,omitempty"`
|
Description *string `json:"description,omitempty"`
|
||||||
@@ -1998,6 +1999,10 @@ type VendorEdge struct {
|
|||||||
Node *Vendor `json:"node"`
|
Node *Vendor `json:"node"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VendorFilter struct {
|
||||||
|
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type VendorRiskAssessment struct {
|
type VendorRiskAssessment struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
Vendor *Vendor `json:"vendor"`
|
Vendor *Vendor `json:"vendor"`
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ func NewVendor(v *coredata.Vendor) *Vendor {
|
|||||||
WebsiteURL: v.WebsiteURL,
|
WebsiteURL: v.WebsiteURL,
|
||||||
Category: v.Category,
|
Category: v.Category,
|
||||||
ShowOnTrustCenter: v.ShowOnTrustCenter,
|
ShowOnTrustCenter: v.ShowOnTrustCenter,
|
||||||
|
SnapshotID: v.SnapshotID,
|
||||||
UpdatedAt: v.UpdatedAt,
|
UpdatedAt: v.UpdatedAt,
|
||||||
CreatedAt: v.CreatedAt,
|
CreatedAt: v.CreatedAt,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3459,7 +3459,7 @@ func (r *organizationResolver) Controls(ctx context.Context, obj *types.Organiza
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vendors is the resolver for the vendors field.
|
// Vendors is the resolver for the vendors field.
|
||||||
func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) (*types.VendorConnection, error) {
|
func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy, filter *types.VendorFilter) (*types.VendorConnection, error) {
|
||||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
|
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
|
||||||
@@ -3474,8 +3474,11 @@ func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organizat
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
var nilSnapshotID *gid.GID = nil
|
|
||||||
vendorFilter := coredata.NewVendorFilter(&nilSnapshotID, nil)
|
var vendorFilter = coredata.NewVendorFilter(nil, nil)
|
||||||
|
if filter != nil {
|
||||||
|
vendorFilter = coredata.NewVendorFilter(&filter.SnapshotID, nil)
|
||||||
|
}
|
||||||
|
|
||||||
page, err := prb.Vendors.ListForOrganizationID(ctx, obj.ID, cursor, vendorFilter)
|
page, err := prb.Vendors.ListForOrganizationID(ctx, obj.ID, cursor, vendorFilter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user