Skip to content

Commit ee0190e

Browse files
authored
all buses sections implementation (#3146)
Signed-off-by: Rehili Ghazwa <[email protected]>
1 parent 056d64f commit ee0190e

File tree

7 files changed

+157
-31
lines changed

7 files changed

+157
-31
lines changed

src/components/dialogs/network-modifications/voltage-level/section/create-voltage-level-section-dialog.tsx

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ModificationDialog } from 'components/dialogs/commons/modificationDialo
1414
import { isNodeBuilt } from 'components/graph/util/model-functions';
1515
import { yupResolver } from '@hookform/resolvers/yup';
1616
import {
17+
ALL_BUS_BAR_SECTIONS,
1718
BUS_BAR_INDEX,
1819
BUSBAR_SECTION_ID,
1920
ID,
@@ -35,20 +36,34 @@ import { EQUIPMENT_INFOS_TYPES } from '../../../../utils/equipment-types';
3536
import { fetchNetworkElementInfos } from '../../../../../services/study/network';
3637
import { DeepNullable } from '../../../../utils/ts-utils';
3738

38-
const getBusBarIndexValue = ({ busbarIndex }: { busbarIndex: string | null }) => {
39+
const getBusBarIndexValue = ({ busbarIndex, allBusbars }: { busbarIndex: string | null; allBusbars: boolean }) => {
3940
if (!busbarIndex) {
4041
return null;
4142
}
43+
if (allBusbars) {
44+
return {
45+
[ID]: 'all',
46+
};
47+
}
4248
return {
4349
[ID]: busbarIndex,
4450
};
4551
};
52+
const getBusBarSectionValue = ({ busbarSectionId }: { busbarSectionId: string | null }) => {
53+
if (!busbarSectionId) {
54+
return null;
55+
}
56+
return {
57+
[ID]: busbarSectionId,
58+
};
59+
};
4660
const emptyFormData = {
4761
[BUS_BAR_INDEX]: null,
4862
[BUSBAR_SECTION_ID]: null,
4963
[IS_AFTER_BUSBAR_SECTION_ID]: null,
5064
[SWITCHES_BEFORE_SECTIONS]: null,
5165
[SWITCHES_AFTER_SECTIONS]: null,
66+
[ALL_BUS_BAR_SECTIONS]: false,
5267
[NEW_SWITCH_STATES]: false,
5368
[SWITCH_BEFORE_NOT_REQUIRED]: false,
5469
[SWITCH_AFTER_NOT_REQUIRED]: false,
@@ -90,6 +105,7 @@ const formSchema = yup
90105
then: (schema) => schema.notRequired(),
91106
otherwise: (schema) => schema.required(),
92107
}),
108+
[ALL_BUS_BAR_SECTIONS]: yup.boolean(),
93109
[NEW_SWITCH_STATES]: yup.boolean(),
94110
[SWITCH_BEFORE_NOT_REQUIRED]: yup.boolean(),
95111
[SWITCH_AFTER_NOT_REQUIRED]: yup.boolean(),
@@ -114,7 +130,9 @@ export default function CreateVoltageLevelSectionDialog({
114130
const [selectedId, setSelectedId] = useState<string>(defaultIdValue ?? null);
115131
const [isExtensionNotFoundOrNotSupportedTopology, setIsExtensionNotFoundOrNotSupportedTopology] =
116132
useState<boolean>(false);
133+
const [isSymmetricalNbBusBarSections, setIsSymmetricalNbBusBarSections] = useState<boolean>(false);
117134
const [busBarSectionInfos, setBusBarSectionInfos] = useState<BusBarSectionInfos[]>();
135+
const [allBusbarSectionsList, setAllBusbarSectionsList] = useState<string[]>([]);
118136
const [dataFetchStatus, setDataFetchStatus] = useState<string>(FetchStatus.IDLE);
119137
const { snackError } = useSnackMessage();
120138
const formMethods = useForm<DeepNullable<CreateVoltageLevelSectionDialogSchemaForm>>({
@@ -145,11 +163,15 @@ export default function CreateVoltageLevelSectionDialog({
145163
)
146164
.then((voltageLevel) => {
147165
if (voltageLevel) {
148-
const isNotSupported =
149-
!voltageLevel.isBusbarSectionPositionFound ||
150-
voltageLevel?.topologyKind !== 'NODE_BREAKER';
151166
setBusBarSectionInfos(voltageLevel?.busBarSectionInfos || []);
152-
setIsExtensionNotFoundOrNotSupportedTopology(isNotSupported);
167+
setAllBusbarSectionsList(
168+
Object.values(voltageLevel?.busBarSectionInfos || {}).flat() as string[]
169+
);
170+
setIsExtensionNotFoundOrNotSupportedTopology(
171+
!voltageLevel.isBusbarSectionPositionFound ||
172+
voltageLevel?.topologyKind !== 'NODE_BREAKER'
173+
);
174+
setIsSymmetricalNbBusBarSections(voltageLevel.isRetrievedBusbarSections);
153175
setDataFetchStatus(FetchStatus.SUCCEED);
154176
}
155177
})
@@ -173,8 +195,13 @@ export default function CreateVoltageLevelSectionDialog({
173195
setSelectedId(editData.voltageLevelId);
174196
}
175197
reset({
176-
[BUS_BAR_INDEX]: getBusBarIndexValue({ busbarIndex: editData?.busbarIndex }) ?? null,
177-
[BUSBAR_SECTION_ID]: getBusBarIndexValue({ busbarIndex: editData?.busbarSectionId }) ?? null,
198+
[BUS_BAR_INDEX]:
199+
getBusBarIndexValue({
200+
busbarIndex: editData?.busbarIndex,
201+
allBusbars: editData?.allBusbars,
202+
}) ?? null,
203+
[ALL_BUS_BAR_SECTIONS]: editData?.allBusbars ?? false,
204+
[BUSBAR_SECTION_ID]: getBusBarSectionValue({ busbarSectionId: editData?.busbarSectionId }) ?? null,
178205
[IS_AFTER_BUSBAR_SECTION_ID]: editData?.afterBusbarSectionId
179206
? POSITION_NEW_SECTION_SIDE.AFTER.id
180207
: POSITION_NEW_SECTION_SIDE.BEFORE.id,
@@ -204,13 +231,24 @@ export default function CreateVoltageLevelSectionDialog({
204231
reset(emptyFormData);
205232
}, [reset]);
206233

234+
const findBusbarKeyForSection = useCallback(
235+
(sectionId: string) => {
236+
const infos = busBarSectionInfos as unknown as BusBarSectionInfos;
237+
return Object.keys(infos || {}).find((key) => infos[key]?.includes(sectionId)) || null;
238+
},
239+
[busBarSectionInfos]
240+
);
241+
207242
const onSubmit = useCallback(
208243
(voltageLevelSection: CreateVoltageLevelSectionDialogSchemaForm) => {
209244
const voltageLevelSectionInfos = {
210245
type: MODIFICATION_TYPES.CREATE_VOLTAGE_LEVEL_SECTION.type,
211246
voltageLevelId: selectedId,
212-
busbarIndex: voltageLevelSection?.busbarIndex?.id || null,
247+
busbarIndex: voltageLevelSection?.allBusbarSections
248+
? findBusbarKeyForSection(voltageLevelSection?.busbarSectionId?.id)
249+
: voltageLevelSection?.busbarIndex?.id || null,
213250
busbarSectionId: voltageLevelSection?.busbarSectionId?.id || null,
251+
allBusbars: voltageLevelSection?.allBusbarSections || false,
214252
afterBusbarSectionId:
215253
voltageLevelSection?.isAfterBusBarSectionId === POSITION_NEW_SECTION_SIDE.AFTER.id,
216254
leftSwitchKind: voltageLevelSection?.switchesBeforeSections || null,
@@ -230,7 +268,7 @@ export default function CreateVoltageLevelSectionDialog({
230268
});
231269
});
232270
},
233-
[selectedId, studyUuid, currentNodeUuid, editData, snackError]
271+
[selectedId, findBusbarKeyForSection, studyUuid, currentNodeUuid, editData, snackError]
234272
);
235273

236274
return (
@@ -258,10 +296,12 @@ export default function CreateVoltageLevelSectionDialog({
258296
<CreateVoltageLevelSectionForm
259297
busBarSectionInfos={busBarSectionInfos}
260298
voltageLevelId={selectedId}
299+
allBusbarSectionsList={allBusbarSectionsList}
261300
studyUuid={studyUuid}
262301
currentNode={currentNode}
263302
currentRootNetworkUuid={currentRootNetworkUuid}
264303
isUpdate={isUpdate}
304+
isSymmetricalNbBusBarSections={isSymmetricalNbBusBarSections}
265305
isNotFoundOrNotSupported={isExtensionNotFoundOrNotSupportedTopology}
266306
/>
267307
)}

src/components/dialogs/network-modifications/voltage-level/section/create-voltage-level-section-form.tsx

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
import React, { useCallback, useEffect, useMemo, useState } from 'react';
88
import {
9+
ALL_BUS_BAR_SECTIONS,
910
BUS_BAR_INDEX,
1011
BUSBAR_SECTION_ID,
1112
IS_AFTER_BUSBAR_SECTION_ID,
@@ -29,23 +30,45 @@ import { useFormContext, useWatch } from 'react-hook-form';
2930
import { BusBarSectionInfos } from './voltage-level-section.type';
3031
import { areIdsEqual, getObjectId } from '../../../../utils/utils';
3132

33+
const getArrayPosition = (data: BusBarSectionInfos[], selectedOptionId: string) => {
34+
if (!selectedOptionId || !data) {
35+
return { position: -1, length: 0 };
36+
}
37+
38+
for (const array of Object.values(data)) {
39+
if (Array.isArray(array)) {
40+
const position = array.indexOf(selectedOptionId);
41+
if (position !== -1) {
42+
return { position, length: array.length };
43+
}
44+
}
45+
}
46+
return { position: -1, length: 0 };
47+
};
48+
49+
type OptionWithDisabled = Option & { disabled?: boolean };
50+
3251
interface VoltageLevelSectionsCreationFormProps {
3352
busBarSectionInfos?: BusBarSectionInfos[];
3453
voltageLevelId: string;
54+
allBusbarSectionsList: string[];
3555
studyUuid: UUID;
3656
currentNode: CurrentTreeNode;
3757
currentRootNetworkUuid: UUID;
3858
isUpdate?: boolean;
59+
isSymmetricalNbBusBarSections: boolean;
3960
isNotFoundOrNotSupported: boolean;
4061
}
4162

4263
export function CreateVoltageLevelSectionForm({
4364
busBarSectionInfos,
4465
voltageLevelId,
66+
allBusbarSectionsList,
4567
studyUuid,
4668
currentNode,
4769
currentRootNetworkUuid,
4870
isUpdate,
71+
isSymmetricalNbBusBarSections,
4972
isNotFoundOrNotSupported,
5073
}: Readonly<VoltageLevelSectionsCreationFormProps>) {
5174
const intl = useIntl();
@@ -74,6 +97,21 @@ export function CreateVoltageLevelSectionForm({
7497
useEffect(() => {
7598
if (busBarSectionInfos && sectionCount) {
7699
const selectedKey = sectionCount?.id;
100+
if (selectedKey === 'all') {
101+
setValue(ALL_BUS_BAR_SECTIONS, true);
102+
if (allBusbarSectionsList && Array.isArray(allBusbarSectionsList)) {
103+
const options = allBusbarSectionsList
104+
.filter((id): id is string => Boolean(id))
105+
.map((id) => ({
106+
id: id,
107+
label: id,
108+
}));
109+
setBusBarSectionsIdOptions(options);
110+
} else {
111+
setBusBarSectionsIdOptions([]);
112+
}
113+
return;
114+
}
77115
const sections = busBarSectionInfos[selectedKey];
78116
if (!sections || !Array.isArray(sections)) {
79117
setBusBarSectionsIdOptions([]);
@@ -89,13 +127,17 @@ export function CreateVoltageLevelSectionForm({
89127
} else {
90128
setBusBarSectionsIdOptions([]);
91129
}
92-
}, [busBarSectionInfos, sectionCount]);
130+
}, [allBusbarSectionsList, busBarSectionInfos, intl, sectionCount, setValue]);
131+
132+
const arrayPosition = useMemo(
133+
() => busBarSectionInfos && getArrayPosition(busBarSectionInfos, selectedOption?.id),
134+
[busBarSectionInfos, selectedOption?.id]
135+
);
93136

94137
useEffect(() => {
95-
if (selectedOption && selectedPositionOption) {
96-
const selectedSectionIndex = busBarSectionsIdOptions.findIndex((option: Option) =>
97-
areIdsEqual(option, selectedOption)
98-
);
138+
if (selectedOption && selectedPositionOption && busBarSectionInfos && arrayPosition) {
139+
const selectedSectionIndex = arrayPosition.position;
140+
const busBarSections = arrayPosition.length - 1;
99141
if (selectedSectionIndex === 0 && selectedPositionOption === POSITION_NEW_SECTION_SIDE.BEFORE.id) {
100142
setValue(SWITCH_BEFORE_NOT_REQUIRED, true);
101143
setIsNotRequiredSwitchBefore(true);
@@ -104,7 +146,7 @@ export function CreateVoltageLevelSectionForm({
104146
setIsNotRequiredSwitchBefore(false);
105147
}
106148
if (
107-
busBarSectionsIdOptions?.length - 1 === selectedSectionIndex &&
149+
busBarSections === selectedSectionIndex &&
108150
selectedPositionOption === POSITION_NEW_SECTION_SIDE.AFTER.id
109151
) {
110152
setValue(SWITCH_AFTER_NOT_REQUIRED, true);
@@ -115,26 +157,38 @@ export function CreateVoltageLevelSectionForm({
115157
}
116158
}
117159
if (isUpdate && isNodeBuilt(currentNode)) {
118-
selectedPositionOption === POSITION_NEW_SECTION_SIDE.AFTER.id
119-
? setValue(SWITCH_AFTER_NOT_REQUIRED, false)
120-
: setValue(SWITCH_BEFORE_NOT_REQUIRED, false);
160+
setValue(SWITCH_AFTER_NOT_REQUIRED, true);
161+
setValue(SWITCH_BEFORE_NOT_REQUIRED, true);
121162
}
122-
}, [selectedOption, busBarSectionsIdOptions, setValue, selectedPositionOption, isUpdate, currentNode]);
163+
}, [selectedOption, setValue, busBarSectionInfos, selectedPositionOption, arrayPosition, isUpdate, currentNode]);
123164

124-
const busBarIndexOptions = useMemo(() => {
165+
const busBarIndexOptions = useMemo((): OptionWithDisabled[] => {
125166
if (busBarSectionInfos) {
126-
return Object.keys(busBarSectionInfos || {})
167+
const sortedOptions = Object.keys(busBarSectionInfos || {})
127168
.sort((a, b) => parseInt(a) - parseInt(b))
128169
.map((key) => ({
129170
id: key,
130171
label: key,
131172
}));
173+
const allOption = {
174+
id: 'all',
175+
label: intl.formatMessage({ id: 'allBusbarSections' }),
176+
disabled: !isSymmetricalNbBusBarSections,
177+
} as Option & { disabled?: boolean };
178+
179+
return [...sortedOptions, allOption];
132180
}
133181
return [];
134-
}, [busBarSectionInfos]);
182+
}, [busBarSectionInfos, intl, isSymmetricalNbBusBarSections]);
135183

136-
const getOptionLabel = (object: string | { id: string | number }) => {
137-
return typeof object === 'string' ? object : String(object?.id ?? '');
184+
const getOptionLabel = (object: string | { id: string | number; label: string | number }) => {
185+
if (typeof object === 'string') {
186+
return object;
187+
}
188+
if (object?.id === 'all') {
189+
return intl.formatMessage({ id: 'allBusbarSections' }) ?? '';
190+
}
191+
return String(object?.id ?? '');
138192
};
139193

140194
const isOptionEqualToValue = (val1: Option, val2: Option) => {
@@ -154,9 +208,32 @@ export function CreateVoltageLevelSectionForm({
154208
name={BUS_BAR_INDEX}
155209
label="Busbar"
156210
onChangeCallback={handleChangeBusbarIndex}
157-
options={busBarIndexOptions}
211+
options={busBarIndexOptions as Option[]}
158212
getOptionLabel={getOptionLabel}
159213
isOptionEqualToValue={isOptionEqualToValue}
214+
renderOption={(props, option) => {
215+
const allOptionsDisabled = (option as any).id === 'all' && (option as any)?.disabled;
216+
const { key, ...otherProps } = props;
217+
return (
218+
<li key={key} {...otherProps}>
219+
<div>
220+
<div>{getOptionLabel(option)}</div>
221+
{allOptionsDisabled && (
222+
<div
223+
style={{
224+
fontSize: '0.85rem',
225+
color: 'red',
226+
marginTop: '2px',
227+
}}
228+
>
229+
{intl.formatMessage({ id: 'allOptionHelperText' })}
230+
</div>
231+
)}
232+
</div>
233+
</li>
234+
);
235+
}}
236+
getOptionDisabled={(option) => (option as any)?.disabled}
160237
size={'small'}
161238
disabled={isNotFoundOrNotSupported}
162239
/>
@@ -165,8 +242,8 @@ export function CreateVoltageLevelSectionForm({
165242
const busbarSectionsField = (
166243
<AutocompleteInput
167244
name={BUSBAR_SECTION_ID}
168-
label="BusBarSections"
169-
options={Object.values(busBarSectionsIdOptions)}
245+
label="BusBarSectionsReference"
246+
options={busBarSectionsIdOptions}
170247
getOptionLabel={getObjectId}
171248
isOptionEqualToValue={areIdsEqual}
172249
size={'small'}

src/components/dialogs/network-modifications/voltage-level/section/voltage-level-section.type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type CreateVoltageLevelSectionDialogSchemaForm = {
1111
isAfterBusBarSectionId: string | null;
1212
switchesBeforeSections?: string | null;
1313
switchesAfterSections?: string | null;
14+
allBusbarSections?: boolean;
1415
newSwitchStates?: boolean;
1516
};
1617

src/components/utils/field-constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ export const IS_AFTER_BUSBAR_SECTION_ID = 'isAfterBusBarSectionId';
249249
export const BUS_BAR_INDEX = 'busbarIndex';
250250
export const SWITCH_BEFORE_NOT_REQUIRED = 'switchBeforeNotRequired';
251251
export const SWITCH_AFTER_NOT_REQUIRED = 'switchAfterNotRequired';
252+
export const ALL_BUS_BAR_SECTIONS = 'allBusbarSections';
252253
export const COUPLING_OMNIBUS = 'couplingOmnibus';
253254
export const SWITCH_KINDS = 'switchKinds';
254255
export const IP_MIN = 'ipMin';

src/services/network-modification-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ export interface CreateVoltageLevelSectionInfos {
816816
voltageLevelId: string;
817817
busbarIndex: string | null;
818818
busbarSectionId: string | null;
819+
allBusbars: boolean;
819820
afterBusbarSectionId: boolean;
820821
leftSwitchKind: string | null;
821822
rightSwitchKind: string | null;

src/translations/en.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,8 @@
825825
"CreateVoltageLevel": "Create a voltage level",
826826
"ModifyVoltageLevel": "Modify a voltage level",
827827
"Substation": "Substation",
828-
"BusBarSections": "Busbar reference section",
828+
"BusBarSections": "Busbar section",
829+
"BusBarSectionsReference": "Busbar reference section",
829830
"BusBarCount": "Busbar Count",
830831
"numberOfSections": "Section Count",
831832
"BusBarSectionID": "ID",
@@ -1583,5 +1584,7 @@
15831584
"BUILT": "Built",
15841585
"BUILT_WITH_WARNING": "Warnings",
15851586
"BUILT_WITH_ERROR": "Errors",
1586-
"NOT_BUILT": "Not built"
1587+
"NOT_BUILT": "Not built",
1588+
"allBusbarSections": "All",
1589+
"allOptionHelperText": "Busbars have different sections (number or index)"
15871590
}

0 commit comments

Comments
 (0)