diff --git a/packages/client/hmi-client/src/App.vue b/packages/client/hmi-client/src/App.vue index f630dfc065..6ad41b1489 100644 --- a/packages/client/hmi-client/src/App.vue +++ b/packages/client/hmi-client/src/App.vue @@ -6,6 +6,7 @@ + + + diff --git a/packages/client/hmi-client/src/components/workflow/ops/dataset-transformer/tera-dataset-transformer.vue b/packages/client/hmi-client/src/components/workflow/ops/dataset-transformer/tera-dataset-transformer.vue index daea41dbf1..5965ea4c5d 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/dataset-transformer/tera-dataset-transformer.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/dataset-transformer/tera-dataset-transformer.vue @@ -80,9 +80,10 @@ const jupyterPanel = ref(); const selectedDataset = ref(null); const updateKernelState = (newKernelState: any) => { kernelState.value = newKernelState; - // Default the dropdown to the first dataframe + // Default the dropdown to the last dataframe if (!selectedDataset.value) { - selectedDataset.value = Object.keys(newKernelState)[0]; + const keys = Object.keys(newKernelState); + selectedDataset.value = keys[keys.length - 1]; } }; diff --git a/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-card.vue b/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-card.vue index 61032a08a5..a3eeaa79b3 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-card.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-card.vue @@ -22,7 +22,7 @@ defineProps<{ selected?: boolean; }>(); -const emit = defineEmits(['use-intervention']); +const emit = defineEmits(['use-intervention', 'delete-intervention-policy']); const contextMenu = ref(); const contextMenuItems = [ @@ -32,6 +32,13 @@ const contextMenuItems = [ command() { emit('use-intervention'); } + }, + { + label: 'Delete', + icon: 'pi pi-trash', + command() { + emit('delete-intervention-policy'); + } } ]; diff --git a/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-drilldown.vue b/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-drilldown.vue index c4f8f0fd0a..87dd8807ad 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-drilldown.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/intervention-policy/tera-intervention-policy-drilldown.vue @@ -36,6 +36,7 @@ :selected="selectedPolicy?.id === policy.id" @click="onReplacePolicy(policy)" @use-intervention="onReplacePolicy(policy)" + @delete-intervention-policy="onDeleteInterventionPolicy(policy)" /> @@ -183,7 +184,8 @@ import { blankIntervention, flattenInterventionData, getInterventionPolicyById, - updateInterventionPolicy + updateInterventionPolicy, + deleteInterventionPolicy } from '@/services/intervention-policy'; import Accordion from 'primevue/accordion'; import AccordionTab from 'primevue/accordiontab'; @@ -406,6 +408,23 @@ const onReplacePolicy = (policy: InterventionPolicy) => { } }; +const onDeleteInterventionPolicy = (policy: InterventionPolicy) => { + confirm.require({ + message: `Are you sure you want to delete the configuration ${policy.name}?`, + header: 'Delete Confirmation', + icon: 'pi pi-exclamation-triangle', + acceptLabel: 'Confirm', + rejectLabel: 'Cancel', + accept: async () => { + if (policy.id) { + await deleteInterventionPolicy(policy.id); + const modelId = props.node.inputs[0].value?.[0]; + fetchInterventionPolicies(modelId); + } + } + }); +}; + const addIntervention = () => { // by default add the first parameter with a static intervention knobs.value.transientInterventionPolicy.interventions.push(blankIntervention); diff --git a/packages/client/hmi-client/src/components/workflow/ops/model-config/tera-model-config-drilldown.vue b/packages/client/hmi-client/src/components/workflow/ops/model-config/tera-model-config-drilldown.vue index 5497361bf5..3187b8da60 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/model-config/tera-model-config-drilldown.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/model-config/tera-model-config-drilldown.vue @@ -7,6 +7,18 @@ hide-dropdown > - -
- - -
-
- - -
-
({ interventionPolicyGroups: props.node.state.interventionPolicyGroups ?? [] }); -const criteriaTooltip = 'TODO'; -const interventionPolicyToolTip = 'TODO'; -const optimizeSettingsToolTip = 'TODO'; -const outputSettingsToolTip = 'TODO'; - const summaryCheckbox = ref(true); const successDisplayChartsCheckbox = ref(true); const interventionsDisplayChartsCheckbox = ref(true); const simulationDisplayChartsCheckbox = ref(true); -const modelConfigName = ref(''); -const modelConfigDesc = ref(''); const showSaveDataDialog = ref(false); const showSaveInterventionPolicy = ref(false); @@ -538,7 +494,6 @@ const datasetId = computed(() => { return output?.value?.[0]?.datasetId ?? ''; }); -const showModelModal = ref(false); const displayOptimizationResultMessage = ref(true); const isRunDisabled = computed(() => { @@ -868,32 +823,6 @@ const setOutputSettingDefaults = () => { } }; -// TODO: utlize with https://github.com/DARPA-ASKEM/terarium/issues/4767 -const saveModelConfiguration = async () => { - if (!modelConfiguration.value) return; - - if (!knobs.value.optimizationRunId) { - logger.error('No optimization run to create model configuration from'); - } - - // TODO: use new interventions - // const optRunId = knobs.value.optimizationRunId; - // const interventions = await getOptimizedInterventions(optRunId); - const configClone = cloneDeep(modelConfiguration.value); - - // setInterventions(configClone, interventions); - configClone.name = modelConfigName.value; - configClone.description = modelConfigDesc.value; - const data = await createModelConfiguration(configClone); - if (!data) { - logger.error('Failed to create model configuration'); - return; - } - - logger.success('Created model configuration'); - showModelModal.value = false; -}; - const setOutputValues = async () => { const preForecastRunId = knobs.value.preForecastRunId; const postForecastRunId = knobs.value.postForecastRunId; diff --git a/packages/client/hmi-client/src/model-representation/mira/mira-util.ts b/packages/client/hmi-client/src/model-representation/mira/mira-util.ts index a8dd9af20b..5c06900ed6 100644 --- a/packages/client/hmi-client/src/model-representation/mira/mira-util.ts +++ b/packages/client/hmi-client/src/model-representation/mira/mira-util.ts @@ -167,7 +167,10 @@ export const extractOutcomeControllersMatrix = ( export const extractTemplateMatrix = (templates: MiraTemplate[]) => { const rowNames = extractConceptNames(templates, 'subject'); - const colNames = extractConceptNames(templates, 'outcome'); + + const colNames = templates[0]?.controller + ? extractConceptNames(templates, 'controllers') + : extractConceptNames(templates, 'outcome'); // Not sure how to parse templates with no subject or no outcomes // and interacts with only controllers and itself, return a matrix @@ -200,7 +203,12 @@ export const extractTemplateMatrix = (templates: MiraTemplate[]) => { if (template.subject) { rowIdx = rowNames.indexOf(template.subject.name); } - if (template.outcome) { + + // Use subject-controller matrix if possible, otherwise fallback to subject-outcome matrix + // Note we still use the subject-outcome matrix grid + if (template.controller) { + colIdx = colNames.indexOf(template.controller.name); + } else if (template.outcome) { colIdx = colNames.indexOf(template.outcome.name); } matrix[rowIdx][colIdx].content = { @@ -208,5 +216,6 @@ export const extractTemplateMatrix = (templates: MiraTemplate[]) => { id: template.name }; } + return { rowNames, colNames, matrix }; }; diff --git a/packages/client/hmi-client/src/model-representation/petrinet/nested-petrinet-renderer.ts b/packages/client/hmi-client/src/model-representation/petrinet/nested-petrinet-renderer.ts index 278a04a646..faf1fae66c 100644 --- a/packages/client/hmi-client/src/model-representation/petrinet/nested-petrinet-renderer.ts +++ b/packages/client/hmi-client/src/model-representation/petrinet/nested-petrinet-renderer.ts @@ -102,7 +102,7 @@ export class NestedPetrinetRenderer extends PetrinetRenderer { species .append('circle') .classed('shape selectableNode', true) - .attr('r', (d) => 0.55 * d.width) // FIXME: need to adjust edge from sqaure mapping to circle + .attr('r', (d) => 0.55 * d.width) .attr('fill', (d) => (d.data.strataType ? getNodeTypeColor(d.data.strataType) : getNestedTypeColor('base'))) .attr('stroke', 'var(--petri-nodeBorder)') .attr('stroke-width', 1) diff --git a/packages/client/hmi-client/src/model-representation/petrinet/petrinet-renderer.ts b/packages/client/hmi-client/src/model-representation/petrinet/petrinet-renderer.ts index 1ca5969508..d5a6d3d447 100644 --- a/packages/client/hmi-client/src/model-representation/petrinet/petrinet-renderer.ts +++ b/packages/client/hmi-client/src/model-representation/petrinet/petrinet-renderer.ts @@ -98,7 +98,7 @@ export class PetrinetRenderer extends BasicRenderer { species .append('circle') .classed('shape selectableNode', true) - .attr('r', (d) => 0.55 * d.width) // FIXME: need to adjust edge from sqaure mapping to circle + .attr('r', (d) => 0.55 * d.width) .attr('fill', (d) => (d.data.strataType ? getNodeTypeColor(d.data.strataType) : 'var(--petri-nodeFill)')) .attr('stroke', 'var(--petri-nodeBorder)') .attr('stroke-width', 1) diff --git a/packages/client/hmi-client/src/page/Home.vue b/packages/client/hmi-client/src/page/Home.vue index 58ea4eaf30..aa1a929f6e 100644 --- a/packages/client/hmi-client/src/page/Home.vue +++ b/packages/client/hmi-client/src/page/Home.vue @@ -97,10 +97,7 @@
- - +