diff --git a/src/lib/components/ComplianceChart.svelte b/src/lib/components/ComplianceChart.svelte index 47693b1..6c76258 100644 --- a/src/lib/components/ComplianceChart.svelte +++ b/src/lib/components/ComplianceChart.svelte @@ -2,11 +2,11 @@ import { goto } from '$app/navigation'; import type { ComplianceStatus } from '$lib/api/evaluation'; import type { TargetOfEvaluation } from '$lib/api/orchestrator'; - import { Chart, type ChartConfiguration, type ChartData } from 'chart.js/auto'; + import { ArcElement, Chart, type ChartConfiguration, type ChartData } from 'chart.js/auto'; import { onMount } from 'svelte'; let canvas: HTMLCanvasElement; - let chart: Chart; + let chart: Chart<'doughnut', { status: string[]; num: number }[]>; export let compliance: Map; export let toe: TargetOfEvaluation; @@ -15,10 +15,13 @@ $: data = buildData(merge); $: updateChart(data); - let config: ChartConfiguration = { + let config: ChartConfiguration<'doughnut', { status: string[]; num: number }[]> = { type: 'doughnut', data: buildData(merge), options: { + parsing: { + key: 'num' + }, animation: false, plugins: { tooltip: { @@ -55,23 +58,26 @@ if (res.length === 0) { return; } else { - goto( - `/cloud/${toe.cloudServiceId}/compliance/${toe.catalogId}/?status=${data.labels[ - res[0].index - ].replace(/\s/g, '')}` - ); + const data = chart.data.datasets[0].data[res[0].index]; + const params = new URLSearchParams(); + + for (const s of data.status) { + params.append('status', s); + } + + goto(`/cloud/${toe.cloudServiceId}/compliance/${toe.catalogId}?${params.toString()}`); } }; }); - function updateChart(data: ChartData) { + function updateChart(data: ChartData<'doughnut', { status: string[]; num: number }[]>) { if (chart) { chart.data = data; chart.update(); } } - function buildData(merge: boolean) { + function buildData(merge: boolean): ChartData<'doughnut', { status: string[]; num: number }[]> { if (merge) { return { labels: ['Non Compliant', 'Compliant', 'Waiting for Data'], @@ -79,19 +85,12 @@ { label: toe.catalogId, data: [ - Array.from(compliance.values()).filter( - (value) => - value == 'EVALUATION_STATUS_NOT_COMPLIANT' || - value == 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY' - ).length, - Array.from(compliance.values()).filter( - (value) => - value == 'EVALUATION_STATUS_COMPLIANT' || - value == 'EVALUATION_STATUS_COMPLIANT_MANUALLY' - ).length, - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_PENDING' - ).length + filter([ + 'EVALUATION_STATUS_NOT_COMPLIANT', + 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY' + ]), + filter(['EVALUATION_STATUS_COMPLIANT', 'EVALUATION_STATUS_COMPLIANT_MANUALLY']), + filter(['EVALUATION_STATUS_PENDING']) ], backgroundColor: ['#991b1b', '#166534', '#d4d4d4'], hoverOffset: 4 @@ -111,21 +110,11 @@ { label: toe.catalogId, data: [ - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_NOT_COMPLIANT' - ).length, - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY' - ).length, - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_COMPLIANT' - ).length, - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_COMPLIANT_MANUALLY' - ).length, - Array.from(compliance.values()).filter( - (value) => value == 'EVALUATION_STATUS_PENDING' - ).length + filter(['EVALUATION_STATUS_NOT_COMPLIANT']), + filter(['EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY']), + filter(['EVALUATION_STATUS_COMPLIANT']), + filter(['EVALUATION_STATUS_COMPLIANT_MANUALLY']), + filter(['EVALUATION_STATUS_PENDING']) ], backgroundColor: ['#991b1b', 'rgb(185 28 28)', '#166534', 'rgb(21 128 61)', '#d4d4d4'], hoverOffset: 4 @@ -134,6 +123,13 @@ }; } } + + function filter(status: string[]) { + return { + status: status, + num: Array.from(compliance.values()).filter((value) => status.includes(value)).length + }; + }
diff --git a/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte b/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte index f66ed08..38677de 100644 --- a/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte +++ b/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte @@ -18,14 +18,6 @@ $: tree = buildTree(data.evaluations, data.filterStatus); - const queryParamToStatus: Map = new Map([ - ['Compliant', 'EVALUATION_STATUS_COMPLIANT'], - ['NonCompliant', 'EVALUATION_STATUS_NOT_COMPLIANT'], - ['ManuallysettoNonCompliant', 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY'], - ['ManuallysettoCompliant', 'EVALUATION_STATUS_COMPLIANT_MANUALLY'], - ['WaitingforData', 'EVALUATION_STATUS_PENDING'] - ]); - /** * This function builds a tree-like structure out of the evaluation results, * with the first level comprising of the top level controls. The second level @@ -33,14 +25,11 @@ * * @param results */ - function buildTree( - results: EvaluationResult[], - status: string | null - ): Map { + function buildTree(results: EvaluationResult[], status: string[]): Map { const tree = new Map(); for (const result of results) { - if (status !== null && result.status !== queryParamToStatus.get(status)) { + if (status !== null && !status.includes(result.status)) { continue; } @@ -57,7 +46,7 @@ continue; } - if (status !== null && result.status == queryParamToStatus.get(status)) { + if (status !== null && status.includes(result.status)) { parent.children.push(result); } } diff --git a/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.ts b/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.ts index f2211e0..6e3cb73 100644 --- a/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.ts +++ b/src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.ts @@ -24,7 +24,7 @@ export const load = (async ({ fetch, params, url }) => { const controls = new Map( (await listControls(params.catalogId, undefined, fetch)).map((c) => [c.id, c]) ); - const filterStatus = url.searchParams.get('status'); + const filterStatus = url.searchParams.getAll('status'); return { evaluations,