-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Add missing risk chart for assessment review
Signed-off-by: ibolton336 <[email protected]>
- Loading branch information
1 parent
4a90493
commit 3a69a0b
Showing
2 changed files
with
192 additions
and
2 deletions.
There are no files selected for viewing
179 changes: 179 additions & 0 deletions
179
.../app/components/application-assessment-donut-chart/application-assessment-donut-chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
import React, { useMemo } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { ChartDonut, ChartLegend } from "@patternfly/react-charts"; | ||
import { RISK_LIST } from "@app/Constants"; | ||
import { | ||
Assessment, | ||
Section, | ||
IdRef, | ||
AssessmentWithArchetypeApplications, | ||
} from "@app/api/models"; | ||
|
||
import { global_palette_blue_300 as defaultColor } from "@patternfly/react-tokens"; | ||
import { useFetchAssessmentsWithArchetypeApplications } from "@app/queries/assessments"; | ||
|
||
export interface ChartData { | ||
red: number; | ||
amber: number; | ||
green: number; | ||
unknown: number; | ||
} | ||
|
||
export const getChartDataFromCategories = ( | ||
categories: Section[] | ||
): ChartData => { | ||
let green = 0; | ||
let amber = 0; | ||
let red = 0; | ||
let unknown = 0; | ||
|
||
categories | ||
.flatMap((f) => f.questions) | ||
.flatMap((f) => f.answers) | ||
.filter((f) => f.selected === true) | ||
.forEach((f) => { | ||
switch (f.risk) { | ||
case "GREEN": | ||
green++; | ||
break; | ||
case "yellow": | ||
amber++; | ||
break; | ||
case "RED": | ||
red++; | ||
break; | ||
default: | ||
unknown++; | ||
} | ||
}); | ||
|
||
return { | ||
red, | ||
amber, | ||
green, | ||
unknown, | ||
} as ChartData; | ||
}; | ||
|
||
export const getChartDataFromMultipleAssessments = ( | ||
assessments: Assessment[] | ||
): ChartData => { | ||
let green = 0, | ||
amber = 0, | ||
red = 0, | ||
unknown = 0; | ||
|
||
assessments.forEach((assessment) => { | ||
assessment.sections | ||
.flatMap((section) => section.questions) | ||
.flatMap((question) => question.answers) | ||
.filter((answer) => answer.selected) | ||
.forEach((answer) => { | ||
switch (answer.risk) { | ||
case "green": | ||
green++; | ||
break; | ||
case "yellow": | ||
amber++; | ||
break; | ||
case "red": | ||
red++; | ||
break; | ||
default: | ||
unknown++; | ||
} | ||
}); | ||
}); | ||
|
||
return { red, amber, green, unknown }; | ||
}; | ||
|
||
export interface IApplicationAssessmentDonutChartProps { | ||
assessmentRefs?: IdRef[]; | ||
} | ||
|
||
export const ApplicationAssessmentDonutChart: React.FC< | ||
IApplicationAssessmentDonutChartProps | ||
> = ({ assessmentRefs }) => { | ||
const { t } = useTranslation(); | ||
const { assessmentsWithArchetypeApplications } = | ||
useFetchAssessmentsWithArchetypeApplications(); | ||
|
||
const filterAssessmentsByRefs = ( | ||
assessments: AssessmentWithArchetypeApplications[], | ||
refs: IdRef[] | ||
) => { | ||
if (refs && refs.length > 0) { | ||
return assessments.filter((assessment) => | ||
refs.some((ref) => ref.id === assessment.id) | ||
); | ||
} | ||
return assessments; | ||
}; | ||
|
||
const filteredAssessments = filterAssessmentsByRefs( | ||
assessmentsWithArchetypeApplications, | ||
assessmentRefs || [] | ||
); | ||
|
||
const charData: ChartData = useMemo(() => { | ||
return getChartDataFromMultipleAssessments(filteredAssessments); | ||
}, [filteredAssessments]); | ||
|
||
const chartDefinition = [ | ||
{ | ||
x: t(RISK_LIST["green"].i18Key), | ||
y: charData.green, | ||
color: RISK_LIST["green"].hexColor, | ||
}, | ||
{ | ||
x: t(RISK_LIST["yellow"].i18Key), | ||
y: charData.amber, | ||
color: RISK_LIST["yellow"].hexColor, | ||
}, | ||
{ | ||
x: t(RISK_LIST["red"].i18Key), | ||
y: charData.red, | ||
color: RISK_LIST["red"].hexColor, | ||
}, | ||
{ | ||
x: t(RISK_LIST["unknown"].i18Key), | ||
y: charData.unknown, | ||
color: RISK_LIST["unknown"].hexColor, | ||
}, | ||
].filter((f) => f.y > 0); | ||
|
||
return ( | ||
<div style={{ height: "250px", width: "380px" }}> | ||
<ChartDonut | ||
ariaDesc="risk-donut-chart" | ||
constrainToVisibleArea={true} | ||
data={chartDefinition.map((elem) => ({ x: elem.x, y: elem.y }))} | ||
labels={({ datum }) => `${datum.x}: ${datum.y}`} | ||
colorScale={chartDefinition.map( | ||
(elem) => elem.color || defaultColor.value | ||
)} | ||
legendComponent={ | ||
<ChartLegend | ||
data={chartDefinition.map((elem) => ({ | ||
name: `${elem.x}: ${elem.y}`, | ||
}))} | ||
colorScale={chartDefinition.map( | ||
(elem) => elem.color || defaultColor.value | ||
)} | ||
/> | ||
} | ||
legendOrientation="vertical" | ||
legendPosition="right" | ||
padding={{ | ||
bottom: 20, | ||
left: 20, | ||
right: 140, | ||
top: 20, | ||
}} | ||
innerRadius={50} | ||
width={380} | ||
/> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters