29
apps/console/src/components/ui/switch.tsx
Normal file
29
apps/console/src/components/ui/switch.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Switch = React.forwardRef<
|
||||
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SwitchPrimitives.Root
|
||||
className={cn(
|
||||
"peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
<SwitchPrimitives.Thumb
|
||||
className={cn(
|
||||
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitives.Root>
|
||||
));
|
||||
Switch.displayName = SwitchPrimitives.Root.displayName;
|
||||
|
||||
export { Switch };
|
||||
@@ -18,6 +18,7 @@ import { OrganizationBreadcrumbBreadcrumbVendorOverviewQuery } from "./__generat
|
||||
import { OrganizationBreadcrumbOrganizationQuery } from "./__generated__/OrganizationBreadcrumbOrganizationQuery.graphql";
|
||||
import { OrganizationBreadcrumbBreadcrumbMitigationViewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbMitigationViewQuery.graphql";
|
||||
import { OrganizationBreadcrumbBreadcrumbControlQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbControlQuery.graphql";
|
||||
import { OrganizationBreadcrumbBreadcrumbRiskShowQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbRiskShowQuery.graphql";
|
||||
import ErrorBoundary from "@/components/ErrorBoundary";
|
||||
|
||||
const New = () => {
|
||||
@@ -418,6 +419,38 @@ function BreadcrumbRiskList() {
|
||||
);
|
||||
}
|
||||
|
||||
function BreadcrumbRiskShow() {
|
||||
const { organizationId, riskId } = useParams();
|
||||
const data = useLazyLoadQuery<OrganizationBreadcrumbBreadcrumbRiskShowQuery>(
|
||||
graphql`
|
||||
query OrganizationBreadcrumbBreadcrumbRiskShowQuery($riskId: ID!) {
|
||||
risk: node(id: $riskId) {
|
||||
id
|
||||
... on Risk {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ riskId: riskId! },
|
||||
{ fetchPolicy: "store-or-network" }
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbNavLink
|
||||
to={`/organizations/${organizationId}/risks/${riskId}`}
|
||||
>
|
||||
{data.risk?.name}
|
||||
</BreadcrumbNavLink>
|
||||
</BreadcrumbItem>
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function BreadCrumb() {
|
||||
return (
|
||||
<Routes>
|
||||
@@ -445,6 +478,16 @@ export function BreadCrumb() {
|
||||
</Route>
|
||||
<Route path="risks" element={<BreadcrumbRiskList />}>
|
||||
<Route path="new" element={<New />} />
|
||||
<Route
|
||||
path=":riskId"
|
||||
element={
|
||||
<Suspense>
|
||||
<BreadcrumbRiskShow />
|
||||
</Suspense>
|
||||
}
|
||||
>
|
||||
<Route path="edit" element={<Edit />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="frameworks" element={<BreadcrumbFrameworkList />}>
|
||||
<Route
|
||||
|
||||
@@ -22,6 +22,7 @@ import { EditPolicyPage } from "./policies/EditPolicyPage";
|
||||
import { NewPolicyPage } from "./policies/NewPolicyPage";
|
||||
import { PolicyListPage } from "./policies/PolicyListPage";
|
||||
import { PolicyPage } from "./policies/PolicyPage";
|
||||
import { EditRiskPage } from "./risks/EditRiskPage";
|
||||
import { NewRiskPage } from "./risks/NewRiskPage";
|
||||
import { RiskListPage } from "./risks/RiskListPage";
|
||||
import ShowRiskView from "./risks/ShowRiskView";
|
||||
@@ -62,6 +63,7 @@ export function OrganizationsRoutes() {
|
||||
<Route path="risks" element={<RiskListPage />} />
|
||||
<Route path="risks/new" element={<NewRiskPage />} />
|
||||
<Route path="risks/:riskId" element={<ShowRiskView />} />
|
||||
<Route path="risks/:riskId/edit" element={<EditRiskPage />} />
|
||||
<Route path="settings" element={<SettingsPage />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Route>
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @generated SignedSource<<6cc6ac4101b94ac06f94f04368fbaa6d>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type OrganizationBreadcrumbBreadcrumbRiskShowQuery$variables = {
|
||||
riskId: string;
|
||||
};
|
||||
export type OrganizationBreadcrumbBreadcrumbRiskShowQuery$data = {
|
||||
readonly risk: {
|
||||
readonly id: string;
|
||||
readonly name?: string;
|
||||
};
|
||||
};
|
||||
export type OrganizationBreadcrumbBreadcrumbRiskShowQuery = {
|
||||
response: OrganizationBreadcrumbBreadcrumbRiskShowQuery$data;
|
||||
variables: OrganizationBreadcrumbBreadcrumbRiskShowQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "riskId"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "riskId"
|
||||
}
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Risk",
|
||||
"abstractKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "OrganizationBreadcrumbBreadcrumbRiskShowQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "risk",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "OrganizationBreadcrumbBreadcrumbRiskShowQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "risk",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "eaafff390efc7cb4b97300fa65d98c99",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "OrganizationBreadcrumbBreadcrumbRiskShowQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query OrganizationBreadcrumbBreadcrumbRiskShowQuery(\n $riskId: ID!\n) {\n risk: node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "3f83f754047443e38a51bd8d2351f81c";
|
||||
|
||||
export default node;
|
||||
@@ -16,6 +16,8 @@ import {
|
||||
CheckCircle2,
|
||||
Clock,
|
||||
X,
|
||||
HelpCircle,
|
||||
ExternalLink,
|
||||
} from "lucide-react";
|
||||
import { PageTemplate } from "@/components/PageTemplate";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -24,6 +26,17 @@ import { MitigationListViewSkeleton } from "./MitigationListPage";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { MitigationListViewImportMitigationMutation as MitigationListViewImportMitigationMutationType } from "./__generated__/MitigationListViewImportMitigationMutation.graphql";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
|
||||
const mitigationListViewQuery = graphql`
|
||||
query MitigationListViewQuery($organizationId: ID!, $first: Int) {
|
||||
@@ -543,12 +556,113 @@ function MitigationListContent({
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3 align-middle">
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
|
||||
className="font-medium block"
|
||||
>
|
||||
{mitigation.name}
|
||||
</Link>
|
||||
<div className="flex items-center gap-3">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
|
||||
className="font-medium group flex items-center relative"
|
||||
>
|
||||
<span className="mr-1">
|
||||
{mitigation.name}
|
||||
</span>
|
||||
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-primary-bg scale-x-0 group-hover:scale-x-100 transition-transform"></span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">
|
||||
<p className="text-xs">
|
||||
Click to view details
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
{/* Enhanced popover for description info */}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="p-0 h-6 w-6 rounded-full hover:bg-primary-bg"
|
||||
aria-label="Learn more about this mitigation"
|
||||
>
|
||||
<HelpCircle className="h-5 w-5 text-primary hover:text-primary" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="w-80 p-4 shadow-md"
|
||||
align="start"
|
||||
sideOffset={5}
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between items-start">
|
||||
<h4 className="font-bold text-md">
|
||||
{mitigation.name}
|
||||
</h4>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-xs"
|
||||
>
|
||||
{mitigation.importance}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{mitigation.description && (
|
||||
<div className="text-sm">
|
||||
<p className="font-semibold mb-1">
|
||||
Why is this important:
|
||||
</p>
|
||||
<p>
|
||||
{mitigation.description.startsWith(
|
||||
"##"
|
||||
)
|
||||
? mitigation.description
|
||||
.split("\n")
|
||||
.find((line) =>
|
||||
line.startsWith(
|
||||
"## Why"
|
||||
)
|
||||
)
|
||||
?.replace("## Why?", "")
|
||||
?.replace("## Why", "")
|
||||
?.trim() ||
|
||||
mitigation.description.split(
|
||||
"\n"
|
||||
)[1] ||
|
||||
""
|
||||
: mitigation.description.substring(
|
||||
0,
|
||||
180
|
||||
) +
|
||||
(mitigation.description
|
||||
.length > 180
|
||||
? "..."
|
||||
: "")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="pt-2 flex justify-end">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-xs gap-1"
|
||||
asChild
|
||||
>
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
|
||||
>
|
||||
<span>
|
||||
Implementation guide
|
||||
</span>
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
@@ -449,8 +449,8 @@ const mitigationRisksQuery = graphql`
|
||||
id
|
||||
name
|
||||
description
|
||||
probability
|
||||
impact
|
||||
inherentLikelihood
|
||||
inherentImpact
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
@@ -491,8 +491,9 @@ type RiskNode = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
probability: number;
|
||||
likelihood: number;
|
||||
impact: number;
|
||||
severity: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
@@ -1846,12 +1847,7 @@ function MitigationViewContent({
|
||||
}, [controlSearchQuery, getControls]);
|
||||
|
||||
// Helper function to get risk severity color
|
||||
const getRiskSeverityColor = (
|
||||
probability: number,
|
||||
impact: number
|
||||
): string => {
|
||||
const severity = probability * impact;
|
||||
|
||||
const getRiskSeverityColor = (severity: number): string => {
|
||||
if (severity >= 0.75) return "bg-red-100 text-red-800";
|
||||
if (severity >= 0.5) return "bg-orange-100 text-orange-800";
|
||||
if (severity >= 0.25) return "bg-yellow-100 text-yellow-800";
|
||||
@@ -1859,17 +1855,15 @@ function MitigationViewContent({
|
||||
};
|
||||
|
||||
// Helper function to get risk severity text
|
||||
const getRiskSeverityText = (probability: number, impact: number): string => {
|
||||
const severity = probability * impact;
|
||||
|
||||
const getRiskSeverityText = (severity: number): string => {
|
||||
if (severity >= 0.75) return "Critical";
|
||||
if (severity >= 0.5) return "High";
|
||||
if (severity >= 0.25) return "Medium";
|
||||
return "Low";
|
||||
};
|
||||
|
||||
// Format probability as text
|
||||
const formatProbability = (value: number): string => {
|
||||
// Format likelihood as text
|
||||
const formatlikelihood = (value: number): string => {
|
||||
if (value <= 0.1) return "Very Low";
|
||||
if (value <= 0.3) return "Low";
|
||||
if (value <= 0.5) return "Medium";
|
||||
@@ -2825,7 +2819,7 @@ function MitigationViewContent({
|
||||
Risk Name
|
||||
</th>
|
||||
<th className="text-left font-medium text-sm py-2 px-4">
|
||||
Probability
|
||||
likelihood
|
||||
</th>
|
||||
<th className="text-left font-medium text-sm py-2 px-4">
|
||||
Impact
|
||||
@@ -2852,7 +2846,7 @@ function MitigationViewContent({
|
||||
</td>
|
||||
<td className="py-3 px-4">
|
||||
<div className="bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full text-xs inline-block">
|
||||
{formatProbability(node.probability)}
|
||||
{formatlikelihood(node.likelihood)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="py-3 px-4">
|
||||
@@ -2863,14 +2857,10 @@ function MitigationViewContent({
|
||||
<td className="py-3 px-4">
|
||||
<div
|
||||
className={`${getRiskSeverityColor(
|
||||
node.probability,
|
||||
node.impact
|
||||
node.severity
|
||||
)} px-2 py-0.5 rounded-full text-xs inline-block`}
|
||||
>
|
||||
{getRiskSeverityText(
|
||||
node.probability,
|
||||
node.impact
|
||||
)}
|
||||
{getRiskSeverityText(node.severity)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<7ecc796e34bf88aa378e81249110be90>>
|
||||
* @generated SignedSource<<b7154e691d26fef3b8f64ec3a39304fd>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -21,9 +21,9 @@ export type MitigationViewRisksQuery$data = {
|
||||
readonly createdAt: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly impact: number;
|
||||
readonly inherentImpact: number;
|
||||
readonly inherentLikelihood: number;
|
||||
readonly name: string;
|
||||
readonly probability: number;
|
||||
readonly updatedAt: string;
|
||||
};
|
||||
}>;
|
||||
@@ -100,14 +100,14 @@ v4 = [
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -259,7 +259,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "61c985f00c12fb3cdab3e345a8c65957",
|
||||
"cacheID": "6e8982bef70e90ee745d6985c82c597e",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -276,11 +276,11 @@ return {
|
||||
},
|
||||
"name": "MitigationViewRisksQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query MitigationViewRisksQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n risks(first: 100) {\n edges {\n node {\n id\n name\n description\n probability\n impact\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
"text": "query MitigationViewRisksQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n risks(first: 100) {\n edges {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "e05802ec519933edce3d0f3487742e3d";
|
||||
(node as any).hash = "0fe825c558627da60c1025efa825f91e";
|
||||
|
||||
export default node;
|
||||
|
||||
61
apps/console/src/pages/organizations/risks/EditRiskPage.tsx
Normal file
61
apps/console/src/pages/organizations/risks/EditRiskPage.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Suspense } from "react";
|
||||
import { useLocation } from "react-router";
|
||||
import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { PageTemplate } from "@/components/PageTemplate";
|
||||
import { EditRiskView } from "./EditRiskView";
|
||||
|
||||
// We'll import this once we create it
|
||||
// import { EditRiskView } from "./EditRiskView";
|
||||
|
||||
export function EditRiskViewSkeleton() {
|
||||
return (
|
||||
<PageTemplate title="Edit Risk">
|
||||
<Card className="max-w-2xl">
|
||||
<CardHeader>
|
||||
<Skeleton className="h-8 w-64" />
|
||||
<Skeleton className="h-4 w-96 mt-2" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-20" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-24" />
|
||||
<Skeleton className="h-24 w-full" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-20" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-20" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end gap-3">
|
||||
<Skeleton className="h-10 w-24" />
|
||||
<Skeleton className="h-10 w-24" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</PageTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
export function EditRiskPage() {
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<Suspense key={location.pathname} fallback={<EditRiskViewSkeleton />}>
|
||||
<ErrorBoundaryWithLocation>
|
||||
<EditRiskView />
|
||||
</ErrorBoundaryWithLocation>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditRiskPage;
|
||||
404
apps/console/src/pages/organizations/risks/EditRiskView.tsx
Normal file
404
apps/console/src/pages/organizations/risks/EditRiskView.tsx
Normal file
@@ -0,0 +1,404 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import {
|
||||
graphql,
|
||||
useMutation,
|
||||
usePreloadedQuery,
|
||||
useQueryLoader,
|
||||
PreloadedQuery,
|
||||
} from "react-relay";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
} from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { PageTemplate } from "@/components/PageTemplate";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Suspense } from "react";
|
||||
import { EditRiskViewSkeleton } from "./EditRiskPage";
|
||||
import type { EditRiskViewQuery } from "./__generated__/EditRiskViewQuery.graphql";
|
||||
import type { EditRiskViewUpdateRiskMutation } from "./__generated__/EditRiskViewUpdateRiskMutation.graphql";
|
||||
|
||||
// Query to get risk details
|
||||
const editRiskViewQuery = graphql`
|
||||
query EditRiskViewQuery($riskId: ID!) {
|
||||
risk: node(id: $riskId) {
|
||||
... on Risk {
|
||||
id
|
||||
name
|
||||
description
|
||||
inherentLikelihood
|
||||
inherentImpact
|
||||
residualLikelihood
|
||||
residualImpact
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Mutation to update risk
|
||||
const updateRiskMutation = graphql`
|
||||
mutation EditRiskViewUpdateRiskMutation($input: UpdateRiskInput!) {
|
||||
updateRisk(input: $input) {
|
||||
risk {
|
||||
id
|
||||
name
|
||||
description
|
||||
inherentLikelihood
|
||||
inherentImpact
|
||||
residualLikelihood
|
||||
residualImpact
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Component to handle the actual editing once data is loaded
|
||||
function EditRiskViewContent({
|
||||
queryRef,
|
||||
}: {
|
||||
queryRef: PreloadedQuery<EditRiskViewQuery>;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const { organizationId, riskId } = useParams<{
|
||||
organizationId: string;
|
||||
riskId: string;
|
||||
}>();
|
||||
const { toast } = useToast();
|
||||
|
||||
const data = usePreloadedQuery(editRiskViewQuery, queryRef);
|
||||
const risk = data.risk;
|
||||
|
||||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [inherentLikelihood, setInherentLikelihood] =
|
||||
useState<string>("MEDIUM");
|
||||
const [inherentImpact, setInherentImpact] = useState<string>("MEDIUM");
|
||||
const [residualLikelihood, setResidualLikelihood] =
|
||||
useState<string>("MEDIUM");
|
||||
const [residualImpact, setResidualImpact] = useState<string>("MEDIUM");
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const [updateRisk, isInFlight] =
|
||||
useMutation<EditRiskViewUpdateRiskMutation>(updateRiskMutation);
|
||||
|
||||
// Helper function to convert float to likelihood string
|
||||
const floatToLikelihood = (value: number): string => {
|
||||
if (value <= 0.2) return "VERY_LOW";
|
||||
if (value <= 0.4) return "LOW";
|
||||
if (value <= 0.6) return "MEDIUM";
|
||||
if (value <= 0.8) return "HIGH";
|
||||
return "VERY_HIGH";
|
||||
};
|
||||
|
||||
// Helper function to convert float to impact string
|
||||
const floatToImpact = (value: number): string => {
|
||||
if (value <= 0.2) return "VERY_LOW";
|
||||
if (value <= 0.4) return "LOW";
|
||||
if (value <= 0.6) return "MEDIUM";
|
||||
if (value <= 0.8) return "HIGH";
|
||||
return "VERY_HIGH";
|
||||
};
|
||||
|
||||
// Map string values to float values
|
||||
const likelihoodToFloat = (value: string): number => {
|
||||
switch (value) {
|
||||
case "VERY_LOW":
|
||||
return 0.1;
|
||||
case "LOW":
|
||||
return 0.3;
|
||||
case "MEDIUM":
|
||||
return 0.5;
|
||||
case "HIGH":
|
||||
return 0.7;
|
||||
case "VERY_HIGH":
|
||||
return 0.9;
|
||||
default:
|
||||
return 0.5;
|
||||
}
|
||||
};
|
||||
|
||||
const impactToFloat = (value: string): number => {
|
||||
switch (value) {
|
||||
case "VERY_LOW":
|
||||
return 0.1;
|
||||
case "LOW":
|
||||
return 0.3;
|
||||
case "MEDIUM":
|
||||
return 0.5;
|
||||
case "HIGH":
|
||||
return 0.7;
|
||||
case "VERY_HIGH":
|
||||
return 0.9;
|
||||
default:
|
||||
return 0.5;
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize form with risk data
|
||||
useEffect(() => {
|
||||
if (risk) {
|
||||
setName(risk.name || "");
|
||||
setDescription(risk.description || "");
|
||||
setInherentLikelihood(floatToLikelihood(risk.inherentLikelihood || 0.5));
|
||||
setInherentImpact(floatToImpact(risk.inherentImpact || 0.5));
|
||||
setResidualLikelihood(floatToLikelihood(risk.residualLikelihood || 0.5));
|
||||
setResidualImpact(floatToImpact(risk.residualImpact || 0.5));
|
||||
}
|
||||
}, [risk]);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!name.trim()) {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Please enter a name for the risk.",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
const input = {
|
||||
id: riskId!,
|
||||
name,
|
||||
description,
|
||||
inherentLikelihood: likelihoodToFloat(inherentLikelihood),
|
||||
inherentImpact: impactToFloat(inherentImpact),
|
||||
residualLikelihood: likelihoodToFloat(residualLikelihood),
|
||||
residualImpact: impactToFloat(residualImpact),
|
||||
};
|
||||
|
||||
updateRisk({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
onCompleted: (response, errors) => {
|
||||
setIsSubmitting(false);
|
||||
if (errors) {
|
||||
console.error("Error updating risk:", errors);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to update risk. Please try again.",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
toast({
|
||||
title: "Success",
|
||||
description: "Risk updated successfully!",
|
||||
});
|
||||
|
||||
navigate(`/organizations/${organizationId}/risks/${riskId}`);
|
||||
},
|
||||
onError: (error) => {
|
||||
setIsSubmitting(false);
|
||||
console.error("Error updating risk:", error);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to update risk. Please try again.",
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PageTemplate
|
||||
title="Edit Risk"
|
||||
description="Update the details of this risk"
|
||||
>
|
||||
<Card className="max-w-2xl">
|
||||
<CardHeader>
|
||||
<CardTitle>Risk Details</CardTitle>
|
||||
<CardDescription>Update the details of this risk</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input
|
||||
id="name"
|
||||
placeholder="Risk name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description">Description</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
placeholder="Describe the risk in detail"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
rows={5}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-medium mb-2">
|
||||
Initial Risk Assessment
|
||||
</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="inherentLikelihood">
|
||||
Inherent Likelihood
|
||||
</Label>
|
||||
<Select
|
||||
value={inherentLikelihood}
|
||||
onValueChange={setInherentLikelihood}
|
||||
>
|
||||
<SelectTrigger id="inherentLikelihood">
|
||||
<SelectValue placeholder="Select likelihood" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="inherentImpact">Inherent Impact</Label>
|
||||
<Select
|
||||
value={inherentImpact}
|
||||
onValueChange={setInherentImpact}
|
||||
>
|
||||
<SelectTrigger id="inherentImpact">
|
||||
<SelectValue placeholder="Select impact" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-medium mb-2">Residual Risk</h3>
|
||||
<p className="text-sm text-tertiary mb-4">
|
||||
Estimate the risk after treatment measures have been applied
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="residualLikelihood">
|
||||
Residual Likelihood
|
||||
</Label>
|
||||
<Select
|
||||
value={residualLikelihood}
|
||||
onValueChange={setResidualLikelihood}
|
||||
>
|
||||
<SelectTrigger id="residualLikelihood">
|
||||
<SelectValue placeholder="Select residual likelihood" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="residualImpact">Residual Impact</Label>
|
||||
<Select
|
||||
value={residualImpact}
|
||||
onValueChange={setResidualImpact}
|
||||
>
|
||||
<SelectTrigger id="residualImpact">
|
||||
<SelectValue placeholder="Select residual impact" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
navigate(`/organizations/${organizationId}/risks/${riskId}`)
|
||||
}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit" disabled={isInFlight || isSubmitting}>
|
||||
{isInFlight || isSubmitting ? "Updating..." : "Update Risk"}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</PageTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
// Main component that loads the query
|
||||
export function EditRiskView() {
|
||||
const { riskId } = useParams<{ riskId: string }>();
|
||||
const [queryRef, loadQuery] =
|
||||
useQueryLoader<EditRiskViewQuery>(editRiskViewQuery);
|
||||
|
||||
useEffect(() => {
|
||||
if (riskId) {
|
||||
loadQuery({ riskId });
|
||||
}
|
||||
}, [loadQuery, riskId]);
|
||||
|
||||
if (!queryRef) {
|
||||
return <EditRiskViewSkeleton />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense fallback={<EditRiskViewSkeleton />}>
|
||||
<EditRiskViewContent queryRef={queryRef} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditRiskView;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { ConnectionHandler, graphql, useMutation } from "react-relay";
|
||||
import {
|
||||
@@ -21,74 +21,18 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
||||
// Risk template library - static definitions of common risks
|
||||
const riskTemplates = [
|
||||
{
|
||||
id: "data-breach",
|
||||
name: "Data Breach",
|
||||
description:
|
||||
"Unauthorized access to sensitive data resulting in data disclosure, theft, or corruption.",
|
||||
probability: "HIGH",
|
||||
impact: "HIGH",
|
||||
},
|
||||
{
|
||||
id: "service-outage",
|
||||
name: "Service Outage",
|
||||
description:
|
||||
"System downtime or degradation affecting availability of services to customers.",
|
||||
probability: "MEDIUM",
|
||||
impact: "HIGH",
|
||||
},
|
||||
{
|
||||
id: "compliance-violation",
|
||||
name: "Compliance Violation",
|
||||
description:
|
||||
"Failure to meet regulatory requirements resulting in penalties or legal action.",
|
||||
probability: "MEDIUM",
|
||||
impact: "VERY_HIGH",
|
||||
},
|
||||
{
|
||||
id: "insider-threat",
|
||||
name: "Insider Threat",
|
||||
description:
|
||||
"Malicious actions by employees or contractors with privileged access to systems or data.",
|
||||
probability: "LOW",
|
||||
impact: "HIGH",
|
||||
},
|
||||
{
|
||||
id: "third-party-risk",
|
||||
name: "Third-Party Risk",
|
||||
description:
|
||||
"Vulnerabilities introduced through vendors, suppliers, or partners with access to systems or data.",
|
||||
probability: "MEDIUM",
|
||||
impact: "MEDIUM",
|
||||
},
|
||||
{
|
||||
id: "ransomware",
|
||||
name: "Ransomware Attack",
|
||||
description:
|
||||
"Malware that encrypts data and demands payment for decryption keys.",
|
||||
probability: "MEDIUM",
|
||||
impact: "VERY_HIGH",
|
||||
},
|
||||
{
|
||||
id: "ddos",
|
||||
name: "DDoS Attack",
|
||||
description:
|
||||
"Distributed denial of service attack overwhelming systems and preventing legitimate access.",
|
||||
probability: "MEDIUM",
|
||||
impact: "HIGH",
|
||||
},
|
||||
{
|
||||
id: "credential-compromise",
|
||||
name: "Credential Compromise",
|
||||
description:
|
||||
"Unauthorized access to accounts due to weak, stolen, or improperly secured credentials.",
|
||||
probability: "HIGH",
|
||||
impact: "HIGH",
|
||||
},
|
||||
];
|
||||
interface RiskTemplate {
|
||||
name: string;
|
||||
description: string;
|
||||
variations: {
|
||||
context: string;
|
||||
impact: number;
|
||||
likelihood: number;
|
||||
recommendedTreatment: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
const createRiskMutation = graphql`
|
||||
mutation NewRiskViewCreateRiskMutation(
|
||||
@@ -101,8 +45,10 @@ const createRiskMutation = graphql`
|
||||
id
|
||||
name
|
||||
description
|
||||
probability
|
||||
impact
|
||||
inherentLikelihood
|
||||
inherentImpact
|
||||
residualLikelihood
|
||||
residualImpact
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
@@ -116,16 +62,40 @@ export default function NewRiskView() {
|
||||
const { organizationId } = useParams<{ organizationId: string }>();
|
||||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [probability, setProbability] = useState<string>("MEDIUM");
|
||||
const [impact, setImpact] = useState<string>("MEDIUM");
|
||||
const [inherentLikelihood, setinherentLikelihood] =
|
||||
useState<string>("MEDIUM");
|
||||
const [inherentImpact, setinherentImpact] = useState<string>("MEDIUM");
|
||||
const [residualLikelihood, setResidualLikelihood] =
|
||||
useState<string>("MEDIUM");
|
||||
const [residualImpact, setResidualImpact] = useState<string>("MEDIUM");
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<string>("");
|
||||
const [riskTemplates, setRiskTemplates] = useState<RiskTemplate[]>([]);
|
||||
const { toast } = useToast();
|
||||
|
||||
const [commitMutation, isInFlight] = useMutation(createRiskMutation);
|
||||
const [createRisk, isInFlight] = useMutation(createRiskMutation);
|
||||
|
||||
useEffect(() => {
|
||||
const loadRiskTemplates = async () => {
|
||||
try {
|
||||
const response = await fetch("/data/risks/risks.json");
|
||||
const data = await response.json();
|
||||
setRiskTemplates(data);
|
||||
} catch (error) {
|
||||
console.error("Error loading risk templates:", error);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to load risk templates. Please try again.",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loadRiskTemplates();
|
||||
}, [toast]);
|
||||
|
||||
// Map string values to float values
|
||||
const probabilityToFloat = (value: string): number => {
|
||||
const likelihoodToFloat = (value: string): number => {
|
||||
switch (value) {
|
||||
case "VERY_LOW":
|
||||
return 0.1;
|
||||
@@ -167,20 +137,48 @@ export default function NewRiskView() {
|
||||
// Clear form if "Select a template" is chosen
|
||||
setName("");
|
||||
setDescription("");
|
||||
setProbability("MEDIUM");
|
||||
setImpact("MEDIUM");
|
||||
setinherentLikelihood("MEDIUM");
|
||||
setinherentImpact("MEDIUM");
|
||||
setResidualLikelihood("MEDIUM");
|
||||
setResidualImpact("MEDIUM");
|
||||
return;
|
||||
}
|
||||
|
||||
const template = riskTemplates.find((t) => t.id === templateId);
|
||||
const template = riskTemplates[parseInt(templateId)];
|
||||
if (template) {
|
||||
setName(template.name);
|
||||
setDescription(template.description);
|
||||
setProbability(template.probability);
|
||||
setImpact(template.impact);
|
||||
// Convert numeric values to string values for the select components
|
||||
const likelihoodValue = floatTolikelihood(
|
||||
template.variations[0].likelihood
|
||||
);
|
||||
const impactValue = floatToImpact(template.variations[0].impact);
|
||||
setinherentLikelihood(likelihoodValue);
|
||||
setinherentImpact(impactValue);
|
||||
// Set residual values to be the same as initial values by default
|
||||
setResidualLikelihood(likelihoodValue);
|
||||
setResidualImpact(impactValue);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to convert float likelihood to string
|
||||
const floatTolikelihood = (value: number): string => {
|
||||
if (value <= 0.2) return "VERY_LOW";
|
||||
if (value <= 0.4) return "LOW";
|
||||
if (value <= 0.6) return "MEDIUM";
|
||||
if (value <= 0.8) return "HIGH";
|
||||
return "VERY_HIGH";
|
||||
};
|
||||
|
||||
// Helper function to convert float impact to string
|
||||
const floatToImpact = (value: number): string => {
|
||||
if (value <= 0.2) return "VERY_LOW";
|
||||
if (value <= 0.4) return "LOW";
|
||||
if (value <= 0.6) return "MEDIUM";
|
||||
if (value <= 0.8) return "HIGH";
|
||||
return "VERY_HIGH";
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -199,11 +197,13 @@ export default function NewRiskView() {
|
||||
organizationId: organizationId!,
|
||||
name,
|
||||
description,
|
||||
probability: probabilityToFloat(probability),
|
||||
impact: impactToFloat(impact),
|
||||
inherentLikelihood: likelihoodToFloat(inherentLikelihood),
|
||||
inherentImpact: impactToFloat(inherentImpact),
|
||||
residualLikelihood: likelihoodToFloat(residualLikelihood),
|
||||
residualImpact: impactToFloat(residualImpact),
|
||||
};
|
||||
|
||||
commitMutation({
|
||||
createRisk({
|
||||
variables: {
|
||||
input,
|
||||
connections: [
|
||||
@@ -268,10 +268,10 @@ export default function NewRiskView() {
|
||||
<SelectTrigger id="template">
|
||||
<SelectValue placeholder="Select a risk template" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="none">Select a template</SelectItem>
|
||||
{riskTemplates.map((template) => (
|
||||
<SelectItem key={template.id} value={template.id}>
|
||||
{riskTemplates.map((template, index) => (
|
||||
<SelectItem key={index} value={index.toString()}>
|
||||
{template.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
@@ -306,12 +306,15 @@ export default function NewRiskView() {
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="probability">Probability</Label>
|
||||
<Select value={probability} onValueChange={setProbability}>
|
||||
<SelectTrigger id="probability">
|
||||
<SelectValue placeholder="Select probability" />
|
||||
<Label htmlFor="inherentLikelihood">Initial Likelihood</Label>
|
||||
<Select
|
||||
value={inherentLikelihood}
|
||||
onValueChange={setinherentLikelihood}
|
||||
>
|
||||
<SelectTrigger id="inherentLikelihood">
|
||||
<SelectValue placeholder="Select inherentLikelihood" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
@@ -322,12 +325,15 @@ export default function NewRiskView() {
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="impact">Impact</Label>
|
||||
<Select value={impact} onValueChange={setImpact}>
|
||||
<SelectTrigger id="impact">
|
||||
<SelectValue placeholder="Select impact" />
|
||||
<Label htmlFor="inherentImpact">Initial Impact</Label>
|
||||
<Select
|
||||
value={inherentImpact}
|
||||
onValueChange={setinherentImpact}
|
||||
>
|
||||
<SelectTrigger id="inherentImpact">
|
||||
<SelectValue placeholder="Select inherentImpact" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
@@ -338,6 +344,57 @@ export default function NewRiskView() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator className="my-4" />
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-medium mb-2">Residual Risk</h3>
|
||||
<p className="text-sm text-tertiary mb-4">
|
||||
Estimate the risk after treatment measures have been applied
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="residualLikelihood">
|
||||
Residual Likelihood
|
||||
</Label>
|
||||
<Select
|
||||
value={residualLikelihood}
|
||||
onValueChange={setResidualLikelihood}
|
||||
>
|
||||
<SelectTrigger id="residualLikelihood">
|
||||
<SelectValue placeholder="Select residual likelihood" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="residualImpact">Residual Impact</Label>
|
||||
<Select
|
||||
value={residualImpact}
|
||||
onValueChange={setResidualImpact}
|
||||
>
|
||||
<SelectTrigger id="residualImpact">
|
||||
<SelectValue placeholder="Select residual impact" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
<SelectItem value="VERY_LOW">Very Low</SelectItem>
|
||||
<SelectItem value="LOW">Low</SelectItem>
|
||||
<SelectItem value="MEDIUM">Medium</SelectItem>
|
||||
<SelectItem value="HIGH">High</SelectItem>
|
||||
<SelectItem value="VERY_HIGH">Very High</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -22,9 +22,9 @@ import { RiskViewSkeleton } from "./RiskListPage";
|
||||
import { RiskListViewPaginationQuery } from "./__generated__/RiskListViewPaginationQuery.graphql";
|
||||
import { RiskListView_risks$key } from "./__generated__/RiskListView_risks.graphql";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "react-router";
|
||||
import { Plus, Trash2 } from "lucide-react";
|
||||
import { Plus, Trash2, Edit } from "lucide-react";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -35,6 +35,13 @@ import {
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { RiskListViewDeleteMutation } from "./__generated__/RiskListViewDeleteMutation.graphql";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
const defaultPageSize = 25;
|
||||
|
||||
@@ -71,8 +78,10 @@ const riskListFragment = graphql`
|
||||
node {
|
||||
id
|
||||
name
|
||||
probability
|
||||
impact
|
||||
inherentLikelihood
|
||||
inherentImpact
|
||||
residualLikelihood
|
||||
residualImpact
|
||||
description
|
||||
createdAt
|
||||
updatedAt
|
||||
@@ -99,21 +108,9 @@ const deleteRiskMutation = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
// Helper functions to convert float values to text
|
||||
const floatToProbabilityText = (value: number): string => {
|
||||
if (value <= 0.1) return "Very Low";
|
||||
if (value <= 0.3) return "Low";
|
||||
if (value <= 0.5) return "Medium";
|
||||
if (value <= 0.7) return "High";
|
||||
return "Very High";
|
||||
};
|
||||
|
||||
const floatToImpactText = (value: number): string => {
|
||||
if (value <= 0.1) return "Very Low";
|
||||
if (value <= 0.3) return "Low";
|
||||
if (value <= 0.5) return "Medium";
|
||||
if (value <= 0.7) return "High";
|
||||
return "Very High";
|
||||
// Helper function to convert float values to percentage
|
||||
const floatToPercentage = (value: number): string => {
|
||||
return `${Math.round(value * 100)}%`;
|
||||
};
|
||||
|
||||
function LoadAboveButton({
|
||||
@@ -170,6 +167,228 @@ function LoadBelowButton({
|
||||
);
|
||||
}
|
||||
|
||||
// Define colors for risk matrix cells
|
||||
const riskMatrixColors = {
|
||||
lowest: "bg-green-500 text-white",
|
||||
low: "bg-lime-300 text-black",
|
||||
medium: "bg-yellow-300 text-black",
|
||||
high: "bg-amber-400 text-white",
|
||||
highest: "bg-red-500 text-white",
|
||||
};
|
||||
|
||||
// Empty cell variants (lighter colors)
|
||||
const emptyRiskMatrixColors = {
|
||||
lowest: "bg-green-50 text-black",
|
||||
low: "bg-lime-50 text-black",
|
||||
medium: "bg-yellow-50 text-black",
|
||||
high: "bg-amber-50 text-black",
|
||||
highest: "bg-red-50 text-black",
|
||||
};
|
||||
|
||||
// Risk Matrix Component
|
||||
function RiskMatrix({
|
||||
risks,
|
||||
isResidual = false,
|
||||
}: {
|
||||
risks: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
inherentLikelihood: number;
|
||||
inherentImpact: number;
|
||||
residualLikelihood?: number;
|
||||
residualImpact?: number;
|
||||
}>;
|
||||
isResidual?: boolean;
|
||||
}): JSX.Element {
|
||||
// Define likelihood and impact ranges for the 5x5 matrix
|
||||
const likelihoodRanges: [number, number][] = [
|
||||
[0.8, 1], // Highest likelihood
|
||||
[0.6, 0.8], // High likelihood
|
||||
[0.4, 0.6], // Medium likelihood
|
||||
[0.2, 0.4], // Low likelihood
|
||||
[0, 0.2], // Lowest likelihood
|
||||
];
|
||||
|
||||
const impactRanges: [number, number][] = [
|
||||
[0, 0.2], // Lowest impact
|
||||
[0.2, 0.4], // Low impact
|
||||
[0.4, 0.6], // Medium impact
|
||||
[0.6, 0.8], // High impact
|
||||
[0.8, 1], // Highest impact
|
||||
];
|
||||
|
||||
const likelihoodLabels = ["Very High", "High", "Medium", "Low", "Very Low"];
|
||||
|
||||
const impactLabels = ["Very Low", "Low", "Medium", "High", "Very High"];
|
||||
|
||||
// Function to get cell content with risks that fall in this cell
|
||||
const getCellContent = (
|
||||
likelihoodRange: [number, number],
|
||||
impactRange: [number, number]
|
||||
) => {
|
||||
return risks.filter((risk) => {
|
||||
const likelihood = isResidual
|
||||
? risk.residualLikelihood ?? risk.inherentLikelihood
|
||||
: risk.inherentLikelihood;
|
||||
const impact = isResidual
|
||||
? risk.residualImpact ?? risk.inherentImpact
|
||||
: risk.inherentImpact;
|
||||
|
||||
return (
|
||||
likelihood > likelihoodRange[0] &&
|
||||
likelihood <= likelihoodRange[1] &&
|
||||
impact > impactRange[0] &&
|
||||
impact <= impactRange[1]
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// Helper to determine cell color based on position in matrix
|
||||
// New matrix has rows indexed from top to bottom (0 = highest likelihood, 4 = lowest likelihood)
|
||||
// and columns indexed from left to right (0 = lowest impact, 4 = highest impact)
|
||||
const getCellColor = (row: number, col: number, isEmpty: boolean): string => {
|
||||
const colorSet = isEmpty ? emptyRiskMatrixColors : riskMatrixColors;
|
||||
|
||||
// Top row (highest likelihood)
|
||||
if (row === 0) {
|
||||
if (col === 0) return colorSet.lowest;
|
||||
if (col === 1) return colorSet.high;
|
||||
return colorSet.highest;
|
||||
}
|
||||
|
||||
// Second row
|
||||
if (row === 1) {
|
||||
if (col === 0) return colorSet.lowest;
|
||||
if (col === 1) return colorSet.medium;
|
||||
if (col === 2) return colorSet.high;
|
||||
return colorSet.highest;
|
||||
}
|
||||
|
||||
// Middle row
|
||||
if (row === 2) {
|
||||
if (col === 0) return colorSet.lowest;
|
||||
if (col === 1) return colorSet.low;
|
||||
if (col === 2) return colorSet.medium;
|
||||
if (col === 3) return colorSet.high;
|
||||
return colorSet.highest;
|
||||
}
|
||||
|
||||
// Fourth row
|
||||
if (row === 3) {
|
||||
if (col === 0) return colorSet.lowest;
|
||||
if (col === 1) return colorSet.low;
|
||||
if (col === 2 || col === 3) return colorSet.medium;
|
||||
return colorSet.high;
|
||||
}
|
||||
|
||||
// Bottom row (lowest likelihood)
|
||||
if (row === 4) {
|
||||
if (col <= 1) return colorSet.lowest;
|
||||
if (col <= 3) return colorSet.low;
|
||||
return colorSet.medium;
|
||||
}
|
||||
|
||||
return "bg-gray-100";
|
||||
};
|
||||
|
||||
// Instead of using refs and tippy, we'll use a component with popover
|
||||
const RiskCell = ({
|
||||
rowIndex,
|
||||
colIndex,
|
||||
likelihoodRange,
|
||||
impactRange,
|
||||
}: {
|
||||
rowIndex: number;
|
||||
colIndex: number;
|
||||
likelihoodRange: [number, number];
|
||||
impactRange: [number, number];
|
||||
}) => {
|
||||
const cellRisks = getCellContent(likelihoodRange, impactRange);
|
||||
const isEmpty = cellRisks.length === 0;
|
||||
const cellColor = getCellColor(rowIndex, colIndex, isEmpty);
|
||||
|
||||
if (isEmpty) {
|
||||
return (
|
||||
<td
|
||||
className={`border aspect-square w-14 h-14 text-center ${cellColor}`}
|
||||
data-risks={0}
|
||||
>
|
||||
<div className="text-sm font-bold flex items-center justify-center h-full"></div>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<td
|
||||
className={`border aspect-square w-14 h-14 text-center ${cellColor} cursor-pointer hover:opacity-90`}
|
||||
data-risks={cellRisks.length}
|
||||
>
|
||||
<div className="text-sm font-bold flex items-center justify-center h-full">
|
||||
{cellRisks.length}
|
||||
</div>
|
||||
</td>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-64 p-3" align="center">
|
||||
<div className="font-medium mb-2">
|
||||
{cellRisks.length} Risk{cellRisks.length > 1 ? "s" : ""}:
|
||||
</div>
|
||||
<ul className="list-disc pl-4 space-y-1">
|
||||
{cellRisks.map((risk) => (
|
||||
<li key={risk.id} className="text-sm">
|
||||
{risk.name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
<div className="flex flex-col">
|
||||
<div className="text-xs font-medium text-center mb-1">CONSEQUENCE</div>
|
||||
<table className="w-full border-collapse table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="p-1 text-center border w-14"></th>
|
||||
{impactLabels.map((label, index) => (
|
||||
<th
|
||||
key={index}
|
||||
className="p-1 text-xs text-center border font-medium w-14"
|
||||
>
|
||||
{label}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{likelihoodRanges.map((likelihoodRange, rowIndex) => (
|
||||
<tr key={rowIndex}>
|
||||
<th className="p-1 text-xs text-center border font-medium w-14 h-14">
|
||||
{likelihoodLabels[rowIndex]}
|
||||
</th>
|
||||
{impactRanges.map((impactRange, colIndex) => (
|
||||
<RiskCell
|
||||
key={colIndex}
|
||||
rowIndex={rowIndex}
|
||||
colIndex={colIndex}
|
||||
likelihoodRange={likelihoodRange}
|
||||
impactRange={impactRange}
|
||||
/>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="text-xs font-medium ml-2 mt-1">LIKELIHOOD</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RiskListViewContent({
|
||||
queryRef,
|
||||
}: {
|
||||
@@ -188,6 +407,9 @@ function RiskListViewContent({
|
||||
} | null>(null);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
// State for toggling between initial and residual risk matrix
|
||||
const [showResidualRisk, setShowResidualRisk] = useState(false);
|
||||
|
||||
// Setup delete mutation
|
||||
const [commitDeleteMutation] =
|
||||
useMutation<RiskListViewDeleteMutation>(deleteRiskMutation);
|
||||
@@ -282,6 +504,46 @@ function RiskListViewContent({
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Combined Risk Matrix with Toggle */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle>
|
||||
{showResidualRisk
|
||||
? "Residual Risk Matrix"
|
||||
: "Initial Risk Matrix"}
|
||||
</CardTitle>
|
||||
<div className="flex items-center space-x-4 border-2 border-gray-300 rounded-lg p-3 bg-gray-50 shadow-md">
|
||||
<Label
|
||||
htmlFor="risk-toggle"
|
||||
className={`text-sm font-semibold cursor-pointer ${
|
||||
!showResidualRisk ? "text-primary" : "text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
Initial
|
||||
</Label>
|
||||
<div className="relative">
|
||||
<Switch
|
||||
id="risk-toggle"
|
||||
checked={showResidualRisk}
|
||||
onCheckedChange={setShowResidualRisk}
|
||||
className="border-2 border-gray-400 data-[state=checked]:border-primary"
|
||||
/>
|
||||
</div>
|
||||
<Label
|
||||
htmlFor="risk-toggle"
|
||||
className={`text-sm font-semibold cursor-pointer ${
|
||||
showResidualRisk ? "text-primary" : "text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
Residual
|
||||
</Label>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<RiskMatrix risks={risks} isResidual={showResidualRisk} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<div className="w-full overflow-auto">
|
||||
@@ -292,12 +554,12 @@ function RiskListViewContent({
|
||||
Name
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/4">
|
||||
Probability
|
||||
Inherent Severity
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/4">
|
||||
Impact
|
||||
Residual Severity
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-[80px]">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-[120px]">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
@@ -331,7 +593,9 @@ function RiskListViewContent({
|
||||
to={`/organizations/${organizationId}/risks/${risk.id}`}
|
||||
className="block p-4 h-full w-full"
|
||||
>
|
||||
{floatToProbabilityText(risk.probability)}
|
||||
{floatToPercentage(
|
||||
risk.inherentLikelihood * risk.inherentImpact
|
||||
)}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="p-0 align-middle w-1/4 whitespace-nowrap">
|
||||
@@ -339,19 +603,40 @@ function RiskListViewContent({
|
||||
to={`/organizations/${organizationId}/risks/${risk.id}`}
|
||||
className="block p-4 h-full w-full"
|
||||
>
|
||||
{floatToImpactText(risk.impact)}
|
||||
{risk.residualLikelihood && risk.residualImpact
|
||||
? floatToPercentage(
|
||||
risk.residualLikelihood * risk.residualImpact
|
||||
)
|
||||
: "Not set"}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="p-4 align-middle w-[80px]">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
setRiskToDelete({ id: risk.id, name: risk.name });
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-4 w-4 text-danger" />
|
||||
</Button>
|
||||
<td className="p-4 align-middle w-[120px]">
|
||||
<div className="flex">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
asChild
|
||||
className="mr-1"
|
||||
>
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/risks/${risk.id}/edit`}
|
||||
>
|
||||
<Edit className="h-4 w-4 text-tertiary" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
setRiskToDelete({
|
||||
id: risk.id,
|
||||
name: risk.name,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-4 w-4 text-danger" />
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
184
apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts
generated
Normal file
184
apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @generated SignedSource<<c0da8faf6e1669e8cf890804a805b2d1>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type EditRiskViewQuery$variables = {
|
||||
riskId: string;
|
||||
};
|
||||
export type EditRiskViewQuery$data = {
|
||||
readonly risk: {
|
||||
readonly description?: string;
|
||||
readonly id?: string;
|
||||
readonly inherentImpact?: number;
|
||||
readonly inherentLikelihood?: number;
|
||||
readonly name?: string;
|
||||
readonly residualImpact?: number;
|
||||
readonly residualLikelihood?: number;
|
||||
};
|
||||
};
|
||||
export type EditRiskViewQuery = {
|
||||
response: EditRiskViewQuery$data;
|
||||
variables: EditRiskViewQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "riskId"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "riskId"
|
||||
}
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
v4 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
v5 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
v6 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
v7 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
v8 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "EditRiskViewQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "risk",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/)
|
||||
],
|
||||
"type": "Risk",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "EditRiskViewQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "risk",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/)
|
||||
],
|
||||
"type": "Risk",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "0cf5e4b47335aeb1fe04520d137942d1",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "EditRiskViewQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query EditRiskViewQuery(\n $riskId: ID!\n) {\n risk: node(id: $riskId) {\n __typename\n ... on Risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n }\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "d057f56759426d63136cef80269dc8a3";
|
||||
|
||||
export default node;
|
||||
167
apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts
generated
Normal file
167
apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @generated SignedSource<<c9530c22837ce495259b6d3ac404da87>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type UpdateRiskInput = {
|
||||
description?: string | null | undefined;
|
||||
id: string;
|
||||
inherentImpact?: number | null | undefined;
|
||||
inherentLikelihood?: number | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
residualImpact?: number | null | undefined;
|
||||
residualLikelihood?: number | null | undefined;
|
||||
};
|
||||
export type EditRiskViewUpdateRiskMutation$variables = {
|
||||
input: UpdateRiskInput;
|
||||
};
|
||||
export type EditRiskViewUpdateRiskMutation$data = {
|
||||
readonly updateRisk: {
|
||||
readonly risk: {
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly inherentImpact: number;
|
||||
readonly inherentLikelihood: number;
|
||||
readonly name: string;
|
||||
readonly residualImpact: number;
|
||||
readonly residualLikelihood: number;
|
||||
readonly updatedAt: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type EditRiskViewUpdateRiskMutation = {
|
||||
response: EditRiskViewUpdateRiskMutation$data;
|
||||
variables: EditRiskViewUpdateRiskMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UpdateRiskPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "updateRisk",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Risk",
|
||||
"kind": "LinkedField",
|
||||
"name": "risk",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "EditRiskViewUpdateRiskMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "EditRiskViewUpdateRiskMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "1fb9a7f1a9a6dc2fd8b1c3235336324b",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "EditRiskViewUpdateRiskMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation EditRiskViewUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n updatedAt\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "75f21269b0c81f77ce4e3547010059ee";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<6488a6430dca9def82544e0ac0ca0db8>>
|
||||
* @generated SignedSource<<63841b5a52846eba02cc6d442cfd4133>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,10 +11,12 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type CreateRiskInput = {
|
||||
description: string;
|
||||
impact: number;
|
||||
inherentImpact: number;
|
||||
inherentLikelihood: number;
|
||||
name: string;
|
||||
organizationId: string;
|
||||
probability: number;
|
||||
residualImpact?: number | null | undefined;
|
||||
residualLikelihood?: number | null | undefined;
|
||||
};
|
||||
export type NewRiskViewCreateRiskMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
@@ -27,9 +29,11 @@ export type NewRiskViewCreateRiskMutation$data = {
|
||||
readonly createdAt: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly impact: number;
|
||||
readonly inherentImpact: number;
|
||||
readonly inherentLikelihood: number;
|
||||
readonly name: string;
|
||||
readonly probability: number;
|
||||
readonly residualImpact: number;
|
||||
readonly residualLikelihood: number;
|
||||
readonly updatedAt: string;
|
||||
};
|
||||
};
|
||||
@@ -99,14 +103,28 @@ v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -195,16 +213,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "345bb376e4168b3b964b8a7ffa4ccbb9",
|
||||
"cacheID": "86d84d72c424807216edf39eb8f0c34f",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "NewRiskViewCreateRiskMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation NewRiskViewCreateRiskMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n id\n name\n description\n probability\n impact\n createdAt\n updatedAt\n }\n }\n }\n}\n"
|
||||
"text": "mutation NewRiskViewCreateRiskMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n createdAt\n updatedAt\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "3cf30aab7c80cc9308343c6ec1577c5a";
|
||||
(node as any).hash = "7ad6c27c192e419839b8105eb2ca9ae7";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<e9f2db8dc7c26cc332a75299317684b7>>
|
||||
* @generated SignedSource<<ada1e6614842f2accf7bbe92a4e845a4>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -190,14 +190,28 @@ return {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -308,16 +322,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "33b15ec024ff6f9963d539be971aef7b",
|
||||
"cacheID": "afcf1c15c2ed7722673da85d53acfef3",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "RiskListViewPaginationQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query RiskListViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RiskListView_risks_pbnwq\n id\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n probability\n impact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n"
|
||||
"text": "query RiskListViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RiskListView_risks_pbnwq\n id\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "59f58f0b1c17242dea5e762b6337bf98";
|
||||
(node as any).hash = "7da0a3d5e4fb09ce7f6b7ddf233702ab";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<f8cd1d0374c4a6de2b577c7fcb35c984>>
|
||||
* @generated SignedSource<<5301e57ef0b2621712f4c8ca693afdeb>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -192,14 +192,28 @@ return {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -310,12 +324,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "78d7871004210dec73a83511b147856f",
|
||||
"cacheID": "56ddd15a8a41c48c01bf0be667569473",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "RiskListViewQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query RiskListViewQuery(\n $organizationId: ID!\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...RiskListView_risks_pbnwq\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n probability\n impact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n"
|
||||
"text": "query RiskListViewQuery(\n $organizationId: ID!\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...RiskListView_risks_pbnwq\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<1d60fbe24f12a69953d5ade8fb94ec1e>>
|
||||
* @generated SignedSource<<c2e3450de2b84e18c9ade3ac1bed3b69>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -19,9 +19,11 @@ export type RiskListView_risks$data = {
|
||||
readonly createdAt: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly impact: number;
|
||||
readonly inherentImpact: number;
|
||||
readonly inherentLikelihood: number;
|
||||
readonly name: string;
|
||||
readonly probability: number;
|
||||
readonly residualImpact: number;
|
||||
readonly residualLikelihood: number;
|
||||
readonly updatedAt: string;
|
||||
};
|
||||
}>;
|
||||
@@ -143,14 +145,28 @@ return {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -255,6 +271,6 @@ return {
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "59f58f0b1c17242dea5e762b6337bf98";
|
||||
(node as any).hash = "7da0a3d5e4fb09ce7f6b7ddf233702ab";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @generated SignedSource<<73623cc6511c56dd418345cd64d500d5>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type CreateRiskMitigationMappingInput = {
|
||||
mitigationId: string;
|
||||
riskId: string;
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMitigationMappingMutation$variables = {
|
||||
input: CreateRiskMitigationMappingInput;
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMitigationMappingMutation$data = {
|
||||
readonly createRiskMitigationMapping: {
|
||||
readonly success: boolean;
|
||||
};
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMitigationMappingMutation = {
|
||||
response: ShowRiskViewCreateRiskMitigationMappingMutation$data;
|
||||
variables: ShowRiskViewCreateRiskMitigationMappingMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "CreateRiskMitigationMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createRiskMitigationMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "success",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "5a8744dfb9cf5f977c2702d848aab7ae",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ShowRiskViewCreateRiskMitigationMappingMutation(\n $input: CreateRiskMitigationMappingInput!\n) {\n createRiskMitigationMapping(input: $input) {\n success\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "bdb664dab4a9e655c0923cfdd4ab0fe9";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<16f4621b72343a04c88df9d0b137c9fd>>
|
||||
* @generated SignedSource<<0ecdbc802635f485dd265dac34b04386>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,23 +9,21 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type CreateRiskMappingInput = {
|
||||
impact: number;
|
||||
mitigationId: string;
|
||||
probability: number;
|
||||
export type CreateRiskPolicyMappingInput = {
|
||||
policyId: string;
|
||||
riskId: string;
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMappingMutation$variables = {
|
||||
input: CreateRiskMappingInput;
|
||||
export type ShowRiskViewCreateRiskPolicyMappingMutation$variables = {
|
||||
input: CreateRiskPolicyMappingInput;
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMappingMutation$data = {
|
||||
readonly createRiskMapping: {
|
||||
export type ShowRiskViewCreateRiskPolicyMappingMutation$data = {
|
||||
readonly createRiskPolicyMapping: {
|
||||
readonly success: boolean;
|
||||
};
|
||||
};
|
||||
export type ShowRiskViewCreateRiskMappingMutation = {
|
||||
response: ShowRiskViewCreateRiskMappingMutation$data;
|
||||
variables: ShowRiskViewCreateRiskMappingMutation$variables;
|
||||
export type ShowRiskViewCreateRiskPolicyMappingMutation = {
|
||||
response: ShowRiskViewCreateRiskPolicyMappingMutation$data;
|
||||
variables: ShowRiskViewCreateRiskPolicyMappingMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
@@ -46,9 +44,9 @@ v1 = [
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "CreateRiskMappingPayload",
|
||||
"concreteType": "CreateRiskPolicyMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createRiskMapping",
|
||||
"name": "createRiskPolicyMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
@@ -67,7 +65,7 @@ return {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "ShowRiskViewCreateRiskMappingMutation",
|
||||
"name": "ShowRiskViewCreateRiskPolicyMappingMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
@@ -76,20 +74,20 @@ return {
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "ShowRiskViewCreateRiskMappingMutation",
|
||||
"name": "ShowRiskViewCreateRiskPolicyMappingMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "32dfd9049a8c6c1d404528bac1316346",
|
||||
"cacheID": "7aac9b6766d79dcc4785f72b6f6805a8",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ShowRiskViewCreateRiskMappingMutation",
|
||||
"name": "ShowRiskViewCreateRiskPolicyMappingMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ShowRiskViewCreateRiskMappingMutation(\n $input: CreateRiskMappingInput!\n) {\n createRiskMapping(input: $input) {\n success\n }\n}\n"
|
||||
"text": "mutation ShowRiskViewCreateRiskPolicyMappingMutation(\n $input: CreateRiskPolicyMappingInput!\n) {\n createRiskPolicyMapping(input: $input) {\n success\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "02f82b14cc6cf7c2e39dad4613e9d191";
|
||||
(node as any).hash = "5a10339ed779d863662406775e38ea7b";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @generated SignedSource<<406a706e512ed01c1924632306a4f81c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DeleteRiskMitigationMappingInput = {
|
||||
mitigationId: string;
|
||||
riskId: string;
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMitigationMappingMutation$variables = {
|
||||
input: DeleteRiskMitigationMappingInput;
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMitigationMappingMutation$data = {
|
||||
readonly deleteRiskMitigationMapping: {
|
||||
readonly success: boolean;
|
||||
};
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMitigationMappingMutation = {
|
||||
response: ShowRiskViewDeleteRiskMitigationMappingMutation$data;
|
||||
variables: ShowRiskViewDeleteRiskMitigationMappingMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "DeleteRiskMitigationMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "deleteRiskMitigationMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "success",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "9a4b56b457c7fb53dc2583da93a3aaa4",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ShowRiskViewDeleteRiskMitigationMappingMutation(\n $input: DeleteRiskMitigationMappingInput!\n) {\n deleteRiskMitigationMapping(input: $input) {\n success\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "d9fece39ecffbd551662d6491088ce4c";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<45a4aca30e16d598cd188f3cbc041a0d>>
|
||||
* @generated SignedSource<<d11690667058b0e7d271b815f510c44c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,21 +9,21 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DeleteRiskMappingInput = {
|
||||
mitigationId: string;
|
||||
export type DeleteRiskPolicyMappingInput = {
|
||||
policyId: string;
|
||||
riskId: string;
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMappingMutation$variables = {
|
||||
input: DeleteRiskMappingInput;
|
||||
export type ShowRiskViewDeleteRiskPolicyMappingMutation$variables = {
|
||||
input: DeleteRiskPolicyMappingInput;
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMappingMutation$data = {
|
||||
readonly deleteRiskMapping: {
|
||||
export type ShowRiskViewDeleteRiskPolicyMappingMutation$data = {
|
||||
readonly deleteRiskPolicyMapping: {
|
||||
readonly success: boolean;
|
||||
};
|
||||
};
|
||||
export type ShowRiskViewDeleteRiskMappingMutation = {
|
||||
response: ShowRiskViewDeleteRiskMappingMutation$data;
|
||||
variables: ShowRiskViewDeleteRiskMappingMutation$variables;
|
||||
export type ShowRiskViewDeleteRiskPolicyMappingMutation = {
|
||||
response: ShowRiskViewDeleteRiskPolicyMappingMutation$data;
|
||||
variables: ShowRiskViewDeleteRiskPolicyMappingMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
@@ -44,9 +44,9 @@ v1 = [
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "DeleteRiskMappingPayload",
|
||||
"concreteType": "DeleteRiskPolicyMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "deleteRiskMapping",
|
||||
"name": "deleteRiskPolicyMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
@@ -65,7 +65,7 @@ return {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "ShowRiskViewDeleteRiskMappingMutation",
|
||||
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
@@ -74,20 +74,20 @@ return {
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "ShowRiskViewDeleteRiskMappingMutation",
|
||||
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "847faec465a30f457c57c5c1524a707d",
|
||||
"cacheID": "a3e208ccc9b5c1248450edaec7ef8417",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ShowRiskViewDeleteRiskMappingMutation",
|
||||
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ShowRiskViewDeleteRiskMappingMutation(\n $input: DeleteRiskMappingInput!\n) {\n deleteRiskMapping(input: $input) {\n success\n }\n}\n"
|
||||
"text": "mutation ShowRiskViewDeleteRiskPolicyMappingMutation(\n $input: DeleteRiskPolicyMappingInput!\n) {\n deleteRiskPolicyMapping(input: $input) {\n success\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "41aa62a4185b1e6061bd7e06abbec85d";
|
||||
(node as any).hash = "5e6b5677587f3c8bad3cec9d751952e1";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<771e7ea5d1af4e722dc5790db8abd623>>
|
||||
* @generated SignedSource<<da6cda7380aec978f37e3adc35942e03>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,7 +9,6 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
|
||||
export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
|
||||
export type ShowRiskViewOrganizationMitigationsQuery$variables = {
|
||||
organizationId: string;
|
||||
@@ -23,7 +22,6 @@ export type ShowRiskViewOrganizationMitigationsQuery$data = {
|
||||
readonly category: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly importance: MitigationImportance;
|
||||
readonly name: string;
|
||||
readonly state: MitigationState;
|
||||
};
|
||||
@@ -104,13 +102,6 @@ v4 = [
|
||||
"name": "category",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "importance",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -253,7 +244,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "ac4f3fc31facab3cb2b9455751a4a528",
|
||||
"cacheID": "a73345064022bd2f11ef2f971cd898b5",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -270,11 +261,11 @@ return {
|
||||
},
|
||||
"name": "ShowRiskViewOrganizationMitigationsQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query ShowRiskViewOrganizationMitigationsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n importance\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
"text": "query ShowRiskViewOrganizationMitigationsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "608bcf7b0e53529673b25ac7762627e2";
|
||||
(node as any).hash = "76ce05cd9f5a367595eb31b5df24a679";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* @generated SignedSource<<86be887d4ec59050fd69900fd80863a2>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type PolicyStatus = "ACTIVE" | "DRAFT";
|
||||
export type ShowRiskViewOrganizationPoliciesQuery$variables = {
|
||||
organizationId: string;
|
||||
};
|
||||
export type ShowRiskViewOrganizationPoliciesQuery$data = {
|
||||
readonly organization: {
|
||||
readonly id: string;
|
||||
readonly policies?: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly status: PolicyStatus;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type ShowRiskViewOrganizationPoliciesQuery = {
|
||||
response: ShowRiskViewOrganizationPoliciesQuery$data;
|
||||
variables: ShowRiskViewOrganizationPoliciesQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "organizationId"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "organizationId"
|
||||
}
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v4 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PolicyEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Policy",
|
||||
"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": "status",
|
||||
"storageKey": null
|
||||
},
|
||||
(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
|
||||
}
|
||||
],
|
||||
v5 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "ShowRiskViewOrganizationPoliciesQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "organization",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "policies",
|
||||
"args": null,
|
||||
"concreteType": "PolicyConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__Organization__policies_connection",
|
||||
"plural": false,
|
||||
"selections": (v4/*: any*/),
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "ShowRiskViewOrganizationPoliciesQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "organization",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v5/*: any*/),
|
||||
"concreteType": "PolicyConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "policies",
|
||||
"plural": false,
|
||||
"selections": (v4/*: any*/),
|
||||
"storageKey": "policies(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v5/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "Organization__policies",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "policies"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "a229f1f805e79f8de378305e021d7fea",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"organization",
|
||||
"policies"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "ShowRiskViewOrganizationPoliciesQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query ShowRiskViewOrganizationPoliciesQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n policies(first: 100) {\n edges {\n node {\n id\n name\n status\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "26cbf19cd716aee7413931357b9c5354";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<61ecdce52780dbfd62783deecb27645d>>
|
||||
* @generated SignedSource<<a6b1be8aa499bb8709a4d4e04edb01b7>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -9,17 +9,29 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
|
||||
export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
|
||||
export type PolicyStatus = "ACTIVE" | "DRAFT";
|
||||
export type ShowRiskViewQuery$variables = {
|
||||
riskId: string;
|
||||
};
|
||||
export type ShowRiskViewQuery$data = {
|
||||
readonly node: {
|
||||
readonly controls?: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly createdAt: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly referenceId: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly createdAt?: string;
|
||||
readonly description?: string;
|
||||
readonly id: string;
|
||||
readonly impact?: number;
|
||||
readonly inherentImpact?: number;
|
||||
readonly inherentLikelihood?: number;
|
||||
readonly mitigations?: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
@@ -27,14 +39,24 @@ export type ShowRiskViewQuery$data = {
|
||||
readonly createdAt: string;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly importance: MitigationImportance;
|
||||
readonly name: string;
|
||||
readonly state: MitigationState;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly name?: string;
|
||||
readonly probability?: number;
|
||||
readonly policies?: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly createdAt: string;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly status: PolicyStatus;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly residualImpact?: number;
|
||||
readonly residualLikelihood?: number;
|
||||
readonly updatedAt?: string;
|
||||
};
|
||||
};
|
||||
@@ -83,38 +105,84 @@ v5 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "probability",
|
||||
"name": "inherentLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
v6 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "impact",
|
||||
"name": "inherentImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
v7 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"name": "residualLikelihood",
|
||||
"storageKey": null
|
||||
},
|
||||
v8 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"name": "residualImpact",
|
||||
"storageKey": null
|
||||
},
|
||||
v9 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
},
|
||||
v10 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
},
|
||||
v11 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v10 = [
|
||||
v12 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
},
|
||||
v13 = {
|
||||
"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
|
||||
},
|
||||
v14 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -141,14 +209,7 @@ v10 = [
|
||||
"name": "category",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "importance",
|
||||
"storageKey": null
|
||||
},
|
||||
(v7/*: any*/),
|
||||
(v9/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -156,47 +217,92 @@ v10 = [
|
||||
"name": "state",
|
||||
"storageKey": null
|
||||
},
|
||||
(v9/*: any*/)
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
}
|
||||
(v12/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v13/*: any*/)
|
||||
],
|
||||
v15 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"concreteType": "PolicyEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"concreteType": "Policy",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "status",
|
||||
"storageKey": null
|
||||
},
|
||||
(v9/*: any*/),
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v12/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v13/*: any*/)
|
||||
],
|
||||
v16 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "referenceId",
|
||||
"storageKey": null
|
||||
},
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
},
|
||||
(v12/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
},
|
||||
(v13/*: any*/)
|
||||
],
|
||||
v11 = [
|
||||
v17 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
@@ -228,6 +334,8 @@ return {
|
||||
(v6/*: any*/),
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
{
|
||||
"alias": "mitigations",
|
||||
"args": null,
|
||||
@@ -235,7 +343,27 @@ return {
|
||||
"kind": "LinkedField",
|
||||
"name": "__Risk__mitigations_connection",
|
||||
"plural": false,
|
||||
"selections": (v10/*: any*/),
|
||||
"selections": (v14/*: any*/),
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "policies",
|
||||
"args": null,
|
||||
"concreteType": "PolicyConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__Risk__policies_connection",
|
||||
"plural": false,
|
||||
"selections": (v15/*: any*/),
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "controls",
|
||||
"args": null,
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__Risk__controls_connection",
|
||||
"plural": false,
|
||||
"selections": (v16/*: any*/),
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
@@ -263,7 +391,7 @@ return {
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v9/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
@@ -274,24 +402,64 @@ return {
|
||||
(v6/*: any*/),
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v11/*: any*/),
|
||||
"args": (v17/*: any*/),
|
||||
"concreteType": "MitigationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "mitigations",
|
||||
"plural": false,
|
||||
"selections": (v10/*: any*/),
|
||||
"selections": (v14/*: any*/),
|
||||
"storageKey": "mitigations(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v11/*: any*/),
|
||||
"args": (v17/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "Risk__mitigations",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "mitigations"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v17/*: any*/),
|
||||
"concreteType": "PolicyConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "policies",
|
||||
"plural": false,
|
||||
"selections": (v15/*: any*/),
|
||||
"storageKey": "policies(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v17/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "Risk__policies",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "policies"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v17/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
"plural": false,
|
||||
"selections": (v16/*: any*/),
|
||||
"storageKey": "controls(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v17/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "Risk__controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
}
|
||||
],
|
||||
"type": "Risk",
|
||||
@@ -303,7 +471,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "b30cf22fe56e7cb776d6d4a5af81e358",
|
||||
"cacheID": "4463fac13f91564f513bfdabcc3e0063",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -315,16 +483,34 @@ return {
|
||||
"node",
|
||||
"mitigations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"node",
|
||||
"policies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"node",
|
||||
"controls"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "ShowRiskViewQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n probability\n impact\n createdAt\n updatedAt\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n importance\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
"text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n createdAt\n updatedAt\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n policies(first: 100) {\n edges {\n node {\n id\n name\n status\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "77f36d2a4405051ede742be63d3e1e38";
|
||||
(node as any).hash = "68db9a4877abc338711844de6da38cb7";
|
||||
|
||||
export default node;
|
||||
|
||||
Reference in New Issue
Block a user