Skip to content

Commit

Permalink
Ca 701 workshop 1 ux (#1170)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene authored Dec 12, 2024
1 parent 12085fc commit 4d177a3
Show file tree
Hide file tree
Showing 23 changed files with 582 additions and 98 deletions.
8 changes: 8 additions & 0 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@ class Meta:


class AssetWriteSerializer(BaseModelSerializer):
ebios_rm_studies = serializers.PrimaryKeyRelatedField(
many=True,
queryset=EbiosRMStudy.objects.all(),
required=False,
allow_null=True,
write_only=True,
)

class Meta:
model = Asset
fields = "__all__"
Expand Down
8 changes: 8 additions & 0 deletions frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -980,5 +980,13 @@
"attackPaths": "Attack paths",
"currentCriticality": "Current criticality",
"residualCriticality": "Residual criticality",
"ebiosRm": "Ebios RM",
"workshopOne": "Workshop 1",
"refIdSemiColon": "Refence ID:",
"addFearedEvent": "Add feared event",
"addEbiosRMstudy": "Add Ebios RM Study",
"noAuthor": "No author assigned",
"noReviewer": "No reviewer assigned",
"selectAudit": "Select audit",
"errorAssetGraphMustNotContainCycles": "The asset graph must not contain cycles."
}
5 changes: 3 additions & 2 deletions frontend/src/lib/components/Forms/ModelForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
export let suggestions: { [key: string]: any } = {};
export let cancelButton = true;
export let duplicate = false;
export let customNameDescription = false;
const URLModel = model.urlModel as urlModel;
export let schema = modelSchema(URLModel);
Expand Down Expand Up @@ -163,7 +164,7 @@
}}
/>
{/if}
{#if shape.name}
{#if shape.name && !customNameDescription}
<TextField
{form}
field="name"
Expand All @@ -173,7 +174,7 @@
data-focusindex="0"
/>
{/if}
{#if shape.description}
{#if shape.description && !customNameDescription}
<TextArea
{form}
field="description"
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/lib/components/Forms/ModelForm/AssetForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,15 @@
label={m.labels()}
allowUserOptions="append"
/>
{#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}
84 changes: 71 additions & 13 deletions frontend/src/lib/components/Forms/ModelForm/EbiosRmForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,40 @@
import type { ModelInfo, CacheLock } from '$lib/utils/types';
import TextField from '$lib/components/Forms/TextField.svelte';
import AutocompleteSelect from '$lib/components/Forms/AutocompleteSelect.svelte';
import Select from '$lib/components/Forms/Select.svelte';
import * as m from '$paraglide/messages.js';
import { getOptions } from '$lib/utils/crud';
import TextArea from '../TextArea.svelte';
import { page } from '$app/stores';
export let form: SuperValidated<any>;
export let model: ModelInfo;
export let cacheLocks: Record<string, CacheLock> = {};
export let formDataCache: Record<string, any> = {};
export let initialData: Record<string, any> = {};
export let context: string;
let activeActivity: string | null = null;
$page.url.searchParams.forEach((value, key) => {
if (key === 'activity' && value === 'one') {
activeActivity = 'one';
} else if (key === 'activity' && value === 'two') {
activeActivity = 'two';
}
});
</script>

{#if context !== 'ebiosRmStudy'}
{#if context != 'selectAudit'}
<TextField
{form}
field="name"
label={m.name()}
cacheLock={cacheLocks['name']}
bind:cachedValue={formDataCache['name']}
data-focusindex="0"
/>
{/if}
{#if context !== 'ebiosRmStudy' && context !== 'selectAudit'}
<TextField
{form}
field="version"
Expand Down Expand Up @@ -50,8 +70,26 @@
helpText={m.ebiosRmMatrixHelpText()}
/>
{:else if context === 'ebiosRmStudy'}
<div class="relative p-2 space-y-2 border rounded-md">
<p class="absolute -top-3 bg-white font-bold">{m.activityOne()}</p>
<div
class="relative p-2 space-y-2 rounded-md {activeActivity === 'one'
? 'border-2 border-primary-500'
: 'border-2 border-gray-300 border-dashed'}"
>
<p
class="absolute -top-3 bg-white font-bold {activeActivity === 'one'
? 'text-primary-500'
: 'text-gray-500'}"
>
{m.activityOne()}
</p>
<TextArea
{form}
field="description"
label={m.description()}
cacheLock={cacheLocks['description']}
bind:cachedValue={formDataCache['description']}
data-focusindex="1"
/>
<TextField
{form}
field="version"
Expand All @@ -66,13 +104,6 @@
cacheLock={cacheLocks['ref_id']}
bind:cachedValue={formDataCache['ref_id']}
/>
<TextArea
{form}
field="observation"
label={m.observation()}
cacheLock={cacheLocks['observation']}
bind:cachedValue={formDataCache['observation']}
/>
<AutocompleteSelect
multiple
{form}
Expand All @@ -92,8 +123,18 @@
label={m.reviewers()}
/>
</div>
<div class="relative p-2 space-y-2 border rounded-md">
<p class="absolute -top-3 bg-white font-bold">{m.activityTwo()}</p>
<div
class="relative p-2 space-y-2 rounded-md {activeActivity === 'two'
? 'border-2 border-primary-500'
: 'border-2 border-gray-300 border-dashed'}"
>
<p
class="absolute -top-3 bg-white font-bold {activeActivity === 'two'
? 'text-primary-500'
: 'text-gray-500'}"
>
{m.activityTwo()}
</p>
<AutocompleteSelect
multiple
{form}
Expand All @@ -106,4 +147,21 @@
label={m.assets()}
/>
</div>
<TextArea
{form}
field="observation"
label={m.observation()}
cacheLock={cacheLocks['observation']}
bind:cachedValue={formDataCache['observation']}
/>
{:else}
<AutocompleteSelect
multiple
{form}
options={getOptions({ objects: model.foreignKeys['compliance_assessments'] })}
field="compliance_assessments"
cacheLock={cacheLocks['compliance_assessments']}
bind:cachedValue={formDataCache['compliance_assessments']}
label={m.complianceAssessment()}
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import * as m from '$paraglide/messages.js';
import { getOptions } from '$lib/utils/crud';
import TextArea from '../TextArea.svelte';
import Checkbox from '$lib/components/Forms/Checkbox.svelte';
export let form: SuperValidated<any>;
export let model: ModelInfo;
Expand Down Expand Up @@ -66,3 +67,4 @@
field="qualifications"
label={m.qualifications()}
/>
<Checkbox {form} field="is_selected" label={m.isSelected()} />
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script lang="ts">
import type { SuperValidated } from 'sveltekit-superforms';
import type { ModelInfo, CacheLock } from '$lib/utils/types';
import TextField from '$lib/components/Forms/TextField.svelte';
import Checkbox from '$lib/components/Forms/Checkbox.svelte';
import AutocompleteSelect from '$lib/components/Forms/AutocompleteSelect.svelte';
import Select from '$lib/components/Forms/Select.svelte';
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib/components/Modals/CreateModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
const modalStore: ModalStore = getModalStore();
export let form: SuperValidated<AnyZodObject>;
export let customNameDescription = false;
export let model: ModelInfo;
export let duplicate = false;
export let invalidateAll = true; // set to false to keep form data using muliple forms on a page
Expand Down Expand Up @@ -47,6 +48,7 @@
</div>
<ModelForm
{form}
{customNameDescription}
{suggestions}
{parent}
{invalidateAll}
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/lib/components/Modals/UpdateModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts">
// Props
/** Exposes parent props to this component. */
export let parent: any;
// Stores
import type { ModelInfo } from '$lib/utils/types';
import type { ModalStore } from '@skeletonlabs/skeleton';
import { getModalStore } from '@skeletonlabs/skeleton';
const modalStore: ModalStore = getModalStore();
export let form: SuperValidated<AnyZodObject>;
export let model: ModelInfo;
export let invalidateAll = true; // set to false to keep form data using muliple forms on a page
export let formAction = '?/update';
export let context = 'default';
export let object: Record<string, any> = {};
let closeModal = true;
export let suggestions: { [key: string]: any } = {};
export let selectOptions: Record<string, any> = {};
export let foreignKeys: Record<string, any> = {};
// Base Classes
const cBase = 'card p-4 w-modal shadow-xl space-y-4';
const cHeader = 'text-2xl font-bold';
export let debug = false;
import ModelForm from '$lib/components/Forms/ModelForm.svelte';
import type { SuperValidated } from 'sveltekit-superforms';
import type { AnyZodObject } from 'zod';
</script>

{#if $modalStore[0]}
<div class="modal-example-form {cBase}">
<div class="flex items-center justify-between">
<header class={cHeader} data-testid="modal-title">
{$modalStore[0].title ?? '(title missing)'}
</header>
<div
role="button"
tabindex="0"
class="flex items-center hover:text-primary-500 cursor-pointer"
on:click={parent.onClose}
on:keydown={parent.onClose}
>
<i class="fa-solid fa-xmark" />
</div>
</div>
<ModelForm
customNameDescription
{form}
{object}
{suggestions}
{parent}
action={formAction}
{invalidateAll}
{model}
{closeModal}
{context}
caching={true}
{selectOptions}
{foreignKeys}
{debug}
/>
</div>
{/if}
9 changes: 6 additions & 3 deletions frontend/src/lib/components/ModelTable/ModelTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,12 @@
{#if pagination && rowsPerPage}
<RowsPerPage {handler} />
{/if}
{#if canCreateObject}
<slot name="addButton" />
{/if}
<div class="flex space-x-2 items-center">
<slot name="optButton" />
{#if canCreateObject}
<slot name="addButton" />
{/if}
</div>
</header>
<!-- Table -->
<table
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/lib/utils/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ export const URL_MODEL_MAP: ModelMap = {
{ field: 'parent_assets', urlModel: 'assets' },
{ field: 'owner', urlModel: 'users' },
{ field: 'folder', urlModel: 'folders', urlParams: 'content_type=DO&content_type=GL' },
{ field: 'filtering_labels', urlModel: 'filtering-labels' }
{ field: 'filtering_labels', urlModel: 'filtering-labels' },
{ field: 'ebios_rm_studies', urlModel: 'ebios-rm', endpointUrl: 'ebios-rm/studies' }
],
selectFields: [{ field: 'type' }],
filters: [
Expand Down Expand Up @@ -609,8 +610,10 @@ export const URL_MODEL_MAP: ModelMap = {
{ field: 'assets', urlModel: 'assets' },
{ field: 'authors', urlModel: 'users', urlParams: 'is_third_party=false' },
{ field: 'reviewers', urlModel: 'users', urlParams: 'is_third_party=false' },
{ field: 'folder', urlModel: 'folders', urlParams: 'content_type=DO' }
]
{ field: 'folder', urlModel: 'folders', urlParams: 'content_type=DO' },
{ field: 'compliance_assessments', urlModel: 'compliance-assessments' }
],
reverseForeignKeyFields: [{ field: 'ebios_rm_studies', urlModel: 'assets' }]
},
'feared-events': {
endpointUrl: 'ebios-rm/feared-events',
Expand All @@ -621,7 +624,7 @@ export const URL_MODEL_MAP: ModelMap = {
verboseNamePlural: 'Feared events',
foreignKeyFields: [
{ field: 'ebios_rm_study', urlModel: 'ebios-rm', endpointUrl: 'ebios-rm/studies' },
{ field: 'assets', urlModel: 'assets' },
{ field: 'assets', urlModel: 'assets', urlParams: 'ebios_rm_studies=' },
{ field: 'qualifications', urlModel: 'qualifications' }
],
selectFields: [{ field: 'gravity', valueType: 'number', detail: true }]
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/utils/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const loadDetail = async ({ event, model, id }) => {
if (info.foreignKeyFields) {
for (const keyField of info.foreignKeyFields) {
const queryParams = keyField.urlParams ? `?${keyField.urlParams}` : '';
const url = `${BASE_API_URL}/${keyField.urlModel}/${queryParams}`;
const url = `${BASE_API_URL}/${keyField.endpointUrl || keyField.urlModel}/${queryParams}`;
const response = await event.fetch(url);
if (response.ok) {
foreignKeys[keyField.field] = await response.json().then((data) => data.results);
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/lib/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ export const AssetSchema = z.object({
.optional(),
reference_link: z.string().url().optional().or(z.literal('')),
owner: z.string().uuid().optional().array().optional(),
filtering_labels: z.string().optional().array().optional()
filtering_labels: z.string().optional().array().optional(),
ebios_rm_studies: z.string().uuid().optional().array().optional()
});

export const FilteringLabelSchema = z.object({
Expand Down Expand Up @@ -400,7 +401,8 @@ export const ebiosRMSchema = z.object({
reviewers: z.array(z.string().optional()).optional(),
observation: z.string().optional().nullable(),
assets: z.string().uuid().optional().array().optional(),
folder: z.string()
folder: z.string(),
compliance_assessments: z.string().uuid().optional().array().optional()
});

export const fearedEventsSchema = z.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ export const load: LayoutServerLoad = async (event) => {
for (const keyField of foreignKeyFields) {
const queryParams = keyField.urlParams ? `?${keyField.urlParams}` : '';
const keyModel = getModelInfo(keyField.urlModel);
const url = keyModel.endpointUrl
let url = keyModel.endpointUrl
? `${BASE_API_URL}/${keyModel.endpointUrl}/${queryParams}`
: `${BASE_API_URL}/${keyModel.urlModel}/${queryParams}`;
if (keyModel.urlModel === 'assets' && event.params.model === 'feared-events') {
url = `${BASE_API_URL}/${keyModel.urlModel}/${queryParams}${object.ebios_rm_study}`;
}
const response = await event.fetch(url);
if (response.ok) {
foreignKeys[keyField.field] = await response.json().then((data) => data.results);
Expand Down
Loading

0 comments on commit 4d177a3

Please sign in to comment.