Skip to content

Commit

Permalink
30 jump to assessment results and filter them if you click on segment…
Browse files Browse the repository at this point in the history
… in compliance pie chart (#40)

* Add onclick event to Chart slices

* Add filter feature if status is set in URL

* Remove unnecessary getElementById
  • Loading branch information
70mm1 authored Sep 11, 2023
1 parent 7c5725f commit 2828d56
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 67 deletions.
119 changes: 67 additions & 52 deletions src/lib/components/ComplianceChart.svelte
Original file line number Diff line number Diff line change
@@ -1,72 +1,87 @@
<script lang="ts">
import { goto } from '$app/navigation';
import type { ComplianceStatus } from '$lib/api/evaluation';
import type { TargetOfEvaluation } from '$lib/api/orchestrator';
import { Chart, type ChartConfiguration } from 'chart.js/auto';
import { onMount } from 'svelte';
let canvas: HTMLCanvasElement;
export let compliance: Map<string, ComplianceStatus>;
export let toe: TargetOfEvaluation;
onMount(() => {
const data = {
labels: ['Non Compliant', 'Compliant', 'Manually set to Compliant', 'Waiting for Data'],
datasets: [
{
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_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
],
backgroundColor: ['#991b1b', '#166534', '#007fc3', '#d4d4d4'],
hoverOffset: 4
}
]
};
const data = {
labels: ['Non Compliant', 'Compliant', 'Manually set to Compliant', 'Waiting for Data'],
datasets: [
{
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_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
],
backgroundColor: ['#991b1b', '#166534', '#007fc3', '#d4d4d4'],
hoverOffset: 4
}
]
};
const config: ChartConfiguration = {
type: 'doughnut',
data: data,
options: {
animation: false,
plugins: {
tooltip: {
titleFont: {
family: 'Inter var'
},
bodyFont: {
family: 'Inter var'
},
footerFont: {
family: 'Inter var'
}
const config: ChartConfiguration = {
type: 'doughnut',
data: data,
options: {
animation: false,
plugins: {
tooltip: {
titleFont: {
family: 'Inter var'
},
bodyFont: {
family: 'Inter var'
},
legend: {
display: false,
labels: {
font: {
family: 'Inter var'
}
footerFont: {
family: 'Inter var'
}
},
legend: {
display: false,
labels: {
font: {
family: 'Inter var'
}
}
}
}
};
}
};
new Chart(canvas, config);
});
onMount(() => {
let chart = new Chart(canvas, config);
export let compliance: Map<string, ComplianceStatus>;
export let toe: TargetOfEvaluation;
canvas.onclick = (evt) => {
const res = chart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true);
console.log(res);
if (res.length === 0) {
return;
} else {
goto(
`/cloud/${toe.cloudServiceId}/compliance/${toe.catalogId}/?status=${data.labels[
res[0].index
].replace(/\s/g, '')}`
);
}
};
});
</script>

<div class="py-3">
<canvas id="acquisitions" bind:this={canvas} class="h-72 w-72 ml-auto mr-auto" />
<canvas id="chart" bind:this={canvas} class="h-72 w-72 ml-auto mr-auto" />
</div>
22 changes: 19 additions & 3 deletions src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
children: EvaluationResult[];
}
$: tree = buildTree(data.evaluations);
$: tree = buildTree(data.evaluations, data.filterStatus);
const queryParamToStatus: Map<string, string> = new Map([
['Compliant', 'EVALUATION_STATUS_COMPLIANT'],
['NonCompliant', 'EVALUATION_STATUS_NOT_COMPLIANT'],
['ManuallysettoCompliant', 'EVALUATION_STATUS_COMPLIANT_MANUALLY'],
['WaitingforData', 'EVALUATION_STATUS_PENDING']
]);
/**
* This function builds a tree-like structure out of the evaluation results,
Expand All @@ -24,10 +31,17 @@
*
* @param results
*/
function buildTree(results: EvaluationResult[]): Map<string, TreeItemData> {
function buildTree(
results: EvaluationResult[],
status: string | null
): Map<string, TreeItemData> {
const tree = new Map<string, TreeItemData>();
for (const result of results) {
if (status !== null && result.status !== queryParamToStatus.get(status)) {
continue;
}
// Top level control is at the first level of the tree
if (result.parentControlId === undefined) {
tree.set(result.controlId, {
Expand All @@ -41,7 +55,9 @@
continue;
}
parent.children.push(result);
if (status !== null && result.status == queryParamToStatus.get(status)) {
parent.children.push(result);
}
}
}
Expand Down
33 changes: 21 additions & 12 deletions src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import { listEvaluationResults } from "$lib/api/evaluation";
import { getCatalog, listControls } from "$lib/api/orchestrator";
import { error } from "@sveltejs/kit";
import type { PageLoad } from "./$types";
import { listEvaluationResults } from '$lib/api/evaluation';
import { getCatalog, listControls } from '$lib/api/orchestrator';

export const load = (async ({ fetch, params }) => {
import { error } from '@sveltejs/kit';

import type { PageLoad } from './$types';

export const load = (async ({ fetch, params, url }) => {
if (params.id == undefined) {
throw error(405, "Required parameter missing")
throw error(405, 'Required parameter missing');
}

const catalog = getCatalog(params.catalogId, fetch)
const catalog = getCatalog(params.catalogId, fetch);

const evaluations = listEvaluationResults(
{
cloudServiceId: params.id,
catalogId: params.catalogId
}, true, fetch)
},
true,
fetch
);

const controls = new Map((await listControls(params.catalogId, undefined, fetch)).map(c => [c.id, c]))
const controls = new Map(
(await listControls(params.catalogId, undefined, fetch)).map((c) => [c.id, c])
);
const filterStatus = url.searchParams.get('status');

return {
evaluations,
catalog,
controls
}
}) satisfies PageLoad
controls,
filterStatus
};
}) satisfies PageLoad;

0 comments on commit 2828d56

Please sign in to comment.