@@ -38,6 +38,7 @@ import {
|
|||||||
Link as LinkIcon,
|
Link as LinkIcon,
|
||||||
CheckSquare,
|
CheckSquare,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
|
AlertTriangle,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
@@ -88,7 +89,10 @@ import { MitigationViewAssignTaskMutation as MitigationViewAssignTaskMutationTyp
|
|||||||
import { MitigationViewUnassignTaskMutation as MitigationViewUnassignTaskMutationType } from "./__generated__/MitigationViewUnassignTaskMutation.graphql";
|
import { MitigationViewUnassignTaskMutation as MitigationViewUnassignTaskMutationType } from "./__generated__/MitigationViewUnassignTaskMutation.graphql";
|
||||||
import { MitigationViewUpdateMitigationStateMutation as MitigationViewUpdateMitigationStateMutationType } from "./__generated__/MitigationViewUpdateMitigationStateMutation.graphql";
|
import { MitigationViewUpdateMitigationStateMutation as MitigationViewUpdateMitigationStateMutationType } from "./__generated__/MitigationViewUpdateMitigationStateMutation.graphql";
|
||||||
import { MitigationViewQuery as MitigationViewQueryType } from "./__generated__/MitigationViewQuery.graphql";
|
import { MitigationViewQuery as MitigationViewQueryType } from "./__generated__/MitigationViewQuery.graphql";
|
||||||
import { MitigationViewOrganizationQuery$data } from "./__generated__/MitigationViewOrganizationQuery.graphql";
|
import {
|
||||||
|
MitigationViewOrganizationQuery,
|
||||||
|
MitigationViewOrganizationQuery$data,
|
||||||
|
} from "./__generated__/MitigationViewOrganizationQuery.graphql";
|
||||||
import {
|
import {
|
||||||
MitigationViewFrameworksQuery,
|
MitigationViewFrameworksQuery,
|
||||||
MitigationViewFrameworksQuery$data,
|
MitigationViewFrameworksQuery$data,
|
||||||
@@ -97,6 +101,10 @@ import {
|
|||||||
MitigationViewLinkedControlsQuery,
|
MitigationViewLinkedControlsQuery,
|
||||||
MitigationViewLinkedControlsQuery$data,
|
MitigationViewLinkedControlsQuery$data,
|
||||||
} from "./__generated__/MitigationViewLinkedControlsQuery.graphql";
|
} from "./__generated__/MitigationViewLinkedControlsQuery.graphql";
|
||||||
|
import {
|
||||||
|
MitigationViewRisksQuery,
|
||||||
|
MitigationViewRisksQuery$data,
|
||||||
|
} from "./__generated__/MitigationViewRisksQuery.graphql";
|
||||||
|
|
||||||
// Function to format ISO8601 duration to human-readable format
|
// Function to format ISO8601 duration to human-readable format
|
||||||
const formatDuration = (isoDuration: string): string => {
|
const formatDuration = (isoDuration: string): string => {
|
||||||
@@ -408,6 +416,30 @@ const deleteControlMappingMutation = graphql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Add query to fetch risks linked to a mitigation
|
||||||
|
const mitigationRisksQuery = graphql`
|
||||||
|
query MitigationViewRisksQuery($mitigationId: ID!) {
|
||||||
|
mitigation: node(id: $mitigationId) {
|
||||||
|
id
|
||||||
|
... on Mitigation {
|
||||||
|
risks(first: 100) @connection(key: "MitigationView_risks") {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
description
|
||||||
|
probability
|
||||||
|
impact
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
// Define type for framework structure
|
// Define type for framework structure
|
||||||
type FrameworkEdge = {
|
type FrameworkEdge = {
|
||||||
node: {
|
node: {
|
||||||
@@ -433,6 +465,29 @@ type ControlNode = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Define Risk type
|
||||||
|
type RiskNode = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
probability: number;
|
||||||
|
impact: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the risks data type
|
||||||
|
type MitigationRisksData = {
|
||||||
|
mitigation?: {
|
||||||
|
id: string;
|
||||||
|
risks?: {
|
||||||
|
edges: Array<{
|
||||||
|
node: RiskNode;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function MitigationViewContent({
|
function MitigationViewContent({
|
||||||
queryRef,
|
queryRef,
|
||||||
}: {
|
}: {
|
||||||
@@ -508,6 +563,25 @@ function MitigationViewContent({
|
|||||||
}
|
}
|
||||||
}, [environment, mitigationId]);
|
}, [environment, mitigationId]);
|
||||||
|
|
||||||
|
// Add state for risks data
|
||||||
|
const [risksData, setRisksData] = useState<MitigationRisksData | null>(null);
|
||||||
|
|
||||||
|
// Load risks data when component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
if (mitigationId) {
|
||||||
|
fetchQuery(environment, mitigationRisksQuery, { mitigationId }).subscribe(
|
||||||
|
{
|
||||||
|
next: (data: unknown) => {
|
||||||
|
setRisksData(data as MitigationRisksData);
|
||||||
|
},
|
||||||
|
error: (error: Error) => {
|
||||||
|
console.error("Error fetching risks:", error);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [environment, mitigationId]);
|
||||||
|
|
||||||
const formatImportance = (importance: string | undefined): string => {
|
const formatImportance = (importance: string | undefined): string => {
|
||||||
if (!importance) return "";
|
if (!importance) return "";
|
||||||
|
|
||||||
@@ -1618,6 +1692,47 @@ function MitigationViewContent({
|
|||||||
);
|
);
|
||||||
}, [controlSearchQuery, getControls]);
|
}, [controlSearchQuery, getControls]);
|
||||||
|
|
||||||
|
// Helper function to get risk severity color
|
||||||
|
const getRiskSeverityColor = (
|
||||||
|
probability: number,
|
||||||
|
impact: number
|
||||||
|
): string => {
|
||||||
|
const severity = probability * impact;
|
||||||
|
|
||||||
|
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";
|
||||||
|
return "bg-green-100 text-green-800";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to get risk severity text
|
||||||
|
const getRiskSeverityText = (probability: number, impact: number): string => {
|
||||||
|
const severity = probability * impact;
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Format impact as text
|
||||||
|
const formatImpact = (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";
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTemplate
|
<PageTemplate
|
||||||
title={data.mitigation.name ?? ""}
|
title={data.mitigation.name ?? ""}
|
||||||
@@ -1692,6 +1807,16 @@ function MitigationViewContent({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="risks" className="flex items-center gap-2">
|
||||||
|
<AlertTriangle className="w-4 h-4" />
|
||||||
|
Risks
|
||||||
|
{risksData?.mitigation?.risks?.edges &&
|
||||||
|
risksData.mitigation.risks.edges.length > 0 && (
|
||||||
|
<span className="ml-1.5 bg-blue-100 text-blue-800 rounded-full text-xs px-2 py-0.5">
|
||||||
|
{risksData.mitigation.risks.edges.length}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
{/* Controls Tab Content */}
|
{/* Controls Tab Content */}
|
||||||
@@ -2490,6 +2615,88 @@ function MitigationViewContent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Risks Tab Content */}
|
||||||
|
<TabsContent value="risks">
|
||||||
|
<div className="mb-8">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<h2 className="text-xl font-semibold">Risks</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
{risksData?.mitigation?.risks?.edges &&
|
||||||
|
risksData.mitigation.risks.edges.length > 0 ? (
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b">
|
||||||
|
<th className="text-left font-medium text-sm py-2 px-4">
|
||||||
|
Risk Name
|
||||||
|
</th>
|
||||||
|
<th className="text-left font-medium text-sm py-2 px-4">
|
||||||
|
Probability
|
||||||
|
</th>
|
||||||
|
<th className="text-left font-medium text-sm py-2 px-4">
|
||||||
|
Impact
|
||||||
|
</th>
|
||||||
|
<th className="text-left font-medium text-sm py-2 px-4">
|
||||||
|
Severity
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{risksData.mitigation.risks.edges.map(({ node }) => (
|
||||||
|
<tr
|
||||||
|
key={node.id}
|
||||||
|
className="border-b hover:bg-gray-50"
|
||||||
|
onClick={() =>
|
||||||
|
navigate(
|
||||||
|
`/organizations/${organizationId}/risks/${node.id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<td className="py-3 px-4 font-medium text-sm">
|
||||||
|
{node.name}
|
||||||
|
</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)}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<div className="bg-purple-100 text-purple-800 px-2 py-0.5 rounded-full text-xs inline-block">
|
||||||
|
{formatImpact(node.impact)}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<div
|
||||||
|
className={`${getRiskSeverityColor(
|
||||||
|
node.probability,
|
||||||
|
node.impact
|
||||||
|
)} px-2 py-0.5 rounded-full text-xs inline-block`}
|
||||||
|
>
|
||||||
|
{getRiskSeverityText(
|
||||||
|
node.probability,
|
||||||
|
node.impact
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-8 text-gray-500">
|
||||||
|
No risks linked to this mitigation yet.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
{/* Right task panel */}
|
{/* Right task panel */}
|
||||||
|
|||||||
286
apps/console/src/pages/organizations/mitigations/__generated__/MitigationViewRisksQuery.graphql.ts
generated
Normal file
286
apps/console/src/pages/organizations/mitigations/__generated__/MitigationViewRisksQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<7ecc796e34bf88aa378e81249110be90>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type MitigationViewRisksQuery$variables = {
|
||||||
|
mitigationId: string;
|
||||||
|
};
|
||||||
|
export type MitigationViewRisksQuery$data = {
|
||||||
|
readonly mitigation: {
|
||||||
|
readonly id: string;
|
||||||
|
readonly risks?: {
|
||||||
|
readonly edges: ReadonlyArray<{
|
||||||
|
readonly node: {
|
||||||
|
readonly createdAt: string;
|
||||||
|
readonly description: string;
|
||||||
|
readonly id: string;
|
||||||
|
readonly impact: number;
|
||||||
|
readonly name: string;
|
||||||
|
readonly probability: number;
|
||||||
|
readonly updatedAt: string;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type MitigationViewRisksQuery = {
|
||||||
|
response: MitigationViewRisksQuery$data;
|
||||||
|
variables: MitigationViewRisksQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "mitigationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "mitigationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
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": "RiskEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Risk",
|
||||||
|
"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": "description",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "probability",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "impact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"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": "MitigationViewRisksQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": "mitigation",
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": "risks",
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RiskConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "__MitigationView_risks_connection",
|
||||||
|
"plural": false,
|
||||||
|
"selections": (v4/*: any*/),
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Mitigation",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "MitigationViewRisksQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": "mitigation",
|
||||||
|
"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": "RiskConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "risks",
|
||||||
|
"plural": false,
|
||||||
|
"selections": (v4/*: any*/),
|
||||||
|
"storageKey": "risks(first:100)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v5/*: any*/),
|
||||||
|
"filters": null,
|
||||||
|
"handle": "connection",
|
||||||
|
"key": "MitigationView_risks",
|
||||||
|
"kind": "LinkedHandle",
|
||||||
|
"name": "risks"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Mitigation",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "61c985f00c12fb3cdab3e345a8c65957",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {
|
||||||
|
"connection": [
|
||||||
|
{
|
||||||
|
"count": null,
|
||||||
|
"cursor": null,
|
||||||
|
"direction": "forward",
|
||||||
|
"path": [
|
||||||
|
"mitigation",
|
||||||
|
"risks"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "e05802ec519933edce3d0f3487742e3d";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -79,7 +79,6 @@ WITH rsks AS (
|
|||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
organization_id,
|
organization_id,
|
||||||
tenant_id,
|
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
probability,
|
probability,
|
||||||
|
|||||||
Reference in New Issue
Block a user