From ec18d4d293bf46ee8387d5559b12c45fe42ebe07 Mon Sep 17 00:00:00 2001 From: sBouzols Date: Wed, 5 Nov 2025 16:44:32 +0100 Subject: [PATCH 1/5] feat(): Add specific parameters management for shortcircuit Signed-off-by: sBouzols --- src/components/parameters/common/constant.ts | 4 + src/components/parameters/common/utils.ts | 68 ++++ .../parameters/loadflow/constants.ts | 5 - .../loadflow/load-flow-general-parameters.tsx | 3 +- .../loadflow/load-flow-parameters-form.tsx | 2 + .../loadflow/load-flow-parameters-utils.ts | 70 +--- .../loadflow/use-load-flow-parameters-form.ts | 36 +- .../parameters/short-circuit/constants.ts | 12 + .../short-circuit/short-circuit-fields.tsx | 51 ++- .../short-circuit-parameters-dialog.tsx | 31 +- .../short-circuit-parameters-form.tsx | 10 +- .../short-circuit-parameters-inline.tsx | 61 +-- .../short-circuit-parameters-utils.ts | 34 ++ .../short-circuit-parameters.type.ts | 23 +- .../use-short-circuit-parameters-form.ts | 373 +++++++++--------- src/hooks/use-parameters-backend.ts | 10 +- src/services/index.ts | 1 + src/services/short-circuit-analysis.ts | 28 +- src/services/study.ts | 24 +- src/translations/en/parameters.ts | 3 + src/translations/fr/parameters.ts | 3 + src/utils/types/parameters.type.ts | 5 +- 22 files changed, 462 insertions(+), 395 deletions(-) create mode 100644 src/components/parameters/common/utils.ts create mode 100644 src/components/parameters/short-circuit/short-circuit-parameters-utils.ts diff --git a/src/components/parameters/common/constant.ts b/src/components/parameters/common/constant.ts index 6f4aeaa0..9fdd9359 100644 --- a/src/components/parameters/common/constant.ts +++ b/src/components/parameters/common/constant.ts @@ -25,3 +25,7 @@ export const VoltageAdornment = { position: 'end', text: KILO_VOLT, }; + +export const VERSION_PARAMETER = 'version'; +export const COMMON_PARAMETERS = 'commonParameters'; +export const SPECIFIC_PARAMETERS = 'specificParametersPerProvider'; diff --git a/src/components/parameters/common/utils.ts b/src/components/parameters/common/utils.ts new file mode 100644 index 00000000..7d0853ed --- /dev/null +++ b/src/components/parameters/common/utils.ts @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +import { UseFormReturn } from 'react-hook-form'; +import { ParameterType, SpecificParameterInfos, SpecificParametersPerProvider } from '../../../utils'; +import { SPECIFIC_PARAMETERS } from './constant'; +import yup from '../../../utils/yupConfig'; + +export const getSpecificParametersFormSchema = (specificParameters: SpecificParameterInfos[]) => { + const shape: { [key: string]: yup.AnySchema } = {}; + + specificParameters?.forEach((param: SpecificParameterInfos) => { + switch (param.type) { + case ParameterType.STRING: + shape[param.name] = yup.string().required(); + break; + case ParameterType.DOUBLE: + shape[param.name] = yup.number().required(); + break; + case ParameterType.INTEGER: + shape[param.name] = yup.number().required(); + break; + case ParameterType.BOOLEAN: + shape[param.name] = yup.boolean().required(); + break; + case ParameterType.STRING_LIST: + shape[param.name] = yup.array().of(yup.string()).required(); + break; + default: + shape[param.name] = yup.mixed().required(); + } + }); + + return yup.object().shape({ + [SPECIFIC_PARAMETERS]: yup.object().shape(shape), + }); +}; + +export const getDefaultSpecificParamsValues = ( + specificParams: SpecificParameterInfos[] +): SpecificParametersPerProvider => { + return specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { + if (param.type === ParameterType.STRING_LIST && param.defaultValue === null) { + acc[param.name] = []; + } else if ( + (param.type === ParameterType.DOUBLE || param.type === ParameterType.INTEGER) && + Number.isNaN(Number(param.defaultValue)) + ) { + acc[param.name] = 0; + } else { + acc[param.name] = param.defaultValue; + } + return acc; + }, {}); +}; + +export const setSpecificParameters = ( + provider: string, + specificParamsDescriptions: Record | null, + formMethods: UseFormReturn +) => { + const specificParams = provider ? (specificParamsDescriptions?.[provider] ?? []) : []; + const specificParamsValues = getDefaultSpecificParamsValues(specificParams); + formMethods.setValue(SPECIFIC_PARAMETERS, specificParamsValues); +}; diff --git a/src/components/parameters/loadflow/constants.ts b/src/components/parameters/loadflow/constants.ts index 119377c3..457eabb5 100644 --- a/src/components/parameters/loadflow/constants.ts +++ b/src/components/parameters/loadflow/constants.ts @@ -8,11 +8,6 @@ export const PARAM_LIMIT_REDUCTION = 'limitReduction'; export const PARAM_PROVIDER_OPENLOADFLOW = 'OpenLoadFlow'; -export const COMMON_PARAMETERS = 'commonParameters'; -export const SPECIFIC_PARAMETERS = 'specificParametersPerProvider'; - -export const VERSION_PARAMETER = 'version'; - // BasicLoadFlowParameters export const PHASE_SHIFTER_REGULATION_ON = 'phaseShifterRegulationOn'; export const DC = 'dc'; diff --git a/src/components/parameters/loadflow/load-flow-general-parameters.tsx b/src/components/parameters/loadflow/load-flow-general-parameters.tsx index 62ec04d2..6bcecabf 100644 --- a/src/components/parameters/loadflow/load-flow-general-parameters.tsx +++ b/src/components/parameters/loadflow/load-flow-general-parameters.tsx @@ -9,7 +9,6 @@ import { memo } from 'react'; import LoadFlowParameterField from './load-flow-parameter-field'; import { BALANCE_TYPE, - COMMON_PARAMETERS, CONNECTED_COMPONENT_MODE, COUNTRIES_TO_BALANCE, DC, @@ -20,7 +19,6 @@ import { PHASE_SHIFTER_REGULATION_ON, READ_SLACK_BUS, SHUNT_COMPENSATOR_VOLTAGE_CONTROL_ON, - SPECIFIC_PARAMETERS, TWT_SPLIT_SHUNT_ADMITTANCE, USE_REACTIVE_LIMITS, VOLTAGE_INIT_MODE, @@ -29,6 +27,7 @@ import { import { useLoadFlowContext } from './use-load-flow-context'; import { ParameterType, SpecificParameterInfos } from '../../../utils/types/parameters.type'; import { ParameterGroup } from '../common/widget'; +import { COMMON_PARAMETERS, SPECIFIC_PARAMETERS } from '../common'; const basicParams: SpecificParameterInfos[] = [ { diff --git a/src/components/parameters/loadflow/load-flow-parameters-form.tsx b/src/components/parameters/loadflow/load-flow-parameters-form.tsx index a81dcceb..6bc09fe6 100644 --- a/src/components/parameters/loadflow/load-flow-parameters-form.tsx +++ b/src/components/parameters/loadflow/load-flow-parameters-form.tsx @@ -66,6 +66,8 @@ export function LoadFlowParametersForm({ defaultLimitReductions, paramsLoaded, } = loadflowMethods; + console.log('SBO LoadFlowParametersForm paramsLoaded', paramsLoaded); + console.log('SBO LoadFlowParametersForm formState', formMethods.formState); return ( diff --git a/src/components/parameters/loadflow/load-flow-parameters-utils.ts b/src/components/parameters/loadflow/load-flow-parameters-utils.ts index ee89a15a..804eb147 100644 --- a/src/components/parameters/loadflow/load-flow-parameters-utils.ts +++ b/src/components/parameters/loadflow/load-flow-parameters-utils.ts @@ -6,10 +6,15 @@ */ import { UseFormReturn } from 'react-hook-form'; -import { ILimitReductionsByVoltageLevel, IST_FORM, LIMIT_DURATION_FORM, LIMIT_REDUCTIONS_FORM } from '../common'; import { - BALANCE_TYPE, COMMON_PARAMETERS, + ILimitReductionsByVoltageLevel, + IST_FORM, + LIMIT_DURATION_FORM, + LIMIT_REDUCTIONS_FORM, +} from '../common'; +import { + BALANCE_TYPE, CONNECTED_COMPONENT_MODE, COUNTRIES_TO_BALANCE, DC, @@ -23,7 +28,6 @@ import { PHASE_SHIFTER_REGULATION_ON, READ_SLACK_BUS, SHUNT_COMPENSATOR_VOLTAGE_CONTROL_ON, - SPECIFIC_PARAMETERS, TWT_SPLIT_SHUNT_ADMITTANCE, USE_REACTIVE_LIMITS, VOLTAGE_INIT_MODE, @@ -31,8 +35,6 @@ import { } from './constants'; import { toFormValuesLimitReductions } from '../common/limitreductions/limit-reductions-form-util'; import yup from '../../../utils/yupConfig'; -import { ParameterType, SpecificParameterInfos } from '../../../utils/types/parameters.type'; -import { SpecificParametersPerProvider } from '../../../utils/types/loadflow.type'; export enum TabValues { GENERAL = 'General', @@ -77,64 +79,6 @@ export const getCommonLoadFlowParametersFormSchema = () => { }); }; -export const getSpecificLoadFlowParametersFormSchema = (specificParameters: SpecificParameterInfos[]) => { - const shape: { [key: string]: yup.AnySchema } = {}; - - specificParameters?.forEach((param: SpecificParameterInfos) => { - switch (param.type) { - case ParameterType.STRING: - shape[param.name] = yup.string().required(); - break; - case ParameterType.DOUBLE: - shape[param.name] = yup.number().required(); - break; - case ParameterType.INTEGER: - shape[param.name] = yup.number().required(); - break; - case ParameterType.BOOLEAN: - shape[param.name] = yup.boolean().required(); - break; - case ParameterType.STRING_LIST: - shape[param.name] = yup.array().of(yup.string()).required(); - break; - default: - shape[param.name] = yup.mixed().required(); - } - }); - - return yup.object().shape({ - [SPECIFIC_PARAMETERS]: yup.object().shape(shape), - }); -}; - -export const getDefaultSpecificParamsValues = ( - specificParams: SpecificParameterInfos[] -): SpecificParametersPerProvider => { - return specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { - if (param.type === ParameterType.STRING_LIST && param.defaultValue === null) { - acc[param.name] = []; - } else if ( - (param.type === ParameterType.DOUBLE || param.type === ParameterType.INTEGER) && - Number.isNaN(Number(param.defaultValue)) - ) { - acc[param.name] = 0; - } else { - acc[param.name] = param.defaultValue; - } - return acc; - }, {}); -}; - -export const setSpecificParameters = ( - provider: string, - specificParamsDescriptions: Record | null, - formMethods: UseFormReturn -) => { - const specificParams = provider ? (specificParamsDescriptions?.[provider] ?? []) : []; - const specificParamsValues = getDefaultSpecificParamsValues(specificParams); - formMethods.setValue(SPECIFIC_PARAMETERS, specificParamsValues); -}; - export const setLimitReductions = ( provider: string, defaultLimitReductions: ILimitReductionsByVoltageLevel[], diff --git a/src/components/parameters/loadflow/use-load-flow-parameters-form.ts b/src/components/parameters/loadflow/use-load-flow-parameters-form.ts index c8b1623a..faded5d1 100644 --- a/src/components/parameters/loadflow/use-load-flow-parameters-form.ts +++ b/src/components/parameters/loadflow/use-load-flow-parameters-form.ts @@ -12,11 +12,8 @@ import { ObjectSchema } from 'yup'; import type { UUID } from 'node:crypto'; import { getCommonLoadFlowParametersFormSchema, - getDefaultSpecificParamsValues, - getSpecificLoadFlowParametersFormSchema, mapLimitReductions, setLimitReductions, - setSpecificParameters, TabValues, } from './load-flow-parameters-utils'; import { LoadFlowParametersInfos, SpecificParametersPerProvider } from '../../../utils/types/loadflow.type'; @@ -25,19 +22,13 @@ import { SpecificParameterInfos, UseParametersBackendReturnProps, } from '../../../utils/types/parameters.type'; -import { ComputingType, PROVIDER } from '../common'; +import { COMMON_PARAMETERS, ComputingType, PROVIDER, SPECIFIC_PARAMETERS, VERSION_PARAMETER } from '../common'; import { getLimitReductionsFormSchema, ILimitReductionsByVoltageLevel, LIMIT_REDUCTIONS_FORM, } from '../common/limitreductions/columns-definitions'; -import { - COMMON_PARAMETERS, - PARAM_LIMIT_REDUCTION, - PARAM_PROVIDER_OPENLOADFLOW, - SPECIFIC_PARAMETERS, - VERSION_PARAMETER, -} from './constants'; +import { PARAM_LIMIT_REDUCTION, PARAM_PROVIDER_OPENLOADFLOW } from './constants'; import yup from '../../../utils/yupConfig'; import { toFormValuesLimitReductions } from '../common/limitreductions/limit-reductions-form-util'; import { DESCRIPTION, NAME } from '../../inputs'; @@ -45,6 +36,11 @@ import { updateParameter } from '../../../services'; import { ElementType } from '../../../utils'; import { getNameElementEditorEmptyFormData, getNameElementEditorSchema } from '../common/name-element-editor'; import { useSnackMessage } from '../../../hooks'; +import { + getDefaultSpecificParamsValues, + getSpecificParametersFormSchema, + setSpecificParameters, +} from '../common/utils'; export interface UseLoadFlowParametersFormReturn { formMethods: UseFormReturn; @@ -121,11 +117,12 @@ export const useLoadFlowParametersForm = ( [PARAM_LIMIT_REDUCTION]: yup.number().nullable(), ...getCommonLoadFlowParametersFormSchema().fields, ...getLimitReductionsFormSchema(limitReductionNumber).fields, - ...getSpecificLoadFlowParametersFormSchema(specificParameters).fields, + ...getSpecificParametersFormSchema(specificParameters).fields, }) .concat(getNameElementEditorSchema(name)); }, [name, limitReductionNumber, specificParameters]); + console.log('SBO LF params?.commonParameters', params?.commonParameters); const formMethods = useForm({ defaultValues: { ...getNameElementEditorEmptyFormData(name, description), @@ -204,17 +201,14 @@ export const useLoadFlowParametersForm = ( const specificParamsPerProvider = _params.specificParametersPerProvider[_params.provider]; const formatted = specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { - if ( - specificParamsPerProvider && - Object.prototype.hasOwnProperty.call(specificParamsPerProvider, param.name) - ) { + if (specificParamsPerProvider && Object.hasOwn(specificParamsPerProvider, param.name)) { if (param.type === ParameterType.BOOLEAN) { acc[param.name] = specificParamsPerProvider[param.name] === 'true'; } else if (param.type === ParameterType.STRING_LIST) { acc[param.name] = - specificParamsPerProvider[param.name] !== '' - ? specificParamsPerProvider[param.name].split(',') - : []; + specificParamsPerProvider[param.name] === '' + ? [] + : specificParamsPerProvider[param.name].split(','); } else { acc[param.name] = specificParamsPerProvider[param.name]; } @@ -286,9 +280,9 @@ export const useLoadFlowParametersForm = ( formData[NAME], ElementType.LOADFLOW_PARAMETERS, formData[DESCRIPTION] ?? '' - ).catch((errmsg) => { + ).catch((error_) => { snackError({ - messageTxt: errmsg, + messageTxt: error_, headerId: 'updateLoadFlowParametersError', }); }); diff --git a/src/components/parameters/short-circuit/constants.ts b/src/components/parameters/short-circuit/constants.ts index e85b84e1..99e91786 100644 --- a/src/components/parameters/short-circuit/constants.ts +++ b/src/components/parameters/short-circuit/constants.ts @@ -24,6 +24,7 @@ export const SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS = 'withVSCConverterStatio export const SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS = 'withShuntCompensators'; export const SHORT_CIRCUIT_WITH_NEUTRAL_POSITION = 'withNeutralPosition'; export const SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE = 'initialVoltageProfileMode'; +export const SHORT_CIRCUIT_ONLY_STARTED_GENERATORS = 'onlyStartedGenerators'; export const intlPredefinedParametersOptions = () => [ { @@ -52,3 +53,14 @@ export const intlInitialVoltageProfileMode = () => { }, }; }; + +export const onlyStartedGeneratorsOptions = { + ALL: { + id: false, + label: 'ShortCircuitAllLabel', + }, + STARTED: { + id: true, + label: 'ShortCircuitStartedLabel', + }, +}; diff --git a/src/components/parameters/short-circuit/short-circuit-fields.tsx b/src/components/parameters/short-circuit/short-circuit-fields.tsx index 2f5b1459..e963354f 100644 --- a/src/components/parameters/short-circuit/short-circuit-fields.tsx +++ b/src/components/parameters/short-circuit/short-circuit-fields.tsx @@ -16,6 +16,7 @@ import { intlPredefinedParametersOptions, PredefinedParameters, SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, + SHORT_CIRCUIT_ONLY_STARTED_GENERATORS, SHORT_CIRCUIT_PREDEFINED_PARAMS, SHORT_CIRCUIT_WITH_FEEDER_RESULT, SHORT_CIRCUIT_WITH_LOADS, @@ -28,6 +29,7 @@ import GridItem from '../../grid/grid-item'; import GridSection from '../../grid/grid-section'; import { CheckboxInput, FieldLabel, MuiSelectInput, RadioInput, SwitchInput } from '../../inputs'; import type { SxStyle } from '../../../utils/styles'; +import { COMMON_PARAMETERS, SPECIFIC_PARAMETERS } from '../common'; export interface ShortCircuitFieldsProps { resetAll: (predefinedParams: PredefinedParameters) => void; @@ -42,22 +44,22 @@ export enum Status { export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Readonly) { const [status, setStatus] = useState(Status.SUCCESS); const watchInitialVoltageProfileMode = useWatch({ - name: SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, + name: `${COMMON_PARAMETERS}.${SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE}`, }); const watchPredefinedParams = useWatch({ name: SHORT_CIRCUIT_PREDEFINED_PARAMS, }); const watchLoads = useWatch({ - name: SHORT_CIRCUIT_WITH_LOADS, + name: `${COMMON_PARAMETERS}.${SHORT_CIRCUIT_WITH_LOADS}`, }); const watchShuntCompensators = useWatch({ - name: SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, + name: `${COMMON_PARAMETERS}.${SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS}`, }); const watchVSC = useWatch({ - name: SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, + name: `${COMMON_PARAMETERS}.${SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS}`, }); const watchNeutralPosition = useWatch({ - name: SHORT_CIRCUIT_WITH_NEUTRAL_POSITION, + name: `${COMMON_PARAMETERS}.${SHORT_CIRCUIT_WITH_NEUTRAL_POSITION}`, }); const isIccMinFeaturesDefaultConfiguration = useMemo(() => { @@ -115,7 +117,7 @@ export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Rea - + ); @@ -130,17 +132,39 @@ export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Rea const initialVoltageProfileModeField = ( ); - const loads = ; - const vsc = ; + const loads = ; + const vsc = ( + + ); const shuntCompensators = ( - + ); const neutralPosition = ( - + + ); + + const onlyStartedGenerators = ( + + // ); useEffect(() => { @@ -166,7 +190,6 @@ export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Rea const isIccMinDefaultConfiguration = isIccMinNominalDefaultConfiguration && isIccMinFeaturesDefaultConfiguration; - setStatus(isIccMaxDefaultConfiguration || isIccMinDefaultConfiguration ? Status.SUCCESS : Status.ERROR); }, [ watchInitialVoltageProfileMode, @@ -201,6 +224,10 @@ export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Rea {initialVoltageProfileModeField} + + + {onlyStartedGenerators} + ); } diff --git a/src/components/parameters/short-circuit/short-circuit-parameters-dialog.tsx b/src/components/parameters/short-circuit/short-circuit-parameters-dialog.tsx index 66cbc27a..27e8b562 100644 --- a/src/components/parameters/short-circuit/short-circuit-parameters-dialog.tsx +++ b/src/components/parameters/short-circuit/short-circuit-parameters-dialog.tsx @@ -10,7 +10,13 @@ import { ElementType } from '../../../utils'; import { NameElementEditorForm } from '../common/name-element-editor'; import { useShortCircuitParametersForm } from './use-short-circuit-parameters-form'; import { ShortCircuitParametersForm } from './short-circuit-parameters-form'; -import { ParametersEditionDialogProps } from '../common'; +import { ComputingType, ParametersEditionDialogProps } from '../common'; +import { OptionalServicesStatus, useParametersBackend } from '../../../hooks'; +import { + fetchShortCircuitParameters, + getShortCircuitSpecificParametersDescription, + updateShortCircuitParameters, +} from '../../../services/short-circuit-analysis'; export function ShortCircuitParametersEditionDialog({ id, @@ -20,15 +26,29 @@ export function ShortCircuitParametersEditionDialog({ name, description, activeDirectory, + user, language, enableDeveloperMode, -}: Readonly) { +}: Readonly) { + const parametersBackend = useParametersBackend( + user, + id, + ComputingType.SHORT_CIRCUIT, + OptionalServicesStatus.Up, + null, + null, + null, + null, + fetchShortCircuitParameters, + updateShortCircuitParameters, + getShortCircuitSpecificParametersDescription + ); + const shortCircuitMethods = useShortCircuitParametersForm({ + parametersBackend, parametersUuid: id, name, description, - studyUuid: null, - studyShortCircuitParameters: null, }); const { @@ -41,6 +61,7 @@ export function ShortCircuitParametersEditionDialog({ open={open} onClose={onClose} onSave={shortCircuitMethods.onSaveDialog} + onValidationError={shortCircuitMethods.onValidationError} formSchema={shortCircuitMethods.formSchema} formMethods={shortCircuitMethods.formMethods} titleId={titleId} @@ -50,6 +71,7 @@ export function ShortCircuitParametersEditionDialog({ > { return ( ); }} - enableDeveloperMode={enableDeveloperMode ?? false} /> ); diff --git a/src/components/parameters/short-circuit/short-circuit-parameters-form.tsx b/src/components/parameters/short-circuit/short-circuit-parameters-form.tsx index c066b173..ad280c3a 100644 --- a/src/components/parameters/short-circuit/short-circuit-parameters-form.tsx +++ b/src/components/parameters/short-circuit/short-circuit-parameters-form.tsx @@ -25,7 +25,9 @@ export function ShortCircuitParametersForm({ renderActions, enableDeveloperMode, }: Readonly) { - const { formMethods, formSchema, paramsLoading, resetAll } = shortCircuitMethods; + const { formMethods, formSchema, paramsLoaded, resetAll } = shortCircuitMethods; + console.log('SBO ShortCircuitParametersForm schema', formSchema); + console.log('SBO ShortCircuitParametersForm formState', formMethods.formState); return ( @@ -40,12 +42,12 @@ export function ShortCircuitParametersForm({ {renderTitleFields?.()} - {paramsLoading ? ( - - ) : ( + {paramsLoaded ? ( + ) : ( + )} void; - shortCircuitParameters: ShortCircuitParametersInfos | null; + parametersBackend: UseParametersBackendReturnProps; enableDeveloperMode: boolean; }>) { const shortCircuitMethods = useShortCircuitParametersForm({ + parametersBackend, parametersUuid: null, name: null, description: null, - studyUuid, - studyShortCircuitParameters: shortCircuitParameters, }); const intl = useIntl(); @@ -55,28 +44,8 @@ export function ShortCircuitParametersInLine({ const [openSelectParameterDialog, setOpenSelectParameterDialog] = useState(false); const { snackError } = useSnackMessage(); - const { getCurrentValues, formMethods } = shortCircuitMethods; - const { setValue, formState, handleSubmit } = formMethods; - - const replaceFormValues = useCallback( - (param: ShortCircuitParametersInfos) => { - const dirty = { shouldDirty: true }; - setValue(SHORT_CIRCUIT_WITH_FEEDER_RESULT, param.parameters.withFeederResult, dirty); - setValue(SHORT_CIRCUIT_PREDEFINED_PARAMS, param.predefinedParameters, dirty); - setValue(SHORT_CIRCUIT_WITH_LOADS, param.parameters.withLoads, dirty); - setValue(SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, param.parameters.withVSCConverterStations, dirty); - setValue(SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, param.parameters.withShuntCompensators, dirty); - setValue(SHORT_CIRCUIT_WITH_NEUTRAL_POSITION, !param.parameters.withNeutralPosition, dirty); - setValue( - SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, - param.parameters.initialVoltageProfileMode === InitialVoltage.CONFIGURED - ? InitialVoltage.CEI909 - : param.parameters.initialVoltageProfileMode, - dirty - ); - }, - [setValue] - ); + const { formMethods } = shortCircuitMethods; + const { getValues, formState, handleSubmit, reset } = formMethods; const handleLoadParameters = useCallback( (newParams: TreeViewFinderNodeProps[]) => { @@ -86,7 +55,9 @@ export function ShortCircuitParametersInLine({ fetchShortCircuitParameters(paramUuid) .then((parameters: ShortCircuitParametersInfos) => { // Replace form data with fetched data - replaceFormValues(parameters); + reset(shortCircuitMethods.toShortCircuitFormValues(parameters), { + keepDefaultValues: true, + }); }) .catch((error) => { console.error(error); @@ -98,7 +69,7 @@ export function ShortCircuitParametersInLine({ } setOpenSelectParameterDialog(false); }, - [snackError, replaceFormValues] + [snackError, shortCircuitMethods, reset] ); useEffect(() => { @@ -118,7 +89,13 @@ export function ShortCircuitParametersInLine({ label="settings.button.chooseSettings" /> setOpenCreateParameterDialog(true)} label="save" /> - + @@ -127,7 +104,7 @@ export function ShortCircuitParametersInLine({ studyUuid={studyUuid} open={openCreateParameterDialog} onClose={() => setOpenCreateParameterDialog(false)} - parameterValues={() => getCurrentValues()} + parameterValues={() => shortCircuitMethods.formatNewParams(getValues())} parameterFormatter={(newParams) => newParams} parameterType={ElementType.SHORT_CIRCUIT_PARAMETERS} /> diff --git a/src/components/parameters/short-circuit/short-circuit-parameters-utils.ts b/src/components/parameters/short-circuit/short-circuit-parameters-utils.ts new file mode 100644 index 00000000..5151d7ed --- /dev/null +++ b/src/components/parameters/short-circuit/short-circuit-parameters-utils.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { + InitialVoltage, + SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, + SHORT_CIRCUIT_WITH_FEEDER_RESULT, + SHORT_CIRCUIT_WITH_LOADS, + SHORT_CIRCUIT_WITH_NEUTRAL_POSITION, + SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, + SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, +} from './constants'; +import yup from '../../../utils/yupConfig'; +import { COMMON_PARAMETERS } from '../common'; + +export const getCommonShortCircuitParametersFormSchema = () => { + return yup.object().shape({ + [COMMON_PARAMETERS]: yup.object().shape({ + [SHORT_CIRCUIT_WITH_FEEDER_RESULT]: yup.boolean().required(), + [SHORT_CIRCUIT_WITH_LOADS]: yup.boolean().required(), + [SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS]: yup.boolean().required(), + [SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS]: yup.boolean().required(), + [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: yup.boolean().required(), + [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: yup + .mixed() + .oneOf(Object.values(InitialVoltage)) + .required(), + }), + }); +}; diff --git a/src/components/parameters/short-circuit/short-circuit-parameters.type.ts b/src/components/parameters/short-circuit/short-circuit-parameters.type.ts index bbeea4de..842bc984 100644 --- a/src/components/parameters/short-circuit/short-circuit-parameters.type.ts +++ b/src/components/parameters/short-circuit/short-circuit-parameters.type.ts @@ -4,6 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { SpecificParametersPerProvider } from '../../../utils'; import { InitialVoltage, PredefinedParameters } from './constants'; export interface VoltageRange { @@ -22,26 +23,8 @@ export interface ShortCircuitParametersDto { } export interface ShortCircuitParametersInfos { - parameters: ShortCircuitParametersDto; predefinedParameters: PredefinedParameters; + commonParameters: ShortCircuitParametersDto; + specificParametersPerProvider: SpecificParametersPerProvider; cei909VoltageRanges?: any; } - -interface VoltageRanges { - maximumNominalVoltage: number; - minimumNominalVoltage: number; - voltage: number; - voltageRangeCoefficient: number; -} -export interface ShortCircuitParameters { - predefinedParameters: NonNullable; - parameters: { - withFeederResult: boolean; - withLoads: boolean; - withVSCConverterStations: boolean; - withShuntCompensators: boolean; - withNeutralPosition: boolean; - initialVoltageProfileMode: NonNullable; - voltageRanges?: VoltageRanges; - }; -} diff --git a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts index 9b0126f8..e5f57e38 100644 --- a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts +++ b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts @@ -5,7 +5,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { FieldValues, useForm, UseFormReturn } from 'react-hook-form'; +import { FieldErrors, useForm, UseFormReturn } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { ObjectSchema } from 'yup'; @@ -16,6 +16,7 @@ import { InitialVoltage, PredefinedParameters, SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, + SHORT_CIRCUIT_ONLY_STARTED_GENERATORS, SHORT_CIRCUIT_PREDEFINED_PARAMS, SHORT_CIRCUIT_WITH_FEEDER_RESULT, SHORT_CIRCUIT_WITH_LOADS, @@ -23,214 +24,233 @@ import { SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, } from './constants'; -import { invalidateStudyShortCircuitStatus, setStudyShortCircuitParameters, updateParameter } from '../../../services'; +import { UseParametersBackendReturnProps } from '../../../utils/types/parameters.type'; +import { updateParameter } from '../../../services'; import { useSnackMessage } from '../../../hooks'; -import { ElementType } from '../../../utils'; +import { ElementType, ParameterType, SpecificParameterInfos, SpecificParametersPerProvider } from '../../../utils'; import { getNameElementEditorEmptyFormData, getNameElementEditorSchema } from '../common/name-element-editor'; -import { - ShortCircuitParameters, - ShortCircuitParametersDto, - ShortCircuitParametersInfos, -} from './short-circuit-parameters.type'; -import { fetchShortCircuitParameters } from '../../../services/short-circuit-analysis'; +import { ShortCircuitParametersInfos } from './short-circuit-parameters.type'; +import { COMMON_PARAMETERS, ComputingType, SPECIFIC_PARAMETERS, VERSION_PARAMETER } from '../common'; +import { getCommonShortCircuitParametersFormSchema } from './short-circuit-parameters-utils'; +import { getDefaultSpecificParamsValues, getSpecificParametersFormSchema } from '../common/utils'; + +const ManagedSpecificParameters = new Set([SHORT_CIRCUIT_ONLY_STARTED_GENERATORS]); export interface UseShortCircuitParametersFormReturn { formMethods: UseFormReturn; formSchema: ObjectSchema; - paramsLoading: boolean; + resetAll: (predefinedParameter: PredefinedParameters) => void; + specificParameters: SpecificParameterInfos[]; + toShortCircuitFormValues: (_params: ShortCircuitParametersInfos) => any; + formatNewParams: (formData: Record) => ShortCircuitParametersInfos; + params: ShortCircuitParametersInfos | null; + currentProvider: string | undefined; + setCurrentProvider: (provider: string) => void; + paramsLoaded: boolean; + onValidationError: (errors: FieldErrors) => void; onSaveInline: (formData: Record) => void; onSaveDialog: (formData: Record) => void; - resetAll: (predefinedParameter: PredefinedParameters) => void; - getCurrentValues: () => FieldValues; } // GridExplore versus GridStudy exclusive input params -type UseShortCircuitParametersFormProps = - | { - parametersUuid: UUID; - name: string; - description: string | null; - studyUuid: null; - studyShortCircuitParameters: null; - } - | { - parametersUuid: null; - name: null; - description: null; - studyUuid: UUID | null; - studyShortCircuitParameters: ShortCircuitParametersInfos | null; - }; +type UseShortCircuitParametersFormProps = { + parametersBackend: UseParametersBackendReturnProps; + parametersUuid: UUID | null; + name: string | null; + description: string | null; +}; export const useShortCircuitParametersForm = ({ + parametersBackend, parametersUuid, name, description, - studyUuid, - studyShortCircuitParameters, }: UseShortCircuitParametersFormProps): UseShortCircuitParametersFormReturn => { + const [, , , , , params, , updateParameters, , specificParamsDescriptions] = parametersBackend; + const [currentProvider, setCurrentProvider] = useState('Courcirc'); const { snackError } = useSnackMessage(); - const [paramsLoading, setParamsLoading] = useState(false); - const [shortCircuitParameters, setShortCircuitParameters] = useState(); + + const filteredSpecificParamsDescriptions = useMemo(() => { + return specificParamsDescriptions?.[currentProvider].filter((sp: SpecificParameterInfos) => + ManagedSpecificParameters.has(sp.name) + ); + }, [currentProvider, specificParamsDescriptions]); + + const defaultSpecificParametersValues = useMemo(() => { + return getDefaultSpecificParamsValues(filteredSpecificParamsDescriptions); + }, [filteredSpecificParamsDescriptions]); + + const specificParameters = useMemo(() => { + return filteredSpecificParamsDescriptions?.map((param: SpecificParameterInfos) => ({ + name: param.name, + type: param.type, + label: param.label, + description: param.description, + possibleValues: param.possibleValues, + defaultValue: param.defaultValue, + })); + }, [filteredSpecificParamsDescriptions]); const formSchema = useMemo(() => { return yup - .object() - .shape({ - [SHORT_CIRCUIT_WITH_FEEDER_RESULT]: yup.boolean().required(), + .object({ [SHORT_CIRCUIT_PREDEFINED_PARAMS]: yup .mixed() .oneOf(Object.values(PredefinedParameters)) .required(), - [SHORT_CIRCUIT_WITH_LOADS]: yup.boolean().required(), - [SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS]: yup.boolean().required(), - [SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS]: yup.boolean().required(), - [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: yup.boolean().required(), - [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: yup - .mixed() - .oneOf(Object.values(InitialVoltage)) - .required(), + ...getCommonShortCircuitParametersFormSchema().fields, + ...getSpecificParametersFormSchema(specificParameters).fields, }) - .required() .concat(getNameElementEditorSchema(name)); - }, [name]); + }, [name, specificParameters]); - const emptyFormData = useMemo(() => { - return { - ...getNameElementEditorEmptyFormData(name, description), - [SHORT_CIRCUIT_WITH_FEEDER_RESULT]: false, - [SHORT_CIRCUIT_PREDEFINED_PARAMS]: PredefinedParameters.ICC_MAX_WITH_CEI909, - [SHORT_CIRCUIT_WITH_LOADS]: false, - [SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS]: false, - [SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS]: false, - [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: false, - [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: InitialVoltage.CEI909 as - | InitialVoltage.NOMINAL - | InitialVoltage.CEI909 - | undefined, - }; - }, [name, description]); + console.log('SBO SC params?.commonParameters', params?.commonParameters); const formMethods = useForm({ - defaultValues: emptyFormData, + defaultValues: { + ...getNameElementEditorEmptyFormData(name, description), + [SHORT_CIRCUIT_PREDEFINED_PARAMS]: PredefinedParameters.ICC_MAX_WITH_CEI909, + [COMMON_PARAMETERS]: { + ...params?.commonParameters, + }, + [SPECIFIC_PARAMETERS]: { + ...defaultSpecificParametersValues, + }, + }, resolver: yupResolver(formSchema as unknown as yup.ObjectSchema), }); - const { getValues, reset, setValue } = formMethods; + const { reset, setValue } = formMethods; // when ever the predefined parameter is manually changed, we need to reset all parameters const resetAll = useCallback( (predefinedParameter: PredefinedParameters) => { const dirty = { shouldDirty: true }; - setValue(SHORT_CIRCUIT_WITH_FEEDER_RESULT, false, dirty); - setValue(SHORT_CIRCUIT_WITH_LOADS, false, dirty); setValue( - SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, - predefinedParameter !== PredefinedParameters.ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP, + COMMON_PARAMETERS, + { + ...params?.commonParameters, // for VERSION_PARAMETER and other non managed params + [SHORT_CIRCUIT_WITH_FEEDER_RESULT]: false, + [SHORT_CIRCUIT_WITH_LOADS]: false, + [SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS]: + predefinedParameter !== PredefinedParameters.ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP, + [SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS]: false, + [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: false, + [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: + predefinedParameter === PredefinedParameters.ICC_MAX_WITH_CEI909 + ? InitialVoltage.CEI909 + : InitialVoltage.NOMINAL, + }, dirty ); - setValue(SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, false, dirty); - setValue(SHORT_CIRCUIT_WITH_NEUTRAL_POSITION, false, dirty); - const initialVoltageProfileMode = - predefinedParameter === PredefinedParameters.ICC_MAX_WITH_CEI909 - ? InitialVoltage.CEI909 - : InitialVoltage.NOMINAL; - - setValue(SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, initialVoltageProfileMode, dirty); setValue(SHORT_CIRCUIT_PREDEFINED_PARAMS, predefinedParameter, dirty); + setValue( + SPECIFIC_PARAMETERS, + { + ...defaultSpecificParametersValues, + [SHORT_CIRCUIT_ONLY_STARTED_GENERATORS]: + predefinedParameter === PredefinedParameters.ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP, + }, + dirty + ); }, - [setValue] + [defaultSpecificParametersValues, params?.commonParameters, setValue] ); - const prepareDataToSend = ( - shortCircuitParams: ShortCircuitParametersInfos, - newParameters: FieldValues - ): ShortCircuitParameters => { - const oldParameters = { ...shortCircuitParams.parameters }; - const { - predefinedParameters: omit, - [NAME]: omit2, - [DESCRIPTION]: omit3, - ...newParametersWithoutPredefinedParameters - } = newParameters; - let parameters = { - ...oldParameters, - ...newParametersWithoutPredefinedParameters, - // we need to add voltageRanges to the parameters only when initialVoltageProfileMode is equals to CEI909 - voltageRanges: undefined, - withNeutralPosition: !newParameters.withNeutralPosition, - }; - if (newParameters.initialVoltageProfileMode === InitialVoltage.CEI909) { - parameters = { - ...parameters, - voltageRanges: shortCircuitParams.cei909VoltageRanges, - initialVoltageProfileMode: InitialVoltage.CONFIGURED, - }; - } - return { - predefinedParameters: newParameters.predefinedParameters, - parameters, - }; + const getSpecificParametersPerProvider = ( + formData: Record, + _specificParametersValues: SpecificParametersPerProvider + ) => { + return Object.keys(formData[SPECIFIC_PARAMETERS]).reduce( + (acc: Record, key: string) => { + if (_specificParametersValues[key].toString() !== formData[SPECIFIC_PARAMETERS][key].toString()) { + acc[key] = formData[SPECIFIC_PARAMETERS][key].toString(); + } + return acc; + }, + {} as Record + ); }; - const getCurrentValues = useCallback(() => { - if (shortCircuitParameters) { - const currentValues = getValues(); - return { ...prepareDataToSend(shortCircuitParameters, currentValues) }; - } - return {}; - }, [shortCircuitParameters, getValues]); + const formatNewParams = useCallback( + (formData: Record): ShortCircuitParametersInfos => { + console.log('SBO formatNewParams formData', formData); + return { + predefinedParameters: formData[SHORT_CIRCUIT_PREDEFINED_PARAMS], + commonParameters: { + [VERSION_PARAMETER]: formData[COMMON_PARAMETERS][VERSION_PARAMETER], // PowSyBl requires that "version" appears first + ...formData[COMMON_PARAMETERS], + }, + specificParametersPerProvider: { + Courcirc: getSpecificParametersPerProvider(formData, defaultSpecificParametersValues), + }, + }; + }, + [defaultSpecificParametersValues] + ); - const formatShortCircuitParameters = ( - parameters: ShortCircuitParametersDto, - predefinedParameters: PredefinedParameters - ): Object => { - return { - [SHORT_CIRCUIT_WITH_FEEDER_RESULT]: parameters.withFeederResult, - [SHORT_CIRCUIT_PREDEFINED_PARAMS]: predefinedParameters, - [SHORT_CIRCUIT_WITH_LOADS]: parameters.withLoads, - [SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS]: parameters.withVSCConverterStations, - [SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS]: parameters.withShuntCompensators, - [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: !parameters.withNeutralPosition, - [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: - parameters.initialVoltageProfileMode === InitialVoltage.CONFIGURED - ? InitialVoltage.CEI909 - : parameters.initialVoltageProfileMode, - }; - }; + const toShortCircuitFormValues = useCallback( + (_params: ShortCircuitParametersInfos) => { + const specificParams = filteredSpecificParamsDescriptions; + const specificParamsPerProvider = _params.specificParametersPerProvider[currentProvider]; + + const formatted = specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { + if (specificParamsPerProvider && Object.hasOwn(specificParamsPerProvider, param.name)) { + if (param.type === ParameterType.BOOLEAN) { + acc[param.name] = specificParamsPerProvider[param.name] === 'true'; + } else if (param.type === ParameterType.STRING_LIST) { + acc[param.name] = + specificParamsPerProvider[param.name] === '' + ? [] + : specificParamsPerProvider[param.name].split(','); + } else { + acc[param.name] = specificParamsPerProvider[param.name]; + } + } else { + acc[param.name] = getDefaultSpecificParamsValues([param])[param.name]; + } + return acc; + }, {}); + console.log('SBO toShortCircuitFormValues specificParams', formatted); + return { + [SHORT_CIRCUIT_PREDEFINED_PARAMS]: _params.predefinedParameters, + [COMMON_PARAMETERS]: { + ..._params.commonParameters, + [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: + _params.commonParameters.initialVoltageProfileMode === InitialVoltage.CONFIGURED + ? InitialVoltage.CEI909 + : _params.commonParameters.initialVoltageProfileMode, + }, + [SPECIFIC_PARAMETERS]: { + ...formatted, + }, + }; + }, + [currentProvider, filteredSpecificParamsDescriptions] + ); + + const paramsLoaded = useMemo(() => !!params && !!currentProvider, [currentProvider, params]); + + const onValidationError = useCallback((errors: FieldErrors) => { + console.log('SBO onValidationError errors', errors); + }, []); const onSaveInline = useCallback( (formData: Record) => { - if (studyUuid && shortCircuitParameters) { - const oldParams = shortCircuitParameters; - setStudyShortCircuitParameters(studyUuid, { - ...prepareDataToSend(shortCircuitParameters, formData), - }) - .then(() => { - invalidateStudyShortCircuitStatus(studyUuid).catch((error) => { - snackError({ - messageTxt: error.message, - headerId: 'invalidateShortCircuitStatusError', - }); - }); - }) - .catch((error) => { - setShortCircuitParameters(oldParams); - snackError({ - messageTxt: error.message, - headerId: 'paramsChangingError', - }); - }); - } + console.log('SBO onSaveInline', formData); + const data = formatNewParams(formData); + console.log('SBO onSaveInline data', data); + updateParameters(data); }, - [shortCircuitParameters, setShortCircuitParameters, snackError, studyUuid] + [updateParameters, formatNewParams] ); const onSaveDialog = useCallback( (formData: Record) => { - if (parametersUuid && shortCircuitParameters) { + if (parametersUuid) { updateParameter( parametersUuid, - prepareDataToSend(shortCircuitParameters, formData), + formatNewParams(formData), formData[NAME], ElementType.SHORT_CIRCUIT_PARAMETERS, formData[DESCRIPTION] ?? '' @@ -242,54 +262,29 @@ export const useShortCircuitParametersForm = ({ }); } }, - [parametersUuid, shortCircuitParameters, snackError] + [formatNewParams, parametersUuid, snackError] ); - // GridExplore init case - useEffect(() => { - if (parametersUuid) { - const timer = setTimeout(() => { - setParamsLoading(true); - }, 700); - fetchShortCircuitParameters(parametersUuid) - .then((params) => { - setShortCircuitParameters(params); - }) - .catch((error) => { - snackError({ - messageTxt: error.message, - headerId: 'paramsRetrievingError', - }); - }) - .finally(() => { - clearTimeout(timer); - setParamsLoading(false); - }); - } - }, [parametersUuid, snackError]); - - // GridStudy init/update case - useEffect(() => { - if (studyShortCircuitParameters) { - setShortCircuitParameters(studyShortCircuitParameters); - } - }, [studyShortCircuitParameters]); - - // common form reset useEffect(() => { - if (shortCircuitParameters) { - const { parameters, predefinedParameters } = shortCircuitParameters; - reset(formatShortCircuitParameters(parameters, predefinedParameters)); + if (!params) { + return; } - }, [reset, shortCircuitParameters]); + reset(toShortCircuitFormValues(params)); + }, [paramsLoaded, params, reset, specificParamsDescriptions, toShortCircuitFormValues]); return { formMethods, formSchema, - paramsLoading, + specificParameters, + toShortCircuitFormValues, + formatNewParams, + params, + currentProvider, + setCurrentProvider, + paramsLoaded, + onValidationError, onSaveInline, onSaveDialog, resetAll, - getCurrentValues, }; }; diff --git a/src/hooks/use-parameters-backend.ts b/src/hooks/use-parameters-backend.ts index 8e94c676..05826d67 100644 --- a/src/hooks/use-parameters-backend.ts +++ b/src/hooks/use-parameters-backend.ts @@ -33,9 +33,9 @@ export const useParametersBackend = ( studyUuid: UUID | null, type: T, optionalServiceStatus: OptionalServicesStatus | undefined, - backendFetchProviders: () => Promise, + backendFetchProviders: (() => Promise) | null, backendFetchProvider: ((studyUuid: UUID) => Promise) | null, - backendFetchDefaultProvider: () => Promise, + backendFetchDefaultProvider: (() => Promise) | null, backendUpdateProvider: ((studyUuid: UUID, newProvider: string) => Promise) | null, backendFetchParameters: (studyUuid: UUID) => Promise>, backendUpdateParameters?: (studyUuid: UUID, newParam: ParametersInfos | null) => Promise, @@ -85,7 +85,7 @@ export const useParametersBackend = ( // PROVIDER RESET const resetProvider = useCallback(() => { - backendFetchDefaultProvider() + backendFetchDefaultProvider?.() .then((defaultProvider) => { const providerNames = Object.keys(providersRef.current); if (providerNames.length > 0) { @@ -105,7 +105,7 @@ export const useParametersBackend = ( // PROVIDER SYNC const fetchAvailableProviders = useCallback(() => { - return backendFetchProviders() + return backendFetchProviders?.() .then((providers) => { // we can consider the provider gotten from back will be also used as // a key for translation @@ -151,7 +151,7 @@ export const useParametersBackend = ( // other dependencies don't change this much useEffect(() => { if (user !== null && studyUuid && optionalServiceStatus === OptionalServicesStatus.Up) { - fetchAvailableProviders().then(() => fetchProvider(studyUuid)); + fetchAvailableProviders()?.then(() => fetchProvider(studyUuid)); } }, [fetchAvailableProviders, fetchProvider, optionalServiceStatus, studyUuid, user]); diff --git a/src/services/index.ts b/src/services/index.ts index 491a7fc7..49bf8d22 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -14,4 +14,5 @@ export * from './study-config'; export * from './userAdmin'; export * from './voltage-init'; export * from './security-analysis'; +export * from './short-circuit-analysis'; export { CustomError } from './businessErrorCode'; diff --git a/src/services/short-circuit-analysis.ts b/src/services/short-circuit-analysis.ts index 0908862c..9b55857a 100644 --- a/src/services/short-circuit-analysis.ts +++ b/src/services/short-circuit-analysis.ts @@ -5,17 +5,39 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { backendFetchJson } from './utils'; +import { UUID } from 'node:crypto'; +import { backendFetch, backendFetchJson } from './utils'; import { ShortCircuitParametersInfos } from '../components/parameters/short-circuit/short-circuit-parameters.type'; const PREFIX_SHORT_CIRCUIT_SERVER_QUERIES = `${import.meta.env.VITE_API_GATEWAY}/shortcircuit`; function getShortCircuitUrl() { - return `${PREFIX_SHORT_CIRCUIT_SERVER_QUERIES}/v1`; + return `${PREFIX_SHORT_CIRCUIT_SERVER_QUERIES}/v1/`; +} + +export function getShortCircuitSpecificParametersDescription() { + console.info('get short circuit specific parameters description'); + const getShortCircuitSpecificParametersUrl = `${getShortCircuitUrl()}parameters/specific-parameters`; + console.debug(getShortCircuitSpecificParametersUrl); + return backendFetchJson(getShortCircuitSpecificParametersUrl); } export function fetchShortCircuitParameters(parameterUuid: string): Promise { console.info('get short circuit analysis parameters'); - const url = `${getShortCircuitUrl()}/parameters/${encodeURIComponent(parameterUuid)}`; + const url = `${getShortCircuitUrl()}parameters/${encodeURIComponent(parameterUuid)}`; return backendFetchJson(url); } + +export function updateShortCircuitParameters(parameterUuid: UUID, newParams: any) { + console.info('set short circuit parameters'); + const setShortCircuitParametersUrl = `${getShortCircuitUrl()}parameters/${parameterUuid}`; + console.debug(setShortCircuitParametersUrl); + return backendFetch(setShortCircuitParametersUrl, { + method: 'PUT', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: newParams ? JSON.stringify(newParams) : null, + }); +} diff --git a/src/services/study.ts b/src/services/study.ts index 3f590717..0b97def6 100644 --- a/src/services/study.ts +++ b/src/services/study.ts @@ -8,10 +8,7 @@ import type { UUID } from 'node:crypto'; import { backendFetch, backendFetchJson } from './utils'; import { NetworkVisualizationParameters } from '../components/parameters/network-visualizations/network-visualizations.types'; -import { - ShortCircuitParameters, - ShortCircuitParametersInfos, -} from '../components/parameters/short-circuit/short-circuit-parameters.type'; +import { type ShortCircuitParametersInfos } from '../components/parameters/short-circuit/short-circuit-parameters.type'; import { VoltageInitStudyParameters } from '../components/parameters/voltage-init/voltage-init.type'; const PREFIX_STUDY_QUERIES = `${import.meta.env.VITE_API_GATEWAY}/study`; @@ -55,25 +52,6 @@ export function getStudyShortCircuitParameters(studyUuid: UUID): Promise = T extends ComputingType.S ? DynamicSimulationParametersFetchReturn : T extends ComputingType.DYNAMIC_SECURITY_ANALYSIS ? DynamicSecurityAnalysisParametersFetchReturn - : Record; + : T extends ComputingType.SHORT_CIRCUIT + ? ShortCircuitParametersInfos + : Record; export type UseParametersBackendReturnProps = [ Record, From 1ccb075c0447de07ff774c5fe59011bef7bc09be Mon Sep 17 00:00:00 2001 From: sBouzols Date: Wed, 5 Nov 2025 18:12:12 +0100 Subject: [PATCH 2/5] feat(): use Radio button instead of checkbox for onlyStartedGeneratorsOption Signed-off-by: sBouzols --- src/components/parameters/short-circuit/constants.ts | 4 ++-- .../parameters/short-circuit/short-circuit-fields.tsx | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/parameters/short-circuit/constants.ts b/src/components/parameters/short-circuit/constants.ts index 99e91786..50647699 100644 --- a/src/components/parameters/short-circuit/constants.ts +++ b/src/components/parameters/short-circuit/constants.ts @@ -56,11 +56,11 @@ export const intlInitialVoltageProfileMode = () => { export const onlyStartedGeneratorsOptions = { ALL: { - id: false, + id: 'false', label: 'ShortCircuitAllLabel', }, STARTED: { - id: true, + id: 'true', label: 'ShortCircuitStartedLabel', }, }; diff --git a/src/components/parameters/short-circuit/short-circuit-fields.tsx b/src/components/parameters/short-circuit/short-circuit-fields.tsx index e963354f..10c96c60 100644 --- a/src/components/parameters/short-circuit/short-circuit-fields.tsx +++ b/src/components/parameters/short-circuit/short-circuit-fields.tsx @@ -14,6 +14,7 @@ import { InitialVoltage, intlInitialVoltageProfileMode, intlPredefinedParametersOptions, + onlyStartedGeneratorsOptions, PredefinedParameters, SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, SHORT_CIRCUIT_ONLY_STARTED_GENERATORS, @@ -157,14 +158,10 @@ export function ShortCircuitFields({ resetAll, enableDeveloperMode = true }: Rea ); const onlyStartedGenerators = ( - - // ); useEffect(() => { From f01423e4255c8aa85324d44aab58bc1aa6434522 Mon Sep 17 00:00:00 2001 From: sBouzols Date: Fri, 7 Nov 2025 16:18:19 +0100 Subject: [PATCH 3/5] refactor(): remove code duplication between LF and SC custom hooks for parameters form. fix(SC): restore boolean inversion for SHORT_CIRCUIT_WITH_NEUTRAL_POSITION and add `cei909VoltageRanges` only when Profile mode is CEI909 Signed-off-by: sBouzols --- src/components/parameters/common/utils.ts | 71 ++++++++--- .../loadflow/load-flow-parameters-form.tsx | 4 +- .../loadflow/load-flow-parameters-type.ts | 19 +++ .../loadflow/use-load-flow-parameters-form.ts | 97 +++++---------- .../use-short-circuit-parameters-form.ts | 114 +++++++----------- src/hooks/use-parameters-backend.ts | 8 +- src/utils/types/loadflow.type.ts | 3 +- src/utils/types/parameters.type.ts | 6 +- 8 files changed, 163 insertions(+), 159 deletions(-) create mode 100644 src/components/parameters/loadflow/load-flow-parameters-type.ts diff --git a/src/components/parameters/common/utils.ts b/src/components/parameters/common/utils.ts index 7d0853ed..9f05f0d2 100644 --- a/src/components/parameters/common/utils.ts +++ b/src/components/parameters/common/utils.ts @@ -5,11 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { UseFormReturn } from 'react-hook-form'; -import { ParameterType, SpecificParameterInfos, SpecificParametersPerProvider } from '../../../utils'; +import { ParameterType, SpecificParameterInfos, SpecificParametersDescription, SpecificParametersValues } from '../../../utils'; import { SPECIFIC_PARAMETERS } from './constant'; import yup from '../../../utils/yupConfig'; -export const getSpecificParametersFormSchema = (specificParameters: SpecificParameterInfos[]) => { +export const getSpecificParametersFormSchema = (specificParameters: SpecificParameterInfos[] | undefined) => { const shape: { [key: string]: yup.AnySchema } = {}; specificParameters?.forEach((param: SpecificParameterInfos) => { @@ -40,18 +40,59 @@ export const getSpecificParametersFormSchema = (specificParameters: SpecificPara }; export const getDefaultSpecificParamsValues = ( - specificParams: SpecificParameterInfos[] -): SpecificParametersPerProvider => { - return specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { - if (param.type === ParameterType.STRING_LIST && param.defaultValue === null) { - acc[param.name] = []; - } else if ( - (param.type === ParameterType.DOUBLE || param.type === ParameterType.INTEGER) && - Number.isNaN(Number(param.defaultValue)) - ) { - acc[param.name] = 0; - } else { - acc[param.name] = param.defaultValue; + specificParametersDescriptionForProvider: SpecificParameterInfos[] +): SpecificParametersValues => { + return specificParametersDescriptionForProvider.reduce( + (acc: SpecificParametersValues, param: SpecificParameterInfos) => { + if (param.type === ParameterType.STRING_LIST && param.defaultValue === null) { + acc[param.name] = []; + } else if ( + (param.type === ParameterType.DOUBLE || param.type === ParameterType.INTEGER) && + Number.isNaN(Number(param.defaultValue)) + ) { + acc[param.name] = 0; + } else { + acc[param.name] = param.defaultValue; + } + return acc; + }, + {} + ); +}; + +export const formatSpecificParameters = ( + specificParametersDescriptionForProvider: SpecificParameterInfos[], + specificParamsList: SpecificParametersValues +): SpecificParametersValues => { + return specificParametersDescriptionForProvider.reduce( + (acc: SpecificParametersValues, param: SpecificParameterInfos) => { + if (specificParamsList && Object.hasOwn(specificParamsList, param.name)) { + if (param.type === ParameterType.BOOLEAN) { + acc[param.name] = specificParamsList[param.name] === 'true'; + } else if (param.type === ParameterType.STRING_LIST) { + acc[param.name] = + specificParamsList[param.name] === '' + ? [] + : (specificParamsList[param.name] as string).split(','); + } else { + acc[param.name] = specificParamsList[param.name]; + } + } else { + acc[param.name] = getDefaultSpecificParamsValues([param])?.[param.name]; + } + return acc; + }, + {} + ); +}; + +export const getAllSpecificParametersValues = ( + formData: Record, + _specificParametersValues: SpecificParametersValues +): SpecificParametersValues => { + return Object.keys(formData[SPECIFIC_PARAMETERS]).reduce((acc: SpecificParametersValues, key: string) => { + if (_specificParametersValues[key].toString() !== formData[SPECIFIC_PARAMETERS][key].toString()) { + acc[key] = formData[SPECIFIC_PARAMETERS][key].toString(); } return acc; }, {}); @@ -59,7 +100,7 @@ export const getDefaultSpecificParamsValues = ( export const setSpecificParameters = ( provider: string, - specificParamsDescriptions: Record | null, + specificParamsDescriptions: SpecificParametersDescription | null, formMethods: UseFormReturn ) => { const specificParams = provider ? (specificParamsDescriptions?.[provider] ?? []) : []; diff --git a/src/components/parameters/loadflow/load-flow-parameters-form.tsx b/src/components/parameters/loadflow/load-flow-parameters-form.tsx index 6bc09fe6..f51e9b89 100644 --- a/src/components/parameters/loadflow/load-flow-parameters-form.tsx +++ b/src/components/parameters/loadflow/load-flow-parameters-form.tsx @@ -60,7 +60,7 @@ export function LoadFlowParametersForm({ handleTabChange, tabIndexesWithError, formattedProviders, - specificParameters, + specificParametersDescriptionForProvider, params, currentProvider, defaultLimitReductions, @@ -85,7 +85,7 @@ export function LoadFlowParametersForm({ diff --git a/src/components/parameters/loadflow/load-flow-parameters-type.ts b/src/components/parameters/loadflow/load-flow-parameters-type.ts new file mode 100644 index 00000000..d963bccc --- /dev/null +++ b/src/components/parameters/loadflow/load-flow-parameters-type.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import type { UUID } from 'node:crypto'; +import { ILimitReductionsByVoltageLevel } from '../common'; +import { SpecificParametersPerProvider } from '../../../utils'; + +export interface LoadFlowParametersInfos { + uuid?: UUID; + provider: string; + limitReduction: number; + commonParameters: Record; + specificParametersPerProvider: SpecificParametersPerProvider; + limitReductions: ILimitReductionsByVoltageLevel[]; +} diff --git a/src/components/parameters/loadflow/use-load-flow-parameters-form.ts b/src/components/parameters/loadflow/use-load-flow-parameters-form.ts index faded5d1..15260338 100644 --- a/src/components/parameters/loadflow/use-load-flow-parameters-form.ts +++ b/src/components/parameters/loadflow/use-load-flow-parameters-form.ts @@ -16,12 +16,7 @@ import { setLimitReductions, TabValues, } from './load-flow-parameters-utils'; -import { LoadFlowParametersInfos, SpecificParametersPerProvider } from '../../../utils/types/loadflow.type'; -import { - ParameterType, - SpecificParameterInfos, - UseParametersBackendReturnProps, -} from '../../../utils/types/parameters.type'; +import { LoadFlowParametersInfos } from './load-flow-parameters-type'; import { COMMON_PARAMETERS, ComputingType, PROVIDER, SPECIFIC_PARAMETERS, VERSION_PARAMETER } from '../common'; import { getLimitReductionsFormSchema, @@ -33,12 +28,14 @@ import yup from '../../../utils/yupConfig'; import { toFormValuesLimitReductions } from '../common/limitreductions/limit-reductions-form-util'; import { DESCRIPTION, NAME } from '../../inputs'; import { updateParameter } from '../../../services'; -import { ElementType } from '../../../utils'; +import { ElementType, SpecificParameterInfos, UseParametersBackendReturnProps } from '../../../utils'; import { getNameElementEditorEmptyFormData, getNameElementEditorSchema } from '../common/name-element-editor'; import { useSnackMessage } from '../../../hooks'; import { + formatSpecificParameters, getDefaultSpecificParamsValues, getSpecificParametersFormSchema, + getAllSpecificParametersValues, setSpecificParameters, } from '../common/utils'; @@ -49,7 +46,7 @@ export interface UseLoadFlowParametersFormReturn { handleTabChange: (event: SyntheticEvent, newValue: TabValues) => void; tabIndexesWithError: TabValues[]; formattedProviders: { id: string; label: string }[]; - specificParameters: SpecificParameterInfos[]; + specificParametersDescriptionForProvider: SpecificParameterInfos[]; defaultLimitReductions: ILimitReductionsByVoltageLevel[]; toLoadFlowFormValues: (_params: LoadFlowParametersInfos) => any; formatNewParams: (formData: Record) => LoadFlowParametersInfos; @@ -93,22 +90,13 @@ export const useLoadFlowParametersForm = ( setSelectedTab(newValue); }, []); - const specificParametersValues = useMemo(() => { - const specificParams = currentProvider ? specificParamsDescriptions?.[currentProvider] : undefined; - return getDefaultSpecificParamsValues(specificParams); + const specificParametersDescriptionForProvider = useMemo(() => { + return currentProvider && specificParamsDescriptions ? specificParamsDescriptions[currentProvider] : []; }, [currentProvider, specificParamsDescriptions]); - const specificParameters = useMemo(() => { - const specificParams = currentProvider ? specificParamsDescriptions?.[currentProvider] : undefined; - return specificParams?.map((param: SpecificParameterInfos) => ({ - name: param.name, - type: param.type, - label: param.label, - description: param.description, - possibleValues: param.possibleValues, - defaultValue: param.defaultValue, - })); - }, [currentProvider, specificParamsDescriptions]); + const specificParametersDefaultValues = useMemo(() => { + return getDefaultSpecificParamsValues(specificParametersDescriptionForProvider); + }, [specificParametersDescriptionForProvider]); const formSchema = useMemo(() => { return yup @@ -117,10 +105,10 @@ export const useLoadFlowParametersForm = ( [PARAM_LIMIT_REDUCTION]: yup.number().nullable(), ...getCommonLoadFlowParametersFormSchema().fields, ...getLimitReductionsFormSchema(limitReductionNumber).fields, - ...getSpecificParametersFormSchema(specificParameters).fields, + ...getSpecificParametersFormSchema(specificParametersDescriptionForProvider).fields, }) .concat(getNameElementEditorSchema(name)); - }, [name, limitReductionNumber, specificParameters]); + }, [name, limitReductionNumber, specificParametersDescriptionForProvider]); console.log('SBO LF params?.commonParameters', params?.commonParameters); const formMethods = useForm({ @@ -132,7 +120,7 @@ export const useLoadFlowParametersForm = ( ...params?.commonParameters, }, [SPECIFIC_PARAMETERS]: { - ...specificParametersValues, + ...specificParametersDefaultValues, }, [LIMIT_REDUCTIONS_FORM]: [], }, @@ -162,21 +150,6 @@ export const useLoadFlowParametersForm = ( [defaultLimitReductions, params?.limitReductions, watchProvider] ); - const getSpecificParametersPerProvider = ( - formData: Record, - _specificParametersValues: SpecificParametersPerProvider - ) => { - return Object.keys(formData[SPECIFIC_PARAMETERS]).reduce( - (acc: Record, key: string) => { - if (_specificParametersValues[key].toString() !== formData[SPECIFIC_PARAMETERS][key].toString()) { - acc[key] = formData[SPECIFIC_PARAMETERS][key].toString(); - } - return acc; - }, - {} as Record - ); - }; - const formatNewParams = useCallback( (formData: Record): LoadFlowParametersInfos => { return { @@ -186,37 +159,24 @@ export const useLoadFlowParametersForm = ( [VERSION_PARAMETER]: formData[COMMON_PARAMETERS][VERSION_PARAMETER], // PowSyBl requires that "version" appears first ...formData[COMMON_PARAMETERS], }, - specificParametersPerProvider: { - [formData.provider]: getSpecificParametersPerProvider(formData, specificParametersValues), - }, + specificParametersPerProvider: specificParametersDefaultValues + ? { + [formData.provider]: getAllSpecificParametersValues( + formData, + specificParametersDefaultValues + ), + } + : {}, + limitReductions: toLimitReductions(formData[LIMIT_REDUCTIONS_FORM]), }; }, - [specificParametersValues, toLimitReductions] + [specificParametersDefaultValues, toLimitReductions] ); const toLoadFlowFormValues = useCallback( (_params: LoadFlowParametersInfos) => { - const specificParams = _params.provider ? specificParamsDescriptions?.[_params.provider] : undefined; - const specificParamsPerProvider = _params.specificParametersPerProvider[_params.provider]; - - const formatted = specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { - if (specificParamsPerProvider && Object.hasOwn(specificParamsPerProvider, param.name)) { - if (param.type === ParameterType.BOOLEAN) { - acc[param.name] = specificParamsPerProvider[param.name] === 'true'; - } else if (param.type === ParameterType.STRING_LIST) { - acc[param.name] = - specificParamsPerProvider[param.name] === '' - ? [] - : specificParamsPerProvider[param.name].split(','); - } else { - acc[param.name] = specificParamsPerProvider[param.name]; - } - } else { - acc[param.name] = getDefaultSpecificParamsValues([param])[param.name]; - } - return acc; - }, {}); + const specificParamsListForCurrentProvider = _params.specificParametersPerProvider[_params.provider]; return { [PROVIDER]: _params.provider, @@ -225,12 +185,15 @@ export const useLoadFlowParametersForm = ( ..._params.commonParameters, }, [SPECIFIC_PARAMETERS]: { - ...formatted, + ...formatSpecificParameters( + specificParametersDescriptionForProvider, + specificParamsListForCurrentProvider + ), }, ...toFormValuesLimitReductions(_params.limitReductions), }; }, - [specificParamsDescriptions] + [specificParametersDescriptionForProvider] ); const paramsLoaded = useMemo(() => !!params && !!currentProvider, [currentProvider, params]); @@ -334,7 +297,7 @@ export const useLoadFlowParametersForm = ( handleTabChange, tabIndexesWithError, formattedProviders, - specificParameters, + specificParametersDescriptionForProvider, defaultLimitReductions, toLoadFlowFormValues, formatNewParams, diff --git a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts index e5f57e38..320391d7 100644 --- a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts +++ b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts @@ -24,15 +24,19 @@ import { SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS, SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS, } from './constants'; -import { UseParametersBackendReturnProps } from '../../../utils/types/parameters.type'; import { updateParameter } from '../../../services'; import { useSnackMessage } from '../../../hooks'; -import { ElementType, ParameterType, SpecificParameterInfos, SpecificParametersPerProvider } from '../../../utils'; +import { ElementType, SpecificParameterInfos, UseParametersBackendReturnProps } from '../../../utils'; import { getNameElementEditorEmptyFormData, getNameElementEditorSchema } from '../common/name-element-editor'; import { ShortCircuitParametersInfos } from './short-circuit-parameters.type'; import { COMMON_PARAMETERS, ComputingType, SPECIFIC_PARAMETERS, VERSION_PARAMETER } from '../common'; import { getCommonShortCircuitParametersFormSchema } from './short-circuit-parameters-utils'; -import { getDefaultSpecificParamsValues, getSpecificParametersFormSchema } from '../common/utils'; +import { + formatSpecificParameters, + getDefaultSpecificParamsValues, + getSpecificParametersFormSchema, + getAllSpecificParametersValues, +} from '../common/utils'; const ManagedSpecificParameters = new Set([SHORT_CIRCUIT_ONLY_STARTED_GENERATORS]); @@ -40,7 +44,7 @@ export interface UseShortCircuitParametersFormReturn { formMethods: UseFormReturn; formSchema: ObjectSchema; resetAll: (predefinedParameter: PredefinedParameters) => void; - specificParameters: SpecificParameterInfos[]; + specificParametersDescriptionForProvider: SpecificParameterInfos[]; toShortCircuitFormValues: (_params: ShortCircuitParametersInfos) => any; formatNewParams: (formData: Record) => ShortCircuitParametersInfos; params: ShortCircuitParametersInfos | null; @@ -70,26 +74,17 @@ export const useShortCircuitParametersForm = ({ const [currentProvider, setCurrentProvider] = useState('Courcirc'); const { snackError } = useSnackMessage(); - const filteredSpecificParamsDescriptions = useMemo(() => { - return specificParamsDescriptions?.[currentProvider].filter((sp: SpecificParameterInfos) => - ManagedSpecificParameters.has(sp.name) - ); + const specificParametersDescriptionForProvider = useMemo(() => { + return currentProvider && specificParamsDescriptions + ? specificParamsDescriptions[currentProvider].filter((sp: SpecificParameterInfos) => + ManagedSpecificParameters.has(sp.name) + ) + : []; }, [currentProvider, specificParamsDescriptions]); - const defaultSpecificParametersValues = useMemo(() => { - return getDefaultSpecificParamsValues(filteredSpecificParamsDescriptions); - }, [filteredSpecificParamsDescriptions]); - - const specificParameters = useMemo(() => { - return filteredSpecificParamsDescriptions?.map((param: SpecificParameterInfos) => ({ - name: param.name, - type: param.type, - label: param.label, - description: param.description, - possibleValues: param.possibleValues, - defaultValue: param.defaultValue, - })); - }, [filteredSpecificParamsDescriptions]); + const specificParametersDefaultValues = useMemo(() => { + return getDefaultSpecificParamsValues(specificParametersDescriptionForProvider); + }, [specificParametersDescriptionForProvider]); const formSchema = useMemo(() => { return yup @@ -99,10 +94,10 @@ export const useShortCircuitParametersForm = ({ .oneOf(Object.values(PredefinedParameters)) .required(), ...getCommonShortCircuitParametersFormSchema().fields, - ...getSpecificParametersFormSchema(specificParameters).fields, + ...getSpecificParametersFormSchema(specificParametersDescriptionForProvider).fields, }) .concat(getNameElementEditorSchema(name)); - }, [name, specificParameters]); + }, [name, specificParametersDescriptionForProvider]); console.log('SBO SC params?.commonParameters', params?.commonParameters); @@ -114,7 +109,7 @@ export const useShortCircuitParametersForm = ({ ...params?.commonParameters, }, [SPECIFIC_PARAMETERS]: { - ...defaultSpecificParametersValues, + ...specificParametersDefaultValues, }, }, resolver: yupResolver(formSchema as unknown as yup.ObjectSchema), @@ -147,31 +142,16 @@ export const useShortCircuitParametersForm = ({ setValue( SPECIFIC_PARAMETERS, { - ...defaultSpecificParametersValues, + ...specificParametersDefaultValues, [SHORT_CIRCUIT_ONLY_STARTED_GENERATORS]: predefinedParameter === PredefinedParameters.ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP, }, dirty ); }, - [defaultSpecificParametersValues, params?.commonParameters, setValue] + [specificParametersDefaultValues, params?.commonParameters, setValue] ); - const getSpecificParametersPerProvider = ( - formData: Record, - _specificParametersValues: SpecificParametersPerProvider - ) => { - return Object.keys(formData[SPECIFIC_PARAMETERS]).reduce( - (acc: Record, key: string) => { - if (_specificParametersValues[key].toString() !== formData[SPECIFIC_PARAMETERS][key].toString()) { - acc[key] = formData[SPECIFIC_PARAMETERS][key].toString(); - } - return acc; - }, - {} as Record - ); - }; - const formatNewParams = useCallback( (formData: Record): ShortCircuitParametersInfos => { console.log('SBO formatNewParams formData', formData); @@ -180,38 +160,31 @@ export const useShortCircuitParametersForm = ({ commonParameters: { [VERSION_PARAMETER]: formData[COMMON_PARAMETERS][VERSION_PARAMETER], // PowSyBl requires that "version" appears first ...formData[COMMON_PARAMETERS], + [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: + formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE] === + InitialVoltage.CEI909 + ? InitialVoltage.CONFIGURED + : formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE], + // this should be inverted for API compatibility + [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: + !formData[COMMON_PARAMETERS][SHORT_CIRCUIT_WITH_NEUTRAL_POSITION], }, specificParametersPerProvider: { - Courcirc: getSpecificParametersPerProvider(formData, defaultSpecificParametersValues), + Courcirc: getAllSpecificParametersValues(formData, specificParametersDefaultValues), }, + // we need to add voltageRanges to the parameters only when initialVoltageProfileMode is equals to CEI909 + cei909VoltageRanges: + formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE] === InitialVoltage.CEI909 + ? params?.cei909VoltageRanges + : undefined, }; }, - [defaultSpecificParametersValues] + [params?.cei909VoltageRanges, specificParametersDefaultValues] ); const toShortCircuitFormValues = useCallback( (_params: ShortCircuitParametersInfos) => { - const specificParams = filteredSpecificParamsDescriptions; - const specificParamsPerProvider = _params.specificParametersPerProvider[currentProvider]; - - const formatted = specificParams?.reduce((acc: Record, param: SpecificParameterInfos) => { - if (specificParamsPerProvider && Object.hasOwn(specificParamsPerProvider, param.name)) { - if (param.type === ParameterType.BOOLEAN) { - acc[param.name] = specificParamsPerProvider[param.name] === 'true'; - } else if (param.type === ParameterType.STRING_LIST) { - acc[param.name] = - specificParamsPerProvider[param.name] === '' - ? [] - : specificParamsPerProvider[param.name].split(','); - } else { - acc[param.name] = specificParamsPerProvider[param.name]; - } - } else { - acc[param.name] = getDefaultSpecificParamsValues([param])[param.name]; - } - return acc; - }, {}); - console.log('SBO toShortCircuitFormValues specificParams', formatted); + const specificParamsListForCurrentProvider = _params.specificParametersPerProvider[currentProvider]; return { [SHORT_CIRCUIT_PREDEFINED_PARAMS]: _params.predefinedParameters, [COMMON_PARAMETERS]: { @@ -220,13 +193,18 @@ export const useShortCircuitParametersForm = ({ _params.commonParameters.initialVoltageProfileMode === InitialVoltage.CONFIGURED ? InitialVoltage.CEI909 : _params.commonParameters.initialVoltageProfileMode, + // invert back the value for the form + [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: !_params.commonParameters.withNeutralPosition, }, [SPECIFIC_PARAMETERS]: { - ...formatted, + ...formatSpecificParameters( + specificParametersDescriptionForProvider, + specificParamsListForCurrentProvider + ), }, }; }, - [currentProvider, filteredSpecificParamsDescriptions] + [currentProvider, specificParametersDescriptionForProvider] ); const paramsLoaded = useMemo(() => !!params && !!currentProvider, [currentProvider, params]); @@ -275,7 +253,7 @@ export const useShortCircuitParametersForm = ({ return { formMethods, formSchema, - specificParameters, + specificParametersDescriptionForProvider, toShortCircuitFormValues, formatNewParams, params, diff --git a/src/hooks/use-parameters-backend.ts b/src/hooks/use-parameters-backend.ts index 05826d67..c6d3da9b 100644 --- a/src/hooks/use-parameters-backend.ts +++ b/src/hooks/use-parameters-backend.ts @@ -16,7 +16,7 @@ import { ComputingType, formatComputingTypeLabel } from '../components/parameter import type { ILimitReductionsByVoltageLevel } from '../components/parameters/common/limitreductions/columns-definitions'; import type { ParametersInfos, - SpecificParametersInfos, + SpecificParametersDescription, UseParametersBackendReturnProps, } from '../utils/types/parameters.type'; @@ -39,7 +39,7 @@ export const useParametersBackend = ( backendUpdateProvider: ((studyUuid: UUID, newProvider: string) => Promise) | null, backendFetchParameters: (studyUuid: UUID) => Promise>, backendUpdateParameters?: (studyUuid: UUID, newParam: ParametersInfos | null) => Promise, - backendFetchSpecificParametersDescription?: () => Promise, + backendFetchSpecificParametersDescription?: () => Promise, backendFetchDefaultLimitReductions?: () => Promise ): UseParametersBackendReturnProps => { const { snackError, snackWarning } = useSnackMessage(); @@ -50,7 +50,9 @@ export const useParametersBackend = ( providerRef.current = provider; const [params, setParams] = useState | null>(null); - const [specificParamsDescription, setSpecificParamsDescription] = useState | null>(null); + const [specificParamsDescription, setSpecificParamsDescription] = useState( + null + ); const [defaultLimitReductions, setDefaultLimitReductions] = useState([]); const optionalServiceStatusRef = useRef(optionalServiceStatus); diff --git a/src/utils/types/loadflow.type.ts b/src/utils/types/loadflow.type.ts index c27477a8..98d87886 100644 --- a/src/utils/types/loadflow.type.ts +++ b/src/utils/types/loadflow.type.ts @@ -7,6 +7,7 @@ import type { UUID } from 'node:crypto'; import type { ILimitReductionsByVoltageLevel } from '../../components/parameters/common/limitreductions/columns-definitions'; +import type { SpecificParametersPerProvider } from '..'; export interface LoadFlowParametersInfos { uuid?: UUID; @@ -16,5 +17,3 @@ export interface LoadFlowParametersInfos { specificParametersPerProvider: SpecificParametersPerProvider; limitReductions: ILimitReductionsByVoltageLevel[]; } - -export type SpecificParametersPerProvider = Record>; diff --git a/src/utils/types/parameters.type.ts b/src/utils/types/parameters.type.ts index 912911ae..98c1036a 100644 --- a/src/utils/types/parameters.type.ts +++ b/src/utils/types/parameters.type.ts @@ -37,7 +37,9 @@ export type SpecificParameterInfos = { label?: string; }; -export type SpecificParametersInfos = Record; +export type SpecificParametersDescription = Record; +export type SpecificParametersValues = Record; +export type SpecificParametersPerProvider = Record; export type ParametersInfos = T extends ComputingType.SENSITIVITY_ANALYSIS ? SensitivityAnalysisParametersInfos @@ -63,6 +65,6 @@ export type UseParametersBackendReturnProps = [ (studyUuid: UUID) => void, (newParams: ParametersInfos) => void, () => Promise | undefined, - Record | null, + SpecificParametersDescription | null, ILimitReductionsByVoltageLevel[], ]; From 1d0b58c18b30e34eb6169109afa9d057182faae4 Mon Sep 17 00:00:00 2001 From: sBouzols Date: Fri, 7 Nov 2025 16:59:48 +0100 Subject: [PATCH 4/5] fix(SC): voltageRanges missing to give with CEI profile Signed-off-by: sBouzols --- .../parameters/short-circuit/constants.ts | 4 ++++ .../short-circuit-parameters.type.ts | 4 +++- .../use-short-circuit-parameters-form.ts | 18 ++++++++++-------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/parameters/short-circuit/constants.ts b/src/components/parameters/short-circuit/constants.ts index 50647699..01d926e0 100644 --- a/src/components/parameters/short-circuit/constants.ts +++ b/src/components/parameters/short-circuit/constants.ts @@ -17,6 +17,7 @@ export enum PredefinedParameters { ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP = 'ICC_MIN_WITH_NOMINAL_VOLTAGE_MAP', } +// common parameters export const SHORT_CIRCUIT_WITH_FEEDER_RESULT = 'withFeederResult'; export const SHORT_CIRCUIT_PREDEFINED_PARAMS = 'predefinedParameters'; export const SHORT_CIRCUIT_WITH_LOADS = 'withLoads'; @@ -24,6 +25,9 @@ export const SHORT_CIRCUIT_WITH_VSC_CONVERTER_STATIONS = 'withVSCConverterStatio export const SHORT_CIRCUIT_WITH_SHUNT_COMPENSATORS = 'withShuntCompensators'; export const SHORT_CIRCUIT_WITH_NEUTRAL_POSITION = 'withNeutralPosition'; export const SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE = 'initialVoltageProfileMode'; +export const SHORT_CIRCUIT_VOLTAGE_RANGES = 'voltageRanges'; + +// specific parameters export const SHORT_CIRCUIT_ONLY_STARTED_GENERATORS = 'onlyStartedGenerators'; export const intlPredefinedParametersOptions = () => [ diff --git a/src/components/parameters/short-circuit/short-circuit-parameters.type.ts b/src/components/parameters/short-circuit/short-circuit-parameters.type.ts index 842bc984..aedd0a28 100644 --- a/src/components/parameters/short-circuit/short-circuit-parameters.type.ts +++ b/src/components/parameters/short-circuit/short-circuit-parameters.type.ts @@ -10,6 +10,8 @@ import { InitialVoltage, PredefinedParameters } from './constants'; export interface VoltageRange { minimumNominalVoltage: number; maximumNominalVoltage: number; + voltage: number; + voltageRangeCoefficient: number; } export interface ShortCircuitParametersDto { @@ -26,5 +28,5 @@ export interface ShortCircuitParametersInfos { predefinedParameters: PredefinedParameters; commonParameters: ShortCircuitParametersDto; specificParametersPerProvider: SpecificParametersPerProvider; - cei909VoltageRanges?: any; + cei909VoltageRanges?: VoltageRange[]; } diff --git a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts index 320391d7..5035b9ef 100644 --- a/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts +++ b/src/components/parameters/short-circuit/use-short-circuit-parameters-form.ts @@ -18,6 +18,7 @@ import { SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE, SHORT_CIRCUIT_ONLY_STARTED_GENERATORS, SHORT_CIRCUIT_PREDEFINED_PARAMS, + SHORT_CIRCUIT_VOLTAGE_RANGES, SHORT_CIRCUIT_WITH_FEEDER_RESULT, SHORT_CIRCUIT_WITH_LOADS, SHORT_CIRCUIT_WITH_NEUTRAL_POSITION, @@ -160,23 +161,24 @@ export const useShortCircuitParametersForm = ({ commonParameters: { [VERSION_PARAMETER]: formData[COMMON_PARAMETERS][VERSION_PARAMETER], // PowSyBl requires that "version" appears first ...formData[COMMON_PARAMETERS], + // this should be inverted for API compatibility + [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: + !formData[COMMON_PARAMETERS][SHORT_CIRCUIT_WITH_NEUTRAL_POSITION], [SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE]: formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE] === InitialVoltage.CEI909 ? InitialVoltage.CONFIGURED : formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE], - // this should be inverted for API compatibility - [SHORT_CIRCUIT_WITH_NEUTRAL_POSITION]: - !formData[COMMON_PARAMETERS][SHORT_CIRCUIT_WITH_NEUTRAL_POSITION], + // we need to add voltageRanges to the parameters only when initialVoltageProfileMode is equals to CEI909 + [SHORT_CIRCUIT_VOLTAGE_RANGES]: + formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE] === + InitialVoltage.CEI909 + ? params?.cei909VoltageRanges + : undefined, }, specificParametersPerProvider: { Courcirc: getAllSpecificParametersValues(formData, specificParametersDefaultValues), }, - // we need to add voltageRanges to the parameters only when initialVoltageProfileMode is equals to CEI909 - cei909VoltageRanges: - formData[COMMON_PARAMETERS][SHORT_CIRCUIT_INITIAL_VOLTAGE_PROFILE_MODE] === InitialVoltage.CEI909 - ? params?.cei909VoltageRanges - : undefined, }; }, [params?.cei909VoltageRanges, specificParametersDefaultValues] From 3e8f98f11c2dae9c073c811224309db104dc98a7 Mon Sep 17 00:00:00 2001 From: sBouzols Date: Wed, 12 Nov 2025 14:41:09 +0100 Subject: [PATCH 5/5] prettier Signed-off-by: sBouzols --- src/components/parameters/common/utils.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/parameters/common/utils.ts b/src/components/parameters/common/utils.ts index 9f05f0d2..682c3fe7 100644 --- a/src/components/parameters/common/utils.ts +++ b/src/components/parameters/common/utils.ts @@ -5,7 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { UseFormReturn } from 'react-hook-form'; -import { ParameterType, SpecificParameterInfos, SpecificParametersDescription, SpecificParametersValues } from '../../../utils'; +import { + ParameterType, + SpecificParameterInfos, + SpecificParametersDescription, + SpecificParametersValues, +} from '../../../utils'; import { SPECIFIC_PARAMETERS } from './constant'; import yup from '../../../utils/yupConfig';