diff --git a/src/components/ui/reactHookForm/utils/HelperPreviousValue.tsx b/src/components/ui/reactHookForm/utils/HelperPreviousValue.tsx index 02253bee2..275bea432 100644 --- a/src/components/ui/reactHookForm/utils/HelperPreviousValue.tsx +++ b/src/components/ui/reactHookForm/utils/HelperPreviousValue.tsx @@ -37,7 +37,7 @@ export function HelperPreviousValue({ } return ( - + {!disabledTooltip ? ( void; + updatePreviousReactiveCapabilityCurveTable: UpdateReactiveCapabilityCurveTable; fetchVoltageLevelEquipments: (voltageLevelId: string) => Promise<(Identifiable & { type: EquipmentType })[]>; tabIndex: number; } diff --git a/src/features/network-modifications/common/reactiveLimits/reactiveCapabilityCurve/reactiveCapability.utils.ts b/src/features/network-modifications/common/reactiveLimits/reactiveCapabilityCurve/reactiveCapability.utils.ts index b5a22fd9f..dad856872 100644 --- a/src/features/network-modifications/common/reactiveLimits/reactiveCapabilityCurve/reactiveCapability.utils.ts +++ b/src/features/network-modifications/common/reactiveLimits/reactiveCapabilityCurve/reactiveCapability.utils.ts @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { array, number, ref, object, TestContext, ValidationError } from 'yup'; -import { FieldValues, UseFormSetValue } from 'react-hook-form'; import { ReactiveCapabilityCurve } from '../reactiveLimits.type'; import { FieldConstants, toNumber, validateValueIsANumber, YUP_REQUIRED } from '../../../../../utils'; import type { GeneratorCreationFormData } from '../../../generator/creation/generatorCreation.utils'; @@ -39,7 +38,7 @@ function getNotNullPFromArray(values: ReactiveCapabilityCurve) { ?.map((element) => { const pValue = element[FieldConstants.P]; - // Note : convertion toNumber is necessary here to prevent corner cases like if + // Note : conversion toNumber is necessary here to prevent corner cases like if // two values are "-0" and "0", which would be considered different by the Set below. return validateValueIsANumber(pValue) ? toNumber(pValue) : null; }) @@ -139,22 +138,6 @@ export const getReactiveCapabilityCurveValidationSchema = ( [id]: getReactiveCapabilityCurveValidationSchemaArray(positiveAndNegativePExist), }); -export function setSelectedReactiveLimits( - id: string, - minMaxReactiveLimits: number, - setValue: UseFormSetValue -) { - setValue(id, minMaxReactiveLimits ? 'MINMAX' : 'CURVE'); -} - -export function setCurrentReactiveCapabilityCurveTable( - previousReactiveCapabilityCurveTable: ReactiveCapabilityCurve, - fieldKey: string, - setValue: UseFormSetValue -) { - setValue(fieldKey, previousReactiveCapabilityCurveTable); -} - function handleReactiveCapabilityCurveChoice( previousChoice: string | null | undefined, currentReactiveLimits: ReactiveLimitsFormData @@ -195,7 +178,7 @@ export function toReactiveCapabilityCurveChoiceForGeneratorCreation( return handleReactiveCapabilityCurveChoice(previousChoice, form.reactiveLimits); } -// In case the user has changed the choice of the reactive capability curve, but not the values, we keep the original choice, or the network equipement value +// In case the user has changed the choice of the reactive capability curve, but not the values, we keep the original choice, or the network equipment value export function toReactiveCapabilityCurveChoiceForGeneratorModification( form: GeneratorModificationFormData, generatorToModify: GeneratorFormInfos | undefined, diff --git a/src/features/network-modifications/common/reactiveLimits/reactiveLimits.type.ts b/src/features/network-modifications/common/reactiveLimits/reactiveLimits.type.ts index e32075185..60722bd9f 100644 --- a/src/features/network-modifications/common/reactiveLimits/reactiveLimits.type.ts +++ b/src/features/network-modifications/common/reactiveLimits/reactiveLimits.type.ts @@ -19,3 +19,5 @@ export interface MinMaxReactiveLimitsFormInfos { export type ReactiveCapabilityCurve = ReactiveCapabilityCurveRow[] | null | undefined; export type ReactiveCapabilityCurveRow = { maxQ: number | null; minQ: number | null; p: number | null }; + +export type UpdateReactiveCapabilityCurveTable = (action: string, index: number) => void; diff --git a/src/features/network-modifications/generator/modification/GeneratorDialogTabsContent.tsx b/src/features/network-modifications/generator/modification/GeneratorDialogTabsContent.tsx index 110db5896..56462c576 100644 --- a/src/features/network-modifications/generator/modification/GeneratorDialogTabsContent.tsx +++ b/src/features/network-modifications/generator/modification/GeneratorDialogTabsContent.tsx @@ -18,6 +18,7 @@ import { ReactiveLimitsForm, SetPointsForm, ShortCircuitForm, + UpdateReactiveCapabilityCurveTable, VoltageRegulationForm, } from '../../common'; import { GeneratorFormInfos } from '../generatorDialog.type'; @@ -34,7 +35,7 @@ import { GridItem } from '../../../../components/composite/grid/grid-item'; export interface GeneratorDialogTabsContentProps extends ConnectivityNetworkProps { generatorToModify?: GeneratorFormInfos | null; - updatePreviousReactiveCapabilityCurveTable: (action: string, index: number) => void; + updatePreviousReactiveCapabilityCurveTable: UpdateReactiveCapabilityCurveTable; fetchVoltageLevelEquipments: (voltageLevelId: string) => Promise<(Identifiable & { type: EquipmentType })[]>; tabIndex: number; } diff --git a/src/features/network-modifications/hvdcLine/index.ts b/src/features/network-modifications/hvdcLine/index.ts new file mode 100644 index 000000000..03f1ce1af --- /dev/null +++ b/src/features/network-modifications/hvdcLine/index.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vsc'; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/characteristics/VscHvdcLineCharacteristicsPane.tsx b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/VscHvdcLineCharacteristicsPane.tsx new file mode 100644 index 000000000..dde552a35 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/VscHvdcLineCharacteristicsPane.tsx @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2023, 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 { useEffect } from 'react'; +import { Grid } from '@mui/material'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useIntl } from 'react-intl'; +import { VSC_CONVERTER_MODE, VscHvdcLineInfo } from '../vscHvdcLine.types'; +import { ActivePowerAdornment, FieldConstants, OhmAdornment, VoltageAdornment } from '../../../../../../utils'; +import { + CheckboxNullableInput, + FloatInput, + GridItem, + GridSection, + SelectInput, + SwitchInput, +} from '../../../../../../components'; +import { PropertiesForm } from '../../../../common/properties'; + +interface VscHvdcLineCharacteristicsPaneProps { + id?: string; + isModification: boolean; + hvdcLineToModify?: VscHvdcLineInfo | null; +} + +export function VscHvdcLineCharacteristicsPane({ + id = FieldConstants.HVDC_LINE, + isModification = false, + hvdcLineToModify, +}: Readonly) { + const intl = useIntl(); + const { trigger } = useFormContext(); + + const angleDroopWatch = useWatch({ + name: `${id}.${FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL}`, + }); + + useEffect(() => { + if (!angleDroopWatch) { + trigger(`${id}.${FieldConstants.P0}`); + trigger(`${id}.${FieldConstants.DROOP}`); + } + }, [angleDroopWatch, trigger, id]); + + const dcNominalVoltageField = ( + + ); + + const dcResistanceField = ( + + ); + + const maximumActivePowerField = ( + + ); + + const operatorActivePowerLimitSide1Field = ( + + ); + + const operatorActivePowerLimitSide2Field = ( + + ); + + const previousConverterMode = () => { + if (hvdcLineToModify?.convertersMode === VSC_CONVERTER_MODE.SIDE_1_INVERTER_SIDE_2_RECTIFIER.id) { + return intl.formatMessage({ + id: VSC_CONVERTER_MODE.SIDE_1_INVERTER_SIDE_2_RECTIFIER.label, + }); + } + if (hvdcLineToModify?.convertersMode === VSC_CONVERTER_MODE.SIDE_1_RECTIFIER_SIDE_2_INVERTER.id) { + return intl.formatMessage({ + id: VSC_CONVERTER_MODE.SIDE_1_RECTIFIER_SIDE_2_INVERTER.label, + }); + } + return undefined; + }; + + const converterModeField = ( + + ); + + const activePowerField = ( + + ); + + const previousAngleDropPowerControl = () => { + if (hvdcLineToModify?.hvdcAngleDroopActivePowerControl?.isEnabled === true) { + return intl.formatMessage({ id: 'On' }); + } + + return intl.formatMessage({ id: 'Off' }); + }; + + function getAngleDroopActivePowerControlField() { + if (isModification) { + return ( + + ); + } + return ( + + ); + } + + const AngleDroopActivePowerControl = getAngleDroopActivePowerControlField(); + + const p0Field = ( + + ); + + const droopField = ( + + ); + + return ( + <> + + + {dcNominalVoltageField} + {dcResistanceField} + {maximumActivePowerField} + + + + {operatorActivePowerLimitSide1Field} + {operatorActivePowerLimitSide2Field} + + + + {converterModeField} + {activePowerField} + {AngleDroopActivePowerControl} + {droopField} + {p0Field} + + + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/characteristics/index.ts b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/index.ts new file mode 100644 index 000000000..2b50ecb2f --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/index.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vscHvdcLineCharacteristicsPane.utils'; +export * from './VscHvdcLineCharacteristicsPane'; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/characteristics/vscHvdcLineCharacteristicsPane.utils.ts b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/vscHvdcLineCharacteristicsPane.utils.ts new file mode 100644 index 000000000..ab1b91dd3 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/characteristics/vscHvdcLineCharacteristicsPane.utils.ts @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2023, 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 { InferType, object, boolean, number, string } from 'yup'; +import { FieldConstants, MUST_BE_GREATER_OR_EQUAL_TO_ZERO } from '../../../../../../utils'; +import { VscHvdcLineInfo } from '../vscHvdcLine.types'; +import { VscHdvLineCreationDto } from '../../creation/vscHvdcLineCreation.types'; +import { VscHdvLineModificationDto } from '../../modification/vscHvdcLineModification.types'; + +export const getVscHvdcLineCharacteristicsCreationSchema = () => + object().shape( + { + [FieldConstants.NOMINAL_V]: number().nullable().min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO).required(), + [FieldConstants.R]: number().nullable().min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO).required(), + [FieldConstants.MAX_P]: number().nullable().required(), + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: number().nullable(), + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: number().nullable(), + [FieldConstants.CONVERTERS_MODE]: string().required(), + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: boolean(), + [FieldConstants.ACTIVE_POWER_SET_POINT]: number().nullable().required(), + [FieldConstants.P0]: number() + .nullable() + .default(null) + .when([FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL, FieldConstants.DROOP], { + is: (angleDroopActivePowerControl: boolean, droop: number) => + angleDroopActivePowerControl || (droop !== null && droop !== undefined), + then: (schema) => schema.required(), + }), + [FieldConstants.DROOP]: number() + .nullable() + .default(null) + .when([FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL, FieldConstants.P0], { + is: (angleDroopActivePowerControl: boolean, p0: number) => + angleDroopActivePowerControl || (p0 !== null && p0 !== undefined), + then: (schema) => schema.required(), + }), + }, + // p0 and droop are mutually dependent via when(), causing a cyclic dependency at runtime. + [[FieldConstants.P0, FieldConstants.DROOP]] // excludedEdges => skip during cycle detection + ); + +export type VscHvdcLineCharacteristicsCreationFormData = InferType< + ReturnType +>; + +export const getVscHvdcLineCharacteristicsModificationSchema = () => + object().shape({ + [FieldConstants.NOMINAL_V]: number().nullable().min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO), + [FieldConstants.R]: number().nullable().min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO), + [FieldConstants.MAX_P]: number().nullable(), + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: number().nullable(), + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: number().nullable(), + [FieldConstants.CONVERTERS_MODE]: string().nullable(), + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: boolean().nullable(), + [FieldConstants.ACTIVE_POWER_SET_POINT]: number().nullable().nullable(), + [FieldConstants.P0]: number().nullable(), + [FieldConstants.DROOP]: number().nullable(), + }); + +export type VscHvdcLineCharacteristicsModificationFormData = InferType< + ReturnType +>; + +export function getVscHvdcLineCharacteristicsEmptyFormData(isModification: boolean) { + return { + [FieldConstants.NOMINAL_V]: null, + [FieldConstants.R]: null, + [FieldConstants.MAX_P]: null, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: null, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: null, + [FieldConstants.CONVERTERS_MODE]: null, + [FieldConstants.ACTIVE_POWER_SET_POINT]: null, + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: isModification ? null : false, + [FieldConstants.P0]: null, + [FieldConstants.DROOP]: null, + }; +} + +export function getVscHvdcLineCharacteristicsFromCopy( + hvdcLine: VscHvdcLineInfo +): VscHvdcLineCharacteristicsCreationFormData { + return { + [FieldConstants.NOMINAL_V]: hvdcLine?.nominalV, + [FieldConstants.R]: hvdcLine?.r, + [FieldConstants.MAX_P]: hvdcLine?.maxP, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: hvdcLine?.hvdcOperatorActivePowerRange?.oprFromCS1toCS2, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: hvdcLine?.hvdcOperatorActivePowerRange?.oprFromCS2toCS1, + [FieldConstants.CONVERTERS_MODE]: hvdcLine?.convertersMode, + [FieldConstants.ACTIVE_POWER_SET_POINT]: hvdcLine?.activePowerSetpoint, + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: hvdcLine?.hvdcAngleDroopActivePowerControl?.isEnabled, + [FieldConstants.P0]: hvdcLine?.hvdcAngleDroopActivePowerControl?.p0, + [FieldConstants.DROOP]: hvdcLine?.hvdcAngleDroopActivePowerControl?.droop, + }; +} + +export function getVscHvdcLineCharacteristicsCreationDtoToForm( + dto: VscHdvLineCreationDto +): VscHvdcLineCharacteristicsCreationFormData { + return { + [FieldConstants.NOMINAL_V]: dto.nominalV ?? 0, + [FieldConstants.R]: dto.r ?? 0, + [FieldConstants.MAX_P]: dto.maxP ?? 0, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: dto?.operatorActivePowerLimitFromSide1ToSide2, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: dto?.operatorActivePowerLimitFromSide2ToSide1, + [FieldConstants.CONVERTERS_MODE]: dto.convertersMode, + [FieldConstants.ACTIVE_POWER_SET_POINT]: dto.activePowerSetpoint ?? 0, + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: dto?.angleDroopActivePowerControl ?? undefined, + [FieldConstants.P0]: dto?.p0, + [FieldConstants.DROOP]: dto?.droop, + }; +} + +export function getVscHvdcLineCharacteristicsModificationDtoToForm( + dto: VscHdvLineModificationDto +): VscHvdcLineCharacteristicsModificationFormData { + return { + [FieldConstants.NOMINAL_V]: dto.nominalV?.value ?? null, + [FieldConstants.R]: dto.r?.value ?? null, + [FieldConstants.MAX_P]: dto.maxP?.value ?? null, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE1]: + dto?.operatorActivePowerLimitFromSide1ToSide2?.value ?? null, + [FieldConstants.OPERATOR_ACTIVE_POWER_LIMIT_SIDE2]: + dto?.operatorActivePowerLimitFromSide2ToSide1?.value ?? null, + [FieldConstants.CONVERTERS_MODE]: dto.convertersMode?.value ?? null, + [FieldConstants.ACTIVE_POWER_SET_POINT]: dto.activePowerSetpoint?.value ?? null, + [FieldConstants.ANGLE_DROOP_ACTIVE_POWER_CONTROL]: dto?.angleDroopActivePowerControl?.value ?? null, + [FieldConstants.P0]: dto?.p0?.value ?? null, + [FieldConstants.DROOP]: dto?.droop?.value ?? null, + }; +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/converterStation/VscConverterStationPane.tsx b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/VscConverterStationPane.tsx new file mode 100644 index 000000000..e751f26ba --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/VscConverterStationPane.tsx @@ -0,0 +1,174 @@ +/** + * Copyright (c) 2023, 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 { useEffect } from 'react'; +import { Grid } from '@mui/material'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useIntl } from 'react-intl'; +import { + CheckboxNullableInput, + FloatInput, + GridItem, + GridSection, + SwitchInput, + TextInput, +} from '../../../../../../components'; +import { ReactiveLimitsForm } from '../../../../common/reactiveLimits/ReactiveLimitsForm'; +import { ConnectivityForm, ConnectivityNetworkProps } from '../../../../common/connectivity'; +import { FieldConstants, PercentageAdornment, ReactivePowerAdornment, VoltageAdornment } from '../../../../../../utils'; +import { UpdateReactiveCapabilityCurveTable } from '../../../../common/reactiveLimits/reactiveLimits.type'; +import { ConverterStationInfos } from '../vscHvdcLine.types'; + +interface VscConverterStationPaneProps extends ConnectivityNetworkProps { + id: string; + stationLabel: string; + isModification?: boolean; + stationToModify?: ConverterStationInfos | null; + updatePreviousReactiveCapabilityCurveTableConverterStation?: UpdateReactiveCapabilityCurveTable; +} + +export function VscConverterStationPane({ + id, + stationLabel, + isModification = false, + stationToModify, + updatePreviousReactiveCapabilityCurveTableConverterStation, + voltageLevelOptions = [], + PositionDiagramPane, + fetchBusesOrBusbarSections, +}: Readonly) { + const intl = useIntl(); + + const { trigger } = useFormContext(); + + const voltageRegulationOnWatch = useWatch({ + name: `${id}.${FieldConstants.VOLTAGE_REGULATION_ON}`, + }); + + useEffect(() => { + if (!voltageRegulationOnWatch) { + trigger(`${id}.${FieldConstants.VOLTAGE_REGULATION_ON}`); + } + }, [voltageRegulationOnWatch, trigger, id]); + + const converterStationIdField = ( + + ); + + const converterStationNameField = ( + + ); + + const connectivityForm = ( + + ); + + const lossFactorField = ( + + ); + + const reactivePowerField = ( + + ); + + const previousVoltageRegulatorOn = () => { + return intl.formatMessage({ + id: stationToModify?.voltageRegulatorOn ? 'On' : 'Off', + }); + }; + const voltageRegulation = isModification ? ( + + ) : ( + + ); + + const voltageField = ( + + ); + + return ( + + + + {converterStationIdField} + {converterStationNameField} + + + {!isModification && ( + <> + + + {connectivityForm} + + + )} + + + + {lossFactorField} + + + + + + + + {reactivePowerField} + + + {voltageRegulation} + {voltageField} + + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/converterStation/index.ts b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/index.ts new file mode 100644 index 000000000..b2b7e7b50 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/index.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vscConverterStationPane.utils'; +export * from './VscConverterStationPane'; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/converterStation/vscConverterStationPane.utils.ts b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/vscConverterStationPane.utils.ts new file mode 100644 index 000000000..d095a6903 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/converterStation/vscConverterStationPane.utils.ts @@ -0,0 +1,272 @@ +/** + * Copyright (c) 2023, 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 { boolean, InferType, number, object, string } from 'yup'; +import { + FieldConstants, + ModificationType, + MUST_BE_GREATER_OR_EQUAL_TO_ZERO, + NORMALIZED_PERCENTAGE, + sanitizeString, + toModificationOperation, + UNDEFINED_CONNECTION_DIRECTION, +} from '../../../../../../utils'; +import { + getReactiveLimitsEmptyFormDataProps, + getReactiveLimitsFormDataProps, + getReactiveLimitsValidationSchema, +} from '../../../../common/reactiveLimits/reactiveLimits.utils'; +import { + getConnectivityFormDataProps, + getConnectivityWithPositionEmptyFormDataProps, + getConnectivityWithPositionSchema, +} from '../../../../common/connectivity/connectivityForm.utils'; +import { + getInjectionActiveReactivePowerEditDataProperties, + getInjectionActiveReactivePowerEmptyFormDataProperties, + getInjectionActiveReactivePowerValidationSchemaProperties, +} from '../../../../common/measurements/injectionActiveReactivePowerForm.utils'; +import { ConverterStationCreationDto } from '../../creation/vscHvdcLineCreation.types'; +import { ConverterStationInfos } from '../vscHvdcLine.types'; +import { ConverterStationModificationDto } from '../../modification/vscHvdcLineModification.types'; + +export type UpdateReactiveCapabilityCurveTableConverterStation = ( + action: string, + index: number, + converterStationName: FieldConstants.CONVERTER_STATION_1 | FieldConstants.CONVERTER_STATION_2 +) => void; + +export const getVscConverterStationCreationSchema = () => + object().shape({ + [FieldConstants.CONVERTER_STATION_ID]: string().nullable().required(), + [FieldConstants.CONVERTER_STATION_NAME]: string().nullable(), + [FieldConstants.LOSS_FACTOR]: number() + .nullable() + .required() + .min(0, NORMALIZED_PERCENTAGE) + .max(100, NORMALIZED_PERCENTAGE), + [FieldConstants.VOLTAGE_REGULATION_ON]: boolean(), + [FieldConstants.REACTIVE_POWER]: number() + .nullable() + .default(null) + .when([FieldConstants.VOLTAGE_REGULATION_ON], { + is: false, + then: (schema) => schema.required(), + }), + [FieldConstants.VOLTAGE]: number() + .nullable() + .default(null) + .min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO) + .when([FieldConstants.VOLTAGE_REGULATION_ON], { + is: true, + then: (schema) => schema.required(), + }), + [FieldConstants.CONNECTIVITY]: getConnectivityWithPositionSchema(), + [FieldConstants.REACTIVE_LIMITS]: getReactiveLimitsValidationSchema(false, true), + }); + +export type VscConverterStationCreationFormData = InferType>; + +export const getVscConverterStationModificationSchema = () => + object().shape({ + [FieldConstants.CONVERTER_STATION_ID]: string(), + [FieldConstants.CONVERTER_STATION_NAME]: string().nullable(), + [FieldConstants.LOSS_FACTOR]: number().nullable().min(0, NORMALIZED_PERCENTAGE).max(100, NORMALIZED_PERCENTAGE), + [FieldConstants.VOLTAGE_REGULATION_ON]: boolean().nullable(), + [FieldConstants.REACTIVE_POWER]: number().nullable(), + [FieldConstants.VOLTAGE]: number().nullable().min(0, MUST_BE_GREATER_OR_EQUAL_TO_ZERO), + [FieldConstants.CONNECTIVITY]: getConnectivityWithPositionSchema(true), + [FieldConstants.STATE_ESTIMATION]: getInjectionActiveReactivePowerValidationSchemaProperties(), + [FieldConstants.REACTIVE_LIMITS]: getReactiveLimitsValidationSchema(true), + }); + +export type VscConverterStationModificationFormData = InferType< + ReturnType +>; + +export function getVscConverterStationEmptyFormData(isModification = false) { + return { + [FieldConstants.CONVERTER_STATION_ID]: isModification ? '' : null, + [FieldConstants.CONVERTER_STATION_NAME]: isModification ? '' : null, + [FieldConstants.LOSS_FACTOR]: null, + [FieldConstants.REACTIVE_POWER]: null, + [FieldConstants.VOLTAGE_REGULATION_ON]: isModification ? null : false, + [FieldConstants.VOLTAGE]: null, + [FieldConstants.CONNECTIVITY]: getConnectivityWithPositionEmptyFormDataProps(isModification), + [FieldConstants.REACTIVE_LIMITS]: getReactiveLimitsEmptyFormDataProps(), + [FieldConstants.STATE_ESTIMATION]: isModification + ? getInjectionActiveReactivePowerEmptyFormDataProperties() + : null, + }; +} + +export function converterStationCreationFormToDto( + formData: VscConverterStationCreationFormData +): ConverterStationCreationDto { + const reactiveLimits = formData[FieldConstants.REACTIVE_LIMITS]; + const isReactiveCapabilityCurveOn = reactiveLimits[FieldConstants.REACTIVE_CAPABILITY_CURVE_CHOICE] === 'CURVE'; + return { + type: ModificationType.CONVERTER_STATION_CREATION, + equipmentId: formData[FieldConstants.CONVERTER_STATION_ID], + equipmentName: formData[FieldConstants.CONVERTER_STATION_NAME] ?? null, + lossFactor: formData[FieldConstants.LOSS_FACTOR], + reactivePowerSetpoint: formData[FieldConstants.REACTIVE_POWER], + voltageRegulationOn: formData[FieldConstants.VOLTAGE_REGULATION_ON], + voltageSetpoint: formData[FieldConstants.VOLTAGE], + voltageLevelId: + formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.VOLTAGE_LEVEL]?.[FieldConstants.ID] ?? '', + busOrBusbarSectionId: + formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.BUS_OR_BUSBAR_SECTION]?.[FieldConstants.ID] ?? '', + connectionName: sanitizeString(formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.CONNECTION_NAME]), + connectionDirection: + formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.CONNECTION_DIRECTION] ?? + UNDEFINED_CONNECTION_DIRECTION, + connectionPosition: formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.CONNECTION_POSITION], + terminalConnected: formData[FieldConstants.CONNECTIVITY]?.[FieldConstants.CONNECTED], + reactiveCapabilityCurve: isReactiveCapabilityCurveOn, + minQ: isReactiveCapabilityCurveOn ? null : (reactiveLimits[FieldConstants.MINIMUM_REACTIVE_POWER] ?? null), + maxQ: isReactiveCapabilityCurveOn ? null : (reactiveLimits[FieldConstants.MAXIMUM_REACTIVE_POWER] ?? null), + reactiveCapabilityCurvePoints: isReactiveCapabilityCurveOn + ? (reactiveLimits[FieldConstants.REACTIVE_CAPABILITY_CURVE_TABLE] ?? []) + : [], + }; +} + +function getConverterStationReactiveLimits(converterStation: ConverterStationCreationDto) { + return converterStation.reactiveCapabilityCurve + ? getReactiveLimitsFormDataProps({ + reactiveCapabilityCurveChoice: 'CURVE', + minimumReactivePower: null, + maximumReactivePower: null, + reactiveCapabilityCurvePoints: converterStation.reactiveCapabilityCurvePoints, + }) + : getReactiveLimitsFormDataProps({ + reactiveCapabilityCurveChoice: 'MINMAX', + minimumReactivePower: converterStation.minQ, + maximumReactivePower: converterStation.maxQ, + reactiveCapabilityCurvePoints: converterStation?.reactiveCapabilityCurvePoints ?? null, + }); +} + +export function converterStationCreationDtoToForm( + dto: ConverterStationCreationDto +): VscConverterStationCreationFormData { + return { + [FieldConstants.CONVERTER_STATION_ID]: dto?.equipmentId, + [FieldConstants.CONVERTER_STATION_NAME]: dto?.equipmentName ?? '', + [FieldConstants.LOSS_FACTOR]: dto?.lossFactor ?? 0, + [FieldConstants.REACTIVE_POWER]: dto?.reactivePowerSetpoint, + [FieldConstants.VOLTAGE_REGULATION_ON]: dto?.voltageRegulationOn, + [FieldConstants.VOLTAGE]: dto?.voltageSetpoint, + [FieldConstants.CONNECTIVITY]: getConnectivityFormDataProps({ + voltageLevelId: dto.voltageLevelId, + busbarSectionId: dto.busOrBusbarSectionId, + connectionDirection: dto.connectionDirection, + connectionName: dto.connectionName, + connectionPosition: dto.connectionPosition, + terminalConnected: dto.terminalConnected, + }), + [FieldConstants.REACTIVE_LIMITS]: getConverterStationReactiveLimits(dto), + }; +} + +export function converterStationCreationFromCopy( + converterStation?: ConverterStationInfos +): VscConverterStationCreationFormData { + return { + [FieldConstants.CONVERTER_STATION_ID]: `${converterStation?.id}(1)`, + [FieldConstants.CONVERTER_STATION_NAME]: converterStation?.name ?? '', + [FieldConstants.LOSS_FACTOR]: converterStation?.lossFactor ?? 0, + [FieldConstants.REACTIVE_POWER]: converterStation?.reactivePowerSetpoint ?? null, + [FieldConstants.VOLTAGE_REGULATION_ON]: converterStation?.voltageRegulatorOn, + [FieldConstants.VOLTAGE]: converterStation?.voltageSetpoint ?? null, + [FieldConstants.CONNECTIVITY]: getConnectivityFormDataProps({ + voltageLevelId: converterStation?.voltageLevelId, + busbarSectionId: converterStation?.busOrBusbarSectionId, + connectionDirection: converterStation?.connectablePosition?.connectionDirection, + connectionName: converterStation?.connectablePosition?.connectionName, + connectionPosition: null, + terminalConnected: true, + }), + [FieldConstants.REACTIVE_LIMITS]: getReactiveLimitsFormDataProps({ + reactiveCapabilityCurveChoice: converterStation?.minMaxReactiveLimits ? 'MINMAX' : 'CURVE', + minimumReactivePower: converterStation?.minMaxReactiveLimits?.minQ, + maximumReactivePower: converterStation?.minMaxReactiveLimits?.maxQ, + reactiveCapabilityCurvePoints: converterStation?.reactiveCapabilityCurvePoints ?? null, + }), + }; +} + +export function converterStationModificationFormToDto( + formData: VscConverterStationModificationFormData +): ConverterStationModificationDto { + const reactiveLimits = formData[FieldConstants.REACTIVE_LIMITS]; + const connectivity = formData[FieldConstants.CONNECTIVITY]; + const estim = formData[FieldConstants.STATE_ESTIMATION]; + const isReactiveCapabilityCurveOn = reactiveLimits[FieldConstants.REACTIVE_CAPABILITY_CURVE_CHOICE] === 'CURVE'; + + return { + type: ModificationType.CONVERTER_STATION_MODIFICATION, + equipmentId: formData[FieldConstants.CONVERTER_STATION_ID] ?? '', + equipmentName: toModificationOperation(formData[FieldConstants.CONVERTER_STATION_NAME]), + voltageLevelId: toModificationOperation(connectivity?.[FieldConstants.VOLTAGE_LEVEL]?.[FieldConstants.ID]), + busOrBusbarSectionId: toModificationOperation( + connectivity?.[FieldConstants.BUS_OR_BUSBAR_SECTION]?.[FieldConstants.ID] + ), + connectionName: toModificationOperation(connectivity?.[FieldConstants.CONNECTION_NAME]), + connectionDirection: toModificationOperation(connectivity?.[FieldConstants.CONNECTION_DIRECTION]), + connectionPosition: toModificationOperation(connectivity?.[FieldConstants.CONNECTION_POSITION]), + terminalConnected: toModificationOperation(connectivity?.[FieldConstants.CONNECTED]), + pMeasurementValue: toModificationOperation(estim?.[FieldConstants.MEASUREMENT_P]?.value), + pMeasurementValidity: toModificationOperation(estim?.[FieldConstants.MEASUREMENT_P]?.validity), + qMeasurementValue: toModificationOperation(estim?.[FieldConstants.MEASUREMENT_Q]?.value), + qMeasurementValidity: toModificationOperation(estim?.[FieldConstants.MEASUREMENT_Q]?.validity), + lossFactor: toModificationOperation(formData[FieldConstants.LOSS_FACTOR]), + reactivePowerSetpoint: toModificationOperation(formData[FieldConstants.REACTIVE_POWER]), + voltageRegulationOn: toModificationOperation(formData[FieldConstants.VOLTAGE_REGULATION_ON]), + voltageSetpoint: toModificationOperation(formData[FieldConstants.VOLTAGE]), + reactiveCapabilityCurve: toModificationOperation(isReactiveCapabilityCurveOn), + minQ: toModificationOperation( + isReactiveCapabilityCurveOn ? null : reactiveLimits[FieldConstants.MINIMUM_REACTIVE_POWER] + ), + maxQ: toModificationOperation( + isReactiveCapabilityCurveOn ? null : reactiveLimits[FieldConstants.MAXIMUM_REACTIVE_POWER] + ), + reactiveCapabilityCurvePoints: isReactiveCapabilityCurveOn + ? (reactiveLimits[FieldConstants.REACTIVE_CAPABILITY_CURVE_TABLE] ?? []) + : [], + }; +} + +export function converterStationModificationDtoToForm( + dto: ConverterStationModificationDto +): VscConverterStationModificationFormData { + return { + [FieldConstants.CONVERTER_STATION_ID]: dto?.equipmentId, + [FieldConstants.CONVERTER_STATION_NAME]: dto?.equipmentName?.value ?? '', + [FieldConstants.LOSS_FACTOR]: dto?.lossFactor?.value ?? null, + [FieldConstants.REACTIVE_POWER]: dto?.reactivePowerSetpoint?.value ?? null, + [FieldConstants.VOLTAGE_REGULATION_ON]: dto?.voltageRegulationOn?.value ?? null, + [FieldConstants.VOLTAGE]: dto?.voltageSetpoint?.value ?? null, + [FieldConstants.CONNECTIVITY]: getConnectivityFormDataProps({ + voltageLevelId: dto?.voltageLevelId?.value ?? null, + busbarSectionId: dto?.busOrBusbarSectionId?.value ?? null, + connectionName: dto?.connectionName?.value ?? null, + connectionDirection: dto?.connectionDirection?.value ?? null, + connectionPosition: dto?.connectionPosition?.value ?? null, + terminalConnected: dto?.terminalConnected?.value ?? null, + isEquipmentModification: true, + }), + [FieldConstants.REACTIVE_LIMITS]: getReactiveLimitsFormDataProps({ + reactiveCapabilityCurveChoice: dto?.reactiveCapabilityCurve?.value ? 'CURVE' : 'MINMAX', + maximumReactivePower: dto?.maxQ?.value ?? null, + minimumReactivePower: dto?.minQ?.value ?? null, + reactiveCapabilityCurvePoints: dto?.reactiveCapabilityCurvePoints ?? null, + }), + [FieldConstants.STATE_ESTIMATION]: getInjectionActiveReactivePowerEditDataProperties(dto), + }; +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogHeader.tsx b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogHeader.tsx new file mode 100644 index 000000000..09d11ca6f --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogHeader.tsx @@ -0,0 +1,60 @@ +/** + * 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 { Grid, TextField } from '@mui/material'; +import { useWatch } from 'react-hook-form'; +import { FieldConstants } from '../../../../../../utils'; +import { filledTextField } from '../../../../common'; +import { GridItem, TextInput } from '../../../../../../components'; +import { VscHvdcLineInfo } from '../vscHvdcLine.types'; + +export interface VscHvdcLineDialogHeaderProps { + hvdcLineToModify?: VscHvdcLineInfo | null; + isModification?: boolean; +} + +export function VscHvdcLineDialogHeader({ + hvdcLineToModify, + isModification = false, +}: Readonly) { + const equipmentId = useWatch({ name: FieldConstants.EQUIPMENT_ID }); + + const lineIdField = isModification ? ( + + ) : ( + + ); + + const lineNameField = ( + + ); + + return ( + + {lineIdField} + {lineNameField} + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabs.tsx b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabs.tsx new file mode 100644 index 000000000..dc4c5bc53 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabs.tsx @@ -0,0 +1,60 @@ +/** + * 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 React from 'react'; +import { Tab, Tabs } from '@mui/material'; +import { FormattedMessage } from 'react-intl'; +import { VscHvdcLineDialogTab } from './vscHvdcLine.utils'; +import { getTabIndicatorStyle, getTabStyle } from '../../../../../parameters'; + +interface VscHvdcLineDialogTabsProps { + tabIndex: number; + tabIndexesWithError: number[]; + setTabIndex: (newTabIndex: number) => void; + isModification?: boolean; +} + +export function VscHvdcLineDialogTabs({ + tabIndex, + tabIndexesWithError, + setTabIndex, + isModification = false, +}: Readonly) { + return ( + setTabIndex(newValue)} + slotProps={{ + indicator: { sx: getTabIndicatorStyle(tabIndexesWithError, tabIndex) }, + }} + > + } + sx={getTabStyle(tabIndexesWithError, VscHvdcLineDialogTab.HVDC_LINE_TAB)} + /> + } + sx={getTabStyle(tabIndexesWithError, VscHvdcLineDialogTab.CONVERTER_STATION_1_TAB)} + /> + } + sx={getTabStyle(tabIndexesWithError, VscHvdcLineDialogTab.CONVERTER_STATION_2_TAB)} + /> + {isModification && ( + } + sx={getTabStyle(tabIndexesWithError, VscHvdcLineDialogTab.STATE_ESTIMATION_TAB)} + /> + )} + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabsContent.tsx b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabsContent.tsx new file mode 100644 index 000000000..ff0eb248a --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineDialogTabsContent.tsx @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2026, 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 { Box } from '@mui/material'; +import { VscHvdcLineDialogTab } from './vscHvdcLine.utils'; +import { VscHvdcLineInfo } from '../vscHvdcLine.types'; +import { ConnectivityNetworkProps } from '../../../../common/connectivity'; +import { GridSection } from '../../../../../../components'; +import { PowerMeasurementsForm } from '../../../../common/measurements'; +import { VscConverterStationPane } from '../converterStation/VscConverterStationPane'; +import { FieldConstants } from '../../../../../../utils'; +import { VscHvdcLineCharacteristicsPane } from '../characteristics/VscHvdcLineCharacteristicsPane'; +import { UpdateReactiveCapabilityCurveTableConverterStation } from '../converterStation'; + +export interface VscHvdcLineDialogTabsContentProps extends ConnectivityNetworkProps { + hvdcLineToModify?: VscHvdcLineInfo | null; + tabIndex: number; + updatePreviousReactiveCapabilityCurveTableConverterStation?: UpdateReactiveCapabilityCurveTableConverterStation; + isModification?: boolean; +} + +export function VscHvdcLineDialogTabsContent({ + hvdcLineToModify, + isModification = false, + tabIndex, + voltageLevelOptions = [], + PositionDiagramPane, + fetchBusesOrBusbarSections, + updatePreviousReactiveCapabilityCurveTableConverterStation, +}: Readonly) { + return ( + <> + + + + {isModification && ( + + )} + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineForm.tsx b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineForm.tsx new file mode 100644 index 000000000..4e3e10353 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/VscHvdcLineForm.tsx @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2026, 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 { Box, Stack } from '@mui/material'; +import { VscHvdcLineDialogHeader, VscHvdcLineDialogHeaderProps } from './VscHvdcLineDialogHeader'; +import { VscHvdcLineDialogTabs } from './VscHvdcLineDialogTabs'; +import { VscHvdcLineDialogTabsContent, VscHvdcLineDialogTabsContentProps } from './VscHvdcLineDialogTabsContent'; +import { HVDC_LINE_TAB_FIELDS, VscHvdcLineDialogTab } from './vscHvdcLine.utils'; +import { useTabsWithError } from '../../../../hooks/useTabsWithError'; +import { UpdateReactiveCapabilityCurveTableConverterStation } from '../converterStation/vscConverterStationPane.utils'; + +interface VscHvdcLineFormProps + extends + VscHvdcLineDialogHeaderProps, + Omit { + updatePreviousReactiveCapabilityCurveTableConverterStation?: UpdateReactiveCapabilityCurveTableConverterStation; +} + +export function VscHvdcLineForm({ + hvdcLineToModify, + voltageLevelOptions, + fetchBusesOrBusbarSections, + PositionDiagramPane, + updatePreviousReactiveCapabilityCurveTableConverterStation, + isModification = false, +}: Readonly) { + const { tabIndex, setTabIndex, tabIndexesWithError } = useTabsWithError( + HVDC_LINE_TAB_FIELDS, + VscHvdcLineDialogTab.HVDC_LINE_TAB + ); + + return ( + + + + + + + + ); +} diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/index.ts b/src/features/network-modifications/hvdcLine/vsc/common/form/index.ts new file mode 100644 index 000000000..79057f5e2 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/index.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vscHvdcLine.utils'; +export * from './VscHvdcLineDialogTabs'; +export * from './VscHvdcLineDialogTabsContent'; +export * from './VscHvdcLineDialogHeader'; +export * from './VscHvdcLineForm'; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/form/vscHvdcLine.utils.ts b/src/features/network-modifications/hvdcLine/vsc/common/form/vscHvdcLine.utils.ts new file mode 100644 index 000000000..88154fa07 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/form/vscHvdcLine.utils.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026, 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 { FieldConstants } from '../../../../../../utils'; + +export const enum VscHvdcLineDialogTab { + HVDC_LINE_TAB = 0, + CONVERTER_STATION_1_TAB = 1, + CONVERTER_STATION_2_TAB = 2, + STATE_ESTIMATION_TAB = 3, +} + +export const HVDC_LINE_TAB_FIELDS: Readonly>> = { + [VscHvdcLineDialogTab.HVDC_LINE_TAB]: [FieldConstants.HVDC_LINE, FieldConstants.ADDITIONAL_PROPERTIES], + [VscHvdcLineDialogTab.CONVERTER_STATION_1_TAB]: [FieldConstants.CONVERTER_STATION_1], + [VscHvdcLineDialogTab.CONVERTER_STATION_2_TAB]: [FieldConstants.CONVERTER_STATION_2], + [VscHvdcLineDialogTab.STATE_ESTIMATION_TAB]: [FieldConstants.STATE_ESTIMATION], +}; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/index.ts b/src/features/network-modifications/hvdcLine/vsc/common/index.ts new file mode 100644 index 000000000..aa60a401a --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/index.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './characteristics'; +export * from './converterStation'; +export * from './form'; +export * from './vscHvdcLine.types'; diff --git a/src/features/network-modifications/hvdcLine/vsc/common/vscHvdcLine.types.ts b/src/features/network-modifications/hvdcLine/vsc/common/vscHvdcLine.types.ts new file mode 100644 index 000000000..fd3d5b0cf --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/common/vscHvdcLine.types.ts @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2026, 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 { + ConnectablePositionInfos, + MeasurementInfo, + MinMaxReactiveLimitsFormInfos, + ReactiveCapabilityCurvePoints, +} from '../../../common'; + +export enum VscConverterMode { + SIDE_1_RECTIFIER_SIDE_2_INVERTER = 'SIDE_1_RECTIFIER_SIDE_2_INVERTER', + SIDE_1_INVERTER_SIDE_2_RECTIFIER = 'SIDE_1_INVERTER_SIDE_2_RECTIFIER', +} + +export interface VscConverterModeValue { + id: string; + label: string; +} + +export const VSC_CONVERTER_MODE: Record = { + [VscConverterMode.SIDE_1_RECTIFIER_SIDE_2_INVERTER]: { + id: 'SIDE_1_RECTIFIER_SIDE_2_INVERTER', + label: 'side1RectifierSide2Inverter', + }, + [VscConverterMode.SIDE_1_INVERTER_SIDE_2_RECTIFIER]: { + id: 'SIDE_1_INVERTER_SIDE_2_RECTIFIER', + label: 'side1InverterSide2Rectifier', + }, +}; + +export interface HvdcOperatorActivePowerRangeInfo { + oprFromCS1toCS2: number; + oprFromCS2toCS1: number; +} + +export interface HvdcAngleDroopActivePowerControlInfo { + isEnabled: boolean; + droop: number; + p0: number; +} + +export interface ConverterStationInfos { + id: string; + name: string | null; + lossFactor: number; + voltageSetpoint: number | null; + reactivePowerSetpoint: number | null; + voltageRegulatorOn: boolean; + voltageLevelId: string; + busOrBusbarSectionId: string; + nominalV: number; + terminalConnected: boolean; + p: number | null; + q: number | null; + reactiveCapabilityCurvePoints: ReactiveCapabilityCurvePoints[]; + minMaxReactiveLimits: MinMaxReactiveLimitsFormInfos | null; + connectablePosition: ConnectablePositionInfos; + measurementP?: MeasurementInfo; + measurementQ?: MeasurementInfo; +} + +export interface VscHvdcLineInfo { + id: string; + name: string; + convertersMode: string; + r: number; + nominalV: number; + activePowerSetpoint: number; + maxP: number; + hvdcAngleDroopActivePowerControl: HvdcAngleDroopActivePowerControlInfo; + hvdcOperatorActivePowerRange: HvdcOperatorActivePowerRangeInfo; + converterStation1: ConverterStationInfos; + converterStation2: ConverterStationInfos; + properties: Record; +} diff --git a/src/features/network-modifications/hvdcLine/vsc/creation/index.ts b/src/features/network-modifications/hvdcLine/vsc/creation/index.ts new file mode 100644 index 000000000..fe79a6f61 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/creation/index.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vscHvdcLineCreation.types'; +export * from './vscHvdcLineCreation.utils'; diff --git a/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.types.ts b/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.types.ts new file mode 100644 index 000000000..924dd4999 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.types.ts @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2026, 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 { ModificationType } from '../../../../../utils'; +import { Property } from '../../../common/properties/properties.type'; +import { ReactiveCapabilityCurvePoints } from '../../../common/reactiveLimits/reactiveLimits.type'; + +interface InjectionCreationDto { + type: ModificationType; + equipmentId: string; + equipmentName: string | null; + voltageLevelId: string; + busOrBusbarSectionId: string; + connectionDirection: string | null; + connectionName?: string | null; + connectionPosition?: number | null; + terminalConnected?: boolean | null; +} + +export interface ConverterStationCreationDto extends InjectionCreationDto { + lossFactor: number | null; + reactivePowerSetpoint: number | null; + voltageRegulationOn?: boolean; + voltageSetpoint: number | null; + reactiveCapabilityCurve: boolean; + minQ: number | null; + maxQ: number | null; + reactiveCapabilityCurvePoints: ReactiveCapabilityCurvePoints[]; +} + +// cf VscCreationInfos server class +export interface VscHdvLineCreationDto { + type: ModificationType; + uuid?: UUID; + equipmentId: string; + equipmentName: string | null; + properties: Property[] | null; + nominalV: number | null; + r: number | null; + maxP: number | null; + operatorActivePowerLimitFromSide1ToSide2: number | null; + operatorActivePowerLimitFromSide2ToSide1: number | null; + convertersMode: string; + activePowerSetpoint: number | null; + angleDroopActivePowerControl: boolean | null; + p0: number | null; + droop: number | null; + converterStation1: ConverterStationCreationDto; + converterStation2: ConverterStationCreationDto; +} diff --git a/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.utils.ts b/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.utils.ts new file mode 100644 index 000000000..0e5fafe32 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/creation/vscHvdcLineCreation.utils.ts @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2026, 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 { InferType, object, string } from 'yup'; +import { DeepNullable, FieldConstants, ModificationType, sanitizeString } from '../../../../../utils'; +import { + creationPropertiesSchema, + getFilledPropertiesFromModification, + toModificationProperties, +} from '../../../common/properties/'; +import { + getVscHvdcLineCharacteristicsCreationSchema, + getVscHvdcLineCharacteristicsCreationDtoToForm, + getVscHvdcLineCharacteristicsEmptyFormData, +} from '../common/characteristics/vscHvdcLineCharacteristicsPane.utils'; +import { + converterStationCreationDtoToForm, + converterStationCreationFormToDto, + getVscConverterStationCreationSchema, + getVscConverterStationEmptyFormData, +} from '../common/converterStation/vscConverterStationPane.utils'; +import { VscHdvLineCreationDto } from './vscHvdcLineCreation.types'; + +export const vscHvdcLineCreationFormSchema = object() + .shape({ + [FieldConstants.EQUIPMENT_ID]: string().required(), + [FieldConstants.EQUIPMENT_NAME]: string().nullable(), + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsCreationSchema(), + [FieldConstants.CONVERTER_STATION_1]: getVscConverterStationCreationSchema(), + [FieldConstants.CONVERTER_STATION_2]: getVscConverterStationCreationSchema(), + }) + .concat(creationPropertiesSchema) + .required(); + +export type VscHvdcLineCreationFormData = InferType; + +export const vscHvdcLineCreationEmptyFormData: DeepNullable = { + [FieldConstants.EQUIPMENT_ID]: null, + [FieldConstants.EQUIPMENT_NAME]: null, + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsEmptyFormData(false), + [FieldConstants.CONVERTER_STATION_1]: getVscConverterStationEmptyFormData(false), + [FieldConstants.CONVERTER_STATION_2]: getVscConverterStationEmptyFormData(false), + [FieldConstants.ADDITIONAL_PROPERTIES]: [], +}; + +export const vscHvdcLineCreationDtoToForm = (lineDto: VscHdvLineCreationDto): VscHvdcLineCreationFormData => { + return { + [FieldConstants.EQUIPMENT_ID]: lineDto.equipmentId, + [FieldConstants.EQUIPMENT_NAME]: lineDto.equipmentName ?? '', + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsCreationDtoToForm(lineDto), + [FieldConstants.CONVERTER_STATION_1]: converterStationCreationDtoToForm(lineDto.converterStation1), + [FieldConstants.CONVERTER_STATION_2]: converterStationCreationDtoToForm(lineDto.converterStation2), + [FieldConstants.ADDITIONAL_PROPERTIES]: getFilledPropertiesFromModification(lineDto.properties), + }; +}; + +export const vscHvdcLineCreationFormToDto = (lineForm: VscHvdcLineCreationFormData): VscHdvLineCreationDto => { + return { + type: ModificationType.VSC_CREATION, + equipmentId: lineForm.equipmentID, + equipmentName: sanitizeString(lineForm.equipmentName), + properties: toModificationProperties(lineForm), + nominalV: lineForm.hvdcLine.nominalV, + r: lineForm.hvdcLine.r, + maxP: lineForm.hvdcLine.maxP, + operatorActivePowerLimitFromSide1ToSide2: lineForm.hvdcLine.operatorActivePowerLimitSide1 ?? null, + operatorActivePowerLimitFromSide2ToSide1: lineForm.hvdcLine.operatorActivePowerLimitSide2 ?? null, + convertersMode: lineForm.hvdcLine.convertersMode, + activePowerSetpoint: lineForm.hvdcLine.activePowerSetpoint, + angleDroopActivePowerControl: lineForm.hvdcLine.angleDroopActivePowerControl ?? null, + p0: lineForm.hvdcLine.p0 ?? null, + droop: lineForm.hvdcLine.droop ?? null, + converterStation1: converterStationCreationFormToDto(lineForm.converterStation1), + converterStation2: converterStationCreationFormToDto(lineForm.converterStation2), + }; +}; diff --git a/src/features/network-modifications/hvdcLine/vsc/index.ts b/src/features/network-modifications/hvdcLine/vsc/index.ts new file mode 100644 index 000000000..b7c210402 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/index.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './common'; +export * from './creation'; +export * from './modification'; diff --git a/src/features/network-modifications/hvdcLine/vsc/modification/index.ts b/src/features/network-modifications/hvdcLine/vsc/modification/index.ts new file mode 100644 index 000000000..7a16e8bb1 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/modification/index.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2026, 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/. + */ + +export * from './vscHvdcLineModification.types'; +export * from './vscHvdcLineModification.utils'; diff --git a/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.types.ts b/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.types.ts new file mode 100644 index 000000000..c0fa3ea16 --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.types.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2026, 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 { UUID } from 'node:crypto'; +import { AttributeModification, ModificationType } from '../../../../../utils'; +import { Property } from '../../../common/properties/properties.type'; +import { ReactiveCapabilityCurvePoints } from '../../../common/reactiveLimits/reactiveLimits.type'; + +interface InjectionModificationDto { + type: ModificationType; + equipmentId: string; + equipmentName: AttributeModification | null; + voltageLevelId: AttributeModification | null; + busOrBusbarSectionId: AttributeModification | null; + connectionDirection: AttributeModification | null; + connectionName: AttributeModification | null; + connectionPosition: AttributeModification | null; + terminalConnected: AttributeModification | null; + pMeasurementValue: AttributeModification | null; + pMeasurementValidity: AttributeModification | null; + qMeasurementValue: AttributeModification | null; + qMeasurementValidity: AttributeModification | null; +} + +export interface ConverterStationModificationDto extends InjectionModificationDto { + lossFactor: AttributeModification | null; + reactivePowerSetpoint: AttributeModification | null; + voltageRegulationOn: AttributeModification | null; + voltageSetpoint: AttributeModification | null; + reactiveCapabilityCurve: AttributeModification | null; + minQ: AttributeModification | null; + maxQ: AttributeModification | null; + reactiveCapabilityCurvePoints: ReactiveCapabilityCurvePoints[]; +} + +// cf VscModificationInfos server class +export interface VscHdvLineModificationDto { + type: ModificationType; + uuid?: UUID; + equipmentId: string; + equipmentName: AttributeModification | null; + properties: Property[] | null; + nominalV: AttributeModification | null; + r: AttributeModification | null; + maxP: AttributeModification | null; + operatorActivePowerLimitFromSide1ToSide2: AttributeModification | null; + operatorActivePowerLimitFromSide2ToSide1: AttributeModification | null; + convertersMode: AttributeModification | null; + activePowerSetpoint: AttributeModification | null; + angleDroopActivePowerControl: AttributeModification | null; + p0: AttributeModification | null; + droop: AttributeModification | null; + converterStation1: ConverterStationModificationDto; + converterStation2: ConverterStationModificationDto; +} diff --git a/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.utils.ts b/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.utils.ts new file mode 100644 index 000000000..0b892440c --- /dev/null +++ b/src/features/network-modifications/hvdcLine/vsc/modification/vscHvdcLineModification.utils.ts @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2026, 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 { InferType, object, string } from 'yup'; +import { + DeepNullable, + FieldConstants, + ModificationType, + sanitizeString, + toModificationOperation, +} from '../../../../../utils'; +import { + getPropertiesFromModification, + modificationPropertiesSchema, + toModificationProperties, +} from '../../../common/properties/'; +import { + getVscHvdcLineCharacteristicsEmptyFormData, + getVscHvdcLineCharacteristicsModificationDtoToForm, + getVscHvdcLineCharacteristicsModificationSchema, +} from '../common/characteristics/vscHvdcLineCharacteristicsPane.utils'; +import { + converterStationModificationDtoToForm, + converterStationModificationFormToDto, + getVscConverterStationEmptyFormData, + getVscConverterStationModificationSchema, +} from '../common/converterStation/vscConverterStationPane.utils'; +import { VscHdvLineModificationDto } from './vscHvdcLineModification.types'; + +export const vscHvdcLineModificationFormSchema = object() + .shape({ + [FieldConstants.EQUIPMENT_ID]: string().required(), + [FieldConstants.EQUIPMENT_NAME]: string().nullable(), + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsModificationSchema(), + [FieldConstants.CONVERTER_STATION_1]: getVscConverterStationModificationSchema(), + [FieldConstants.CONVERTER_STATION_2]: getVscConverterStationModificationSchema(), + }) + .concat(modificationPropertiesSchema) + .required(); + +export type VscHvdcLineModificationFormData = InferType; + +export const vscHvdcLineModificationEmptyFormData: DeepNullable = { + [FieldConstants.EQUIPMENT_ID]: null, + [FieldConstants.EQUIPMENT_NAME]: null, + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsEmptyFormData(true), + [FieldConstants.CONVERTER_STATION_1]: getVscConverterStationEmptyFormData(true), + [FieldConstants.CONVERTER_STATION_2]: getVscConverterStationEmptyFormData(true), + [FieldConstants.ADDITIONAL_PROPERTIES]: [], +}; + +export const vscHvdcLineModificationDtoToForm = ( + lineDto: VscHdvLineModificationDto, + includePreviousValues = true +): VscHvdcLineModificationFormData => { + return { + [FieldConstants.EQUIPMENT_ID]: lineDto.equipmentId, + [FieldConstants.EQUIPMENT_NAME]: lineDto.equipmentName?.value, + [FieldConstants.HVDC_LINE]: getVscHvdcLineCharacteristicsModificationDtoToForm(lineDto), + [FieldConstants.CONVERTER_STATION_1]: converterStationModificationDtoToForm(lineDto.converterStation1), + [FieldConstants.CONVERTER_STATION_2]: converterStationModificationDtoToForm(lineDto.converterStation2), + ...getPropertiesFromModification(lineDto?.properties, includePreviousValues), + }; +}; + +export const vscHvdcLineModificationFormToDto = ( + lineForm: VscHvdcLineModificationFormData +): VscHdvLineModificationDto => { + return { + type: ModificationType.VSC_MODIFICATION, + equipmentId: lineForm.equipmentID, + equipmentName: toModificationOperation(sanitizeString(lineForm.equipmentName)), + properties: toModificationProperties(lineForm), + nominalV: toModificationOperation(lineForm.hvdcLine.nominalV), + r: toModificationOperation(lineForm.hvdcLine.r), + maxP: toModificationOperation(lineForm.hvdcLine.maxP), + operatorActivePowerLimitFromSide1ToSide2: toModificationOperation( + lineForm.hvdcLine.operatorActivePowerLimitSide1 + ), + operatorActivePowerLimitFromSide2ToSide1: toModificationOperation( + lineForm.hvdcLine.operatorActivePowerLimitSide2 + ), + convertersMode: toModificationOperation(lineForm.hvdcLine.convertersMode), + activePowerSetpoint: toModificationOperation(lineForm.hvdcLine.activePowerSetpoint), + angleDroopActivePowerControl: toModificationOperation(lineForm.hvdcLine.angleDroopActivePowerControl), + p0: toModificationOperation(lineForm.hvdcLine.p0), + droop: toModificationOperation(lineForm.hvdcLine.droop), + converterStation1: converterStationModificationFormToDto(lineForm.converterStation1), + converterStation2: converterStationModificationFormToDto(lineForm.converterStation2), + }; +}; diff --git a/src/features/network-modifications/index.ts b/src/features/network-modifications/index.ts index 9dd89ea41..ed66d126e 100644 --- a/src/features/network-modifications/index.ts +++ b/src/features/network-modifications/index.ts @@ -14,6 +14,7 @@ export * from './by-filter'; export * from './generator'; export * from './battery'; export * from './shunt-compensator'; +export * from './hvdcLine'; export * from './line'; export * from './twoWindingsTransformer'; export * from './static-var-compensator'; diff --git a/src/features/network-modifications/static-var-compensator/common/static-var-compensator-dialog-tabs.tsx b/src/features/network-modifications/static-var-compensator/common/static-var-compensator-dialog-tabs.tsx index 454a320ad..4c4e981b2 100644 --- a/src/features/network-modifications/static-var-compensator/common/static-var-compensator-dialog-tabs.tsx +++ b/src/features/network-modifications/static-var-compensator/common/static-var-compensator-dialog-tabs.tsx @@ -26,11 +26,11 @@ export function StaticVarCompensatorDialogTabs({ } + label={} sx={getTabStyle(tabIndexesWithError, StaticVarCompensatorDialogTab.CONNECTIVITY_TAB)} /> } + label={} sx={getTabStyle(tabIndexesWithError, StaticVarCompensatorDialogTab.SET_POINTS_LIMITS_TAB)} /> } + label={} sx={getTabStyle(tabIndexesWithError, StaticVarCompensatorDialogTab.ADDITIONAL_INFO_TAB)} /> diff --git a/src/hooks/useModificationLabelComputer.tsx b/src/hooks/useModificationLabelComputer.tsx index 5fe1161b2..696973c19 100644 --- a/src/hooks/useModificationLabelComputer.tsx +++ b/src/hooks/useModificationLabelComputer.tsx @@ -23,7 +23,11 @@ const getOperatingStatusModificationValues = (modification: ModificationValues, return { action: modification.action, energizedEnd: modification.energizedVoltageLevelId, - computedLabel: formatBold ? {modification.equipmentId} : modification.equipmentId, + computedLabel: formatBold ? ( + {modification.equipmentId} + ) : ( + modification.equipmentId + ), }; }; @@ -31,19 +35,23 @@ const getEquipmentAttributeModificationValues = (modification: ModificationValue return { equipmentAttributeName: modification.equipmentAttributeName, equipmentAttributeValue: modification.equipmentAttributeValue, - computedLabel: formatBold ? {modification.equipmentId} : modification.equipmentId, + computedLabel: formatBold ? ( + {modification.equipmentId} + ) : ( + modification.equipmentId + ), }; }; const getVoltageLevelWithSubstationModificationValues = (modification: ModificationValues, formatBold: boolean) => { return { voltageLevelEquipmentId: formatBold ? ( - {modification.voltageLevelEquipmentId} + {modification.voltageLevelEquipmentId} ) : ( modification.voltageLevelEquipmentId ), substationEquipmentId: formatBold ? ( - {modification.substationEquipmentId} + {modification.substationEquipmentId} ) : ( modification.substationEquipmentId ), @@ -125,7 +133,13 @@ export const useModificationLabelComputer = () => { case MODIFICATION_TYPES.VOLTAGE_LEVEL_CREATION_SUBSTATION_CREATION.type: return getVoltageLevelWithSubstationModificationValues(modificationValues, formatBold); default: - return { computedLabel: formatBold ? {getLabel(modif)} : getLabel(modif) }; + return { + computedLabel: formatBold ? ( + {getLabel(modif)} + ) : ( + getLabel(modif) + ), + }; } }, [getLabel] diff --git a/src/translations/en/networkModificationsEn.ts b/src/translations/en/networkModificationsEn.ts index ceadd0778..3a91ed800 100644 --- a/src/translations/en/networkModificationsEn.ts +++ b/src/translations/en/networkModificationsEn.ts @@ -89,6 +89,10 @@ export const networkModificationsEn = { StateEstimationTab: 'State estimation', TwoWindingsTransformerRatioTapChangerTab: 'Ratio tap changer', TwoWindingsTransformerPhaseTapChangerTab: 'Phase tap changer', + StaticVarCompensatorAutomatonTab: 'Automaton', + HvdcLineTab: 'HVDC Line', + ConverterStation1Tab: 'Converter station 1', + ConverterStation2Tab: 'Converter station 2', ModificationReadError: 'An error occurred while fetching the modification', CompositeModification: 'Composite modification', @@ -402,12 +406,27 @@ export const networkModificationsEn = { 'Susceptance Fixed value should be less than susceptance maximum value', StaticVarCompensatorErrorSFixLessThanSMin: 'Susceptance Fixed value should be greater than susceptance minimum value', - StaticVarCompensatorConnectivityTab: 'Connectivity', - StaticVarCompensatorSetPointsAndLimitsTab: 'Set points & Limits', - StaticVarCompensatorAutomatonTab: 'Automaton', - StaticVarCompensatorAdditionalInfosTab: 'Additional information', b0: 'Fixed part of susceptance', fixQAtNominalV: 'Q fixed', + CreateVsc: 'Create HVDC (VSC)', + HvdcCreationError: 'Error while creating HVDC line', + ModifyVsc: 'Modify HVDC (VSC)', + HvdcModificationError: 'Error while modifying HVDC line', + converterStation1: 'Converter station 1', + converterStation2: 'Converter station 2', + converterStationId: 'Converter station ID', + converterStationName: 'Converter station name', + dcNominalVoltageLabel: 'DC nominal voltage', + dcResistanceLabel: 'DC resistance', + operatorActivePowerLimitSide2Label: 'Operator active power limit (Side2->Side1)', + operatorActivePowerLimitSide1Label: 'Operator active power limit (Side1->Side2)', + converterModeLabel: 'Converters mode', + lossFactorLabel: 'Loss Factor', + angleDroopActivePowerControlLabel: 'Angle droop active power control', + p0Label: 'P0', + droopLabel: 'k', + side1RectifierSide2Inverter: 'Flow (Side1->Side2)', + side1InverterSide2Rectifier: 'Flow (Side2->Side1)', copyLink: 'Copy link', linkCopied: 'Link copied', linkCopyError: 'Error while attempting to copy link', diff --git a/src/translations/fr/networkModificationsFr.ts b/src/translations/fr/networkModificationsFr.ts index 48ed56e59..1cf0dca94 100644 --- a/src/translations/fr/networkModificationsFr.ts +++ b/src/translations/fr/networkModificationsFr.ts @@ -93,6 +93,10 @@ export const networkModificationsFr = { StateEstimationTab: "Estimation d'état", TwoWindingsTransformerRatioTapChangerTab: 'Régleur', TwoWindingsTransformerPhaseTapChangerTab: 'Déphaseur', + StaticVarCompensatorAutomatonTab: 'Automate', + HvdcLineTab: 'Ligne HVDC', + ConverterStation1Tab: 'Station 1', + ConverterStation2Tab: 'Station 2', ModificationReadError: 'Une erreur est survenue lors de la récupération de la modification', CompositeModification: 'Modification composite', @@ -408,12 +412,27 @@ export const networkModificationsFr = { 'La valeur de Susceptance Fixe doit être inférieure à la valeur de susceptance maximum', StaticVarCompensatorErrorSFixLessThanSMin: 'La valeur de Susceptance Fixe doit être supérieure à la valeur de susceptance minimum', - StaticVarCompensatorConnectivityTab: 'Connectivité', - StaticVarCompensatorSetPointsAndLimitsTab: 'Consignes & Limites', - StaticVarCompensatorAutomatonTab: 'Automate', - StaticVarCompensatorAdditionalInfosTab: 'Compléments', b0: 'Susceptance fixe', fixQAtNominalV: 'Q fixe', + CreateVsc: "Création d'une HVDC (VSC)", + HvdcCreationError: "Erreur lors de la création d'une ligne HVDC", + ModifyVsc: 'Modifier une HVDC (VSC)', + HvdcModificationError: "Erreur lors de la modification d'une ligne HVDC", + converterStation1: 'Station 1', + converterStation2: 'Station 2', + converterStationId: 'ID de la station', + converterStationName: 'Nom de la station', + dcNominalVoltageLabel: 'Tension nominale DC', + dcResistanceLabel: 'Résistance DC', + operatorActivePowerLimitSide2Label: 'Limite de fonctionnement (2->1)', + operatorActivePowerLimitSide1Label: 'Limite de fonctionnement (1->2)', + converterModeLabel: 'Mode de fonctionnement des stations', + lossFactorLabel: 'Coefficient de pertes', + angleDroopActivePowerControlLabel: 'Emulation AC', + p0Label: 'P0', + droopLabel: 'Gain', + side1RectifierSide2Inverter: 'Flux (1->2)', + side1InverterSide2Rectifier: 'Flux (2->1)', copyLink: 'Copier le lien', linkCopied: 'Lien copié', linkCopyError: 'Erreur lors de la copie du lien', diff --git a/src/utils/constants/fieldConstants.ts b/src/utils/constants/fieldConstants.ts index 6519286f4..5fa4400bc 100644 --- a/src/utils/constants/fieldConstants.ts +++ b/src/utils/constants/fieldConstants.ts @@ -10,6 +10,7 @@ export enum FieldConstants { ADDED = 'added', ADDITIONAL_PROPERTIES = 'AdditionalProperties', AG_GRID_ROW_UUID = 'agGridRowUuid', + ANGLE_DROOP_ACTIVE_POWER_CONTROL = 'angleDroopActivePowerControl', API_CALL = 'apiCall', APPLY_SEGMENTS_LIMITS = 'applySegmentsLimits', APPLICABILITY_FIELD = 'applicability', @@ -34,6 +35,11 @@ export enum FieldConstants { CONNECTIVITY_2 = 'connectivity2', CONTINGENCY_LIST_TYPE = 'contingencyListType', CONTINGENCY_NAME = 'contingencyName', + CONVERTERS_MODE = 'convertersMode', + CONVERTER_STATION_1 = 'converterStation1', + CONVERTER_STATION_2 = 'converterStation2', + CONVERTER_STATION_ID = 'converterStationId', + CONVERTER_STATION_NAME = 'converterStationName', COUNTRIES_1 = 'countries1', COUNTRIES_2 = 'countries2', COUNTRIES = 'countries', @@ -68,6 +74,7 @@ export enum FieldConstants { G1 = 'g1', G2 = 'g2', HIGH_TAP_POSITION = 'highTapPosition', + HVDC_LINE = 'hvdcLine', HVDC_LINE_LCC_DELETION_SPECIFIC_TYPE = 'HVDC_LINE_WITH_LCC', ID = 'id', REGULATING = 'isRegulating', @@ -75,9 +82,11 @@ export enum FieldConstants { SHORTCIRCUIT_PARAMETERS = 'shortcircuitParameters', LOAD_TYPE = 'loadType', LOAD_TAP_CHANGING_CAPABILITIES = 'hasLoadTapChangingCapabilities', + LOSS_FACTOR = 'lossFactor', LOW_TAP_POSITION = 'lowTapPosition', MARGINAL_COST = 'marginalCost', MIN_Q_AT_NOMINAL_V = 'minQAtNominalV', + MAX_P = 'maxP', MAX_Q_AT_NOMINAL_V = 'maxQAtNominalV', MIN_SUSCEPTANCE = 'minSusceptance', MAX_SUSCEPTANCE = 'maxSusceptance', @@ -97,6 +106,9 @@ export enum FieldConstants { NOMINAL_VOLTAGE_3 = 'nominalVoltage3', NOMINAL_VOLTAGE = 'nominalVoltage', OPERATION_TYPE = 'type', + OPERATOR_ACTIVE_POWER_LIMIT_SIDE1 = 'operatorActivePowerLimitSide1', + OPERATOR_ACTIVE_POWER_LIMIT_SIDE2 = 'operatorActivePowerLimitSide2', + P0 = 'p0', PERMANENT_LIMIT = 'permanentLimit', PHASE_TAP_CHANGER = 'phaseTapChanger', PHASE_TAP_CHANGER_STATUS = 'phaseTapChangerStatus', @@ -113,6 +125,7 @@ export enum FieldConstants { RATED_NOMINAL_POWER = 'ratedNominalPower', RATIO_TAP_CHANGER = 'ratioTapChanger', RATIO_TAP_CHANGER_STATUS = 'ratioTapChangerStatus', + REACTIVE_POWER = 'reactivePower', REACTIVE_POWER_SET_POINT = 'reactivePowerSetpoint', REGULATION_MODE = 'regulationMode', REGULATION_SIDE = 'regulationSide', @@ -147,9 +160,11 @@ export enum FieldConstants { VALUE = 'value', VALUE_1 = 'value1', VALUE_2 = 'value2', + VOLTAGE = 'voltage', VOLTAGE_LEVEL = 'voltageLevel', VOLTAGE_LEVEL_ID = 'voltageLevelId', VOLTAGE_REGULATION = 'voltageRegulation', + VOLTAGE_REGULATION_ON = 'voltageRegulationOn', SWITCH_KINDS = 'switchKinds', SWITCH_KIND = 'switchKind', ADD_SUBSTATION_CREATION = 'addSubstationCreationId',