Add categories on risk

Signed-off-by: Antoine Bouchardy <antoine@getprobo.com>
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Antoine Bouchardy
2025-04-19 15:19:48 -07:00
committed by Bryan Frimin
parent 09fb70d75f
commit b137ec6bdf
20 changed files with 677 additions and 244 deletions

View File

@@ -46,6 +46,7 @@ const editRiskViewQuery = graphql`
id
name
description
category
inherentLikelihood
inherentImpact
residualLikelihood
@@ -71,6 +72,7 @@ const updateRiskMutation = graphql`
id
name
description
category
inherentLikelihood
inherentImpact
residualLikelihood
@@ -104,6 +106,7 @@ function EditRiskViewContent({
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [category, setCategory] = useState("");
const [inherentLikelihood, setInherentLikelihood] = useState<number>(3);
const [inherentImpact, setInherentImpact] = useState<number>(3);
const [residualLikelihood, setResidualLikelihood] = useState<number>(3);
@@ -120,6 +123,7 @@ function EditRiskViewContent({
if (risk) {
setName(risk.name || "");
setDescription(risk.description || "");
setCategory(risk.category || "");
// Set values directly as integers
setInherentLikelihood(risk.inherentLikelihood || 3);
setInherentImpact(risk.inherentImpact || 3);
@@ -148,6 +152,7 @@ function EditRiskViewContent({
id: riskId!,
name,
description,
category,
inherentLikelihood,
inherentImpact,
residualLikelihood,
@@ -203,6 +208,17 @@ function EditRiskViewContent({
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2">
<Label htmlFor="category">Category</Label>
<Input
id="category"
placeholder="Risk category"
value={category}
onChange={(e) => setCategory(e.target.value)}
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="name">Name</Label>
<Input

View File

@@ -16,6 +16,7 @@ import {
useTransition,
} from "react";
import type { ListRiskViewQuery } from "./__generated__/ListRiskViewQuery.graphql";
import type { RiskTreatment } from "./__generated__/ListRiskView_risks.graphql";
import { useParams, useSearchParams } from "react-router";
import { PageTemplate } from "@/components/PageTemplate";
import { RiskViewSkeleton } from "./ListRiskPage";
@@ -84,8 +85,20 @@ const listRiskViewFragment = graphql`
residualImpact
treatment
description
category
createdAt
updatedAt
owner {
id
fullName
}
mesures(first: 1) {
edges {
node {
category
}
}
}
}
}
pageInfo {
@@ -197,6 +210,31 @@ const emptyRiskMatrixColors = {
high: "bg-red-50 text-black",
};
type RiskNode = {
readonly id: string;
readonly name: string;
readonly inherentLikelihood: number;
readonly inherentImpact: number;
readonly residualLikelihood: number;
readonly residualImpact: number;
readonly treatment: RiskTreatment;
readonly description: string;
readonly category: string;
readonly createdAt: string;
readonly updatedAt: string;
readonly owner: {
readonly id: string;
readonly fullName: string;
} | null;
readonly mesures: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
};
}>;
};
};
// Risk Matrix Component
function RiskMatrix({
risks,
@@ -676,17 +714,23 @@ function ListRiskViewContent({
<table className="w-full caption-bottom text-sm">
<thead className="[&_tr]:border-b">
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/2">
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/6">
Category
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/3">
Name
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/6">
Inherent
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/6">
Treatment
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/6">
Inherent Severity
Residual
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/6">
Residual Severity
Owner
</th>
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-[120px]">
Action
@@ -697,7 +741,7 @@ function ListRiskViewContent({
{risks.length === 0 ? (
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
<td
colSpan={5}
colSpan={7}
className="text-center p-4 align-middle text-tertiary"
>
No risks found. Create a new risk to get started.
@@ -709,7 +753,15 @@ function ListRiskViewContent({
key={risk.id}
className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg cursor-pointer"
>
<td className="p-0 align-middle font-medium w-1/2">
<td className="p-0 align-middle w-1/6">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
className="block p-4 h-full w-full"
>
{risk.category}
</Link>
</td>
<td className="p-0 align-middle font-medium w-1/3">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
className="block p-4 h-full w-full"
@@ -717,14 +769,6 @@ function ListRiskViewContent({
{risk.name}
</Link>
</td>
<td className="p-0 align-middle w-1/6 whitespace-nowrap">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
className="block p-4 h-full w-full"
>
{formatTreatment(risk.treatment)}
</Link>
</td>
<td className="p-0 align-middle w-1/6 whitespace-nowrap">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
@@ -734,23 +778,15 @@ function ListRiskViewContent({
className="px-2 py-0.5 text-xs rounded-full font-medium inline-block"
style={{
backgroundColor:
risk.inherentLikelihood *
risk.inherentImpact >=
20
risk.inherentLikelihood * risk.inherentImpact >= 20
? "#ef4444"
: risk.inherentLikelihood *
risk.inherentImpact >=
12
: risk.inherentLikelihood * risk.inherentImpact >= 12
? "#f59e0b"
: risk.inherentLikelihood *
risk.inherentImpact >=
5
: risk.inherentLikelihood * risk.inherentImpact >= 5
? "#10b981"
: "#94a3b8",
color:
risk.inherentLikelihood *
risk.inherentImpact >=
12
risk.inherentLikelihood * risk.inherentImpact >= 12
? "white"
: "inherit",
}}
@@ -762,6 +798,14 @@ function ListRiskViewContent({
</span>
</Link>
</td>
<td className="p-0 align-middle w-1/6 whitespace-nowrap">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
className="block p-4 h-full w-full"
>
{formatTreatment(risk.treatment)}
</Link>
</td>
<td className="p-0 align-middle w-1/6 whitespace-nowrap">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
@@ -772,23 +816,15 @@ function ListRiskViewContent({
className="px-2 py-0.5 text-xs rounded-full font-medium inline-block"
style={{
backgroundColor:
risk.residualLikelihood *
risk.residualImpact >=
20
risk.residualLikelihood * risk.residualImpact >= 20
? "#ef4444"
: risk.residualLikelihood *
risk.residualImpact >=
12
: risk.residualLikelihood * risk.residualImpact >= 12
? "#f59e0b"
: risk.residualLikelihood *
risk.residualImpact >=
5
: risk.residualLikelihood * risk.residualImpact >= 5
? "#10b981"
: "#94a3b8",
color:
risk.residualLikelihood *
risk.residualImpact >=
12
risk.residualLikelihood * risk.residualImpact >= 12
? "white"
: "inherit",
}}
@@ -796,14 +832,21 @@ function ListRiskViewContent({
{riskScoreToSeverity(
risk.residualLikelihood * risk.residualImpact
)}{" "}
({risk.residualLikelihood * risk.residualImpact}
)
({risk.residualLikelihood * risk.residualImpact})
</span>
) : (
"Not set"
)}
</Link>
</td>
<td className="p-0 align-middle w-1/6">
<Link
to={`/organizations/${organizationId}/risks/${risk.id}`}
className="block p-4 h-full w-full"
>
{risk.owner?.fullName || "Unassigned"}
</Link>
</td>
<td className="p-4 align-middle w-[120px]">
<div className="flex">
<Button

View File

@@ -30,7 +30,7 @@ import {
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import PeopleSelector from "@/components/PeopleSelector";
import { User } from "lucide-react";
import { User, Loader2 } from "lucide-react";
import { Suspense } from "react";
import type { NewRiskViewQuery } from "./__generated__/NewRiskViewQuery.graphql";
@@ -43,6 +43,7 @@ interface RiskTemplate {
likelihood: number;
recommendedTreatment: string;
}[];
category: string;
}
const newRiskQuery = graphql`
@@ -64,6 +65,7 @@ const createRiskMutation = graphql`
id
name
description
category
inherentLikelihood
inherentImpact
residualLikelihood
@@ -95,14 +97,45 @@ function NewRiskForm({
const [ownerId, setOwnerId] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [selectedTemplate, setSelectedTemplate] = useState<string>("");
const [selectedCategory, setSelectedCategory] = useState<string>("");
const [riskTemplates, setRiskTemplates] = useState<RiskTemplate[]>([]);
const [ownerError, setOwnerError] = useState<string>("");
const [isLoadingTemplates, setIsLoadingTemplates] = useState(true);
const { toast } = useToast();
const [createRisk, isInFlight] = useMutation(createRiskMutation);
// Get unique categories from risk templates
const categories = Array.from(new Set(riskTemplates.map(template => template.category)));
// Filter risks by selected category
const filteredRisks = riskTemplates.filter(template =>
!selectedCategory || template.category === selectedCategory
).map(template => ({
...template,
originalIndex: riskTemplates.findIndex(t => t.name === template.name && t.description === template.description)
}));
// Handle category selection
const selectCategory = (category: string) => {
setSelectedCategory(category);
// Only reset template if we're changing categories
if (selectedCategory !== category) {
setSelectedTemplate("");
}
// Focus on the risk dropdown after a short delay to ensure it's rendered
setTimeout(() => {
const selectTrigger = document.getElementById('template');
if (selectTrigger) {
selectTrigger.focus();
}
}, 0);
};
useEffect(() => {
const loadRiskTemplates = async () => {
try {
setIsLoadingTemplates(true);
const response = await fetch("/data/risks/risks.json");
const data = await response.json();
setRiskTemplates(data);
@@ -113,6 +146,8 @@ function NewRiskForm({
description: "Failed to load risk templates. Please try again.",
variant: "destructive",
});
} finally {
setIsLoadingTemplates(false);
}
};
@@ -135,33 +170,24 @@ function NewRiskForm({
return;
}
const template = riskTemplates[parseInt(templateId)];
const selectedIndex = parseInt(templateId);
const template = riskTemplates[selectedIndex];
if (template) {
setName(template.name);
setDescription(template.description);
// Convert template values to 1-5 scale
const likelihoodValue =
Math.round(template.variations[0].likelihood * 5) || 3;
const impactValue = Math.round(template.variations[0].impact * 5) || 3;
// Ensure values are in 1-5 range
setInherentLikelihood(Math.min(Math.max(likelihoodValue, 1), 5));
setInherentImpact(Math.min(Math.max(impactValue, 1), 5));
// Set residual values to be the same as initial values by default
setResidualLikelihood(Math.min(Math.max(likelihoodValue, 1), 5));
setResidualImpact(Math.min(Math.max(impactValue, 1), 5));
// Set recommended treatment if available
if (template.variations[0].recommendedTreatment) {
setTreatment(template.variations[0].recommendedTreatment.toUpperCase());
}
setTreatment("MITIGATED");
}
};
// Clear error when owner is selected
const handleOwnerSelect = (id: string | null) => {
setOwnerId(id);
setOwnerError("");
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
let hasError = false;
if (!name.trim()) {
toast({
@@ -169,6 +195,15 @@ function NewRiskForm({
description: "Please enter a name for the risk.",
variant: "destructive",
});
hasError = true;
}
if (!ownerId) {
setOwnerError("Please select a risk owner");
hasError = true;
}
if (hasError) {
return;
}
@@ -178,6 +213,7 @@ function NewRiskForm({
organizationId: organizationId!,
name,
description,
category: selectedCategory,
inherentLikelihood,
inherentImpact,
residualLikelihood,
@@ -242,27 +278,52 @@ function NewRiskForm({
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2">
<Label htmlFor="template">Risk Template</Label>
<Select
value={selectedTemplate}
onValueChange={handleTemplateChange}
>
<SelectTrigger id="template">
<SelectValue placeholder="Select a risk template" />
</SelectTrigger>
<SelectContent className="max-h-[300px] overflow-y-auto">
<SelectItem value="none">Select a template</SelectItem>
{riskTemplates.map((template, index) => (
<SelectItem key={index} value={index.toString()}>
{template.name}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-sm text-tertiary">
Select a template to prefill the form or create a custom risk.
</p>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="template">Risk Template</Label>
<div className="flex flex-wrap gap-2 mb-2">
{isLoadingTemplates ? (
<div className="flex items-center gap-2 text-tertiary">
<Loader2 className="h-4 w-4 animate-spin" />
<span>Loading categories...</span>
</div>
) : (
categories.map((category) => (
<Button
key={category}
variant={selectedCategory === category ? "default" : "outline"}
size="sm"
onClick={() => selectCategory(category)}
className="rounded-full"
>
{category}
</Button>
))
)}
</div>
<Select
value={selectedTemplate}
onValueChange={handleTemplateChange}
>
<SelectTrigger id="template">
<SelectValue placeholder="Select a risk template" />
</SelectTrigger>
<SelectContent className="max-h-[300px] overflow-y-auto">
<SelectItem value="none">Select a template</SelectItem>
{filteredRisks.map((template) => (
<SelectItem
key={template.originalIndex}
value={template.originalIndex.toString()}
>
{template.name}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-sm text-tertiary">
Select a risk template to prefill the form or create a custom risk.
</p>
</div>
</div>
<div className="space-y-2">
@@ -291,14 +352,18 @@ function NewRiskForm({
<Label htmlFor="owner" className="flex items-center gap-2">
<User className="h-4 w-4" />
Risk Owner
<span className="text-destructive">*</span>
</Label>
<PeopleSelector
organizationRef={data.organization}
selectedPersonId={ownerId}
onSelect={setOwnerId}
placeholder="Select risk owner (optional)"
required={false}
onSelect={handleOwnerSelect}
placeholder="Select risk owner"
required={true}
/>
{ownerError && (
<p className="text-sm text-destructive mt-1">Please select a risk owner</p>
)}
</div>
<div className="grid grid-cols-2 gap-4">

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<fc9fe251d08f57babcab4e395b6c0aec>>
* @generated SignedSource<<028d64b4c532fdc04b77de62bd70311b>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -20,6 +20,7 @@ export type EditRiskViewQuery$data = {
readonly " $fragmentSpreads": FragmentRefs<"PeopleSelector_organization">;
};
readonly risk: {
readonly category?: string;
readonly description?: string;
readonly id?: string;
readonly inherentImpact?: number;
@@ -82,45 +83,52 @@ v6 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "inherentLikelihood",
"name": "category",
"storageKey": null
},
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "inherentImpact",
"name": "inherentLikelihood",
"storageKey": null
},
v8 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "residualLikelihood",
"name": "inherentImpact",
"storageKey": null
},
v9 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "residualImpact",
"name": "residualLikelihood",
"storageKey": null
},
v10 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "treatment",
"name": "residualImpact",
"storageKey": null
},
v11 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"name": "treatment",
"storageKey": null
},
v12 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
v13 = {
"alias": null,
"args": null,
"concreteType": "People",
@@ -129,25 +137,25 @@ v12 = {
"plural": false,
"selections": [
(v3/*: any*/),
(v11/*: any*/)
(v12/*: any*/)
],
"storageKey": null
},
v13 = [
v14 = [
{
"kind": "Variable",
"name": "id",
"variableName": "organizationId"
}
],
v14 = {
v15 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v15 = [
v16 = [
{
"kind": "Literal",
"name": "first",
@@ -191,7 +199,8 @@ return {
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
(v12/*: any*/)
(v11/*: any*/),
(v13/*: any*/)
],
"type": "Risk",
"abstractKey": null
@@ -201,7 +210,7 @@ return {
},
{
"alias": "organization",
"args": (v13/*: any*/),
"args": (v14/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
@@ -236,7 +245,7 @@ return {
"name": "node",
"plural": false,
"selections": [
(v14/*: any*/),
(v15/*: any*/),
(v3/*: any*/),
{
"kind": "InlineFragment",
@@ -248,7 +257,8 @@ return {
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
(v12/*: any*/)
(v11/*: any*/),
(v13/*: any*/)
],
"type": "Risk",
"abstractKey": null
@@ -258,20 +268,20 @@ return {
},
{
"alias": "organization",
"args": (v13/*: any*/),
"args": (v14/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v14/*: any*/),
(v15/*: any*/),
(v3/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": (v15/*: any*/),
"args": (v16/*: any*/),
"concreteType": "PeopleConnection",
"kind": "LinkedField",
"name": "peoples",
@@ -294,7 +304,7 @@ return {
"plural": false,
"selections": [
(v3/*: any*/),
(v11/*: any*/),
(v12/*: any*/),
{
"alias": null,
"args": null,
@@ -302,7 +312,7 @@ return {
"name": "primaryEmailAddress",
"storageKey": null
},
(v14/*: any*/)
(v15/*: any*/)
],
"storageKey": null
},
@@ -346,7 +356,7 @@ return {
},
{
"alias": null,
"args": (v15/*: any*/),
"args": (v16/*: any*/),
"filters": [
"orderBy"
],
@@ -365,16 +375,16 @@ return {
]
},
"params": {
"cacheID": "5d84f3bb7bcc5123adcf8fe776baea73",
"cacheID": "cdae5e406ef1b70c372791cc998e82ac",
"id": null,
"metadata": {},
"name": "EditRiskViewQuery",
"operationKind": "query",
"text": "query EditRiskViewQuery(\n $riskId: ID!\n $organizationId: 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 treatment\n owner {\n id\n fullName\n }\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
"text": "query EditRiskViewQuery(\n $riskId: ID!\n $organizationId: ID!\n) {\n risk: node(id: $riskId) {\n __typename\n ... on Risk {\n id\n name\n description\n category\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n owner {\n id\n fullName\n }\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
}
};
})();
(node as any).hash = "616261dd100b7243f955cd94e39e7ac9";
(node as any).hash = "3ea38c607c8a1d3f18eaa964476f1529";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<feef659391195d68121d9db49de0ffc6>>
* @generated SignedSource<<5a97a0d2387d66d74de35ec9b5bc86cf>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -11,6 +11,7 @@
import { ConcreteRequest } from 'relay-runtime';
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type UpdateRiskInput = {
category?: string | null | undefined;
description?: string | null | undefined;
id: string;
inherentImpact?: number | null | undefined;
@@ -27,6 +28,7 @@ export type EditRiskViewUpdateRiskMutation$variables = {
export type EditRiskViewUpdateRiskMutation$data = {
readonly updateRisk: {
readonly risk: {
readonly category: string;
readonly description: string;
readonly id: string;
readonly inherentImpact: number;
@@ -101,6 +103,13 @@ v2 = [
"name": "description",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
},
{
"alias": null,
"args": null,
@@ -187,16 +196,16 @@ return {
"selections": (v2/*: any*/)
},
"params": {
"cacheID": "31fc731869a56e3bdc73aae7c114a385",
"cacheID": "a640c5be0a7614478f2d229154d9206a",
"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 treatment\n updatedAt\n owner {\n id\n fullName\n }\n }\n }\n}\n"
"text": "mutation EditRiskViewUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n id\n name\n description\n category\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n updatedAt\n owner {\n id\n fullName\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "777e70d85a1de9db8b625b1f5b109c7e";
(node as any).hash = "7f4cfbd3d1e3fa396b7ffbcac1e12b0a";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<121c9ad6ab399476692b98d1838f70d7>>
* @generated SignedSource<<f0234c8da839e9d7babc696edb1171aa>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -95,6 +95,13 @@ v8 = {
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v9 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
};
return {
"fragment": {
@@ -228,6 +235,7 @@ return {
"name": "description",
"storageKey": null
},
(v9/*: any*/),
{
"alias": null,
"args": null,
@@ -242,6 +250,66 @@ return {
"name": "updatedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v8/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 1
}
],
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mesures",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v9/*: any*/),
(v8/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": "mesures(first:1)"
},
(v7/*: any*/)
],
"storageKey": null
@@ -329,16 +397,16 @@ return {
]
},
"params": {
"cacheID": "402fdc7c2f504ba8640e2ecd2f8f2cb8",
"cacheID": "398efd65ce3f24d13b357e8cf32c4f6e",
"id": null,
"metadata": {},
"name": "ListRiskViewPaginationQuery",
"operationKind": "query",
"text": "query ListRiskViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ListRiskView_risks_pbnwq\n id\n }\n}\n\nfragment ListRiskView_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 treatment\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 ListRiskViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ListRiskView_risks_pbnwq\n id\n }\n}\n\nfragment ListRiskView_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 treatment\n description\n category\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n mesures(first: 1) {\n edges {\n node {\n category\n id\n }\n }\n }\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 = "a5f7d6424459d2a3b471bb0a4f0a4169";
(node as any).hash = "3fc46af4f252617f4547c988184bb168";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<677eff2bfb212e672f0d95b56adeebe7>>
* @generated SignedSource<<d4fc01f5c38bce1054b2198af7e021f2>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -96,6 +96,13 @@ v8 = {
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v9 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
};
return {
"fragment": {
@@ -230,6 +237,7 @@ return {
"name": "description",
"storageKey": null
},
(v9/*: any*/),
{
"alias": null,
"args": null,
@@ -244,6 +252,66 @@ return {
"name": "updatedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v6/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 1
}
],
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mesures",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v9/*: any*/),
(v6/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": "mesures(first:1)"
},
(v8/*: any*/)
],
"storageKey": null
@@ -331,12 +399,12 @@ return {
]
},
"params": {
"cacheID": "fcdb0ca740c0a11d5e4961407baadffa",
"cacheID": "519139d7f492b8d719abf1b0e788853a",
"id": null,
"metadata": {},
"name": "ListRiskViewQuery",
"operationKind": "query",
"text": "query ListRiskViewQuery(\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 ...ListRiskView_risks_pbnwq\n }\n}\n\nfragment ListRiskView_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 treatment\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 ListRiskViewQuery(\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 ...ListRiskView_risks_pbnwq\n }\n}\n\nfragment ListRiskView_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 treatment\n description\n category\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n mesures(first: 1) {\n edges {\n node {\n category\n id\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<9a0b8102088652729e5c161730fe26a9>>
* @generated SignedSource<<1dd4443afe99bdd114d082b0d175776d>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -17,12 +17,24 @@ export type ListRiskView_risks$data = {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly createdAt: string;
readonly description: string;
readonly id: string;
readonly inherentImpact: number;
readonly inherentLikelihood: number;
readonly mesures: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
};
}>;
};
readonly name: string;
readonly owner: {
readonly fullName: string;
readonly id: string;
} | null | undefined;
readonly residualImpact: number;
readonly residualLikelihood: number;
readonly treatment: RiskTreatment;
@@ -53,6 +65,13 @@ v1 = {
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
};
return {
"argumentDefinitions": [
@@ -185,6 +204,7 @@ return {
"name": "description",
"storageKey": null
},
(v2/*: any*/),
{
"alias": null,
"args": null,
@@ -199,6 +219,65 @@ return {
"name": "updatedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 1
}
],
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mesures",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": "mesures(first:1)"
},
{
"alias": null,
"args": null,
@@ -280,6 +359,6 @@ return {
};
})();
(node as any).hash = "a5f7d6424459d2a3b471bb0a4f0a4169";
(node as any).hash = "3fc46af4f252617f4547c988184bb168";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<f5de62a6351fe2691ad8aff671be4aad>>
* @generated SignedSource<<5b015e6ca9ba83b884026cca65dcdc1c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -11,6 +11,7 @@
import { ConcreteRequest } from 'relay-runtime';
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type CreateRiskInput = {
category: string;
description: string;
inherentImpact: number;
inherentLikelihood: number;
@@ -29,6 +30,7 @@ export type NewRiskViewCreateRiskMutation$data = {
readonly createRisk: {
readonly riskEdge: {
readonly node: {
readonly category: string;
readonly createdAt: string;
readonly description: string;
readonly id: string;
@@ -103,6 +105,13 @@ v3 = {
"name": "description",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
},
{
"alias": null,
"args": null,
@@ -224,16 +233,16 @@ return {
]
},
"params": {
"cacheID": "9f296661d12f36362aeecd2a1fd4aa63",
"cacheID": "c568f60a75535b2597f860405b4eba79",
"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 inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\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 category\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n createdAt\n updatedAt\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "7f70a20771d9f05f62e952a59c5484e3";
(node as any).hash = "bcacfff0f67ad5cf0ecbfe26c0a5b6f9";
export default node;