Skip to content

Commit

Permalink
feat: add nested risk analyses in workshop 5
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene committed Dec 6, 2024
1 parent 33a7a42 commit ab29baa
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 4 deletions.
1 change: 1 addition & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ class RiskAssessmentViewSet(BaseModelViewSet):
"authors",
"risk_matrix",
"status",
"ebios_rm_studies"
]

@action(detail=False, name="Risk assessments per status")
Expand Down
5 changes: 5 additions & 0 deletions backend/ebios_rm/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class EbiosRMStudyViewSet(BaseModelViewSet):
@action(detail=False, name="Get status choices")
def status(self, request):
return Response(dict(EbiosRMStudy.Status.choices))

@action(detail=True, name="Get risk matrix", url_path="risk-matrix")
def risk_matrix(self, request, pk=None):
ebios_rm_study = self.get_object()
return Response(RiskMatrixReadSerializer(ebios_rm_study.risk_matrix).data)

@method_decorator(cache_page(60 * LONG_CACHE_TTL))
@action(detail=True, name="Get likelihood choices")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@
],
ws5: [
{ title: safeTranslate(m.ebiosWs5_1()), status: riskAnalysisCreated ? 'done' : 'to_do', href: '#' },
{ title: safeTranslate(m.ebiosWs5_2()), status: 'done', href: '#' },
{ title: safeTranslate(m.ebiosWs5_3()), status: 'to_do', href: '#' },
{ title: safeTranslate(m.ebiosWs5_4()), status: 'to_do', href: '#' },
{ title: safeTranslate(m.ebiosWs5_5()), status: 'done', href: '#' }
{ title: safeTranslate(m.ebiosWs5_2()), status: 'done', href: `${$page.url.pathname}/workshop-five/risk-analyses?next=${$page.url.pathname}` },
{ title: safeTranslate(m.ebiosWs5_3()), status: 'to_do', href: `${$page.url.pathname}/workshop-five/risk-analyses?next=${$page.url.pathname}` },
{ title: safeTranslate(m.ebiosWs5_4()), status: 'to_do', href: `${$page.url.pathname}/workshop-five/risk-analyses?next=${$page.url.pathname}` },
{ title: safeTranslate(m.ebiosWs5_5()), status: 'done', href: `${$page.url.pathname}/workshop-five/risk-analyses?next=${$page.url.pathname}` }
]
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
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 = 'risk-assessments';
const createSchema = modelSchema(URLModel);
const ebiosMatrixRes = await fetch(`${BASE_API_URL}/ebios-rm/studies/${params.id}/risk-matrix/`);
const risk_matrix_id = await ebiosMatrixRes.json().then((res) => res.id);
const initialData = {
ebios_rm_studies: [params.id],
risk_matrix: risk_matrix_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: 'risk-assessments',
action: 'create'
// redirectToWrittenObject: redirectToWrittenObject
});
},
delete: async (event) => {
return defaultDeleteFormAction({ event, urlModel: 'risk-assessments' });
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<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, data.model.foreignKeys).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 ab29baa

Please sign in to comment.