Skip to content

Commit

Permalink
Add strategic scenarios page
Browse files Browse the repository at this point in the history
  • Loading branch information
nas-tabchiche committed Dec 5, 2024
1 parent 1e5ce90 commit e17f39c
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@
status: 'to_do',
href: `${$page.url.pathname}/workshop-three/ecosystem?next=${$page.url.pathname}`
},
{ title: safeTranslate(m.ebiosWs3_2()), status: 'to_do', href: '#' },
{
title: safeTranslate(m.ebiosWs3_2()),
status: 'to_do',
href: `${$page.url.pathname}/workshop-three/strategic-scenarios?next=${$page.url.pathname}`
},
{
title: safeTranslate(m.ebiosWs3_3()),
status: 'done',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { defaultDeleteFormAction, defaultWriteFormAction } from '$lib/utils/actions';
import { BASE_API_URL } from '$lib/utils/constants';
import { getModelInfo, urlParamModelForeignKeyFields } 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 = 'attack-paths';
const createSchema = modelSchema(URLModel);
const initialData = {
ebios_rm_study: params.id
};
const createForm = await superValidate(initialData, zod(createSchema), { errors: false });
const model: ModelInfo = getModelInfo(URLModel);
const foreignKeyFields = urlParamModelForeignKeyFields(URLModel);

const selectOptions: Record<string, any> = {};
if (model.selectFields) {
await Promise.all(
model.selectFields.map(async (selectField) => {
const url = model.endpointUrl
? `${BASE_API_URL}/${model.endpointUrl}/${selectField.field}`
: `${BASE_API_URL}/${model.urlModel}/${selectField.field}`;
const response = await fetch(url);
if (!response.ok) {
console.error(`Failed to fetch data from ${url}: ${response.statusText}`);
return null;
}
const data = await response.json();
if (data) {
selectOptions[selectField.field] = Object.entries(data).map(([key, value]) => ({
label: value,
value: key
}));
}
})
);
}
model.selectOptions = selectOptions;

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 endpoint = `${BASE_API_URL}/${model.endpointUrl}?ebios_rm_study=${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: 'attack-paths',
action: 'create'
// redirectToWrittenObject: redirectToWrittenObject
});
},
delete: async (event) => {
return defaultDeleteFormAction({ event, urlModel: 'attack-paths' });
}
};
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 e17f39c

Please sign in to comment.