diff --git a/apps/console/src/components/SortableTable.tsx b/apps/console/src/components/SortableTable.tsx index 1d0f6de73..ed23cb8cc 100644 --- a/apps/console/src/components/SortableTable.tsx +++ b/apps/console/src/components/SortableTable.tsx @@ -21,7 +21,7 @@ type Order = { field: string; }; -const SortableContext = createContext({ +export const SortableContext = createContext({ order: { direction: "DESC", field: "CREATED_AT", diff --git a/apps/console/src/hooks/forms/__generated__/useRiskFormFragment.graphql.ts b/apps/console/src/hooks/forms/__generated__/useRiskFormFragment.graphql.ts index fcb7ea998..5e4e25d5d 100644 --- a/apps/console/src/hooks/forms/__generated__/useRiskFormFragment.graphql.ts +++ b/apps/console/src/hooks/forms/__generated__/useRiskFormFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<38b7fae585eb2c09409935db8ad3cfe9>> + * @generated SignedSource<<828d1e2364b7b8c540508d9fb7104b06>> * @lightSyntaxTransform * @nogrep */ @@ -17,6 +17,7 @@ export type useRiskFormFragment$data = { readonly id: string; readonly inherentImpact: number; readonly inherentLikelihood: number; + readonly inherentRiskScore: number; readonly name: string; readonly note: string; readonly owner: { @@ -24,6 +25,7 @@ export type useRiskFormFragment$data = { } | null | undefined; readonly residualImpact: number; readonly residualLikelihood: number; + readonly residualRiskScore: number; readonly treatment: RiskTreatment; readonly " $fragmentType": "useRiskFormFragment"; }; @@ -103,6 +105,20 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "inherentRiskScore", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "residualRiskScore", + "storageKey": null + }, { "alias": null, "args": null, @@ -128,6 +144,6 @@ return { }; })(); -(node as any).hash = "7ad9386b4049af3f139d7269bb5229c2"; +(node as any).hash = "d9b52f879eadba5f7b1c18dcdbf85559"; export default node; diff --git a/apps/console/src/hooks/forms/useRiskForm.tsx b/apps/console/src/hooks/forms/useRiskForm.tsx index ac3500954..50791095e 100644 --- a/apps/console/src/hooks/forms/useRiskForm.tsx +++ b/apps/console/src/hooks/forms/useRiskForm.tsx @@ -18,6 +18,8 @@ const RiskFragment = graphql` inherentImpact residualLikelihood residualImpact + inherentRiskScore + residualRiskScore note owner { id diff --git a/apps/console/src/hooks/graph/RiskGraph.ts b/apps/console/src/hooks/graph/RiskGraph.ts index 4715469f8..c58963083 100644 --- a/apps/console/src/hooks/graph/RiskGraph.ts +++ b/apps/console/src/hooks/graph/RiskGraph.ts @@ -1,10 +1,10 @@ -import { ConnectionHandler, graphql } from "relay-runtime"; +import { graphql } from "relay-runtime"; import { useTranslate } from "@probo/i18n"; import { useMutationWithToasts } from "../useMutationWithToasts.ts"; import type { RiskGraphDeleteMutation } from "./__generated__/RiskGraphDeleteMutation.graphql.ts"; import { usePreloadedQuery, - useRefetchableFragment, + usePaginationFragment, type PreloadedQuery, } from "react-relay"; import type { RiskGraphListQuery } from "./__generated__/RiskGraphListQuery.graphql.ts"; @@ -44,7 +44,7 @@ const risksFragment = graphql` @refetchable(queryName: "RisksListQuery") @argumentDefinitions( first: { type: "Int", defaultValue: 50 } - order: { type: "RiskOrder", defaultValue: null } + order: { type: "RiskOrder", defaultValue: { direction: DESC, field: CREATED_AT } } after: { type: "CursorKey", defaultValue: null } before: { type: "CursorKey", defaultValue: null } last: { type: "Int", defaultValue: null } @@ -58,6 +58,7 @@ const risksFragment = graphql` orderBy: $order filter: { snapshotId: $snapshotId } ) @connection(key: "RisksListQuery_risks", filters: ["filter"]) { + __id edges { node { id @@ -65,6 +66,10 @@ const risksFragment = graphql` name category treatment + owner { + id + fullName + } inherentLikelihood inherentImpact residualLikelihood @@ -80,21 +85,18 @@ const risksFragment = graphql` export const RisksConnectionKey = "RisksListQuery_risks"; -export function useRisksQuery(queryRef: PreloadedQuery, snapshotId?: string | null) { +export function useRisksQuery(queryRef: PreloadedQuery) { const data = usePreloadedQuery(risksQuery, queryRef); - const [dataFragment, refetch] = useRefetchableFragment( + const pagination = usePaginationFragment( risksFragment, data.organization as RiskGraphFragment$key, ); - const risks = dataFragment?.risks?.edges.map((edge) => edge.node); + const risks = pagination.data?.risks?.edges.map((edge) => edge.node); + return { + ...pagination, risks, - refetch, - connectionId: ConnectionHandler.getConnectionID( - data.organization.id, - RisksConnectionKey, - { filter: { snapshotId: snapshotId || null } } - ), + connectionId: pagination.data.risks.__id, }; } diff --git a/apps/console/src/hooks/graph/__generated__/RiskGraphFragment.graphql.ts b/apps/console/src/hooks/graph/__generated__/RiskGraphFragment.graphql.ts index 1174eeef2..729df3a18 100644 --- a/apps/console/src/hooks/graph/__generated__/RiskGraphFragment.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/RiskGraphFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<2b964bdee12b49230932678f583c7401>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -14,6 +14,7 @@ import { FragmentRefs } from "relay-runtime"; export type RiskGraphFragment$data = { readonly id: string; readonly risks: { + readonly __id: string; readonly edges: ReadonlyArray<{ readonly node: { readonly category: string; @@ -22,6 +23,10 @@ export type RiskGraphFragment$data = { readonly inherentLikelihood: number; readonly inherentRiskScore: number; readonly name: string; + readonly owner: { + readonly fullName: string; + readonly id: string; + } | null | undefined; readonly residualImpact: number; readonly residualLikelihood: number; readonly residualRiskScore: number; @@ -74,7 +79,10 @@ return { "name": "last" }, { - "defaultValue": null, + "defaultValue": { + "direction": "DESC", + "field": "CREATED_AT" + }, "kind": "LocalArgument", "name": "order" }, @@ -183,6 +191,25 @@ return { "name": "treatment", "storageKey": null }, + { + "alias": null, + "args": null, + "concreteType": "People", + "kind": "LinkedField", + "name": "owner", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "fullName", + "storageKey": null + } + ], + "storageKey": null + }, { "alias": null, "args": null, @@ -288,6 +315,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": null @@ -299,6 +338,6 @@ return { }; })(); -(node as any).hash = "95c68a022cbf075eede9b7417393a369"; +(node as any).hash = "d8048ddb0ff8d4b08b7b9676d9b98f1a"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/RiskGraphListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/RiskGraphListQuery.graphql.ts index 34bb750e7..2d489bc04 100644 --- a/apps/console/src/hooks/graph/__generated__/RiskGraphListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/RiskGraphListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -76,6 +76,14 @@ v5 = [ "kind": "Literal", "name": "first", "value": 50 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } } ]; return { @@ -178,6 +186,25 @@ return { "name": "treatment", "storageKey": null }, + { + "alias": null, + "args": null, + "concreteType": "People", + "kind": "LinkedField", + "name": "owner", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "fullName", + "storageKey": null + } + ], + "storageKey": null + }, { "alias": null, "args": null, @@ -234,18 +261,6 @@ return { "name": "note", "storageKey": null }, - { - "alias": null, - "args": null, - "concreteType": "People", - "kind": "LinkedField", - "name": "owner", - "plural": false, - "selections": [ - (v2/*: any*/) - ], - "storageKey": null - }, (v4/*: any*/) ], "storageKey": null @@ -298,6 +313,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": null @@ -323,12 +350,12 @@ return { ] }, "params": { - "cacheID": "b2114c476ed7e095fc9d2317b6b1c554", + "cacheID": "225123bb702f2bce307ca69bea183e88", "id": null, "metadata": {}, "name": "RiskGraphListQuery", "operationKind": "query", - "text": "query RiskGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...RiskGraphFragment_3iomuz\n }\n}\n\nfragment RiskGraphFragment_3iomuz on Organization {\n risks(first: 50, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n category\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n ...useRiskFormFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n" + "text": "query RiskGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...RiskGraphFragment_3iomuz\n }\n}\n\nfragment RiskGraphFragment_3iomuz on Organization {\n risks(first: 50, orderBy: {direction: DESC, field: CREATED_AT}, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n category\n treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n ...useRiskFormFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n note\n owner {\n id\n }\n}\n" } }; })(); diff --git a/apps/console/src/hooks/graph/__generated__/RiskGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/RiskGraphNodeQuery.graphql.ts index 6353a896e..34eedc1d6 100644 --- a/apps/console/src/hooks/graph/__generated__/RiskGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/RiskGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<494ff8512e4a50c2bbc2cb3453dbab1c>> + * @generated SignedSource<<9abcf06eed9cb70f62b2aed2b907e9e5>> * @lightSyntaxTransform * @nogrep */ @@ -655,12 +655,12 @@ return { ] }, "params": { - "cacheID": "03ef938803c52b572e23e691d50c4188", + "cacheID": "c3d393180d6273b2e910c7ebffb75df7", "id": null, "metadata": {}, "name": "RiskGraphNodeQuery", "operationKind": "query", - "text": "query RiskGraphNodeQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n ... on Risk {\n id\n snapshotId\n name\n description\n treatment\n owner {\n id\n fullName\n }\n note\n inherentRiskScore\n residualRiskScore\n measuresInfo: measures(first: 0) {\n totalCount\n }\n documentsInfo: documents(first: 0) {\n totalCount\n }\n controlsInfo: controls(first: 0) {\n totalCount\n }\n ...useRiskFormFragment\n ...RiskOverviewTabFragment\n ...RiskMeasuresTabFragment\n ...RiskDocumentsTabFragment\n ...RiskControlsTabFragment\n }\n id\n }\n}\n\nfragment LinkedDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment LinkedMeasuresCardFragment on Measure {\n id\n name\n state\n}\n\nfragment RiskControlsTabFragment on Risk {\n id\n controls(first: 20) {\n edges {\n node {\n id\n sectionTitle\n name\n framework {\n id\n name\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment RiskDocumentsTabFragment on Risk {\n id\n documents(first: 100) {\n edges {\n node {\n id\n ...LinkedDocumentsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment RiskMeasuresTabFragment on Risk {\n id\n measures(first: 100) {\n edges {\n node {\n id\n ...LinkedMeasuresCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment RiskOverviewTabFragment on Risk {\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n" + "text": "query RiskGraphNodeQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n ... on Risk {\n id\n snapshotId\n name\n description\n treatment\n owner {\n id\n fullName\n }\n note\n inherentRiskScore\n residualRiskScore\n measuresInfo: measures(first: 0) {\n totalCount\n }\n documentsInfo: documents(first: 0) {\n totalCount\n }\n controlsInfo: controls(first: 0) {\n totalCount\n }\n ...useRiskFormFragment\n ...RiskOverviewTabFragment\n ...RiskMeasuresTabFragment\n ...RiskDocumentsTabFragment\n ...RiskControlsTabFragment\n }\n id\n }\n}\n\nfragment LinkedDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment LinkedMeasuresCardFragment on Measure {\n id\n name\n state\n}\n\nfragment RiskControlsTabFragment on Risk {\n id\n controls(first: 20) {\n edges {\n node {\n id\n sectionTitle\n name\n framework {\n id\n name\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment RiskDocumentsTabFragment on Risk {\n id\n documents(first: 100) {\n edges {\n node {\n id\n ...LinkedDocumentsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment RiskMeasuresTabFragment on Risk {\n id\n measures(first: 100) {\n edges {\n node {\n id\n ...LinkedMeasuresCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment RiskOverviewTabFragment on Risk {\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n note\n owner {\n id\n }\n}\n" } }; })(); diff --git a/apps/console/src/hooks/graph/__generated__/RisksListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/RisksListQuery.graphql.ts index baab98945..467763da9 100644 --- a/apps/console/src/hooks/graph/__generated__/RisksListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/RisksListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<4a0922eabd4e20c574db91e75f45a562>> + * @generated SignedSource<<29125e9f2562c96a6076ed8b0504a4b1>> * @lightSyntaxTransform * @nogrep */ @@ -11,7 +11,7 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type OrderDirection = "ASC" | "DESC"; -export type RiskOrderField = "CATEGORY" | "CREATED_AT" | "INHERENT_RISK_SCORE" | "NAME" | "RESIDUAL_RISK_SCORE" | "TREATMENT" | "UPDATED_AT"; +export type RiskOrderField = "CATEGORY" | "CREATED_AT" | "INHERENT_RISK_SCORE" | "NAME" | "OWNER_FULL_NAME" | "RESIDUAL_RISK_SCORE" | "TREATMENT" | "UPDATED_AT"; export type RiskOrder = { direction: OrderDirection; field: RiskOrderField; @@ -62,7 +62,10 @@ v4 = { "name": "last" }, v5 = { - "defaultValue": null, + "defaultValue": { + "direction": "DESC", + "field": "CREATED_AT" + }, "kind": "LocalArgument", "name": "order" }, @@ -261,6 +264,25 @@ return { "name": "treatment", "storageKey": null }, + { + "alias": null, + "args": null, + "concreteType": "People", + "kind": "LinkedField", + "name": "owner", + "plural": false, + "selections": [ + (v14/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "fullName", + "storageKey": null + } + ], + "storageKey": null + }, { "alias": null, "args": null, @@ -317,18 +339,6 @@ return { "name": "note", "storageKey": null }, - { - "alias": null, - "args": null, - "concreteType": "People", - "kind": "LinkedField", - "name": "owner", - "plural": false, - "selections": [ - (v14/*: any*/) - ], - "storageKey": null - }, (v13/*: any*/) ], "storageKey": null @@ -381,6 +391,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": null @@ -406,16 +428,16 @@ return { ] }, "params": { - "cacheID": "161eb78d1d5100120c68db5d8106aa7e", + "cacheID": "34a33dde7e4e7868a885b6b6317f506b", "id": null, "metadata": {}, "name": "RisksListQuery", "operationKind": "query", - "text": "query RisksListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: RiskOrder = null\n $snapshotId: ID = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RiskGraphFragment_25MC8O\n id\n }\n}\n\nfragment RiskGraphFragment_25MC8O on Organization {\n risks(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n category\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n ...useRiskFormFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n" + "text": "query RisksListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: RiskOrder = {direction: DESC, field: CREATED_AT}\n $snapshotId: ID = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RiskGraphFragment_25MC8O\n id\n }\n}\n\nfragment RiskGraphFragment_25MC8O on Organization {\n risks(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: {snapshotId: $snapshotId}) {\n edges {\n node {\n id\n snapshotId\n name\n category\n treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n ...useRiskFormFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n note\n owner {\n id\n }\n}\n" } }; })(); -(node as any).hash = "95c68a022cbf075eede9b7417393a369"; +(node as any).hash = "d8048ddb0ff8d4b08b7b9676d9b98f1a"; export default node; diff --git a/apps/console/src/pages/organizations/risks/FormRiskDialog.tsx b/apps/console/src/pages/organizations/risks/FormRiskDialog.tsx index ea7bdbd12..46c559854 100644 --- a/apps/console/src/pages/organizations/risks/FormRiskDialog.tsx +++ b/apps/console/src/pages/organizations/risks/FormRiskDialog.tsx @@ -41,6 +41,7 @@ type Props = { risk?: RiskKey; connection?: string; ref?: ReturnType; + onSuccess?: () => void; }; type RiskTemplate = { @@ -82,6 +83,7 @@ export default function FormRiskDialog({ risk, connection, ref: refProps, + onSuccess, }: Props) { const { __ } = useTranslate(); const organizationId = useOrganizationId(); @@ -131,6 +133,7 @@ export default function FormRiskDialog({ onSuccess: () => { ref?.current?.close(); reset(); + onSuccess?.(); }, }); }); diff --git a/apps/console/src/pages/organizations/risks/RisksPage.tsx b/apps/console/src/pages/organizations/risks/RisksPage.tsx index 1524b05e2..505ef3dd4 100644 --- a/apps/console/src/pages/organizations/risks/RisksPage.tsx +++ b/apps/console/src/pages/organizations/risks/RisksPage.tsx @@ -40,7 +40,17 @@ export default function RisksPage(props: Props) { const { snapshotId } = useParams<{ snapshotId?: string }>(); const isSnapshotMode = Boolean(snapshotId); - const { connectionId, risks, refetch } = useRisksQuery(props.queryRef, snapshotId); + const { connectionId, risks, ...pagination } = useRisksQuery(props.queryRef); + + const refetch = ({ order }: { order: { direction: string; field: string } }) => { + pagination.refetch({ + snapshotId, + order: { + direction: order.direction as "ASC" | "DESC", + field: order.field as "NAME" | "CATEGORY" | "TREATMENT" | "INHERENT_RISK_SCORE" | "RESIDUAL_RISK_SCORE" | "OWNER_FULL_NAME" | "CREATED_AT" + } + }, { fetchPolicy: 'network-only' }); + }; usePageTitle(__("Risks")); @@ -56,6 +66,9 @@ export default function RisksPage(props: Props) { {!isSnapshotMode && ( { + pagination.refetch({ snapshotId }); + }} trigger={} /> )} @@ -73,7 +86,7 @@ export default function RisksPage(props: Props) { risks={risks} /> - + {__("Risk name")} @@ -85,6 +98,9 @@ export default function RisksPage(props: Props) { {__("Residual Risk")} + + {__("Owner")} + @@ -163,6 +179,7 @@ function RiskRow(props: RowProps) { + {risk.owner?.fullName || __("Unassigned")} {!isSnapshotMode && ( diff --git a/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogMutation.graphql.ts index e313a7c08..4cf4f9081 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogMutation.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<7d5730a1c721f5256e6e0c07199aa0d2>> + * @generated SignedSource<<66f4e8603a811d1fb363ae88ea697b22>> * @lightSyntaxTransform * @nogrep */ @@ -209,6 +209,20 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "inherentRiskScore", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "residualRiskScore", + "storageKey": null + }, { "alias": null, "args": null, @@ -256,12 +270,12 @@ return { ] }, "params": { - "cacheID": "e2131409b62d6cd6bd8a6d008f2ac1f5", + "cacheID": "a6ca4767b2443f6b4d02d6fdd1358600", "id": null, "metadata": {}, "name": "FormRiskDialogMutation", "operationKind": "mutation", - "text": "mutation FormRiskDialogMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n ...useRiskFormFragment\n id\n }\n }\n }\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n" + "text": "mutation FormRiskDialogMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n ...useRiskFormFragment\n id\n }\n }\n }\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n note\n owner {\n id\n }\n}\n" } }; })(); diff --git a/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogUpdateRiskMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogUpdateRiskMutation.graphql.ts index ff47596f8..d3f376e23 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogUpdateRiskMutation.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/FormRiskDialogUpdateRiskMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<4122b3e15107bc0f2c5f8b842b882603>> * @lightSyntaxTransform * @nogrep */ @@ -178,6 +178,20 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "inherentRiskScore", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "residualRiskScore", + "storageKey": null + }, { "alias": null, "args": null, @@ -206,12 +220,12 @@ return { ] }, "params": { - "cacheID": "546b1e60a2e87bf71a1851ca76485767", + "cacheID": "59f586a59973ca023df027fdfb0d4bed", "id": null, "metadata": {}, "name": "FormRiskDialogUpdateRiskMutation", "operationKind": "mutation", - "text": "mutation FormRiskDialogUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n ...useRiskFormFragment\n id\n }\n }\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n" + "text": "mutation FormRiskDialogUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n ...useRiskFormFragment\n id\n }\n }\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n inherentRiskScore\n residualRiskScore\n note\n owner {\n id\n }\n}\n" } }; })(); diff --git a/pkg/coredata/risk.go b/pkg/coredata/risk.go index 0114f58e2..aae77790f 100644 --- a/pkg/coredata/risk.go +++ b/pkg/coredata/risk.go @@ -46,6 +46,9 @@ type ( SourceID *gid.GID `db:"source_id"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` + + // Ordering only + OwnerFullName *string `db:"owner_full_name"` } Risks []*Risk @@ -69,6 +72,8 @@ func (r *Risk) CursorKey(orderBy RiskOrderField) page.CursorKey { return page.CursorKey{ID: r.ID, Value: r.InherentRiskScore} case RiskOrderFieldResidualRiskScore: return page.CursorKey{ID: r.ID, Value: r.ResidualRiskScore} + case RiskOrderFieldOwnerFullName: + return page.CursorKey{ID: r.ID, Value: r.OwnerFullName} } panic(fmt.Sprintf("unsupported order by: %s", orderBy)) @@ -136,6 +141,7 @@ WITH rsks AS ( r.description, r.category, r.owner_id, + p.full_name as owner_full_name, r.treatment, r.note, r.inherent_likelihood, @@ -153,6 +159,8 @@ WITH rsks AS ( risks r INNER JOIN risks_measures rm ON r.id = rm.risk_id + LEFT JOIN + peoples p ON r.owner_id = p.id WHERE rm.measure_id = @measure_id ) @@ -163,6 +171,7 @@ SELECT description, category, owner_id, + owner_full_name, treatment, note, inherent_likelihood, @@ -243,12 +252,43 @@ func (r *Risks) LoadByOrganizationID( filter *RiskFilter, ) error { q := ` +WITH rsks AS ( + SELECT + r.id, + r.tenant_id, + r.organization_id, + r.name, + r.description, + r.owner_id, + p.full_name as owner_full_name, + r.treatment, + r.note, + r.inherent_likelihood, + r.inherent_impact, + r.inherent_risk_score, + r.residual_likelihood, + r.residual_impact, + r.residual_risk_score, + r.category, + r.snapshot_id, + r.source_id, + r.search_vector, + r.created_at, + r.updated_at + FROM + risks r + LEFT JOIN + peoples p ON r.owner_id = p.id + WHERE + r.organization_id = @organization_id +) SELECT id, organization_id, name, description, owner_id, + owner_full_name, treatment, note, inherent_likelihood, @@ -262,9 +302,9 @@ SELECT source_id, created_at, updated_at -FROM risks +FROM + rsks WHERE %s - AND organization_id = @organization_id AND %s AND %s ` @@ -304,6 +344,7 @@ SELECT description, category, owner_id, + NULL as owner_full_name, treatment, note, inherent_likelihood, diff --git a/pkg/coredata/risk_order_field.go b/pkg/coredata/risk_order_field.go index 3bb5f5427..ddf0beed2 100644 --- a/pkg/coredata/risk_order_field.go +++ b/pkg/coredata/risk_order_field.go @@ -26,6 +26,7 @@ const ( RiskOrderFieldTreatment RiskOrderField = "TREATMENT" RiskOrderFieldInherentRiskScore RiskOrderField = "INHERENT_RISK_SCORE" RiskOrderFieldResidualRiskScore RiskOrderField = "RESIDUAL_RISK_SCORE" + RiskOrderFieldOwnerFullName RiskOrderField = "OWNER_FULL_NAME" ) func (p RiskOrderField) Column() string { diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 37c233985..4fe770a17 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -431,6 +431,10 @@ enum RiskOrderField @goEnum( value: "github.com/getprobo/probo/pkg/coredata.RiskOrderFieldResidualRiskScore" ) + OWNER_FULL_NAME + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskOrderFieldOwnerFullName" + ) } enum EvidenceOrderField diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 1b4b315bc..1636bfe63 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -8564,6 +8564,10 @@ enum RiskOrderField @goEnum( value: "github.com/getprobo/probo/pkg/coredata.RiskOrderFieldResidualRiskScore" ) + OWNER_FULL_NAME + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskOrderFieldOwnerFullName" + ) } enum EvidenceOrderField @@ -88188,6 +88192,7 @@ var ( "TREATMENT": coredata.RiskOrderFieldTreatment, "INHERENT_RISK_SCORE": coredata.RiskOrderFieldInherentRiskScore, "RESIDUAL_RISK_SCORE": coredata.RiskOrderFieldResidualRiskScore, + "OWNER_FULL_NAME": coredata.RiskOrderFieldOwnerFullName, } marshalNRiskOrderField2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskOrderField = map[coredata.RiskOrderField]string{ coredata.RiskOrderFieldCreatedAt: "CREATED_AT", @@ -88197,6 +88202,7 @@ var ( coredata.RiskOrderFieldTreatment: "TREATMENT", coredata.RiskOrderFieldInherentRiskScore: "INHERENT_RISK_SCORE", coredata.RiskOrderFieldResidualRiskScore: "RESIDUAL_RISK_SCORE", + coredata.RiskOrderFieldOwnerFullName: "OWNER_FULL_NAME", } )