From f65dc2973e25b9fd13abe7764cd29aa55d0899be Mon Sep 17 00:00:00 2001 From: Nicolas Borde Date: Thu, 27 Jun 2024 16:57:29 +0200 Subject: [PATCH] feat: [SDCOSMO-1974] implement scenario selector for scenario parameters --- doc/scenarioParametersConfiguration.md | 25 ++++---- public/locales/en/translation.json | 4 ++ public/locales/fr/translation.json | 4 ++ .../ScenarioSelect.js | 64 +++++++++++++++++++ .../ScenarioParametersInputs/index.js | 1 + src/services/config/SolutionSchema.js | 1 + src/utils/ConfigUtils.js | 1 + .../generic/VarTypesComponentsMapping.js | 2 + 8 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 src/components/ScenarioParameters/components/ScenarioParametersInputs/ScenarioSelect.js diff --git a/doc/scenarioParametersConfiguration.md b/doc/scenarioParametersConfiguration.md index 8ece47b21..dd8011a76 100644 --- a/doc/scenarioParametersConfiguration.md +++ b/doc/scenarioParametersConfiguration.md @@ -757,15 +757,16 @@ components, whose value depend on the **input component type** and the **paramet Here is the list of `data-cy` patterns for all generic input components provided by the azure-sample-webapp: -| varType | subType | input component | `data-cy` pattern | -| ------------- | -------- | -------------------- | ---------------------------- | -| `bool` | | Switch boolean input | `toggle-input-` | -| `date` | | Date picker | `date-input-` | -| `enum` | | Dropdown list | `enum-input-` | -| `enum` | `RADIO` | Radio buttons | `radio-input-` | -| `int` | | Number input | `number-input-` | -| `number` | | Number input | `number-input-` | -| `number` | `SLIDER` | Slider | `slider-input-` | -| `string` | | Text field | `text-input-` | -| `%DATASETID%` | | File upload | `file-upload-` | -| `%DATASETID%` | `TABLE` | Editable table | `table-` | +| varType | subType | input component | `data-cy` pattern | +| ------------- | ----------- | -------------------- | ------------------------------- | +| `bool` | | Switch boolean input | `toggle-input-` | +| `date` | | Date picker | `date-input-` | +| `enum` | | Dropdown list | `enum-input-` | +| `enum` | `RADIO` | Radio buttons | `radio-input-` | +| `enum` | `SCENARIOS` | Scenarios select | `scenarios-input-` | +| `int` | | Number input | `number-input-` | +| `number` | | Number input | `number-input-` | +| `number` | `SLIDER` | Slider | `slider-input-` | +| `string` | | Text field | `text-input-` | +| `%DATASETID%` | | File upload | `file-upload-` | +| `%DATASETID%` | `TABLE` | Editable table | `table-` | diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 6d37a7e4b..4764030ce 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -557,6 +557,10 @@ "noFileMessage": "None", "fileNamePlaceholder": "{{fileExtension}} file" }, + "scenarioSelect": { + "noValues": "No scenario selected", + "noOptions": "No scenarios available" + }, "loading": { "line": { "workspace": { diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index c7e0f3814..7d0726fae 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -557,6 +557,10 @@ "noFileMessage": "Aucun", "fileNamePlaceholder": "fichier {{fileExtension}}" }, + "scenarioSelect": { + "noValues": "Aucun scénario sélectionné", + "noOptions": "Aucun scénario disponible" + }, "loading": { "line": { "workspace": { diff --git a/src/components/ScenarioParameters/components/ScenarioParametersInputs/ScenarioSelect.js b/src/components/ScenarioParameters/components/ScenarioParametersInputs/ScenarioSelect.js new file mode 100644 index 000000000..57c1de353 --- /dev/null +++ b/src/components/ScenarioParameters/components/ScenarioParametersInputs/ScenarioSelect.js @@ -0,0 +1,64 @@ +// Copyright (c) Cosmo Tech. +// Licensed under the MIT license. +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import PropTypes from 'prop-types'; +import { Grid } from '@mui/material'; +import { SingleSelect } from '@cosmotech/ui'; +import { useSortedScenarioList } from '../../../../hooks/ScenarioListHooks'; +import { useCurrentScenarioId } from '../../../../state/hooks/ScenarioHooks'; +import { TranslationUtils } from '../../../../utils'; + +export const ScenarioSelect = ({ parameterData, context, parameterValue, setParameterValue, isDirty }) => { + const { t } = useTranslation(); + const scenarioList = useSortedScenarioList(); + const currentScenarioId = useCurrentScenarioId(); + const runTemplateFilter = parameterData.options?.runTemplateFilter; + + const mappedScenarioList = useMemo(() => { + const filteredScenarioList = + runTemplateFilter == null || runTemplateFilter?.length === 0 + ? scenarioList + : scenarioList.filter((scenario) => { + return runTemplateFilter.includes(scenario.runTemplateId) && scenario.id !== currentScenarioId; + }); + + return filteredScenarioList.map((scenario) => ({ key: scenario.id, label: scenario.name })); + }, [runTemplateFilter, scenarioList, currentScenarioId]); + + const labels = useMemo(() => { + return { + label: t(TranslationUtils.getParameterTranslationKey(parameterData.id), parameterData.id), + noValue: t('genericcomponent.scenarioSelect.noValues', 'No scenario selected'), + noOptions: t('genericcomponent.scenarioSelect.noOptions', 'No scenarios available'), + }; + }, [t, parameterData.id]); + + return ( + + setParameterValue(newValue ?? null)} + disabled={!context.editMode} + isDirty={isDirty} + /> + + ); +}; + +ScenarioSelect.propTypes = { + parameterData: PropTypes.object.isRequired, + context: PropTypes.object.isRequired, + parameterValue: PropTypes.any, + setParameterValue: PropTypes.func.isRequired, + isDirty: PropTypes.bool, + gridItemProps: PropTypes.object, +}; + +ScenarioSelect.defaultProps = { + isDirty: false, +}; diff --git a/src/components/ScenarioParameters/components/ScenarioParametersInputs/index.js b/src/components/ScenarioParameters/components/ScenarioParametersInputs/index.js index 0a1f528a5..c18d7c473 100644 --- a/src/components/ScenarioParameters/components/ScenarioParametersInputs/index.js +++ b/src/components/ScenarioParameters/components/ScenarioParametersInputs/index.js @@ -11,3 +11,4 @@ export { GenericToggleInput } from './GenericToggleInput'; export { GenericUploadFile } from './GenericUploadFile'; export { GenericTable } from './GenericTable'; export { GenericSliderInput } from './GenericSliderInput'; +export { ScenarioSelect } from './ScenarioSelect'; diff --git a/src/services/config/SolutionSchema.js b/src/services/config/SolutionSchema.js index a75facaa1..2de2bf904 100644 --- a/src/services/config/SolutionSchema.js +++ b/src/services/config/SolutionSchema.js @@ -52,6 +52,7 @@ const basicParameterOptions = z.object({ dateFormat: z.string().optional().nullable(), columns: z.array(basicColumnField).optional().nullable(), shouldRenameFileOnUpload: z.string().optional().nullable(), + runTemplateFilter: z.array(z.string().optional().nullable()).optional().nullable(), }); const basicParameterGroupOptions = z.object({ diff --git a/src/utils/ConfigUtils.js b/src/utils/ConfigUtils.js index 74b32b496..93f63d99e 100644 --- a/src/utils/ConfigUtils.js +++ b/src/utils/ConfigUtils.js @@ -72,6 +72,7 @@ const getParameterAttribute = (parameter, attributeName) => { 'subType', 'canChangeRowsNumber', 'shouldRenameFileOnUpload', + 'runTemplateFilter', ]; if (!knownAttributesNames.includes(attributeName)) { console.warn(`The attribute "${attributeName}" is not a known attribute in the scenario parameters configuration.`); diff --git a/src/utils/scenarioParameters/generic/VarTypesComponentsMapping.js b/src/utils/scenarioParameters/generic/VarTypesComponentsMapping.js index 8ffb8d547..961333555 100644 --- a/src/utils/scenarioParameters/generic/VarTypesComponentsMapping.js +++ b/src/utils/scenarioParameters/generic/VarTypesComponentsMapping.js @@ -11,6 +11,7 @@ import { GenericTextInput, GenericToggleInput, GenericUploadFile, + ScenarioSelect, } from '../../../components/ScenarioParameters/components/ScenarioParametersInputs'; import { DATASET_ID_VARTYPE } from '../../../services/config/ApiConstants'; @@ -19,6 +20,7 @@ export const GENERIC_VAR_TYPES_COMPONENTS_MAPPING = { date: GenericDateInput, enum: GenericEnumInput, 'enum-RADIO': GenericRadioInput, + 'enum-SCENARIOS': ScenarioSelect, list: GenericMultiSelect, int: GenericNumberInput, 'number-SLIDER': GenericSliderInput,