Skip to content

Commit 2306135

Browse files
Merge remote-tracking branch 'origin/main' into tabstabs/add-branch-type
2 parents 8698c3d + fd53b40 commit 2306135

File tree

12 files changed

+131
-53
lines changed

12 files changed

+131
-53
lines changed

src/components/dialogs/network-modifications/generation-dispatch/generation-dispatch-dialog.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const GenerationDispatchDialog = ({
9191
editData,
9292
currentNode,
9393
studyUuid,
94+
currentRootNetworkUuid,
9495
isUpdate,
9596
editDataFetchStatus,
9697
...dialogProps
@@ -169,7 +170,11 @@ const GenerationDispatchDialog = ({
169170
isDataFetching={isUpdate && editDataFetchStatus === FetchStatus.RUNNING}
170171
{...dialogProps}
171172
>
172-
<GenerationDispatchForm />
173+
<GenerationDispatchForm
174+
currentNode={currentNode}
175+
studyUuid={studyUuid}
176+
currentRootNetworkUuid={currentRootNetworkUuid}
177+
/>
173178
</ModificationDialog>
174179
</CustomFormProvider>
175180
);

src/components/dialogs/network-modifications/generation-dispatch/generation-dispatch-form.jsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,33 @@ import { FormattedMessage } from 'react-intl';
2222
import SubstationsGeneratorsOrderingPane from './substations-generators-ordering-pane';
2323
import GridItem from '../../commons/grid-item';
2424
import GridSection from '../../commons/grid-section';
25+
import { useEffect, useState } from 'react';
26+
import { fetchEquipmentsIds } from '../../../../services/study/network-map';
27+
28+
const GenerationDispatchForm = ({ currentNode, studyUuid, currentRootNetworkUuid }) => {
29+
const currentNodeUuid = currentNode?.id;
30+
31+
const [substations, setSubstations] = useState([]);
2532

26-
const GenerationDispatchForm = () => {
2733
const handleCoefficientValueChange = (id, value) => {
2834
return formatPercentageValue(value);
2935
};
3036

37+
useEffect(() => {
38+
if (studyUuid && currentNodeUuid && currentRootNetworkUuid) {
39+
fetchEquipmentsIds(
40+
studyUuid,
41+
currentNodeUuid,
42+
currentRootNetworkUuid,
43+
undefined,
44+
EQUIPMENT_TYPES.SUBSTATION,
45+
true
46+
).then((values) => {
47+
setSubstations(values.sort((a, b) => a.localeCompare(b)));
48+
});
49+
}
50+
}, [studyUuid, currentNodeUuid, currentRootNetworkUuid]);
51+
3152
const lossCoefficientField = (
3253
<FloatInput
3354
name={LOSS_COEFFICIENT}
@@ -112,7 +133,7 @@ const GenerationDispatchForm = () => {
112133
</Grid>
113134
<GridSection title="GeneratorsOrdering" />
114135
<Grid container direction="column" spacing={2} alignItems="start">
115-
<SubstationsGeneratorsOrderingPane />
136+
<SubstationsGeneratorsOrderingPane substations={substations} />
116137
</Grid>
117138
</Box>
118139
);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
import { AutocompleteInputProps, genHelperError } from '@gridsuite/commons-ui';
8+
9+
import { useController } from 'react-hook-form';
10+
import { SyntheticEvent } from 'react';
11+
import { Autocomplete, AutocompleteProps, TextField, TextFieldProps, Theme } from '@mui/material';
12+
13+
const styles = {
14+
autocomplete: (theme: Theme) => ({
15+
'.MuiAutocomplete-inputRoot': {
16+
display: 'flex',
17+
alignItems: 'flex-start',
18+
justifyContent: 'flex-start',
19+
flexWrap: 'nowrap',
20+
padding: '1px',
21+
paddingLeft: '5px',
22+
},
23+
'.Mui-expanded, .Mui-focused, .Mui-focusVisible': {
24+
width: 'inherit',
25+
background: theme.palette.tabBackground,
26+
flexWrap: 'wrap',
27+
},
28+
}),
29+
};
30+
31+
type SubstationsAutocompleteProps = Pick<AutocompleteProps<string, true, false, false>, 'disabled'> & {
32+
name: AutocompleteInputProps['name'];
33+
label?: TextFieldProps['label'];
34+
disabled?: boolean;
35+
substations: string[];
36+
};
37+
38+
export default function SubstationsAutocomplete({
39+
name,
40+
label,
41+
disabled,
42+
substations,
43+
...props
44+
}: SubstationsAutocompleteProps) {
45+
const {
46+
field: { onChange, value, ref },
47+
fieldState: { error },
48+
} = useController({ name });
49+
50+
const handleChange = (_: SyntheticEvent, value: string[]) => {
51+
onChange(value);
52+
};
53+
54+
return (
55+
<Autocomplete
56+
multiple
57+
disabled={disabled}
58+
value={value}
59+
onChange={handleChange}
60+
options={substations}
61+
size={'small'}
62+
sx={styles.autocomplete}
63+
renderInput={({ inputProps, ...rest }) => (
64+
<TextField
65+
inputRef={ref}
66+
inputProps={{ ...inputProps }}
67+
label={label}
68+
{...genHelperError(error?.message)}
69+
{...rest}
70+
/>
71+
)}
72+
autoHighlight={true}
73+
disableCloseOnSelect={true}
74+
{...props}
75+
/>
76+
);
77+
}

src/components/dialogs/network-modifications/generation-dispatch/substations-generators-ordering-pane.jsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright (c) 2023, RTE (http://www.rte-france.com)
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -10,9 +10,11 @@ import { useIntl } from 'react-intl';
1010
import { useMemo } from 'react';
1111
import { useFieldArray } from 'react-hook-form';
1212
import { DndTable, DndColumnType } from '@gridsuite/commons-ui';
13+
import SubstationsAutocomplete from './substations-autocomplete.js';
1314

14-
const SubstationsGeneratorsOrderingPane = ({ id = SUBSTATIONS_GENERATORS_ORDERING }) => {
15+
const SubstationsGeneratorsOrderingPane = ({ substations }) => {
1516
const intl = useIntl();
17+
const id = SUBSTATIONS_GENERATORS_ORDERING;
1618

1719
const columnsDefinition = useMemo(() => {
1820
return [
@@ -21,7 +23,12 @@ const SubstationsGeneratorsOrderingPane = ({ id = SUBSTATIONS_GENERATORS_ORDERIN
2123
dataKey: SUBSTATION_IDS,
2224
initialValue: [],
2325
editable: true,
24-
type: DndColumnType.CHIP_ITEMS,
26+
type: DndColumnType.CUSTOM,
27+
component: (rowIndex) =>
28+
SubstationsAutocomplete({
29+
name: `${id}[${rowIndex}].${SUBSTATION_IDS}`,
30+
substations: substations,
31+
}),
2532
},
2633
].map((column) => ({
2734
...column,
@@ -30,7 +37,7 @@ const SubstationsGeneratorsOrderingPane = ({ id = SUBSTATIONS_GENERATORS_ORDERIN
3037
.toLowerCase()
3138
.replace(/^\w/, (c) => c.toUpperCase()),
3239
}));
33-
}, [intl]);
40+
}, [intl, substations, id]);
3441

3542
const useFieldArraySubstationsGeneratorsOrdering = useFieldArray({
3643
name: `${id}`,

src/components/graph/network-modification-tree-model.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -274,20 +274,4 @@ export default class NetworkModificationTreeModel {
274274
this.isAnyNodeBuilding =
275275
this.treeNodes.find((node) => node?.data?.globalBuildStatus === BUILD_STATUS.BUILDING) !== undefined;
276276
}
277-
278-
setCaseName(newCaseName: string) {
279-
if (this.treeNodes.length > 0 && this.treeNodes[0].data && newCaseName) {
280-
const nodeWithOldName = this.treeNodes[0];
281-
//check if the node we are modifying is a ROOT node
282-
if (isReactFlowRootNodeData(nodeWithOldName)) {
283-
this.treeNodes[0] = {
284-
...nodeWithOldName,
285-
data: {
286-
...nodeWithOldName.data,
287-
caseName: newCaseName,
288-
},
289-
};
290-
}
291-
}
292-
}
293277
}

src/components/graph/nodes/root-node.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ const styles = {
4242

4343
const RootNode = (props: NodeProps<RootNodeType>) => {
4444
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
45+
const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetworkUuid);
46+
const rootNetworks = useSelector((state: AppState) => state.rootNetworks);
47+
48+
const currentRootNetwork = rootNetworks.find(
49+
(rootNetwork) => rootNetwork.rootNetworkUuid === currentRootNetworkUuid
50+
);
51+
4552
const isSelectedNode = () => {
4653
return props.id === currentNode?.id;
4754
};
@@ -57,7 +64,7 @@ const RootNode = (props: NodeProps<RootNodeType>) => {
5764
}}
5865
isConnectable={false}
5966
/>
60-
<Tooltip title={props.data.caseName} placement="top" disableHoverListener={!props.data.caseName}>
67+
<Tooltip title={currentRootNetwork?.name} placement="top" disableHoverListener={!currentRootNetwork?.name}>
6168
<IconButton sx={isSelectedNode() ? styles.rootSelected : styles.root}>
6269
{(props.data.globalBuildStatus === BUILD_STATUS.BUILDING && <CircularProgress size={24} />) || (
6370
<PhotoIcon />

src/components/graph/tree-node.type.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export type NetworkModificationNodeData = AbstractNode & {
6565
nodeType?: NetworkModificationNodeType;
6666
};
6767

68-
type NodeCommonData = {
68+
export type NodeCommonData = {
6969
label: string;
7070
globalBuildStatus?: BUILD_STATUS;
7171
description?: string;
@@ -78,8 +78,7 @@ export type ModificationNode = Node<ReactFlowModificationNodeData, NodeType.NETW
7878
id: UUID;
7979
};
8080

81-
export type ReactFlowRootNodeData = NodeCommonData & { caseName?: string };
82-
export type RootNode = Node<ReactFlowRootNodeData, NodeType.ROOT> & { id: UUID };
81+
export type RootNode = Node<NodeCommonData, NodeType.ROOT> & { id: UUID };
8382

8483
export type CurrentTreeNode = ModificationNode | RootNode;
8584

src/components/graph/util/model-functions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import type NetworkModificationTreeModel from '../network-modification-tree-mode
1111
import {
1212
CurrentTreeNode,
1313
NetworkModificationNodeData,
14+
NodeCommonData,
1415
NodeType,
1516
ReactFlowModificationNodeData,
16-
ReactFlowRootNodeData,
1717
RootNodeData,
1818
} from '../tree-node.type';
1919

@@ -35,7 +35,7 @@ export function isRootNode(node: NetworkModificationNodeData | RootNodeData): no
3535
return node.type === NodeType.ROOT;
3636
}
3737

38-
function convertRootNodeToReactFlowModelNode(node: NetworkModificationNodeData | RootNodeData): ReactFlowRootNodeData {
38+
function convertRootNodeToReactFlowModelNode(node: NetworkModificationNodeData | RootNodeData): NodeCommonData {
3939
return {
4040
label: node.name,
4141
description: node.description ?? undefined,

src/components/study-container.jsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import NetworkModificationTreeModel from './graph/network-modification-tree-mode
3232
import { getFirstNodeOfType, isNodeBuilt, isNodeRenamed, isSameNode } from './graph/util/model-functions';
3333
import { BUILD_STATUS } from './network/constants';
3434
import { useAllComputingStatus } from './computing-status/use-all-computing-status';
35-
import { fetchCaseName } from '../services/study/index';
3635
import { fetchNetworkModificationTree } from '../services/study/tree-subtree';
3736
import { fetchNetworkExistence, fetchRootNetworkIndexationStatus } from '../services/study/network';
3837
import { fetchStudy, recreateStudyNetwork, reindexAllRootNetwork } from 'services/study/study';
@@ -293,19 +292,8 @@ export function StudyContainer({ view, onChangeTab }) {
293292
.then((tree) => {
294293
const networkModificationTreeModel = new NetworkModificationTreeModel();
295294
networkModificationTreeModel.setTreeElements(tree);
295+
dispatch(loadNetworkModificationTreeSuccess(networkModificationTreeModel));
296296

297-
fetchCaseName(studyUuid, currentRootNetworkUuid)
298-
.then((res) => {
299-
if (res) {
300-
networkModificationTreeModel.setCaseName(res);
301-
dispatch(loadNetworkModificationTreeSuccess(networkModificationTreeModel));
302-
}
303-
})
304-
.catch((err) => {
305-
snackWarning({
306-
headerId: 'CaseNameLoadError',
307-
});
308-
});
309297
// If a current node is already defined then override it cause it could have diferent status in different root networks
310298
if (currentNodeRef.current) {
311299
// Find the updated current node in the tree model
@@ -348,7 +336,7 @@ export function StudyContainer({ view, onChangeTab }) {
348336
.finally(() => console.debug('Network modification tree loading finished'));
349337
// Note: studyUuid and dispatch don't change
350338
},
351-
[studyUuid, currentRootNetworkUuid, dispatch, snackError, snackWarning]
339+
[studyUuid, currentRootNetworkUuid, dispatch, snackError]
352340
);
353341

354342
const checkRootNetworkIndexation = useCallback(() => {

src/services/study/index.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,6 @@ export function buildNode(studyUuid: UUID, currentNodeUuid: UUID, currentRootNet
295295
return backendFetchText(url, { method: 'post' });
296296
}
297297

298-
export function fetchCaseName(studyUuid: UUID, rootNetworkUuid: UUID) {
299-
console.info('Fetching case name');
300-
const url = getStudyUrl(studyUuid) + '/root-networks/' + encodeURIComponent(rootNetworkUuid) + '/case/name';
301-
console.debug(url);
302-
303-
return backendFetchText(url);
304-
}
305-
306298
export function isNodeExists(studyUuid: UUID, nodeName: string) {
307299
const existsNodeUrl =
308300
getStudyUrl(studyUuid) +

0 commit comments

Comments
 (0)