diff --git a/src/components/model/ModelAssociations.svelte b/src/components/model/ModelAssociations.svelte index 53e6d97c54..865719cbb9 100644 --- a/src/components/model/ModelAssociations.svelte +++ b/src/components/model/ModelAssociations.svelte @@ -33,14 +33,12 @@ close: void; save: void; selectAssociation: Association; - updateSpecifications: Record< - number, - { - priority?: number; - revision: number | null; - selected: boolean; - } - >; + updateSpecifications: { + id: number; + priority?: number; + revision: number | null; + selected: boolean; + }; }>(); let metadataMap: Record = {}; @@ -106,11 +104,9 @@ detail: { id, priority }, } = event; dispatch('updateSpecifications', { - ...selectedSpecifications, - [id]: { - ...selectedSpecifications[id], - priority, - }, + ...selectedSpecifications[id], + id, + priority, }); } @@ -119,11 +115,9 @@ detail: { id, revision }, } = event; dispatch('updateSpecifications', { - ...selectedSpecifications, - [id]: { - ...selectedSpecifications[id], - revision, - }, + ...selectedSpecifications[id], + id, + revision, }); } @@ -204,16 +198,16 @@
{#if model !== null && selectedSpecificationsList.length > 0} {#each selectedSpecificationsList as spec} - {#if spec.selected} + {#if spec.selected && metadataMap[spec.id]} {#if selectedAssociationId === 'goal'} revision)} + revisions={metadataMap[spec.id].versions.map(({ revision }) => revision)} selectedRevision={selectedSpecifications[spec.id].revision} on:updatePriority={onUpdatePriority} on:updateRevision={onUpdateRevision} @@ -224,9 +218,9 @@ hasEditPermission={hasEditSpecPermission} isSelected={selectedSpecification?.id === spec.id} metadataId={spec.id} - metadataName={metadataMap[spec.id]?.name} + metadataName={metadataMap[spec.id].name} metadataType={selectedAssociationId} - revisions={metadataMap[spec.id]?.versions.map(({ revision }) => revision)} + revisions={metadataMap[spec.id].versions.map(({ revision }) => revision)} selectedRevision={selectedSpecifications[spec.id].revision} on:updateRevision={onUpdateRevision} on:selectSpecification={onSelectSpecification} diff --git a/src/components/model/ModelAssociationsListItem.svelte b/src/components/model/ModelAssociationsListItem.svelte index 00f1dc7393..e85aa0f41a 100644 --- a/src/components/model/ModelAssociationsListItem.svelte +++ b/src/components/model/ModelAssociationsListItem.svelte @@ -41,9 +41,9 @@ $: permissionError = `You do not have permission to edit model ${metadataType}s`; $: upButtonHidden = priority !== undefined && priority <= 0; - function focusInput() { + function focusPriorityInput() { if (document.activeElement !== priorityInput) { - priorityInput.focus(); + priorityInput?.focus(); } return true; @@ -69,14 +69,14 @@ function onDecreasePriority() { if (priority !== undefined) { - focusInput(); + focusPriorityInput(); updatePriority(priority + 1); } } function onIncreasePriority() { if (priority !== undefined) { - focusInput(); + focusPriorityInput(); updatePriority(priority - 1); } } @@ -113,14 +113,7 @@ } -
+
{#if priority !== undefined} diff --git a/src/routes/models/[id]/+page.svelte b/src/routes/models/[id]/+page.svelte index 0133569e03..fdb0964312 100644 --- a/src/routes/models/[id]/+page.svelte +++ b/src/routes/models/[id]/+page.svelte @@ -26,14 +26,12 @@ import { featurePermissions } from '../../../utilities/permissions'; import type { PageData } from './$types'; - type AssociationSpecificationMap = Record< - number, - { - priority?: number; - revision: number | null; - selected: boolean; - } - >; + type AssociationSpecification = { + priority?: number; + revision: number | null; + selected: boolean; + }; + type AssociationSpecificationMap = Record; export let data: PageData; let hasCreatePermission: boolean = false; @@ -374,17 +372,28 @@ }, }; break; - case 'goal': + case 'goal': { + const nextPriority = Object.keys(selectedGoalModelSpecifications).reduce( + (prevPriority: number, selectedGoalModelSpecificationId) => { + const goalSpecification = selectedGoalModelSpecifications[parseInt(selectedGoalModelSpecificationId)]; + if (goalSpecification.selected === true) { + return prevPriority + 1; + } + return prevPriority; + }, + 0, + ); selectedGoalModelSpecifications = { ...selectedGoalModelSpecifications, [id]: { ...selectedGoalModelSpecifications[id], - priority: 0, + priority: nextPriority, revision: selectedGoalModelSpecifications[id]?.revision ?? null, selected, }, }; break; + } case 'constraint': default: selectedConstraintModelSpecifications = { @@ -398,21 +407,113 @@ } } - function onUpdateSpecifications(event: CustomEvent) { - const { detail: updatedSpecifications } = event; - - selectedSpecifications = updatedSpecifications; + function onUpdateSpecifications( + event: CustomEvent<{ + id: number; + priority?: number; + revision: number | null; + selected: boolean; + }>, + ) { + const { + detail: { id, priority, revision, selected }, + } = event; switch (selectedAssociation) { case 'condition': - selectedConditionModelSpecifications = selectedSpecifications; + selectedConditionModelSpecifications = { + ...selectedConditionModelSpecifications, + [id]: { + revision, + selected, + }, + }; break; - case 'goal': - selectedGoalModelSpecifications = selectedSpecifications; + case 'goal': { + const goalModelSpecificationsList = Object.keys(selectedGoalModelSpecifications) + .reduce( + ( + prevSpecificationsList: { + id: string; + priority?: number; + revision: number | null; + selected: boolean; + }[], + key, + ) => { + if (`${key}` !== `${id}`) { + return [ + ...prevSpecificationsList, + { + id: key, + ...selectedGoalModelSpecifications[parseInt(key)], + }, + ]; + } + + return prevSpecificationsList; + }, + [], + ) + .sort((goalSpecA, goalSpecB) => { + if (goalSpecA.priority != null && goalSpecB.priority != null) { + return goalSpecA.priority - goalSpecB.priority; + } + return 0; + }); + + const prevPriority = selectedGoalModelSpecifications[id].priority ?? 0; + const nextPriority = priority != null ? Math.min(priority, goalModelSpecificationsList.length) : 0; + const priorityModifier = nextPriority < prevPriority ? 1 : -1; + + selectedGoalModelSpecifications = goalModelSpecificationsList + .map(goalSpecification => { + if ( + goalSpecification.selected && + goalSpecification.priority != null && + ((priorityModifier < 0 && + goalSpecification.priority >= prevPriority && + goalSpecification.priority <= nextPriority) || + (goalSpecification.priority <= prevPriority && goalSpecification.priority >= nextPriority)) + ) { + return { + ...goalSpecification, + priority: goalSpecification.priority + priorityModifier, + }; + } + + return goalSpecification; + }) + .reduce( + (prevGoalSpecificationMap: Record, goalModelSpecification) => { + return { + ...prevGoalSpecificationMap, + [goalModelSpecification.id]: { + priority: goalModelSpecification.priority, + revision: goalModelSpecification.revision, + selected: goalModelSpecification.selected, + }, + }; + }, + { + [id]: { + priority: nextPriority, + revision, + selected, + }, + }, + ); break; + } case 'constraint': default: - selectedConstraintModelSpecifications = selectedSpecifications; + selectedConstraintModelSpecifications = { + ...selectedConstraintModelSpecifications, + [id]: { + revision, + selected, + }, + }; } }