Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5fbbcdc
change endpoint to get voltage level topology
EtienneLt Oct 6, 2025
715c115
Merge branch 'main' into refactor-voltage-level-topology
EtienneLt Oct 6, 2025
6b0f2a1
remove useless imports
EtienneLt Oct 6, 2025
bab8ef3
fix
EtienneLt Oct 10, 2025
ca4987a
Merge branch 'main' into refactor-voltage-level-topology
EtienneLt Oct 14, 2025
72bb575
reviex with fixes from back
EtienneLt Oct 14, 2025
78668e9
Merge branch 'main' into refactor-voltage-level-topology
ghazwarhili Oct 17, 2025
bc4157b
resolving conflicts
ghazwarhili Oct 21, 2025
3390129
Merge remote-tracking branch 'origin/refactor-voltage-level-topology'…
ghazwarhili Oct 21, 2025
c1cb8a2
Update with new common tabular DTO (#3346)
dbraquart Oct 21, 2025
e59d77a
Bump version to v2.26.0-SNAPSHOT
gridsuite-actions[bot] Oct 21, 2025
618a7e2
Fix spreadsheet global filter (#3336)
Tristan-WorkGH Oct 21, 2025
93fc339
fix control for coupling creation and refactor labels (#3402)
EtienneLt Oct 22, 2025
143852f
add some control on vl and generator creation (#3393)
EtienneLt Oct 22, 2025
427d4f6
fix empty value if value is 0 (#3403)
EtienneLt Oct 22, 2025
3c54616
Support string data in numerical spreadsheet columns (#3401)
dbraquart Oct 22, 2025
f2fe9aa
Refactor diagram card generic (#3369)
sBouzols Oct 23, 2025
32303bc
Fix `useOneBusShortcircuitAnalysisLoader` which must consider `rootNe…
sBouzols Oct 23, 2025
e777daa
Enable row counter spinner when switching of root network (#3408)
Meklo Oct 24, 2025
434ba09
Fix security group compression (#3410)
EstherDarkish Oct 27, 2025
93eeed4
refactor according to map server
EtienneLt Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gridstudy-app",
"version": "2.25.0-SNAPSHOT",
"version": "2.26.0-SNAPSHOT",
"license": "MPL-2.0",
"private": true,
"type": "module",
Expand Down
3 changes: 2 additions & 1 deletion src/components/custom-aggrid/cell-renderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export interface NumericCellRendererProps extends CustomCellRendererProps {
}

export const NumericCellRenderer = (props: NumericCellRendererProps) => {
const cellValue = formatNumericCell(props.value, props.fractionDigits);
const numericalValue = typeof props.value === 'number' ? props.value : Number.parseFloat(props.value);
const cellValue = formatNumericCell(numericalValue, props.fractionDigits);
return (
<Box sx={mergeSx(styles.tableCell)}>
<Tooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ const ModificationByAssignmentDialog: FC<any> = ({
const field = FieldType[fieldKey];
const value = assignment[VALUE_FIELD];
let valueConverted = convertInputValue(field, value);
if (!valueConverted || valueConverted === '') {
valueConverted = emptyValueStr;
}
valueConverted = valueConverted !== 0 && !valueConverted ? emptyValueStr : valueConverted;
return {
...assignment,
[VALUE_FIELD]: valueConverted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ const formSchema = yup
[EQUIPMENT_NAME]: yup.string().nullable(),
[ENERGY_SOURCE]: yup.string().nullable().required(),
[MAXIMUM_ACTIVE_POWER]: yup.number().nullable().required(),
[MINIMUM_ACTIVE_POWER]: yup.number().nullable().required(),
[MINIMUM_ACTIVE_POWER]: yup
.number()
.nullable()
.max(yup.ref(MAXIMUM_ACTIVE_POWER), 'generatorMinimumActivePowerMaxValueError')
.required(),
[RATED_NOMINAL_POWER]: yup.number().nullable().min(0, 'mustBeGreaterOrEqualToZero'),
...getShortCircuitFormSchema(),
[PLANNED_ACTIVE_POWER_SET_POINT]: yup.number().nullable(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function LimitSetsModificationDialog({
modificationType,
modifications,
modificationUuid: editData?.uuid,
type: ModificationType.LIMIT_SETS_TABULAR_MODIFICATION,
tabularType: ModificationType.LIMIT_SETS_TABULAR_MODIFICATION,
csvFilename: formData[CSV_FILENAME],
}).catch((error) => {
snackError({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,14 @@ import {
import yup from 'components/utils/yup-config';
import type { UUID } from 'node:crypto';

type TabularModificationCommonType = {
export type TabularModificationEditDataType = {
uuid: UUID;
type: ModificationType.TABULAR_MODIFICATION | ModificationType.TABULAR_CREATION;
properties: TabularProperty[];
csvFilename: string;
};
export type TabularModificationModificationType = TabularModificationCommonType & {
type: 'TABULAR_MODIFICATION';
modificationType: ModificationType;
modifications: Modification[];
};
export type TabularModificationCreationType = TabularModificationCommonType & {
type: 'TABULAR_CREATION';
creationType: ModificationType;
creations: Modification[];
};
export type TabularModificationEditDataType = TabularModificationModificationType | TabularModificationCreationType;

export enum TabularModificationType {
CREATION = 'creation',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useOpenShortWaitFetching } from 'components/dialogs/commons/handle-modi
import { FORM_LOADING_DELAY } from 'components/network/constants.js';
import { TABULAR_PROPERTIES, MODIFICATIONS_TABLE, CSV_FILENAME, TYPE } from 'components/utils/field-constants.js';
import { ModificationDialog } from 'components/dialogs/commons/modificationDialog.js';
import { createTabularCreation, createTabularModification } from 'services/study/network-modifications.js';
import { createTabularModification } from 'services/study/network-modifications.js';
import { FetchStatus } from 'services/utils.type';
import {
convertGeneratorOrBatteryModificationFromBackToFront,
Expand All @@ -32,9 +32,7 @@ import {
Modification,
tabularFormSchema,
TabularFormType,
TabularModificationCreationType,
TabularModificationEditDataType,
TabularModificationModificationType,
TabularModificationType,
transformProperties,
} from './tabular-common.js';
Expand All @@ -51,12 +49,12 @@ import { NetworkModificationDialogProps } from '../../../graph/menus/network-mod
function convertCreations(creations: Modification[]): Modification[] {
return creations.map((creat: Modification) => {
let creation: Modification = {};
Object.keys(formatModification(creat)).forEach((key) => {
for (const key of Object.keys(formatModification(creat))) {
const entry = convertCreationFieldFromBackToFront(key, creat[key]);
(Array.isArray(entry) ? entry : [entry]).forEach((item) => {
for (const item of Array.isArray(entry) ? entry : [entry]) {
creation[item.key] = item.value;
});
});
}
}
creation = addPropertiesFromBack(creation, creat?.[TABULAR_PROPERTIES]);
return creation;
});
Expand Down Expand Up @@ -98,7 +96,7 @@ export function TabularDialog({
const disableSave = Object.keys(errors).length > 0;

const initTabularModificationData = useCallback(
(editData: TabularModificationModificationType) => {
(editData: TabularModificationEditDataType) => {
const modificationType = editData.modificationType;
const modifications = editData.modifications.map((modif: Modification) => {
let modification = formatModification(modif);
Expand All @@ -108,9 +106,9 @@ export function TabularDialog({
) {
modification = convertGeneratorOrBatteryModificationFromBackToFront(modification);
} else {
Object.keys(modification).forEach((key) => {
for (const key of Object.keys(modification)) {
modification[key] = convertInputValues(getFieldType(modificationType, key), modif[key]);
});
}
}
modification = addPropertiesFromBack(modification, modif?.[TABULAR_PROPERTIES]);
return modification;
Expand All @@ -126,9 +124,9 @@ export function TabularDialog({
);

const initTabularCreationData = useCallback(
(editData: TabularModificationCreationType) => {
const equipmentType = getEquipmentTypeFromCreationType(editData?.creationType);
const creations = convertCreations(editData?.creations);
(editData: TabularModificationEditDataType) => {
const equipmentType = getEquipmentTypeFromCreationType(editData?.modificationType);
const creations = convertCreations(editData?.modifications);
reset({
[TYPE]: equipmentType,
[MODIFICATIONS_TABLE]: creations,
Expand All @@ -142,9 +140,9 @@ export function TabularDialog({
useEffect(() => {
if (editData) {
if (dialogMode === TabularModificationType.CREATION) {
initTabularCreationData(editData as TabularModificationCreationType);
initTabularCreationData(editData);
} else {
initTabularModificationData(editData as TabularModificationModificationType);
initTabularModificationData(editData);
}
}
}, [editData, dialogMode, initTabularCreationData, initTabularModificationData]);
Expand All @@ -162,7 +160,7 @@ export function TabularDialog({
modificationType,
modifications,
modificationUuid: editData?.uuid,
type: ModificationType.TABULAR_MODIFICATION,
tabularType: ModificationType.TABULAR_MODIFICATION,
csvFilename: formData[CSV_FILENAME],
properties: formData[TABULAR_PROPERTIES],
}).catch((error) => {
Expand All @@ -177,21 +175,24 @@ export function TabularDialog({

const submitTabularCreation = useCallback(
(formData: TabularFormType) => {
const creationType = TABULAR_CREATION_TYPES[formData[TYPE]];
const creations = formData[MODIFICATIONS_TABLE]?.map((row) => {
const modificationType = TABULAR_CREATION_TYPES[formData[TYPE]];
const modifications = formData[MODIFICATIONS_TABLE]?.map((row) => {
const creation: Modification = {
type: creationType,
type: modificationType,
};
// first transform and clean "property_*" fields
const propertiesModifications = transformProperties(row);

// then transform all other fields
Object.keys(row).forEach((key) => {
for (const key of Object.keys(row)) {
const entry = convertCreationFieldFromFrontToBack(key, row[key]);
creation[entry.key] = entry.value;
});
}
// For now, we do not manage reactive limits by diagram
if (creationType === 'GENERATOR_CREATION' || creationType === 'BATTERY_CREATION') {
if (
modificationType === ModificationType.GENERATOR_CREATION ||
modificationType === ModificationType.BATTERY_CREATION
) {
convertReactiveCapabilityCurvePointsFromFrontToBack(creation);
}

Expand All @@ -200,12 +201,13 @@ export function TabularDialog({
}
return creation;
});
createTabularCreation({
createTabularModification({
studyUuid,
nodeUuid: currentNodeUuid,
creationType,
creations,
modificationType,
modifications,
modificationUuid: editData?.uuid,
tabularType: ModificationType.TABULAR_CREATION,
csvFilename: formData[CSV_FILENAME],
properties: formData[TABULAR_PROPERTIES],
}).catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,26 @@
import { AutocompleteInput } from '@gridsuite/commons-ui';
import { BUS_BAR_SECTION_ID1, BUS_BAR_SECTION_ID2, COUPLING_OMNIBUS } from 'components/utils/field-constants';
import GridItem from '../../../commons/grid-item';
import { useEffect } from 'react';
import { useFormContext } from 'react-hook-form';

// TODO should use "name" props instead of `${COUPLING_OMNIBUS}.(...)`
export const CouplingOmnibusCreation = ({ index, sectionOptions }) => {
const { getValues, watch, trigger } = useFormContext();
// Watch BUS_BAR_SECTION_ID1 changed
useEffect(() => {
const subscription = watch((value, { name }) => {
// force trigger validation on BUS_BAR_SECTION_ID2 if it has a value
if (
name === `${COUPLING_OMNIBUS}.${index}.${BUS_BAR_SECTION_ID1}` &&
getValues(`${COUPLING_OMNIBUS}.${index}.${BUS_BAR_SECTION_ID2}`)
) {
trigger(`${COUPLING_OMNIBUS}.${index}.${BUS_BAR_SECTION_ID2}`);
}
});
return () => subscription.unsubscribe();
}, [watch, trigger, getValues, index]);

const busBarSectionId1Field = (
<AutocompleteInput
allowNewValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import { useForm } from 'react-hook-form';
import { ModificationDialog } from 'components/dialogs/commons/modificationDialog';

import VoltageLevelCreationForm from './voltage-level-creation-form';
import { controlCouplingOmnibusBetweenSections } from '../voltage-level-creation-utils';
import { EQUIPMENT_TYPES } from 'components/utils/equipment-types';
import { useIntl } from 'react-intl';
import { FORM_LOADING_DELAY } from 'components/network/constants';
Expand Down Expand Up @@ -142,8 +141,27 @@ const formSchema = yup
[SUBSTATION_NAME]: yup.string().nullable(),
[COUNTRY]: yup.string().nullable(),
[SUBSTATION_CREATION]: creationPropertiesSchema,
[NOMINAL_V]: yup.number().nullable().min(0, 'mustBeGreaterOrEqualToZero').required(),
[LOW_VOLTAGE_LIMIT]: yup.number().nullable().min(0, 'mustBeGreaterOrEqualToZero'),
[NOMINAL_V]: yup
.number()
.nullable()
.min(0, 'mustBeGreaterOrEqualToZero')
.when([LOW_VOLTAGE_LIMIT], {
is: (lowVoltageLimit) => lowVoltageLimit != null,
then: (schema) => schema.min(yup.ref(LOW_VOLTAGE_LIMIT), 'voltageLevelNominalVoltageMinValueError'),
})
.when([HIGH_VOLTAGE_LIMIT], {
is: (highVoltageLimit) => highVoltageLimit != null,
then: (schema) => schema.max(yup.ref(HIGH_VOLTAGE_LIMIT), 'voltageLevelNominalVoltageMaxValueError'),
})
.required(),
[LOW_VOLTAGE_LIMIT]: yup
.number()
.nullable()
.min(0, 'mustBeGreaterOrEqualToZero')
.when([HIGH_VOLTAGE_LIMIT], {
is: (highVoltageLimit) => highVoltageLimit != null,
then: (schema) => schema.max(yup.ref(HIGH_VOLTAGE_LIMIT), 'voltageLevelNominalVoltageMaxValueError'),
}),
[HIGH_VOLTAGE_LIMIT]: yup.number().nullable().min(0, 'mustBeGreaterOrEqualToZero'),
[LOW_SHORT_CIRCUIT_CURRENT_LIMIT]: yup
.number()
Expand All @@ -167,17 +185,16 @@ const formSchema = yup
is: (sectionCount) => sectionCount > 1,
then: (schema) => schema.required(),
}),
[COUPLING_OMNIBUS]: yup
.array()
.of(
yup.object().shape({
[BUS_BAR_SECTION_ID1]: yup.string().nullable().required(),
[BUS_BAR_SECTION_ID2]: yup.string().nullable().required(),
})
)
.test('coupling-omnibus-between-sections', (values) =>
controlCouplingOmnibusBetweenSections(values, 'CouplingOmnibusBetweenSameBusbar')
),
[COUPLING_OMNIBUS]: yup.array().of(
yup.object().shape({
[BUS_BAR_SECTION_ID1]: yup.string().nullable().required(),
[BUS_BAR_SECTION_ID2]: yup
.string()
.nullable()
.required()
.notOneOf([yup.ref(BUS_BAR_SECTION_ID1), null], 'CreateCouplingDeviceIdenticalBusBar'),
})
),
})
.concat(creationPropertiesSchema);
const VoltageLevelCreationDialog = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ import {
MoveFeederBayInfos,
MoveVoltageLevelFeederBaysInfos,
} from '../../../../../services/network-modification-types';
import { fetchNetworkElementInfos } from '../../../../../services/study/network';
import { fetchVoltageLevelFeederBaysBusBarSectionsInformation } from '../../../../../services/study/network';
import { EquipmentModificationDialogProps } from '../../../../graph/menus/network-modifications/network-modification-menu.type';
import { EQUIPMENT_INFOS_TYPES, EQUIPMENT_TYPES } from '../../../../utils/equipment-types';
import { DeepNullable } from '../../../../utils/ts-utils';
import { FeederBayInfos, FeederBaysFormInfos, FeederBaysInfos } from './move-voltage-level-feeder-bays.type';
import { moveVoltageLevelFeederBays } from '../../../../../services/study/network-modifications';
import { AnyObject, TestFunction } from 'yup';
import { FeederBaysBusBarSectionsInfos } from '../../../../../services/study/network-map.type';

const isActiveRow = (row: FeederBaysFormInfos) => row && !row.isRemoved;
const checkConnectionPositionField: TestFunction<string | undefined, AnyObject> = (currentPosition, context) => {
Expand Down Expand Up @@ -224,10 +224,12 @@ export default function MoveVoltageLevelFeederBaysDialog({
);

const handleVoltageLevelDataFetch = useCallback(
(voltageLevel: any) => {
const busBarSectionInfos = Object.values(voltageLevel?.busBarSectionInfos || {}).flat() as string[];
(feederBaysBusBarSectionInfo: FeederBaysBusBarSectionsInfos) => {
const busBarSectionInfos = Object.values(
feederBaysBusBarSectionInfo?.busBarSectionsInfos || {}
).flat() as string[];
const feederBaysInfos: FeederBaysInfos = (
Object.entries(voltageLevel?.feederBaysInfos || {}) as [string, FeederBayInfos[]][]
Object.entries(feederBaysBusBarSectionInfo?.feederBaysInfos || {}) as [string, FeederBayInfos[]][]
).flatMap(([equipmentId, feederBayInfos]) =>
feederBayInfos.map((feederBay) => ({
equipmentId,
Expand Down Expand Up @@ -255,21 +257,18 @@ export default function MoveVoltageLevelFeederBaysDialog({
);

const onEquipmentIdChange = useCallback(
(equipmentId: string) => {
if (equipmentId) {
(voltageLevelId: string) => {
if (voltageLevelId) {
setDataFetchStatus(FetchStatus.RUNNING);
fetchNetworkElementInfos(
fetchVoltageLevelFeederBaysBusBarSectionsInformation(
studyUuid,
currentNodeUuid,
currentRootNetworkUuid,
EQUIPMENT_TYPES.VOLTAGE_LEVEL,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
true
voltageLevelId
)
.then((voltageLevel) => {
if (voltageLevel) {
handleVoltageLevelDataFetch(voltageLevel);
.then((feederBaysBusBarSectionInfo) => {
if (feederBaysBusBarSectionInfo) {
handleVoltageLevelDataFetch(feederBaysBusBarSectionInfo);
}
})
.catch(() => {
Expand Down
Loading
Loading