Skip to content

Commit

Permalink
Feat/redirect after mapping entity assesment creation (#984)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene authored Oct 26, 2024
1 parent 716418d commit faab97d
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 62 deletions.
19 changes: 16 additions & 3 deletions frontend/src/lib/utils/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ export async function defaultWriteFormAction({
event,
urlModel,
action,
doRedirect = true
doRedirect = true,
redirectToWrittenObject = false
}: {
event: RequestEvent;
urlModel: string;
action: FormAction;
doRedirect?: boolean;
redirectToWrittenObject?: boolean;
}) {
const formData = await event.request.formData();
if (!formData) {
Expand Down Expand Up @@ -154,20 +156,31 @@ export async function defaultWriteFormAction({
const next = getSecureRedirect(event.url.searchParams.get('next'));
if (next && doRedirect) redirect(302, next);

if (redirectToWrittenObject) {
return { form, redirect: `/${urlModel}/${writtenObject.id}` };
}
return { form };
}

export async function nestedWriteFormAction({
event,
action
action,
redirectToWrittenObject = false
}: {
event: RequestEvent;
action: FormAction;
redirectToWrittenObject: boolean;
}) {
const request = event.request.clone();
const formData = await request.formData();
const urlModel = formData.get('urlmodel') as string;
return defaultWriteFormAction({ event, urlModel, action, doRedirect: false });
return defaultWriteFormAction({
event,
urlModel,
action,
doRedirect: false,
redirectToWrittenObject
});
}

export async function defaultDeleteFormAction({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,13 @@ export const load: PageServerLoad = async ({ params, fetch }) => {

export const actions: Actions = {
create: async (event) => {
return defaultWriteFormAction({ event, urlModel: event.params.model!, action: 'create' });
const redirectToWrittenObject = Boolean(event.params.model === 'entity-assessments');
return defaultWriteFormAction({
event,
urlModel: event.params.model!,
action: 'create',
redirectToWrittenObject: redirectToWrittenObject
});
},
delete: async (event) => {
return defaultDeleteFormAction({ event, urlModel: event.params.model! });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import ModelTable from '$lib/components/ModelTable/ModelTable.svelte';
import type { ModalComponent, ModalSettings, ModalStore } from '@skeletonlabs/skeleton';
import { getModalStore } from '@skeletonlabs/skeleton';
import type { PageData } from './$types';
import type { ActionData, PageData } from './$types';
import * as m from '$paraglide/messages';
import { checkConstraints } from '$lib/utils/crud';
import { getSecureRedirect } from '$lib/utils/helpers';
import { goto } from '$app/navigation';
export let data: PageData;
export let form: ActionData;
$: URLModel = data.URLModel;
const modalStore: ModalStore = getModalStore();
Expand Down Expand Up @@ -42,6 +45,10 @@
}
modalStore.trigger(modal);
}
$: if (form && form.redirect) {
goto(getSecureRedirect(form.redirect));
}
</script>

{#if data.table}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export const load: PageServerLoad = async (event) => {

export const actions: Actions = {
create: async (event) => {
return nestedWriteFormAction({ event, action: 'create' });
const redirectToWrittenObject = Boolean(event.params.model === 'projects');
return nestedWriteFormAction({ event, action: 'create', redirectToWrittenObject });
},
delete: async (event) => {
return nestedDeleteFormAction({ event });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<script lang="ts">
import DetailView from '$lib/components/DetailView/DetailView.svelte';
import type { PageData } from './$types';
import type { PageData, ActionData } from './$types';
import { goto } from '$app/navigation';
import { getSecureRedirect } from '$lib/utils/helpers';
export let data: PageData;
export let form: ActionData;
$: if (form && form.redirect) {
goto(getSecureRedirect(form.redirect));
}
</script>

<DetailView {data} />
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ export const load: PageServerLoad = async ({ params, fetch }) => {

export const actions: Actions = {
create: async (event) => {
const redirectToWrittenObject = Boolean(event.params.model === 'compliance-assessments');
return defaultWriteFormAction({
event,
urlModel: event.params.model as string,
action: 'create'
action: 'create',
redirectToWrittenObject: redirectToWrittenObject
});
},
delete: async (event) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
import ModelTable from '$lib/components/ModelTable/ModelTable.svelte';
import type { ModalComponent, ModalSettings, ModalStore } from '@skeletonlabs/skeleton';
import { getModalStore } from '@skeletonlabs/skeleton';
import type { PageData } from './$types';
import type { PageData, ActionData } from './$types';
import * as m from '$paraglide/messages';
import { checkConstraints } from '$lib/utils/crud';
import { goto } from '$app/navigation';
import { getSecureRedirect } from '$lib/utils/helpers';
export let data: PageData;
export let form: ActionData;
$: URLModel = data.URLModel;
$: if (form && form.redirect) {
goto(getSecureRedirect(form.redirect));
}
const modalStore: ModalStore = getModalStore();
function modalCreateForm(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ export const load = (async ({ fetch, params }) => {

export const actions: Actions = {
create: async (event) => {
return nestedWriteFormAction({ event, action: 'create' });
const request = event.request.clone();
const formData = await request.formData();
const form = await superValidate(formData, zod(ComplianceAssessmentSchema));
const redirectToWrittenObject = Boolean(form.data.baseline);
return nestedWriteFormAction({ event, action: 'create', redirectToWrittenObject });
},
createSuggestedControls: async (event) => {
const formData = await event.request.formData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
TreeViewNode
} from '@skeletonlabs/skeleton';
import { getSecureRedirect } from '$lib/utils/helpers';
import { goto } from '$app/navigation';
import { getModalStore, getToastStore, popup, SlideToggle } from '@skeletonlabs/skeleton';
import type { ActionData, PageData } from './$types';
import TreeViewItemContent from './TreeViewItemContent.svelte';
Expand All @@ -26,7 +29,6 @@
import { URL_MODEL_MAP } from '$lib/utils/crud';
import type { Node } from './types';
import { toCamelCase } from '$lib/utils/locales';
import { safeTranslate } from '$lib/utils/i18n';
import * as m from '$paraglide/messages';
Expand All @@ -39,10 +41,10 @@
import { ProgressRadial } from '@skeletonlabs/skeleton';
import List from '$lib/components/List/List.svelte';
breadcrumbObject.set(data.compliance_assessment);
const tree = data.tree;
$: breadcrumbObject.set(data.compliance_assessment);
$: tree = data.tree;
const compliance_assessment_donut_values = data.compliance_assessment_donut_values;
$: compliance_assessment_donut_values = data.compliance_assessment_donut_values;
const user = $page.data.user;
const model = URL_MODEL_MAP['compliance-assessments'];
Expand Down Expand Up @@ -80,6 +82,7 @@
};
function transformToTreeView(nodes: Node[]) {
if (!tree) return [];
return nodes.map(([id, node]) => {
node.resultCounts = countResults(node);
const hasAssessableChildren = Object.keys(node.children || {}).length > 0;
Expand Down Expand Up @@ -108,7 +111,10 @@
};
});
}
const treeViewNodes: TreeViewNode[] = transformToTreeView(Object.entries(tree));
let treeViewNodes: TreeViewNode[];
$: if (tree) {
treeViewNodes = transformToTreeView(Object.entries(tree));
}
function assessableNodesCount(nodes: TreeViewNode[]): number {
let count = 0;
Expand Down Expand Up @@ -188,6 +194,10 @@
modalStore.trigger(modal);
}
$: if (form && form.redirect) {
goto(getSecureRedirect(form.redirect));
}
$: if (createAppliedControlsLoading === true && form) createAppliedControlsLoading = false;
</script>

Expand Down Expand Up @@ -251,46 +261,48 @@
</div>
{/each}
</div>
<div class="flex w-1/3 relative">
{#if data.global_score.score >= 0}
<div class="absolute font-bold text-sm">{m.maturity()}</div>
<div class="flex justify-center items-center w-full">
<ProgressRadial
stroke={100}
meter={displayScoreColor(data.global_score.score, data.global_score.max_score)}
font={125}
value={(data.global_score.score * 100) / data.global_score.max_score}
width={'w-52'}
>
{data.global_score.score}
</ProgressRadial>
</div>
{/if}
</div>
<div class="w-1/3">
<DonutChart
s_label="Result"
name="compliance_result"
title={m.compliance()}
orientation="horizontal"
values={compliance_assessment_donut_values.result.values}
colors={compliance_assessment_donut_values.result.values.map(
(object) => object.itemStyle.color
)}
/>
</div>
<div class="w-1/3">
<DonutChart
s_label="Status"
name="compliance_status"
title={m.progress()}
orientation="horizontal"
values={compliance_assessment_donut_values.status.values}
colors={compliance_assessment_donut_values.status.values.map(
(object) => object.itemStyle.color
)}
/>
</div>
{#key compliance_assessment_donut_values}
<div class="flex w-1/3 relative">
{#if data.global_score.score >= 0}
<div class="absolute font-bold text-sm">{m.maturity()}</div>
<div class="flex justify-center items-center w-full">
<ProgressRadial
stroke={100}
meter={displayScoreColor(data.global_score.score, data.global_score.max_score)}
font={125}
value={(data.global_score.score * 100) / data.global_score.max_score}
width={'w-52'}
>
{data.global_score.score}
</ProgressRadial>
</div>
{/if}
</div>
<div class="w-1/3">
<DonutChart
s_label="Result"
name="compliance_result"
title={m.compliance()}
orientation="horizontal"
values={compliance_assessment_donut_values.result.values}
colors={compliance_assessment_donut_values.result.values.map(
(object) => object.itemStyle.color
)}
/>
</div>
<div class="w-1/3">
<DonutChart
s_label="Status"
name="compliance_status"
title={m.progress()}
orientation="horizontal"
values={compliance_assessment_donut_values.status.values}
colors={compliance_assessment_donut_values.status.values.map(
(object) => object.itemStyle.color
)}
/>
</div>
{/key}
<div class="flex flex-col space-y-2 ml-4">
<div class="flex flex-row space-x-2">
<button class="btn variant-filled-primary w-full" use:popup={popupDownload}
Expand Down Expand Up @@ -379,7 +391,9 @@
<div class=" flex items-center font-semibold">
<span class="h4">{m.associatedRequirements()}</span>
<span class="badge variant-soft-primary ml-1">
{assessableNodesCount(treeViewNodes)}
{#if treeViewNodes}
{assessableNodesCount(treeViewNodes)}
{/if}
</span>
<div id="toggle" class="flex items-center justify-center space-x-4 text-xs ml-auto mr-4">
{#if $displayOnlyAssessableNodes}
Expand Down Expand Up @@ -408,12 +422,14 @@
<i class="fa-solid fa-diagram-project" />
<p>{m.mappingInferenceTip()}</p>
</div>
{#key $displayOnlyAssessableNodes}
<RecursiveTreeView
nodes={transformToTreeView(Object.entries(tree))}
bind:expandedNodes
hover="hover:bg-initial"
/>
{#key data}
{#key $displayOnlyAssessableNodes}
<RecursiveTreeView
nodes={transformToTreeView(Object.entries(tree))}
bind:expandedNodes
hover="hover:bg-initial"
/>
{/key}
{/key}
</div>
</div>
2 changes: 2 additions & 0 deletions frontend/tests/functional/detailed/common.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ for (const key of testPages) {
items[key].build,
'dependency' in items[key] ? items[key].dependency : null
);
await pages[key].goto();
await expect(page).toHaveURL(pages[key].url);

if (await pages[key].getRow(items[key].build.name || items[key].build.email).isHidden()) {
await pages[key].searchInput.fill(items[key].build.name || items[key].build.email);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ test('compliance assessments scoring is working properly', async ({
testObjectsData[requirement].build,
'dependency' in testObjectsData[requirement] ? testObjectsData[requirement].dependency : null
);

await requiredPage.goto();
await requiredPage.hasUrl();
}

await complianceAssessmentsPage.viewItemDetail(
Expand Down

0 comments on commit faab97d

Please sign in to comment.