From 78e63955355c30bbd291d32f2088550debd368a8 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 17 Jun 2025 17:20:15 +0200 Subject: [PATCH] Add pagination on vendors Signed-off-by: Bryan Frimin --- apps/console/src/components/SortableTable.tsx | 10 +- apps/console/src/hooks/graph/VendorGraph.ts | 63 ++- .../PeopleGraphPaginatedFragment.graphql.ts | 6 +- .../PeopleGraphPaginatedQuery.graphql.ts | 10 +- .../__generated__/PeopleListQuery.graphql.ts | 10 +- .../VendorGraphListQuery.graphql.ts | 426 +++++++++--------- .../VendorGraphPaginatedFragment.graphql.ts | 332 ++++++++++++++ .../__generated__/VendorsListQuery.graphql.ts | 413 +++++++++++++++++ .../organizations/people/PeopleListPage.tsx | 2 +- .../organizations/vendors/VendorsPage.tsx | 28 +- 10 files changed, 1029 insertions(+), 271 deletions(-) create mode 100644 apps/console/src/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql.ts create mode 100644 apps/console/src/hooks/graph/__generated__/VendorsListQuery.graphql.ts diff --git a/apps/console/src/components/SortableTable.tsx b/apps/console/src/components/SortableTable.tsx index bce831f7f..d507862d5 100644 --- a/apps/console/src/components/SortableTable.tsx +++ b/apps/console/src/components/SortableTable.tsx @@ -38,13 +38,13 @@ export function SortableTable({ refetch, hasNext, loadNext, - isLoading, + isLoadingNext, ...props }: ComponentProps & { refetch: (o: { order: Order }) => void; hasNext: boolean; - loadNext: () => void; - isLoading: boolean; + loadNext: (...args: any[]) => void; + isLoadingNext: boolean; }) { const { __ } = useTranslate(); const [order, setOrder] = useState(defaultOrder); @@ -63,8 +63,8 @@ export function SortableTable({ variant="tertiary" onClick={() => loadNext()} className="mt-3 mx-auto" - disabled={isLoading} - icon={isLoading ? Spinner : IconChevronDown} + disabled={isLoadingNext} + icon={isLoadingNext ? Spinner : IconChevronDown} > {__("Show more")} diff --git a/apps/console/src/hooks/graph/VendorGraph.ts b/apps/console/src/hooks/graph/VendorGraph.ts index 97eb50f48..3d0326587 100644 --- a/apps/console/src/hooks/graph/VendorGraph.ts +++ b/apps/console/src/hooks/graph/VendorGraph.ts @@ -92,27 +92,48 @@ export const vendorsQuery = graphql` query VendorGraphListQuery($organizationId: ID!) { node(id: $organizationId) { ... on Organization { - vendors(first: 25) @connection(key: "VendorsPage_vendors") { - __id - edges { - node { - id - name - websiteUrl - updatedAt - riskAssessments( - first: 1 - orderBy: { direction: DESC, field: ASSESSED_AT } - ) { - edges { - node { - id - assessedAt - expiresAt - dataSensitivity - businessImpact - } - } + id + ...VendorGraphPaginatedFragment + } + } + } +`; + +export const paginatedVendorsFragment = graphql` + fragment VendorGraphPaginatedFragment on Organization + @refetchable(queryName: "VendorsListQuery") + @argumentDefinitions( + first: { type: "Int", defaultValue: 50 } + order: { type: "VendorOrder", defaultValue: null } + after: { type: "CursorKey", defaultValue: null } + before: { type: "CursorKey", defaultValue: null } + last: { type: "Int", defaultValue: null } + ) { + vendors( + first: $first + after: $after + last: $last + before: $before + orderBy: $order + ) @connection(key: "VendorsListQuery_vendors") { + __id + edges { + node { + id + name + websiteUrl + updatedAt + riskAssessments( + first: 1 + orderBy: { direction: DESC, field: ASSESSED_AT } + ) { + edges { + node { + id + assessedAt + expiresAt + dataSensitivity + businessImpact } } } diff --git a/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedFragment.graphql.ts b/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedFragment.graphql.ts index a862c4110..ddc45ef56 100644 --- a/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedFragment.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<452165e3b8b1cdef4b8e62d53c8a73ed>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -58,7 +58,7 @@ return { "name": "before" }, { - "defaultValue": 1, + "defaultValue": 50, "kind": "LocalArgument", "name": "first" }, @@ -247,6 +247,6 @@ return { }; })(); -(node as any).hash = "e1720a7dc0b7914edb8a07f63d5cf95a"; +(node as any).hash = "c163b7909a337efd22088852b9908045"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedQuery.graphql.ts index f3aae3659..38fece81c 100644 --- a/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/PeopleGraphPaginatedQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<56d7fa0e53727e6a52fc6ab7bc805ceb>> + * @generated SignedSource<<43878b22fe8a689f41bcd506711ddb5f>> * @lightSyntaxTransform * @nogrep */ @@ -57,7 +57,7 @@ v4 = [ { "kind": "Literal", "name": "first", - "value": 1 + "value": 50 } ]; return { @@ -233,7 +233,7 @@ return { ] } ], - "storageKey": "peoples(first:1)" + "storageKey": "peoples(first:50)" }, { "alias": null, @@ -256,12 +256,12 @@ return { ] }, "params": { - "cacheID": "838b4fd1617a05fcb681c1e533cc0a9f", + "cacheID": "b154e94ac7e783a492bc5aed7d44229d", "id": null, "metadata": {}, "name": "PeopleGraphPaginatedQuery", "operationKind": "query", - "text": "query PeopleGraphPaginatedQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...PeopleGraphPaginatedFragment\n }\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment on Organization {\n peoples(first: 1) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" + "text": "query PeopleGraphPaginatedQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...PeopleGraphPaginatedFragment\n }\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment on Organization {\n peoples(first: 50) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" } }; })(); diff --git a/apps/console/src/hooks/graph/__generated__/PeopleListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/PeopleListQuery.graphql.ts index daf5b3c5d..e720c10dc 100644 --- a/apps/console/src/hooks/graph/__generated__/PeopleListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/PeopleListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -46,7 +46,7 @@ v1 = { "name": "before" }, v2 = { - "defaultValue": 1, + "defaultValue": 50, "kind": "LocalArgument", "name": "first" }, @@ -329,16 +329,16 @@ return { ] }, "params": { - "cacheID": "e26cb4d1b42b5500dd12ee294ccce2e5", + "cacheID": "a17ff68897dbcf3daa33b073bc83f1bb", "id": null, "metadata": {}, "name": "PeopleListQuery", "operationKind": "query", - "text": "query PeopleListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 1\n $last: Int = null\n $order: PeopleOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...PeopleGraphPaginatedFragment_16fISc\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment_16fISc on Organization {\n peoples(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" + "text": "query PeopleListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: PeopleOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...PeopleGraphPaginatedFragment_16fISc\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment_16fISc on Organization {\n peoples(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\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 = "e1720a7dc0b7914edb8a07f63d5cf95a"; +(node as any).hash = "c163b7909a337efd22088852b9908045"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/VendorGraphListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/VendorGraphListQuery.graphql.ts index ed7f51806..2855e7d53 100644 --- a/apps/console/src/hooks/graph/__generated__/VendorGraphListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/VendorGraphListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -9,35 +9,14 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type BusinessImpact = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM"; -export type DataSensitivity = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "NONE"; +import { FragmentRefs } from "relay-runtime"; export type VendorGraphListQuery$variables = { organizationId: string; }; export type VendorGraphListQuery$data = { readonly node: { - readonly vendors?: { - readonly __id: string; - readonly edges: ReadonlyArray<{ - readonly node: { - readonly id: string; - readonly name: string; - readonly riskAssessments: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly assessedAt: any; - readonly businessImpact: BusinessImpact; - readonly dataSensitivity: DataSensitivity; - readonly expiresAt: any; - readonly id: string; - }; - }>; - }; - readonly updatedAt: any; - readonly websiteUrl: string | null | undefined; - }; - }>; - }; + readonly id?: string; + readonly " $fragmentSpreads": FragmentRefs<"VendorGraphPaginatedFragment">; }; }; export type VendorGraphListQuery = { @@ -75,177 +54,10 @@ v3 = { "storageKey": null }, v4 = [ - { - "alias": null, - "args": null, - "concreteType": "VendorEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "Vendor", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "websiteUrl", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - { - "alias": null, - "args": [ - { - "kind": "Literal", - "name": "first", - "value": 1 - }, - { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "ASSESSED_AT" - } - } - ], - "concreteType": "VendorRiskAssessmentConnection", - "kind": "LinkedField", - "name": "riskAssessments", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "VendorRiskAssessmentEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "VendorRiskAssessment", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "assessedAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "expiresAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "dataSensitivity", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "businessImpact", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})" - }, - (v3/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - } - ], - "storageKey": null - }, - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__id", - "storageKey": null - } - ] - } -], -v5 = [ { "kind": "Literal", "name": "first", - "value": 25 + "value": 50 } ]; return { @@ -266,15 +78,11 @@ return { { "kind": "InlineFragment", "selections": [ + (v2/*: any*/), { - "alias": "vendors", "args": null, - "concreteType": "VendorConnection", - "kind": "LinkedField", - "name": "__VendorsPage_vendors_connection", - "plural": false, - "selections": (v4/*: any*/), - "storageKey": null + "kind": "FragmentSpread", + "name": "VendorGraphPaginatedFragment" } ], "type": "Organization", @@ -302,61 +110,231 @@ return { "plural": false, "selections": [ (v3/*: any*/), + (v2/*: any*/), { "kind": "InlineFragment", "selections": [ { "alias": null, - "args": (v5/*: any*/), + "args": (v4/*: any*/), "concreteType": "VendorConnection", "kind": "LinkedField", "name": "vendors", "plural": false, - "selections": (v4/*: any*/), - "storageKey": "vendors(first:25)" + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Vendor", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "websiteUrl", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 1 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "ASSESSED_AT" + } + } + ], + "concreteType": "VendorRiskAssessmentConnection", + "kind": "LinkedField", + "name": "riskAssessments", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessmentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessment", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "assessedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "expiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "dataSensitivity", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "businessImpact", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})" + }, + (v3/*: any*/) + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": "vendors(first:50)" }, { "alias": null, - "args": (v5/*: any*/), - "filters": null, + "args": (v4/*: any*/), + "filters": [ + "orderBy" + ], "handle": "connection", - "key": "VendorsPage_vendors", + "key": "VendorsListQuery_vendors", "kind": "LinkedHandle", "name": "vendors" } ], "type": "Organization", "abstractKey": null - }, - (v2/*: any*/) + } ], "storageKey": null } ] }, "params": { - "cacheID": "ce175c4c5d08117d3acdbd3eed92ca95", + "cacheID": "e2eade63dcf3d7ea071463a2e5993293", "id": null, - "metadata": { - "connection": [ - { - "count": null, - "cursor": null, - "direction": "forward", - "path": [ - "node", - "vendors" - ] - } - ] - }, + "metadata": {}, "name": "VendorGraphListQuery", "operationKind": "query", - "text": "query VendorGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n vendors(first: 25) {\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 }\n }\n }\n id\n }\n}\n" + "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" } }; })(); -(node as any).hash = "ef2b4fb44af8cef6cd3f50a6746c6de3"; +(node as any).hash = "3bb12a4d7a49090154bb56951e69f4aa"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql.ts b/apps/console/src/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql.ts new file mode 100644 index 000000000..d89cfefb5 --- /dev/null +++ b/apps/console/src/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql.ts @@ -0,0 +1,332 @@ +/** + * @generated SignedSource<<93638f7eeb1634fc19aaaa95cae0c7b8>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +export type BusinessImpact = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM"; +export type DataSensitivity = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "NONE"; +import { FragmentRefs } from "relay-runtime"; +export type VendorGraphPaginatedFragment$data = { + readonly id: string; + readonly vendors: { + readonly __id: string; + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly name: string; + readonly riskAssessments: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly assessedAt: any; + readonly businessImpact: BusinessImpact; + readonly dataSensitivity: DataSensitivity; + readonly expiresAt: any; + readonly id: string; + }; + }>; + }; + readonly updatedAt: any; + readonly websiteUrl: string | null | undefined; + }; + }>; + }; + readonly " $fragmentType": "VendorGraphPaginatedFragment"; +}; +export type VendorGraphPaginatedFragment$key = { + readonly " $data"?: VendorGraphPaginatedFragment$data; + readonly " $fragmentSpreads": FragmentRefs<"VendorGraphPaginatedFragment">; +}; + +import VendorsListQuery_graphql from './VendorsListQuery.graphql'; + +const node: ReaderFragment = (function(){ +var v0 = [ + "vendors" +], +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}; +return { + "argumentDefinitions": [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "before" + }, + { + "defaultValue": 50, + "kind": "LocalArgument", + "name": "first" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "last" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "order" + } + ], + "kind": "Fragment", + "metadata": { + "connection": [ + { + "count": null, + "cursor": null, + "direction": "bidirectional", + "path": (v0/*: any*/) + } + ], + "refetch": { + "connection": { + "forward": { + "count": "first", + "cursor": "after" + }, + "backward": { + "count": "last", + "cursor": "before" + }, + "path": (v0/*: any*/) + }, + "fragmentPathInResult": [ + "node" + ], + "operation": VendorsListQuery_graphql, + "identifierInfo": { + "identifierField": "id", + "identifierQueryVariableName": "id" + } + } + }, + "name": "VendorGraphPaginatedFragment", + "selections": [ + { + "alias": "vendors", + "args": [ + { + "kind": "Variable", + "name": "orderBy", + "variableName": "order" + } + ], + "concreteType": "VendorConnection", + "kind": "LinkedField", + "name": "__VendorsListQuery_vendors_connection", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Vendor", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "websiteUrl", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 1 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "ASSESSED_AT" + } + } + ], + "concreteType": "VendorRiskAssessmentConnection", + "kind": "LinkedField", + "name": "riskAssessments", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessmentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessment", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "assessedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "expiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "dataSensitivity", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "businessImpact", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})" + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": null + }, + (v1/*: any*/) + ], + "type": "Organization", + "abstractKey": null +}; +})(); + +(node as any).hash = "1d2bf7c29e77d60d0a955a62b98c85ab"; + +export default node; diff --git a/apps/console/src/hooks/graph/__generated__/VendorsListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/VendorsListQuery.graphql.ts new file mode 100644 index 000000000..1005bb700 --- /dev/null +++ b/apps/console/src/hooks/graph/__generated__/VendorsListQuery.graphql.ts @@ -0,0 +1,413 @@ +/** + * @generated SignedSource<<9f3bb5320763a3026c5efad2a0fd88d2>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type OrderDirection = "ASC" | "DESC"; +export type VendorOrderField = "NAME"; +export type VendorOrder = { + direction: OrderDirection; + field: VendorOrderField; +}; +export type VendorsListQuery$variables = { + after?: any | null | undefined; + before?: any | null | undefined; + first?: number | null | undefined; + id: string; + last?: number | null | undefined; + order?: VendorOrder | null | undefined; +}; +export type VendorsListQuery$data = { + readonly node: { + readonly " $fragmentSpreads": FragmentRefs<"VendorGraphPaginatedFragment">; + }; +}; +export type VendorsListQuery = { + response: VendorsListQuery$data; + variables: VendorsListQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" +}, +v1 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "before" +}, +v2 = { + "defaultValue": 50, + "kind": "LocalArgument", + "name": "first" +}, +v3 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "id" +}, +v4 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "last" +}, +v5 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "order" +}, +v6 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "id" + } +], +v7 = { + "kind": "Variable", + "name": "after", + "variableName": "after" +}, +v8 = { + "kind": "Variable", + "name": "before", + "variableName": "before" +}, +v9 = { + "kind": "Variable", + "name": "first", + "variableName": "first" +}, +v10 = { + "kind": "Variable", + "name": "last", + "variableName": "last" +}, +v11 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null +}, +v12 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v13 = [ + (v7/*: any*/), + (v8/*: any*/), + (v9/*: any*/), + (v10/*: any*/), + { + "kind": "Variable", + "name": "orderBy", + "variableName": "order" + } +]; +return { + "fragment": { + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/), + (v3/*: any*/), + (v4/*: any*/), + (v5/*: any*/) + ], + "kind": "Fragment", + "metadata": null, + "name": "VendorsListQuery", + "selections": [ + { + "alias": null, + "args": (v6/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "args": [ + (v7/*: any*/), + (v8/*: any*/), + (v9/*: any*/), + (v10/*: any*/), + { + "kind": "Variable", + "name": "order", + "variableName": "order" + } + ], + "kind": "FragmentSpread", + "name": "VendorGraphPaginatedFragment" + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/), + (v4/*: any*/), + (v5/*: any*/), + (v3/*: any*/) + ], + "kind": "Operation", + "name": "VendorsListQuery", + "selections": [ + { + "alias": null, + "args": (v6/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v11/*: any*/), + (v12/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": (v13/*: any*/), + "concreteType": "VendorConnection", + "kind": "LinkedField", + "name": "vendors", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Vendor", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v12/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "websiteUrl", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 1 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "ASSESSED_AT" + } + } + ], + "concreteType": "VendorRiskAssessmentConnection", + "kind": "LinkedField", + "name": "riskAssessments", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessmentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorRiskAssessment", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v12/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "assessedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "expiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "dataSensitivity", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "businessImpact", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "riskAssessments(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"ASSESSED_AT\"})" + }, + (v11/*: any*/) + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": null + }, + { + "alias": null, + "args": (v13/*: any*/), + "filters": [ + "orderBy" + ], + "handle": "connection", + "key": "VendorsListQuery_vendors", + "kind": "LinkedHandle", + "name": "vendors" + } + ], + "type": "Organization", + "abstractKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "70fb3d49e78996ae4cefbaa8f5605c2c", + "id": null, + "metadata": {}, + "name": "VendorsListQuery", + "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" + } +}; +})(); + +(node as any).hash = "1d2bf7c29e77d60d0a955a62b98c85ab"; + +export default node; diff --git a/apps/console/src/pages/organizations/people/PeopleListPage.tsx b/apps/console/src/pages/organizations/people/PeopleListPage.tsx index 141424cd2..1d705e609 100644 --- a/apps/console/src/pages/organizations/people/PeopleListPage.tsx +++ b/apps/console/src/pages/organizations/people/PeopleListPage.tsx @@ -53,7 +53,7 @@ export default function PeopleListPage({ refetch={refetch} hasNext={hasNext} loadNext={loadNext} - isLoading={isLoadingNext} + isLoadingNext={isLoadingNext} > diff --git a/apps/console/src/pages/organizations/vendors/VendorsPage.tsx b/apps/console/src/pages/organizations/vendors/VendorsPage.tsx index 477a42497..58457599d 100644 --- a/apps/console/src/pages/organizations/vendors/VendorsPage.tsx +++ b/apps/console/src/pages/organizations/vendors/VendorsPage.tsx @@ -17,16 +17,26 @@ import { } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; import { usePageTitle } from "@probo/hooks"; -import { usePreloadedQuery, type PreloadedQuery } from "react-relay"; +import { + usePaginationFragment, + usePreloadedQuery, + type PreloadedQuery, +} from "react-relay"; import { useOrganizationId } from "/hooks/useOrganizationId"; import { faviconUrl } from "@probo/helpers"; import type { NodeOf } from "/types"; import { CreateVendorDialog } from "./dialogs/CreateVendorDialog"; -import { useDeleteVendor, vendorsQuery } from "/hooks/graph/VendorGraph"; +import { + paginatedVendorsFragment, + useDeleteVendor, + vendorsQuery, +} from "/hooks/graph/VendorGraph"; import type { VendorGraphListQuery, VendorGraphListQuery$data, } from "/hooks/graph/__generated__/VendorGraphListQuery.graphql"; +import type { VendorGraphPaginatedFragment$key } from "/hooks/graph/__generated__/VendorGraphPaginatedFragment.graphql"; +import { SortableTable } from "/components/SortableTable"; type Vendor = NodeOf; @@ -39,9 +49,13 @@ export default function VendorsPage(props: Props) { const organizationId = useOrganizationId(); const data = usePreloadedQuery(vendorsQuery, props.queryRef); + const pagination = usePaginationFragment( + paginatedVendorsFragment, + data.node as VendorGraphPaginatedFragment$key + ); - const vendors = data.node?.vendors?.edges.map((edge) => edge.node); - const connectionId = data.node!.vendors!.__id; + const vendors = pagination.data.vendors?.edges.map((edge) => edge.node); + const connectionId = pagination.data.vendors.__id; usePageTitle(__("Vendors")); @@ -54,13 +68,13 @@ export default function VendorsPage(props: Props) { )} > - + @@ -81,7 +95,7 @@ export default function VendorsPage(props: Props) { /> ))} -
{__("Vendor")}
+ ); }