Skip to content

Commit

Permalink
feat: add step 1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene committed Dec 4, 2024
1 parent 41373e5 commit 1abf468
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 6 deletions.
9 changes: 9 additions & 0 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from core.models import *
from iam.models import *
from ebios_rm.models import EbiosRMStudy

from rest_framework import serializers
from rest_framework.exceptions import PermissionDenied
Expand Down Expand Up @@ -593,6 +594,14 @@ class ComplianceAssessmentWriteSerializer(BaseModelSerializer):
required=False,
allow_null=True,
)
ebios_rm_studies = serializers.SlugRelatedField(
many=True,
slug_field="id",
queryset=EbiosRMStudy.objects.all(),
required=False,
allow_null=True,
write_only=True,
)
create_applied_controls_from_suggestions = serializers.BooleanField(
write_only=True, required=False, default=False
)
Expand Down
2 changes: 1 addition & 1 deletion backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1971,7 +1971,7 @@ class ComplianceAssessmentViewSet(BaseModelViewSet):
"""

model = ComplianceAssessment
filterset_fields = ["framework", "project", "status"]
filterset_fields = ["framework", "project", "status", "ebios_rm_studies"]
search_fields = ["name", "description", "ref_id"]
ordering_fields = ["name", "description"]

Expand Down
3 changes: 2 additions & 1 deletion frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -925,5 +925,6 @@
"activityTwo": "Activity 2",
"ebiosRmStudy": "Ebios RM study",
"qualifications": "Qualifications",
"impacts": "Impacts"
"impacts": "Impacts",
"ebiosRmStudies": "Ebios RM studies"
}
2 changes: 1 addition & 1 deletion frontend/src/lib/components/Forms/Form.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
const { form, message, tainted, delayed, errors, allErrors, enhance } = _form;
</script>

{#if debug}
{#if true}
<SuperDebug data={$form} />
<SuperDebug data={$tainted} />
<SuperDebug data={$errors} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@
options={getOptions({ objects: model.foreignKeys['baseline'] })}
/>
{/if}
{#if initialData.ebios_rm_studies}
<AutocompleteSelect
{form}
field="ebios_rm_studies"
multiple
cacheLock={cacheLocks['ebios_rm_studies']}
bind:cachedValue={formDataCache['ebios_rm_studies']}
label={m.ebiosRmStudies()}
options={getOptions({ objects: model.foreignKeys['ebios_rm_studies'] })}
hidden
/>
{/if}
<AutocompleteSelect
{form}
options={getOptions({
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/utils/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ export const URL_MODEL_MAP: ModelMap = {
{ field: 'framework', urlModel: 'frameworks' },
{ field: 'authors', urlModel: 'users' },
{ field: 'reviewers', urlModel: 'users', urlParams: 'is_third_party=false' },
{ field: 'baseline', urlModel: 'compliance-assessments' }
{ field: 'baseline', urlModel: 'compliance-assessments' },
{ field: 'ebios_rm_studies', urlModel: 'ebios-rm' }
],
selectFields: [{ field: 'status' }],
filters: [{ field: 'status' }]
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ export const ComplianceAssessmentSchema = baseNamedObject({
reviewers: z.array(z.string().optional()).optional(),
baseline: z.string().optional().nullable(),
create_applied_controls_from_suggestions: z.boolean().optional().default(false),
observation: z.string().optional().nullable()
observation: z.string().optional().nullable(),
ebios_rm_studies: z.string().uuid().optional().array().optional()
});

export const EvidenceSchema = baseNamedObject({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
status: 'to_do',
href: `${$page.url.pathname}/workshop-one/feared-events?next=${$page.url.pathname}`
},
{ title: safeTranslate(m.ebiosWs1_4()), status: 'to_do', href: '#' }
{
title: safeTranslate(m.ebiosWs1_4()),
status: 'to_do',
href: `${$page.url.pathname}/workshop-one/base?next=${$page.url.pathname}`
}
],
ws2: [
{ title: safeTranslate(m.ebiosWs2_1()), status: 'to_do', href: '#' },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { defaultDeleteFormAction, defaultWriteFormAction } from '$lib/utils/actions';
import { BASE_API_URL } from '$lib/utils/constants';
import {
getModelInfo,
urlParamModelForeignKeyFields,
urlParamModelSelectFields
} from '$lib/utils/crud';
import { modelSchema } from '$lib/utils/schemas';
import type { ModelInfo, urlModel } from '$lib/utils/types';
import { type Actions } from '@sveltejs/kit';
import { superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
import { z } from 'zod';
import type { PageServerLoad } from './$types';
import { listViewFields } from '$lib/utils/table';
import { tableSourceMapper, type TableSource } from '@skeletonlabs/skeleton';

export const load: PageServerLoad = async ({ params, fetch }) => {
const schema = z.object({ id: z.string().uuid() });
const deleteForm = await superValidate(zod(schema));
const URLModel = 'compliance-assessments';
const createSchema = modelSchema(URLModel);
const initialData = {
ebios_rm_studies: [params.id]
};
const createForm = await superValidate(initialData, zod(createSchema), { errors: false });
const model: ModelInfo = getModelInfo(URLModel);
const foreignKeyFields = urlParamModelForeignKeyFields(URLModel);
const selectFields = model.selectFields;

const foreignKeys: Record<string, any> = {};

for (const keyField of foreignKeyFields) {
const model = getModelInfo(keyField.urlModel);
const queryParams = keyField.urlParams ? `?${keyField.urlParams}` : '';
const url = model.endpointUrl
? `${BASE_API_URL}/${model.endpointUrl}/${queryParams}`
: `${BASE_API_URL}/${model.urlModel}/${queryParams}`;
const response = await fetch(url);
if (response.ok) {
foreignKeys[keyField.field] = await response.json().then((data) => data.results);
} else {
console.error(`Failed to fetch data for ${keyField.field}: ${response.statusText}`);
}
}

model['foreignKeys'] = foreignKeys;

const selectOptions: Record<string, any> = {};

if (selectFields) {
for (const selectField of selectFields) {
const url = `${BASE_API_URL}/${URLModel}/${
selectField.detail ? params.id + '/' : ''
}${selectField.field}/`;
const response = await fetch(url);
if (response.ok) {
selectOptions[selectField.field] = await response.json().then((data) =>
Object.entries(data).map(([key, value]) => ({
label: value,
value: key
}))
);
} else {
console.error(`Failed to fetch data for ${selectField.field}: ${response.statusText}`);
}
}
}

model['selectOptions'] = selectOptions;

const endpoint = model.endpointUrl
? `${BASE_API_URL}/${model.endpointUrl}?ebios_rm_studies=${params.id}`
: `${BASE_API_URL}/${model.urlModel}?ebios_rm_studies=${params.id}`;
const res = await fetch(endpoint);
const data = await res.json().then((res) => res.results);

const bodyData = tableSourceMapper(data, listViewFields[URLModel as urlModel].body);

const headData: Record<string, string> = listViewFields[URLModel as urlModel].body.reduce(
(obj, key, index) => {
obj[key] = listViewFields[URLModel as urlModel].head[index];
return obj;
},
{}
);

const table: TableSource = {
head: headData,
body: bodyData,
meta: data // metaData
};

return { createForm, deleteForm, model, URLModel, table };
};

export const actions: Actions = {
create: async (event) => {
// const redirectToWrittenObject = Boolean(event.params.model === 'entity-assessments');
return defaultWriteFormAction({
event,
urlModel: 'compliance-assessments',
action: 'create'
// redirectToWrittenObject: redirectToWrittenObject
});
},
delete: async (event) => {
return defaultDeleteFormAction({ event, urlModel: 'compliance-assessments' });
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts">
import ModelTable from '$lib/components/ModelTable/ModelTable.svelte';
import type { PageData } from './$types';
import { safeTranslate } from '$lib/utils/i18n';
import type { ModalComponent, ModalSettings, ModalStore } from '@skeletonlabs/skeleton';
import { getModalStore } from '@skeletonlabs/skeleton';
import CreateModal from '$lib/components/Modals/CreateModal.svelte';
import MissingConstraintsModal from '$lib/components/Modals/MissingConstraintsModal.svelte';
import { checkConstraints } from '$lib/utils/crud';
import * as m from '$paraglide/messages.js';
const modalStore: ModalStore = getModalStore();
export let data: PageData;
const URLModel = data.URLModel;
function modalCreateForm(): void {
let modalComponent: ModalComponent = {
ref: CreateModal,
props: {
form: data.createForm,
model: data.model
}
};
let modal: ModalSettings = {
type: 'component',
component: modalComponent,
// Data
title: safeTranslate('add-' + data.model.localName)
};
if (
checkConstraints(
data.createForm.constraints,
Object.fromEntries(
Object.entries(data.model.foreignKeys).filter(([key]) => key !== 'risk_matrix')
)
).length > 0
) {
modalComponent = {
ref: MissingConstraintsModal
};
modal = {
type: 'component',
component: modalComponent,
title: m.warning(),
body: safeTranslate('add-' + data.model.localName).toLowerCase(),
value: checkConstraints(data.createForm.constraints, data.model.foreignKeys)
};
}
modalStore.trigger(modal);
}
</script>

<ModelTable source={data.table} deleteForm={data.deleteForm} {URLModel}>
<div slot="addButton">
<span class="inline-flex overflow-hidden rounded-md border bg-white shadow-sm">
<button
class="inline-block border-e p-3 btn-mini-primary w-12 focus:relative"
data-testid="add-button"
title={safeTranslate('add-' + data.model.localName)}
on:click={modalCreateForm}
><i class="fa-solid fa-file-circle-plus"></i>
</button>
</span>
</div>
</ModelTable>

0 comments on commit 1abf468

Please sign in to comment.