Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjusted creation of manual evalaution results to new API #45

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/lib/api/evaluation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type ComplianceStatus =
| 'EVALUATION_STATUS_NOT_COMPLIANT'
| 'EVALUATION_STATUS_COMPLIANT'
| 'EVALUATION_STATUS_COMPLIANT_MANUALLY'
| 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY'
| 'EVALUATION_STATUS_PENDING'
| 'EVALUATION_STATUS_DELEGATED'
;
Expand All @@ -28,7 +29,8 @@ export interface EvaluationResult {
parentControlId?: string
timestamp: string,
failingAssessmentResultIds: string[]
comment?: string
comment?: string,
validUntil?: string
}

export async function startEvaluation(toe: TargetOfEvaluation): Promise<StartEvaluationResponse> {
Expand Down
67 changes: 52 additions & 15 deletions src/lib/components/AddEvaluationResultDialog.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
<script lang="ts" context="module">
export interface AddEvaluationResultEvent {
name: string;
comment: string;
validUntil: Date;
status: ComplianceStatus;
}
</script>

<script lang="ts">
import type { ComplianceStatus } from '$lib/api/evaluation';
import {
Dialog,
DialogOverlay,
Expand All @@ -7,16 +17,27 @@
TransitionRoot
} from '@rgossiaux/svelte-headlessui';
import { createEventDispatcher } from 'svelte';
import ComplianceStatusSelect from './ComplianceStatusSelect.svelte';
export let open = false;
let name: string;
let comment: string;

const dispatch = createEventDispatcher<{ addResult: { name: string; comment: string } }>();
const dispatch = createEventDispatcher<{
addResult: AddEvaluationResultEvent;
}>();

interface $$Events {
addResult: CustomEvent<AddEvaluationResultEvent>;
}

function submit() {
dispatch('addResult', { comment: comment, name: name });
let date = new Date();
date.setDate(date.getDate() + 30);
dispatch('addResult', { comment: comment, name: name, validUntil: date, status: status });
open = false;
}

let status: ComplianceStatus = 'EVALUATION_STATUS_COMPLIANT_MANUALLY';
</script>

<TransitionRoot show={open}>
Expand Down Expand Up @@ -52,31 +73,29 @@
</DialogTitle>
<p class="mt-1 text-sm leading-6 text-gray-600">
Using this form, you can provide a manual evaluation result that will be
considered as <b>compliant</b>.
considered as <ComplianceStatusSelect bind:status />
</p>

<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="mt-2 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-4">
<label
for="username"
class="block text-sm font-medium leading-6 text-gray-900">Name</label
>
<label for="name" class="block text-sm font-medium leading-6 text-gray-900">
Name
</label>
<div class="mt-2">
<input
type="text"
name="first-name"
id="first-name"
autocomplete="given-name"
name="name"
id="name"
autocomplete="name"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-clouditor sm:text-sm sm:leading-6"
bind:value={name}
/>
</div>
</div>

<div class="col-span-full">
<label for="about" class="block text-sm font-medium leading-6 text-gray-900"
>Comment</label
>
<label for="about" class="block text-sm font-medium leading-6 text-gray-900">
Comment
</label>
<div class="mt-2">
<textarea
id="about"
Expand All @@ -91,6 +110,24 @@
based on your comment.
</p>
</div>

<div class="sm:col-span-4">
<label
for="validity"
class="block text-sm font-medium leading-6 text-gray-900">Validity</label
>
<div class="mt-2">
<input
type="text"
name="first-name"
id="first-name"
autocomplete="given-name"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-clouditor sm:text-sm sm:leading-6"
value="1 month"
disabled
/>
</div>
</div>
</div>
<div class="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
<button
Expand Down
13 changes: 11 additions & 2 deletions src/lib/components/ComplianceChart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@
export let toe: TargetOfEvaluation;

const data = {
labels: ['Non Compliant', 'Compliant', 'Manually set to Compliant', 'Waiting for Data'],
labels: [
'Non Compliant',
'Manually set to 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_NOT_COMPLIANT_MANUALLY'
).length,
Array.from(compliance.values()).filter((value) => value == 'EVALUATION_STATUS_COMPLIANT')
.length,
Array.from(compliance.values()).filter(
Expand All @@ -26,7 +35,7 @@
Array.from(compliance.values()).filter((value) => value == 'EVALUATION_STATUS_PENDING')
.length
],
backgroundColor: ['#991b1b', '#166534', '#007fc3', '#d4d4d4'],
backgroundColor: ['#991b1b', '#991b1b', '#166534', '#166534', '#d4d4d4'],
hoverOffset: 4
}
]
Expand Down
87 changes: 87 additions & 0 deletions src/lib/components/ComplianceStatusSelect.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script lang="ts">
import type { ComplianceStatus } from '$lib/api/evaluation';
import {
Listbox,
ListboxButton,
ListboxLabel,
ListboxOption,
ListboxOptions,
Transition
} from '@rgossiaux/svelte-headlessui';
import { Check, ChevronDown } from '@steeze-ui/heroicons';
import { Icon } from '@steeze-ui/svelte-icon';

const publishingOptions = [
{
name: 'Compliant',
description: 'This job posting can be viewed by anyone who has the link.',
bgColor: 'bg-green-800',
hoverColor: 'hover:bg-green-900 focus:ring-green-800',
divideColor: 'divide-green-900',
status: 'EVALUATION_STATUS_COMPLIANT_MANUALLY'
},
{
name: 'Non-Compliant',
description: 'This job posting will no longer be publicly accessible.',
bgColor: 'bg-red-800',
hoverColor: 'hover:bg-red-900 focus:ring-red-900',
divideColor: 'divide-red-900',
status: 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY'
}
];

export let status: ComplianceStatus = 'EVALUATION_STATUS_COMPLIANT_MANUALLY';

$: selected =
status == 'EVALUATION_STATUS_COMPLIANT_MANUALLY' ? publishingOptions[0] : publishingOptions[1];
</script>

<Listbox bind:value={status}>
<ListboxLabel class="sr-only">Change published status</ListboxLabel>
<div class="relative">
<div class="inline-flex divide-x {selected.divideColor} rounded-md shadow-sm">
<div
class="inline-flex items-center gap-x-1.5 rounded-l-md px-3 py-2 text-white shadow-sm {selected.bgColor}"
>
<Icon src={Check} class="-ml-0.5 h-5 w-5" aria-hidden="true" />
<p class="text-sm font-semibold">{selected.name}</p>
</div>
<ListboxButton
class="inline-flex items-center rounded-l-none rounded-r-md {selected.bgColor} {selected.hoverColor} p-2 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-50"
>
<span class="sr-only">Change published status</span>
<Icon src={ChevronDown} class="h-5 w-5 text-white" aria-hidden="true" />
</ListboxButton>
</div>

<Transition leave="transition ease-in duration-100" leaveFrom="opacity-100" leaveTo="opacity-0">
<ListboxOptions
class="absolute right-0 z-10 mt-2 w-72 origin-top-right divide-y divide-gray-200 overflow-hidden rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
{#each publishingOptions as option (option.name)}
<ListboxOption value={option.status} let:active let:selected>
<li
class="{active
? 'bg-clouditor text-white'
: 'text-gray-900'} cursor-default select-none p-4 text-sm"
>
<div class="flex flex-col">
<div class="flex justify-between">
<p class={selected ? 'font-semibold' : 'font-normal'}>{option.name}</p>
{#if selected}
<span class="active ? 'text-white' : 'text-clouditor'">
<Icon src={Check} class="h-5 w-5" aria-hidden="true" />
</span>
{/if}
</div>
<p class="{active ? 'text-indigo-200' : 'text-gray-500'} mt-2">
{option.description}
</p>
</div>
</li>
</ListboxOption>
{/each}
</ListboxOptions>
</Transition>
</div>
</Listbox>
4 changes: 3 additions & 1 deletion src/lib/components/ControlComplianceItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
{#if result.status == 'EVALUATION_STATUS_COMPLIANT'}
<Icon src={CheckCircle} theme="solid" class="w-8 h-8 text-green-800" />
{:else if result.status == 'EVALUATION_STATUS_COMPLIANT_MANUALLY'}
<Icon src={CheckCircle} theme="solid" class="w-8 h-8 text-clouditor" />
<Icon src={CheckCircle} theme="solid" class="w-8 h-8 text-green-800" />
{:else if result.status == 'EVALUATION_STATUS_NOT_COMPLIANT_MANUALLY'}
<Icon src={XCircle} theme="solid" class="w-8 h-8 text-red-800" />
{:else if result.status == 'EVALUATION_STATUS_PENDING'}
<button on:click={addResult}>
<Icon src={EllipsisHorizontalCircle} theme="solid" class="w-8 h-8 text-gray-400" />
Expand Down
14 changes: 10 additions & 4 deletions src/routes/(app)/cloud/[id]/compliance/[catalogId]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<script lang="ts">
import { invalidate } from '$app/navigation';
import { createEvaluationResult, type EvaluationResult } from '$lib/api/evaluation';
import type { Control } from '$lib/api/orchestrator';
import type { AddEvaluationResultEvent } from '$lib/components/AddEvaluationResultDialog.svelte';
import ControlComplianceItem from '$lib/components/ControlComplianceItem.svelte';
import { Disclosure, DisclosureButton, DisclosurePanel } from '@rgossiaux/svelte-headlessui';
import { Minus, Plus } from '@steeze-ui/heroicons';
import { Icon } from '@steeze-ui/svelte-icon';
import type { PageData } from './$types';
import { invalidate } from '$app/navigation';

export let data: PageData;

Expand Down Expand Up @@ -64,18 +65,23 @@
return tree;
}

async function addResult(e: CustomEvent<{ name: string; comment: string }>, control: Control) {
async function addResult(e: CustomEvent<AddEvaluationResultEvent>, control?: Control) {
if (control == undefined) {
return;
}

let result: EvaluationResult = {
id: '',
controlId: control.id,
cloudServiceId: data.service.id,
controlCategoryName: control.categoryName,
controlCatalogId: data.catalog.id,
parentControlId: control.parentControlId,
status: 'EVALUATION_STATUS_COMPLIANT_MANUALLY',
status: e.detail.status,
timestamp: new Date().toISOString(),
failingAssessmentResultIds: [],
comment: e.detail.comment
comment: e.detail.comment,
validUntil: e.detail.validUntil.toISOString()
};

result = await createEvaluationResult(result);
Expand Down