diff --git a/src/components/app-top-bar.jsx b/src/components/app-top-bar.jsx
index 245a024b3f..e77cfaf642 100644
--- a/src/components/app-top-bar.jsx
+++ b/src/components/app-top-bar.jsx
@@ -70,6 +70,7 @@ const AppTopBar = ({ user, tabIndex, onChangeTab, userManager }) => {
const theme = useSelector((state) => state[PARAM_THEME]);
const studyUuid = useSelector((state) => state.studyUuid);
const currentNode = useSelector((state) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state) => state.currentRootNetwork);
const [isDialogSearchOpen, setIsDialogSearchOpen] = useState(false);
const [appsAndUrls, setAppsAndUrls] = useState([]);
@@ -175,6 +176,7 @@ const AppTopBar = ({ user, tabIndex, onChangeTab, userManager }) => {
diff --git a/src/components/computing-status/use-all-computing-status.ts b/src/components/computing-status/use-all-computing-status.ts
index ceff069737..ca5387e013 100644
--- a/src/components/computing-status/use-all-computing-status.ts
+++ b/src/components/computing-status/use-all-computing-status.ts
@@ -60,7 +60,7 @@ const dynamicSimulationStatusCompletions = ['dynamicSimulationResult', 'dynamicS
const voltageInitStatusCompletions = ['voltageInitResult', 'voltageInit_failed'];
const stateEstimationStatusCompletions = ['stateEstimationResult', 'stateEstimation_failed'];
// this hook loads all current computation status into redux then keeps them up to date according to notifications
-export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): void => {
+export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID): void => {
const securityAnalysisAvailability = useOptionalServiceStatus(OptionalServicesNames.SecurityAnalysis);
const sensitivityAnalysisAvailability = useOptionalServiceStatus(OptionalServicesNames.SensitivityAnalysis);
const nonEvacuatedEnergyAvailability = useOptionalServiceStatus(OptionalServicesNames.SensitivityAnalysis);
@@ -72,6 +72,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchLoadFlowStatus,
loadFlowStatusInvalidations,
loadFlowStatusCompletions,
@@ -82,6 +83,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchSecurityAnalysisStatus,
securityAnalysisStatusInvalidations,
securityAnalysisStatusCompletions,
@@ -93,6 +95,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchSensitivityAnalysisStatus,
sensitivityAnalysisStatusInvalidations,
sensitivityAnalysisStatusCompletions,
@@ -104,6 +107,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchNonEvacuatedEnergyStatus,
nonEvacuatedEnergyStatusInvalidations,
nonEvacuatedEnergyStatusCompletions,
@@ -115,6 +119,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchShortCircuitAnalysisStatus,
shortCircuitAnalysisStatusInvalidations,
shortCircuitAnalysisStatusCompletions,
@@ -126,6 +131,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchOneBusShortCircuitAnalysisStatus,
oneBusShortCircuitAnalysisStatusInvalidations,
oneBusShortCircuitAnalysisStatusCompletions,
@@ -137,6 +143,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchDynamicSimulationStatus,
dynamicSimulationStatusInvalidations,
dynamicSimulationStatusCompletions,
@@ -148,6 +155,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchVoltageInitStatus,
voltageInitStatusInvalidations,
voltageInitStatusCompletions,
@@ -159,6 +167,7 @@ export const useAllComputingStatus = (studyUuid: UUID, currentNodeUuid: UUID): v
useComputingStatus(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
fetchStateEstimationStatus,
stateEstimationStatusInvalidations,
stateEstimationStatusCompletions,
diff --git a/src/components/computing-status/use-computing-status.ts b/src/components/computing-status/use-computing-status.ts
index 0c23d97e34..cf9207e1c3 100644
--- a/src/components/computing-status/use-computing-status.ts
+++ b/src/components/computing-status/use-computing-status.ts
@@ -20,7 +20,8 @@ interface UseComputingStatusProps {
(
studyUuid: UUID,
nodeUuid: UUID,
- fetcher: (studyUuid: UUID, nodeUuid: UUID) => Promise,
+ currentRootNetworkUuid: UUID,
+ fetcher: (studyUuid: UUID, nodeUuid: UUID, currentRootNetworkUuid: UUID) => Promise,
invalidations: string[],
completions: string[],
resultConversion: (x: string) => RunningStatus,
@@ -31,15 +32,17 @@ interface UseComputingStatusProps {
interface LastUpdateProps {
studyUpdatedForce: StudyUpdated;
- fetcher: (studyUuid: UUID, nodeUuid: UUID) => Promise;
+ fetcher: (studyUuid: UUID, nodeUuid: UUID, currentRootNetworkUuid: UUID) => Promise;
}
function isWorthUpdate(
studyUpdatedForce: StudyUpdated,
- fetcher: (studyUuid: UUID, nodeUuid: UUID) => Promise,
+ fetcher: (studyUuid: UUID, nodeUuid: UUID, currentRootNetworkUuid: UUID) => Promise,
lastUpdateRef: RefObject,
nodeUuidRef: RefObject,
+ rootNetworkUuidRef: RefObject,
nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
invalidations: string[]
): boolean {
const headers = studyUpdatedForce?.eventData?.headers;
@@ -49,6 +52,9 @@ function isWorthUpdate(
if (nodeUuidRef.current !== nodeUuid) {
return true;
}
+ if (rootNetworkUuidRef.current !== currentRootNetworkUuid) {
+ return true;
+ }
if (fetcher && lastUpdateRef.current?.fetcher !== fetcher) {
return true;
}
@@ -84,6 +90,7 @@ function isWorthUpdate(
export const useComputingStatus: UseComputingStatusProps = (
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
fetcher,
invalidations,
completions,
@@ -92,6 +99,8 @@ export const useComputingStatus: UseComputingStatusProps = (
optionalServiceAvailabilityStatus = OptionalServicesStatus.Up
) => {
const nodeUuidRef = useRef(null);
+ const rootNetworkUuidRef = useRef(null);
+
const studyUpdatedForce = useSelector((state: AppState) => state.studyUpdated);
const lastUpdateRef = useRef(null);
const dispatch = useDispatch();
@@ -114,9 +123,14 @@ export const useComputingStatus: UseComputingStatusProps = (
dispatch(setLastCompletedComputation());
nodeUuidRef.current = nodeUuid;
- fetcher(studyUuid, nodeUuid)
+ rootNetworkUuidRef.current = currentRootNetworkUuid;
+ fetcher(studyUuid, nodeUuid, currentRootNetworkUuid)
.then((res: string) => {
- if (!canceledRequest && nodeUuidRef.current === nodeUuid) {
+ if (
+ !canceledRequest &&
+ nodeUuidRef.current === nodeUuid &&
+ rootNetworkUuidRef.current === currentRootNetworkUuid
+ ) {
const status = resultConversion(res);
dispatch(setComputingStatus(computingType, status));
if (isComputationCompleted(status)) {
@@ -133,25 +147,49 @@ export const useComputingStatus: UseComputingStatusProps = (
return () => {
canceledRequest = true;
};
- }, [nodeUuid, fetcher, studyUuid, resultConversion, dispatch, computingType, isComputationCompleted]);
+ }, [
+ nodeUuid,
+ currentRootNetworkUuid,
+ fetcher,
+ studyUuid,
+ resultConversion,
+ dispatch,
+ computingType,
+ isComputationCompleted,
+ ]);
/* initial fetch and update */
useEffect(() => {
- if (!studyUuid || !nodeUuid || optionalServiceAvailabilityStatus !== OptionalServicesStatus.Up) {
+ if (
+ !studyUuid ||
+ !nodeUuid ||
+ !currentRootNetworkUuid ||
+ optionalServiceAvailabilityStatus !== OptionalServicesStatus.Up
+ ) {
return;
}
-
const isUpdateForUs = isWorthUpdate(
studyUpdatedForce,
fetcher,
lastUpdateRef,
nodeUuidRef,
+ rootNetworkUuidRef,
nodeUuid,
+ currentRootNetworkUuid,
invalidations
);
lastUpdateRef.current = { studyUpdatedForce, fetcher };
if (isUpdateForUs) {
update();
}
- }, [update, fetcher, nodeUuid, invalidations, studyUpdatedForce, studyUuid, optionalServiceAvailabilityStatus]);
+ }, [
+ update,
+ fetcher,
+ nodeUuid,
+ invalidations,
+ currentRootNetworkUuid,
+ studyUpdatedForce,
+ studyUuid,
+ optionalServiceAvailabilityStatus,
+ ]);
};
diff --git a/src/components/diagrams/diagram-pane.tsx b/src/components/diagrams/diagram-pane.tsx
index cc86db304b..cc32e58651 100644
--- a/src/components/diagrams/diagram-pane.tsx
+++ b/src/components/diagrams/diagram-pane.tsx
@@ -48,7 +48,7 @@ import { AppState, CurrentTreeNode, DiagramState } from 'redux/reducer';
import { SLDMetadata, DiagramMetadata } from '@powsybl/network-viewer';
// Returns a callback that returns a promise
-const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
+const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode, currentRootNetworkUuid: UUID) => {
const { snackError } = useSnackMessage();
const paramUseName = useSelector((state: AppState) => state[PARAM_USE_NAME]);
const { getNameOrId } = useNameOrId();
@@ -61,6 +61,7 @@ const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
? getVoltageLevelSingleLineDiagram({
studyUuid: studyUuid,
currentNodeUuid: currentNode?.id,
+ currentRootNetworkUuid: currentRootNetworkUuid,
voltageLevelId: voltageLevelId,
useName: paramUseName,
centerLabel: networkVisuParams.singleLineDiagramParameters.centerLabel,
@@ -73,6 +74,7 @@ const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
[
currentNode,
studyUuid,
+ currentRootNetworkUuid,
paramUseName,
networkVisuParams.singleLineDiagramParameters.centerLabel,
networkVisuParams.singleLineDiagramParameters.diagonalLabel,
@@ -87,6 +89,7 @@ const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
? getSubstationSingleLineDiagram({
studyUuid: studyUuid,
currentNodeUuid: currentNode?.id,
+ currentRootNetworkUuid: currentRootNetworkUuid,
substationId: voltageLevelId,
useName: paramUseName,
centerLabel: networkVisuParams.singleLineDiagramParameters.centerLabel,
@@ -104,6 +107,7 @@ const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
networkVisuParams.singleLineDiagramParameters.substationLayout,
paramUseName,
currentNode,
+ currentRootNetworkUuid,
language,
]
);
@@ -113,12 +117,18 @@ const useDisplayView = (studyUuid: UUID, currentNode: CurrentTreeNode) => {
? getNetworkAreaDiagramUrl(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
voltageLevelsIds,
depth,
networkVisuParams.networkAreaDiagramParameters.initNadWithGeoData
)
: null,
- [studyUuid, currentNode, networkVisuParams.networkAreaDiagramParameters.initNadWithGeoData]
+ [
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+ networkVisuParams.networkAreaDiagramParameters.initNadWithGeoData,
+ ]
);
// this callback returns a promise
@@ -305,6 +315,7 @@ const styles = {
interface DiagramPaneProps {
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
showInSpreadsheet: (equipment: { equipmentId: string | null; equipmentType: EquipmentType | null }) => void;
visible: boolean;
}
@@ -324,18 +335,25 @@ type DiagramView = {
depth?: number;
error?: string;
nodeId?: UUID;
+ rootNetworkId?: UUID;
additionalMetadata?: any;
fetchSvg?: () => Promise>;
};
-export function DiagramPane({ studyUuid, currentNode, showInSpreadsheet, visible }: DiagramPaneProps) {
+export function DiagramPane({
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+ showInSpreadsheet,
+ visible,
+}: DiagramPaneProps) {
const { snackError } = useSnackMessage();
const dispatch = useDispatch();
const intl = useIntl();
const studyUpdatedForce = useSelector((state: AppState) => state.studyUpdated);
const [views, setViews] = useState([]);
const fullScreenDiagram = useSelector((state: AppState) => state.fullScreenDiagram);
- const createView = useDisplayView(studyUuid, currentNode);
+ const createView = useDisplayView(studyUuid, currentNode, currentRootNetworkUuid);
const diagramStates = useSelector((state: AppState) => state.diagramStates);
const networkAreaDiagramDepth = useSelector((state: AppState) => state.networkAreaDiagramDepth);
const previousNetworkAreaDiagramDepth = useRef(networkAreaDiagramDepth);
@@ -354,7 +372,8 @@ export function DiagramPane({ studyUuid, currentNode, showInSpreadsheet, visible
const { openDiagramView, closeDiagramView, closeDiagramViews } = useDiagram();
const currentNodeRef = useRef();
currentNodeRef.current = currentNode;
-
+ const currentRootNetworkRef = useRef();
+ currentRootNetworkRef.current = currentRootNetworkUuid;
const viewsRef = useRef([]);
viewsRef.current = views;
/**
@@ -797,14 +816,23 @@ export function DiagramPane({ studyUuid, currentNode, showInSpreadsheet, visible
updateDiagramsByIds(allDiagramIds, true);
}, [currentNode, updateDiagramsByIds]);
+ // This effect will trigger the diagrams' forced update
// This effect will trigger the diagrams' forced update
useEffect(() => {
if (studyUpdatedForce.eventData.headers) {
+ if (
+ studyUpdatedForce.eventData.headers['rootNetwork'] !== currentRootNetworkRef.current &&
+ currentRootNetworkRef
+ ) {
+ return;
+ }
if (studyUpdatedForce.eventData.headers['updateType'] === 'loadflowResult') {
//TODO reload data more intelligently
+
updateDiagramsByCurrentNode();
} else if (studyUpdatedForce.eventData.headers['updateType'] === 'study') {
// FM if we want to reload data more precisely, we need more information from notifications
+
updateDiagramsByCurrentNode();
} else if (studyUpdatedForce.eventData.headers['updateType'] === 'buildCompleted') {
if (studyUpdatedForce.eventData.headers['node'] === currentNodeRef.current?.id) {
diff --git a/src/components/diagrams/singleLineDiagram/position-diagram-pane.tsx b/src/components/diagrams/singleLineDiagram/position-diagram-pane.tsx
index 3adfbfaa29..9e5e89b2b9 100644
--- a/src/components/diagrams/singleLineDiagram/position-diagram-pane.tsx
+++ b/src/components/diagrams/singleLineDiagram/position-diagram-pane.tsx
@@ -22,6 +22,7 @@ interface PositionDiagramPaneProps {
onClose: () => void;
voltageLevelId?: { id: UUID };
currentNodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
studyUuid: UUID;
}
@@ -30,6 +31,7 @@ const PositionDiagramPane: FC = ({
onClose,
voltageLevelId,
currentNodeUuid,
+ currentRootNetworkUuid,
studyUuid,
}) => {
const useName = useSelector((state: AppState) => state[PARAM_USE_NAME]);
@@ -47,6 +49,7 @@ const PositionDiagramPane: FC = ({
getVoltageLevelSingleLineDiagram({
studyUuid: studyUuid,
currentNodeUuid: currentNodeUuid,
+ currentRootNetworkUuid: currentRootNetworkUuid,
voltageLevelId: voltageLevelId?.id,
useName: useName,
centerLabel: networkVisuParams.singleLineDiagramParameters.centerLabel,
@@ -58,6 +61,7 @@ const PositionDiagramPane: FC = ({
[
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
voltageLevelId?.id,
useName,
networkVisuParams.singleLineDiagramParameters.centerLabel,
diff --git a/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx b/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx
index dd2a8b4d68..794b500aa5 100644
--- a/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx
+++ b/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx
@@ -127,6 +127,8 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
const diagramViewerRef = useRef();
const { snackError } = useSnackMessage();
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
+
const [modificationInProgress, setModificationInProgress] = useState(false);
const isAnyNodeBuilding = useIsAnyNodeBuilding();
const [locallySwitchedBreaker, setLocallySwitchedBreaker] = useState();
@@ -147,7 +149,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
isDiagramRunningOneBusShortcircuitAnalysis,
displayOneBusShortcircuitAnalysisLoader,
resetOneBusShortcircuitAnalysisLoader,
- ] = useOneBusShortcircuitAnalysisLoader(props.diagramId, currentNode?.id!);
+ ] = useOneBusShortcircuitAnalysisLoader(props.diagramId, currentNode?.id!, currentRootNetworkUuid!);
// dynamic simulation event configuration states
const [equipmentToConfigDynamicSimulationEvent, setEquipmentToConfigDynamicSimulationEvent] =
@@ -299,7 +301,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
dispatch(setComputingStatus(ComputingType.SHORT_CIRCUIT_ONE_BUS, RunningStatus.RUNNING));
displayOneBusShortcircuitAnalysisLoader();
dispatch(setComputationStarting(true));
- startShortCircuitAnalysis(studyUuid, currentNode?.id, busId)
+ startShortCircuitAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid, busId)
.catch((error) => {
snackError({
messageTxt: error.message,
@@ -319,6 +321,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
displayOneBusShortcircuitAnalysisLoader,
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
snackError,
resetOneBusShortcircuitAnalysisLoader,
]
@@ -349,6 +352,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
fetchNetworkElementInfos(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.HVDC_LINE,
EQUIPMENT_INFOS_TYPES.MAP.type,
equipmentId,
@@ -370,7 +374,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
});
}
},
- [studyUuid, currentNode?.id, snackError, handleOpenDeletionDialog, removeEquipment]
+ [studyUuid, currentNode?.id, currentRootNetworkUuid, snackError, handleOpenDeletionDialog, removeEquipment]
);
const handleOpenDynamicSimulationEventDialog = useCallback(
@@ -488,6 +492,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
defaultIdValue={equipmentToModify?.equipmentId}
isUpdate={true}
onClose={() => closeModificationDialog()}
@@ -505,6 +510,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) {
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
defaultIdValue={equipmentToDelete?.equipmentId}
isUpdate={true}
onClose={() => closeDeletionDialog()}
diff --git a/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx b/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx
index 6be3eba70e..fdc1485673 100644
--- a/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx
+++ b/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx
@@ -43,7 +43,11 @@ const styles = {
//the first function submits the sld data on hand to the redux store and the second function reset the redux store state
type oneBusShortcircuitAnalysisLoader = [ReactElement, boolean, () => void, () => void];
-export function useOneBusShortcircuitAnalysisLoader(diagramId: string, nodeId: UUID): oneBusShortcircuitAnalysisLoader {
+export function useOneBusShortcircuitAnalysisLoader(
+ diagramId: string,
+ nodeId: UUID,
+ rootNetworkUuid: UUID
+): oneBusShortcircuitAnalysisLoader {
const studyUpdatedForce = useSelector((state: AppState) => state.studyUpdated);
const oneBusShortCircuitAnalysisDiagram = useSelector((state: AppState) => state.oneBusShortCircuitAnalysisDiagram);
@@ -83,6 +87,9 @@ export function useOneBusShortcircuitAnalysisLoader(diagramId: string, nodeId: U
useEffect(() => {
if (studyUpdatedForce.eventData.headers) {
+ if (studyUpdatedForce.eventData.headers['rootNetwork'] !== rootNetworkUuid) {
+ return;
+ }
if (
studyUpdatedForce.eventData.headers['updateType'] === 'oneBusShortCircuitAnalysisResult' ||
studyUpdatedForce.eventData.headers['updateType'] === 'oneBusShortCircuitAnalysis_failed'
@@ -90,7 +97,7 @@ export function useOneBusShortcircuitAnalysisLoader(diagramId: string, nodeId: U
resetOneBusShortcircuitAnalysisLoader();
}
}
- }, [resetOneBusShortcircuitAnalysisLoader, studyUpdatedForce]);
+ }, [resetOneBusShortcircuitAnalysisLoader, studyUpdatedForce, rootNetworkUuid]);
return [
oneBusShortcircuitAnalysisLoaderMessage,
diff --git a/src/components/dialogs/case-list-selector.jsx b/src/components/dialogs/case-list-selector.jsx
new file mode 100644
index 0000000000..afc1e2abf3
--- /dev/null
+++ b/src/components/dialogs/case-list-selector.jsx
@@ -0,0 +1,233 @@
+/**
+ * Copyright (c) 2020, 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 { useCallback, useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+
+import { FormattedMessage, useIntl } from 'react-intl';
+import { PARAM_FAVORITE_CONTINGENCY_LISTS } from '../../utils/config-params';
+import { useSelector } from 'react-redux';
+import { ElementType } from '@gridsuite/commons-ui';
+import { useSnackMessage, CheckBoxList } from '@gridsuite/commons-ui';
+import { updateConfigParameter } from '../../services/config';
+import { fetchContingencyAndFiltersLists } from '../../services/directory';
+import { fetchContingencyCount } from '../../services/study';
+import { DirectoryItemSelector } from '@gridsuite/commons-ui';
+import { isNodeBuilt } from 'components/graph/util/model-functions';
+import DeleteIcon from '@mui/icons-material/Delete';
+import IconButton from '@mui/material/IconButton';
+import { toggleElementFromList } from 'components/utils/utils';
+import { Grid, DialogActions, Button, DialogTitle, Typography, Dialog, DialogContent, Alert } from '@mui/material';
+
+function makeButton(onClick, message, disabled) {
+ return (
+
+
+
+ );
+}
+
+const CaseListSelector = (props) => {
+ const favoriteContingencyListUuids = useSelector((state) => state[PARAM_FAVORITE_CONTINGENCY_LISTS]);
+
+ const currentNode = useSelector((state) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state) => state.currentRootNetwork);
+
+ const [contingencyList, setContingencyList] = useState([]);
+
+ const [simulatedContingencyCount, setSimulatedContingencyCount] = useState(0);
+
+ const [checkedContingencyList, setCheckedContingencyList] = useState([]);
+
+ const [favoriteSelectorOpen, setFavoriteSelectorOpen] = useState(false);
+
+ const { snackError } = useSnackMessage();
+
+ const intl = useIntl();
+
+ const handleClose = () => {
+ props.onClose();
+ };
+
+ const handleStart = () => {
+ props.onStart(checkedContingencyList.map((c) => c.id));
+ };
+
+ const saveFavorites = useCallback(
+ (newList) => {
+ updateConfigParameter(PARAM_FAVORITE_CONTINGENCY_LISTS, newList)
+ .then()
+ .catch((error) => {
+ snackError({
+ messageTxt: error.message,
+ headerId: 'paramsChangingError',
+ });
+ });
+ },
+ [snackError]
+ );
+
+ useEffect(() => {
+ setSimulatedContingencyCount(null);
+ var discardResult = false;
+ if (isNodeBuilt(currentNode) && props.open) {
+ fetchContingencyCount(
+ props.studyUuid,
+ currentNode.id,
+ currentRootNetworkUuid,
+ checkedContingencyList.map((c) => c.id)
+ ).then((contingencyCount) => {
+ if (!discardResult) {
+ setSimulatedContingencyCount(contingencyCount);
+ }
+ });
+ }
+ return () => {
+ discardResult = true;
+ };
+ }, [props.open, props.studyUuid, currentNode, currentRootNetworkUuid, checkedContingencyList]);
+
+ useEffect(() => {
+ if (favoriteContingencyListUuids && favoriteContingencyListUuids.length > 0 && props.open) {
+ fetchContingencyAndFiltersLists(favoriteContingencyListUuids)
+ .then((res) => {
+ const mapCont = res.reduce((map, obj) => {
+ map[obj.elementUuid] = {
+ id: obj.elementUuid,
+ type: obj.type,
+ name: obj.elementName,
+ };
+ return map;
+ }, {});
+ setContingencyList(
+ favoriteContingencyListUuids
+ .map((id) => mapCont[id])
+ .filter((item) => item !== undefined)
+ .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
+ );
+ })
+ .catch(() => {
+ snackError({
+ headerId: 'getContingencyListError',
+ });
+ });
+ } else {
+ setContingencyList([]);
+ }
+ }, [favoriteContingencyListUuids, snackError, props.open]);
+
+ function getSimulatedContingencyCountLabel() {
+ return simulatedContingencyCount != null ? simulatedContingencyCount : '...';
+ }
+
+ const handleAddFavorite = () => {
+ setFavoriteSelectorOpen(true);
+ };
+
+ const removeFromFavorites = useCallback(
+ (toRemove) => {
+ const toRemoveIdsSet = new Set(toRemove.map((e) => e.id));
+ saveFavorites(contingencyList.map((e) => e.id).filter((id) => !toRemoveIdsSet.has(id)));
+
+ setCheckedContingencyList((oldChecked) => oldChecked.filter((item) => !toRemoveIdsSet.has(item.id)));
+ },
+ [contingencyList, saveFavorites]
+ );
+
+ const addFavorites = (favorites) => {
+ if (favorites && favorites.length > 0) {
+ // avoid duplicates here
+ const newFavoriteIdsSet = new Set([...favoriteContingencyListUuids, ...favorites.map((item) => item.id)]);
+ saveFavorites(Array.from([...newFavoriteIdsSet]));
+ }
+ setFavoriteSelectorOpen(false);
+ };
+
+ const handleSecondaryAction = useCallback(
+ (item, isItemHovered) =>
+ isItemHovered && (
+ {
+ e.stopPropagation();
+ removeFromFavorites([item]);
+ }}
+ size={'small'}
+ >
+
+
+ ),
+ [removeFromFavorites]
+ );
+
+ return (
+ <>
+
+
+ >
+ );
+};
+
+CaseListSelector.propTypes = {
+ open: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ onStart: PropTypes.func.isRequired,
+ studyUuid: PropTypes.string,
+ currentNodeUuid: PropTypes.string,
+};
+
+export default CaseListSelector;
diff --git a/src/components/dialogs/connectivity/branch-connectivity-form.tsx b/src/components/dialogs/connectivity/branch-connectivity-form.tsx
index 2bad50dd8b..15ea1de722 100644
--- a/src/components/dialogs/connectivity/branch-connectivity-form.tsx
+++ b/src/components/dialogs/connectivity/branch-connectivity-form.tsx
@@ -18,6 +18,7 @@ import GridItem from '../commons/grid-item';
interface BranchConnectivityFormProps {
currentNode: CurrentTreeNode;
studyUuid: UUID;
+ currentRootNetworkUuid: UUID;
isModification?: boolean;
previousValues?: any;
}
@@ -25,10 +26,11 @@ interface BranchConnectivityFormProps {
const BranchConnectivityForm: FunctionComponent = ({
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isModification = false,
previousValues,
}) => {
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id, currentRootNetworkUuid);
const id1 = `${CONNECTIVITY}.${CONNECTIVITY_1}`;
const id2 = `${CONNECTIVITY}.${CONNECTIVITY_2}`;
@@ -37,6 +39,7 @@ const BranchConnectivityForm: FunctionComponent = (
id={id1}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
voltageLevelOptions={voltageLevelOptions}
withPosition={true}
isEquipmentModification={isModification}
@@ -52,6 +55,7 @@ const BranchConnectivityForm: FunctionComponent = (
id={id2}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
voltageLevelOptions={voltageLevelOptions}
withPosition={true}
isEquipmentModification={isModification}
diff --git a/src/components/dialogs/connectivity/connectivity-form.jsx b/src/components/dialogs/connectivity/connectivity-form.jsx
index ae8683e5ae..0008c8f60c 100644
--- a/src/components/dialogs/connectivity/connectivity-form.jsx
+++ b/src/components/dialogs/connectivity/connectivity-form.jsx
@@ -57,6 +57,7 @@ export const ConnectivityForm = ({
newBusOrBusbarSectionOptions = [],
studyUuid,
currentNode,
+ currentRootNetworkUuid,
onVoltageLevelChangeCallback = undefined,
isEquipmentModification = false,
previousValues,
@@ -79,16 +80,28 @@ export const ConnectivityForm = ({
return;
}
if (watchVoltageLevelId) {
- fetchBusesOrBusbarSectionsForVoltageLevel(studyUuid, currentNodeUuid, watchVoltageLevelId).then(
- (busesOrbusbarSections) => {
- setBusOrBusbarSectionOptions(busesOrbusbarSections);
- }
- );
+ fetchBusesOrBusbarSectionsForVoltageLevel(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ watchVoltageLevelId
+ ).then((busesOrbusbarSections) => {
+ setBusOrBusbarSectionOptions(busesOrbusbarSections);
+ });
} else {
setBusOrBusbarSectionOptions([]);
setValue(`${id}.${BUS_OR_BUSBAR_SECTION}`, null);
}
- }, [watchVoltageLevelId, studyUuid, currentNodeUuid, voltageLevelOptions, setValue, id, isEquipmentModification]);
+ }, [
+ watchVoltageLevelId,
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ voltageLevelOptions,
+ setValue,
+ id,
+ isEquipmentModification,
+ ]);
useEffect(() => {
if (isEquipmentModification) {
@@ -295,6 +308,7 @@ export const ConnectivityForm = ({
onClose={handleCloseDiagramPane}
voltageLevelId={{ id: watchVoltageLevelId }}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
>
);
diff --git a/src/components/dialogs/contingency-list-selector.jsx b/src/components/dialogs/contingency-list-selector.jsx
index 2f8b2bf0f1..425089bd47 100644
--- a/src/components/dialogs/contingency-list-selector.jsx
+++ b/src/components/dialogs/contingency-list-selector.jsx
@@ -38,6 +38,7 @@ const ContingencyListSelector = (props) => {
const favoriteContingencyListUuids = useSelector((state) => state[PARAM_FAVORITE_CONTINGENCY_LISTS]);
const currentNode = useSelector((state) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state) => state.currentRootNetwork);
const [contingencyList, setContingencyList] = useState([]);
@@ -80,6 +81,7 @@ const ContingencyListSelector = (props) => {
fetchContingencyCount(
props.studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
checkedContingencyList.map((c) => c.id)
).then((contingencyCount) => {
if (!discardResult) {
@@ -90,7 +92,7 @@ const ContingencyListSelector = (props) => {
return () => {
discardResult = true;
};
- }, [props.open, props.studyUuid, currentNode, checkedContingencyList]);
+ }, [props.open, props.studyUuid, currentNode, checkedContingencyList, currentRootNetworkUuid]);
useEffect(() => {
if (favoriteContingencyListUuids && favoriteContingencyListUuids.length > 0 && props.open) {
diff --git a/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx b/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx
index cfb3921a52..b5ea5e4f95 100644
--- a/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx
+++ b/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx
@@ -38,6 +38,7 @@ export const DynamicSimulationEventDialog = (props: DynamicSimulationEventDialog
const { snackError } = useSnackMessage();
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const currentNodeId = currentNode?.id;
const [dataFetchStatus, setDataFetchStatus] = useState(FetchStatus.IDLE);
const [event, setEvent] = useState();
@@ -86,15 +87,15 @@ export const DynamicSimulationEventDialog = (props: DynamicSimulationEventDialog
// load event for equipment
useEffect(() => {
- if (!studyUuid || !currentNodeId) {
+ if (!studyUuid || !currentNodeId || !currentRootNetworkUuid) {
return;
}
setDataFetchStatus(FetchStatus.RUNNING);
- fetchDynamicSimulationEvent(studyUuid, currentNodeId, equipmentId).then((event) => {
+ fetchDynamicSimulationEvent(studyUuid, currentNodeId, currentRootNetworkUuid, equipmentId).then((event) => {
setDataFetchStatus(FetchStatus.SUCCEED);
setEvent(event);
});
- }, [currentNodeId, equipmentId, studyUuid, reset]);
+ }, [currentNodeId, equipmentId, currentRootNetworkUuid, studyUuid, reset]);
// reset form data when event available after fetch
useEffect(() => {
@@ -117,7 +118,7 @@ export const DynamicSimulationEventDialog = (props: DynamicSimulationEventDialog
// submit form
const handleSubmit = useCallback(
(formObj: { [KEY in EventPropertyName]: any }) => {
- if (!studyUuid || !currentNodeId) {
+ if (!studyUuid || !currentNodeId || !currentRootNetworkUuid) {
return;
}
// formObj to EventProperty[]
@@ -160,14 +161,24 @@ export const DynamicSimulationEventDialog = (props: DynamicSimulationEventDialog
properties,
};
- saveDynamicSimulationEvent(studyUuid, currentNodeId, submitEvent).catch((error) => {
+ saveDynamicSimulationEvent(studyUuid, currentNodeId, currentRootNetworkUuid, submitEvent).catch((error) => {
snackError({
messageTxt: error.message,
headerId: 'DynamicSimulationEventSaveError',
});
});
},
- [currentNodeId, equipmentId, equipmentType, snackError, studyUuid, eventType, event, eventDefinition]
+ [
+ currentNodeId,
+ equipmentId,
+ currentRootNetworkUuid,
+ equipmentType,
+ snackError,
+ studyUuid,
+ eventType,
+ event,
+ eventDefinition,
+ ]
);
const waitingOpen = useOpenShortWaitFetching({
diff --git a/src/components/dialogs/equipment-id/equipment-id-selector.jsx b/src/components/dialogs/equipment-id/equipment-id-selector.jsx
index b05e5e86e0..0f3b38de91 100644
--- a/src/components/dialogs/equipment-id/equipment-id-selector.jsx
+++ b/src/components/dialogs/equipment-id/equipment-id-selector.jsx
@@ -29,6 +29,7 @@ const styles = {
export const EquipmentIdSelector = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
defaultValue,
setSelectedId,
equipmentType,
@@ -43,10 +44,12 @@ export const EquipmentIdSelector = ({
const [selectedValue, setSelectedValue] = useState(null);
useEffect(() => {
- fetchEquipmentsIds(studyUuid, currentNodeUuid, undefined, equipmentType, true).then((values) => {
- setEquipmentOptions(values.sort((a, b) => a.localeCompare(b)));
- });
- }, [studyUuid, currentNodeUuid, equipmentType]);
+ fetchEquipmentsIds(studyUuid, currentNodeUuid, currentRootNetworkUuid, undefined, equipmentType, true).then(
+ (values) => {
+ setEquipmentOptions(values.sort((a, b) => a.localeCompare(b)));
+ }
+ );
+ }, [studyUuid, currentNodeUuid, currentRootNetworkUuid, equipmentType]);
// We go through this effect to force a rerender and display the loading icon.
useEffect(() => {
diff --git a/src/components/dialogs/equipment-search-dialog.tsx b/src/components/dialogs/equipment-search-dialog.tsx
index e4b8785693..b2cd924ce1 100644
--- a/src/components/dialogs/equipment-search-dialog.tsx
+++ b/src/components/dialogs/equipment-search-dialog.tsx
@@ -27,6 +27,7 @@ interface EquipmentSearchDialogProps {
onSelectionChange: (equipment: EquipmentInfos) => void;
equipmentType: EquipmentType;
currentNodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
}
/**
@@ -36,6 +37,7 @@ interface EquipmentSearchDialogProps {
* @param {Function} onSelectionChange: callback when the selection changes
* @param {String} equipmentType: the type of equipment we want to search
* @param {String} currentNodeUuid: the node selected
+ * @param {String} currentRootNetworkUuid: the root network UUID
*/
const EquipmentSearchDialog: FC = ({
open,
@@ -43,6 +45,7 @@ const EquipmentSearchDialog: FC = ({
onSelectionChange,
equipmentType,
currentNodeUuid,
+ currentRootNetworkUuid,
}) => {
const intl = useIntl();
const studyUuid = useSelector((state: AppState) => state.studyUuid);
@@ -50,6 +53,7 @@ const EquipmentSearchDialog: FC = ({
// @ts-expect-error TODO: manage null case
studyUuid: studyUuid,
nodeUuid: currentNodeUuid,
+ currentRootNetworkUuid: currentRootNetworkUuid,
inUpstreamBuiltParentNode: true,
equipmentType: equipmentType,
});
diff --git a/src/components/dialogs/export-dialog.jsx b/src/components/dialogs/export-dialog.jsx
index ad04428fc0..0f58990a4c 100644
--- a/src/components/dialogs/export-dialog.jsx
+++ b/src/components/dialogs/export-dialog.jsx
@@ -47,7 +47,7 @@ const STRING_LIST = 'STRING_LIST';
* @param {String} title Title of the dialog
*/
-const ExportDialog = ({ open, onClose, onClick, studyUuid, nodeUuid, title }) => {
+const ExportDialog = ({ open, onClose, onClick, studyUuid, nodeUuid, rootNetworkUuid, title }) => {
const [formatsWithParameters, setFormatsWithParameters] = useState([]);
const [selectedFormat, setSelectedFormat] = useState('');
const [loading, setLoading] = useState(false);
@@ -122,7 +122,7 @@ const ExportDialog = ({ open, onClose, onClick, studyUuid, nodeUuid, title }) =>
}, []);
const handleExportClick = () => {
if (selectedFormat) {
- const downloadUrl = getExportUrl(studyUuid, nodeUuid, selectedFormat);
+ const downloadUrl = getExportUrl(studyUuid, nodeUuid, rootNetworkUuid, selectedFormat);
let suffix;
const urlSearchParams = new URLSearchParams();
if (Object.keys(currentParameters).length > 0) {
@@ -245,6 +245,7 @@ ExportDialog.propTypes = {
onClick: PropTypes.func.isRequired,
studyUuid: PropTypes.string,
nodeUuid: PropTypes.string,
+ rootNetworkUuid: PropTypes.string,
title: PropTypes.string.isRequired,
};
diff --git a/src/components/dialogs/form-search-copy-hook.js b/src/components/dialogs/form-search-copy-hook.js
index 9c41e7cff6..7f7a911a15 100644
--- a/src/components/dialogs/form-search-copy-hook.js
+++ b/src/components/dialogs/form-search-copy-hook.js
@@ -11,7 +11,14 @@ import { useSnackMessage } from '@gridsuite/commons-ui';
import { EQUIPMENT_INFOS_TYPES } from '../utils/equipment-types';
import { fetchNetworkElementInfos } from '../../services/study/network';
-export const useFormSearchCopy = ({ studyUuid, currentNodeUuid, toFormValues, setFormValues, elementType }) => {
+export const useFormSearchCopy = ({
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ toFormValues,
+ setFormValues,
+ elementType,
+}) => {
const intl = useIntl();
const { snackInfo, snackError } = useSnackMessage();
@@ -23,6 +30,7 @@ export const useFormSearchCopy = ({ studyUuid, currentNodeUuid, toFormValues, se
const fetchElementPromise = fetchNetworkElementInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
elementType,
EQUIPMENT_INFOS_TYPES.FORM.type,
element.id,
diff --git a/src/components/dialogs/import-case-dialog.tsx b/src/components/dialogs/import-case-dialog.tsx
new file mode 100644
index 0000000000..0c2949231c
--- /dev/null
+++ b/src/components/dialogs/import-case-dialog.tsx
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2024, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import { useIntl } from 'react-intl';
+import { ElementType, DirectoryItemSelector, TreeViewFinderNodeProps } from '@gridsuite/commons-ui';
+import { FunctionComponent } from 'react';
+
+interface ImportCaseDialogProps {
+ open: boolean;
+ onClose: () => void;
+ onSelectCase: (selectedElement: TreeViewFinderNodeProps) => void;
+}
+
+const ImportCaseDialog: FunctionComponent = ({ open, onClose, onSelectCase }) => {
+ const intl = useIntl();
+
+ const processSelectedElements = (selectedElements: TreeViewFinderNodeProps[]) => {
+ if (selectedElements && selectedElements.length > 0) {
+ const selectedCase = selectedElements[0]; // Assuming single selection
+ onSelectCase(selectedCase);
+ }
+ onClose();
+ };
+
+ return (
+
+ );
+};
+
+export default ImportCaseDialog;
diff --git a/src/components/dialogs/network-modifications/battery/creation/battery-creation-dialog.jsx b/src/components/dialogs/network-modifications/battery/creation/battery-creation-dialog.jsx
index d1cf5d35a1..340ce8abf7 100644
--- a/src/components/dialogs/network-modifications/battery/creation/battery-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/battery/creation/battery-creation-dialog.jsx
@@ -93,7 +93,15 @@ const formSchema = yup
.concat(creationPropertiesSchema)
.required();
-const BatteryCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, editDataFetchStatus, ...dialogProps }) => {
+const BatteryCreationDialog = ({
+ editData,
+ currentNode,
+ studyUuid,
+ currentRootNetworkUuid,
+ isUpdate,
+ editDataFetchStatus,
+ ...dialogProps
+}) => {
const currentNodeUuid = currentNode.id;
const { snackError } = useSnackMessage();
@@ -135,6 +143,7 @@ const BatteryCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, edi
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.BATTERY,
@@ -235,7 +244,11 @@ const BatteryCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, edi
isDataFetching={isUpdate && editDataFetchStatus === FetchStatus.RUNNING}
{...dialogProps}
>
-
+
@@ -253,6 +267,7 @@ BatteryCreationDialog.propTypes = {
editData: PropTypes.object,
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
+ currentRootNetworkUuid: PropTypes.string,
isUpdate: PropTypes.bool,
editDataFetchStatus: PropTypes.string,
};
diff --git a/src/components/dialogs/network-modifications/battery/creation/battery-creation-form.jsx b/src/components/dialogs/network-modifications/battery/creation/battery-creation-form.jsx
index ea4b5456e9..1095b1473b 100644
--- a/src/components/dialogs/network-modifications/battery/creation/battery-creation-form.jsx
+++ b/src/components/dialogs/network-modifications/battery/creation/battery-creation-form.jsx
@@ -24,8 +24,8 @@ import useVoltageLevelsListInfos from '../../../../../hooks/use-voltage-levels-l
import GridItem from '../../../commons/grid-item';
import GridSection from '../../../commons/grid-section';
-const BatteryCreationForm = ({ studyUuid, currentNode }) => {
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id);
+const BatteryCreationForm = ({ studyUuid, currentNode, currentRootNetworkUuid }) => {
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id, currentRootNetworkUuid);
const batteryIdField = (
@@ -39,6 +39,7 @@ const BatteryCreationForm = ({ studyUuid, currentNode }) => {
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
);
diff --git a/src/components/dialogs/network-modifications/battery/modification/battery-modification-dialog.jsx b/src/components/dialogs/network-modifications/battery/modification/battery-modification-dialog.jsx
index ff73c17176..2d900b99d8 100644
--- a/src/components/dialogs/network-modifications/battery/modification/battery-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/battery/modification/battery-modification-dialog.jsx
@@ -110,6 +110,7 @@ const BatteryModificationDialog = ({
editData,
defaultIdValue,
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -199,6 +200,7 @@ const BatteryModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.BATTERY,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -245,7 +247,7 @@ const BatteryModificationDialog = ({
setBatteryToModify(null);
}
},
- [studyUuid, currentNode, getValues, setValue, setValuesAndEmptyOthers, reset, editData]
+ [studyUuid, currentNode, currentRootNetworkUuid, getValues, setValue, setValuesAndEmptyOthers, reset, editData]
);
useEffect(() => {
@@ -323,6 +325,7 @@ const BatteryModificationDialog = ({
diff --git a/src/components/dialogs/network-modifications/delete-attaching-line/delete-attaching-line-form.jsx b/src/components/dialogs/network-modifications/delete-attaching-line/delete-attaching-line-form.jsx
index faab7acd59..426ac10a35 100644
--- a/src/components/dialogs/network-modifications/delete-attaching-line/delete-attaching-line-form.jsx
+++ b/src/components/dialogs/network-modifications/delete-attaching-line/delete-attaching-line-form.jsx
@@ -20,20 +20,22 @@ import { fetchEquipmentsIds } from '../../../../services/study/network-map';
import GridSection from '../../commons/grid-section';
import GridItem from '../../commons/grid-item';
-const DeleteAttachingLineForm = ({ studyUuid, currentNode }) => {
+const DeleteAttachingLineForm = ({ studyUuid, currentNode, currentRootNetworkUuid }) => {
const [linesOptions, setLinesOptions] = useState([]);
useEffect(() => {
- fetchEquipmentsIds(studyUuid, currentNode.id, undefined, 'LINE', true).then((values) => {
- setLinesOptions(
- values
- .sort((a, b) => a.localeCompare(b))
- .map((value) => {
- return { id: value };
- })
- );
- });
- }, [studyUuid, currentNode?.id]);
+ fetchEquipmentsIds(studyUuid, currentNode.id, currentRootNetworkUuid, undefined, 'LINE', true).then(
+ (values) => {
+ setLinesOptions(
+ values
+ .sort((a, b) => a.localeCompare(b))
+ .map((value) => {
+ return { id: value };
+ })
+ );
+ }
+ );
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid]);
const lineToAttachTo1Field = (
-
+
);
@@ -144,6 +150,7 @@ const EquipmentDeletionDialog = ({
EquipmentDeletionDialog.propTypes = {
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
+ currentRootNetworkUuid: PropTypes.string,
editData: PropTypes.object,
isUpdate: PropTypes.bool,
defaultIdValue: PropTypes.string,
diff --git a/src/components/dialogs/network-modifications/equipment-deletion/equipment-deletion-form.jsx b/src/components/dialogs/network-modifications/equipment-deletion/equipment-deletion-form.jsx
index 78dda4deaa..162818b4e2 100644
--- a/src/components/dialogs/network-modifications/equipment-deletion/equipment-deletion-form.jsx
+++ b/src/components/dialogs/network-modifications/equipment-deletion/equipment-deletion-form.jsx
@@ -25,7 +25,7 @@ import { fetchEquipmentsIds } from '../../../../services/study/network-map';
import useGetLabelEquipmentTypes from '../../../../hooks/use-get-label-equipment-types';
import GridItem from '../../commons/grid-item';
-const DeleteEquipmentForm = ({ studyUuid, currentNode, editData }) => {
+const DeleteEquipmentForm = ({ studyUuid, currentNode, currentRootNetworkUuid, editData }) => {
const { snackError } = useSnackMessage();
const editedIdRef = useRef(null);
const currentTypeRef = useRef(null);
@@ -66,7 +66,7 @@ const DeleteEquipmentForm = ({ studyUuid, currentNode, editData }) => {
currentTypeRef.current = watchType;
}
let ignore = false;
- fetchEquipmentsIds(studyUuid, currentNode?.id, undefined, watchType, true)
+ fetchEquipmentsIds(studyUuid, currentNode?.id, currentRootNetworkUuid, undefined, watchType, true)
.then((vals) => {
// check race condition here
if (!ignore) {
@@ -83,10 +83,10 @@ const DeleteEquipmentForm = ({ studyUuid, currentNode, editData }) => {
ignore = true;
};
}
- }, [studyUuid, currentNode?.id, watchType, snackError]);
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid, watchType, snackError]);
useEffect(() => {
- if (studyUuid && currentNode?.id) {
+ if (studyUuid && currentNode?.id && currentRootNetworkUuid) {
if (editData?.equipmentId) {
if (editedIdRef.current === null) {
// The first time we render an edition, we want to merge the
@@ -104,6 +104,7 @@ const DeleteEquipmentForm = ({ studyUuid, currentNode, editData }) => {
hvdcLccSpecificUpdate(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
watchEquipmentId,
watchEquipmentId === editedIdRef.current ? editData : null
);
@@ -111,7 +112,16 @@ const DeleteEquipmentForm = ({ studyUuid, currentNode, editData }) => {
setValue(DELETION_SPECIFIC_DATA, null);
}
}
- }, [studyUuid, currentNode?.id, watchEquipmentId, snackError, setValue, hvdcLccSpecificUpdate, editData]);
+ }, [
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ watchEquipmentId,
+ snackError,
+ setValue,
+ hvdcLccSpecificUpdate,
+ editData,
+ ]);
const handleChange = useCallback(() => {
setValue(EQUIPMENT_ID, null);
diff --git a/src/components/dialogs/network-modifications/equipment-deletion/hvdc-lcc-deletion/hvdc-lcc-deletion-utils.js b/src/components/dialogs/network-modifications/equipment-deletion/hvdc-lcc-deletion/hvdc-lcc-deletion-utils.js
index 3837004c80..fdc1975186 100644
--- a/src/components/dialogs/network-modifications/equipment-deletion/hvdc-lcc-deletion/hvdc-lcc-deletion-utils.js
+++ b/src/components/dialogs/network-modifications/equipment-deletion/hvdc-lcc-deletion/hvdc-lcc-deletion-utils.js
@@ -78,8 +78,8 @@ const useHvdcLccDeletion = () => {
);
const specificUpdate = useCallback(
- (studyUuid, nodeId, equipmentId, editData) => {
- fetchHvdcLineWithShuntCompensators(studyUuid, nodeId, equipmentId)
+ (studyUuid, nodeId, currentRootNetworkUuid, equipmentId, editData) => {
+ fetchHvdcLineWithShuntCompensators(studyUuid, nodeId, currentRootNetworkUuid, equipmentId)
.then((hvdcLineData) => {
updateMcsLists(hvdcLineData, editData);
})
diff --git a/src/components/dialogs/network-modifications/generator/creation/generator-creation-dialog.jsx b/src/components/dialogs/network-modifications/generator/creation/generator-creation-dialog.jsx
index da967689ed..dee749311d 100644
--- a/src/components/dialogs/network-modifications/generator/creation/generator-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/generator/creation/generator-creation-dialog.jsx
@@ -127,6 +127,7 @@ const GeneratorCreationDialog = ({
editData,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -193,6 +194,7 @@ const GeneratorCreationDialog = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.GENERATOR,
@@ -336,6 +338,7 @@ const GeneratorCreationDialog = ({
equipmentType={'GENERATOR'}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
diff --git a/src/components/dialogs/network-modifications/generator/creation/generator-creation-form.jsx b/src/components/dialogs/network-modifications/generator/creation/generator-creation-form.jsx
index 2b85c99e1a..d636544778 100644
--- a/src/components/dialogs/network-modifications/generator/creation/generator-creation-form.jsx
+++ b/src/components/dialogs/network-modifications/generator/creation/generator-creation-form.jsx
@@ -37,9 +37,9 @@ import useVoltageLevelsListInfos from '../../../../../hooks/use-voltage-levels-l
import GridItem from '../../../commons/grid-item';
import GridSection from '../../../commons/grid-section';
-const GeneratorCreationForm = ({ studyUuid, currentNode }) => {
+const GeneratorCreationForm = ({ studyUuid, currentNode, currentRootNetworkUuid }) => {
const currentNodeUuid = currentNode?.id;
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid, currentRootNetworkUuid);
const generatorIdField = (
@@ -65,6 +65,7 @@ const GeneratorCreationForm = ({ studyUuid, currentNode }) => {
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
);
@@ -132,6 +133,7 @@ const GeneratorCreationForm = ({ studyUuid, currentNode }) => {
diff --git a/src/components/dialogs/network-modifications/generator/modification/generator-modification-dialog.jsx b/src/components/dialogs/network-modifications/generator/modification/generator-modification-dialog.jsx
index da501f240f..06486408ca 100644
--- a/src/components/dialogs/network-modifications/generator/modification/generator-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/generator/modification/generator-modification-dialog.jsx
@@ -135,6 +135,7 @@ const GeneratorModificationDialog = ({
editData, // contains data when we try to edit an existing hypothesis from the current node's list
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the SLD
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -242,6 +243,7 @@ const GeneratorModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.GENERATOR,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -284,7 +286,7 @@ const GeneratorModificationDialog = ({
setGeneratorToModify(null);
}
},
- [studyUuid, currentNode, reset, getValues, setValue, setValuesAndEmptyOthers, editData]
+ [studyUuid, currentNode, currentRootNetworkUuid, reset, getValues, setValue, setValuesAndEmptyOthers, editData]
);
useEffect(() => {
@@ -391,6 +393,7 @@ const GeneratorModificationDialog = ({
{
const currentNodeUuid = currentNode?.id;
const intl = useIntl();
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid, currentRootNetworkUuid);
const energySourceLabelId = getEnergySourceLabel(generatorToModify?.energySource);
const previousEnergySourceLabel = energySourceLabelId
@@ -181,6 +182,7 @@ const GeneratorModificationForm = ({
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
isEquipmentModification={true}
previousValues={generatorToModify}
/>
@@ -232,6 +234,7 @@ const GeneratorModificationForm = ({
{
- if (studyUuid && currentNode.id) {
- fetchVoltageLevelsListInfos(studyUuid, currentNode.id)
+ if (studyUuid && currentNode.id && currentRootNetworkUuid) {
+ fetchVoltageLevelsListInfos(studyUuid, currentNode.id, currentRootNetworkUuid)
.then((values) => {
setVoltageLevelOptions(values.sort((a, b) => a.id.localeCompare(b.id)));
})
@@ -89,7 +90,7 @@ const RegulatingTerminalModificationDialog = ({
console.error('Error fetching voltage levels: ', error);
});
}
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const onSubmit = useCallback(
(voltageRegulationGenerator) => {
@@ -125,6 +126,7 @@ const RegulatingTerminalModificationDialog = ({
voltageLevelOptions={voltageLevelOptions}
equipmentSectionTypeDefaultValue={''}
currentNodeUuid={currentNode.id}
+ currentRootNetworkUuid={currentRootNetworkUuid}
studyUuid={studyUuid}
previousRegulatingTerminalValue={previousData?.regulatingTerminalVlId}
previousEquipmentSectionTypeValue={getTapChangerEquipmentSectionTypeValue(previousData)}
@@ -161,6 +163,7 @@ RegulatingTerminalModificationDialog.propTypes = {
data: PropTypes.object,
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
+ currentRootNetworkUuid: PropTypes.string,
onModifyRegulatingTerminalGenerator: PropTypes.func,
};
diff --git a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-converter-station.tsx b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-converter-station.tsx
index 8776060cf9..1d0c3fe1da 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-converter-station.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-converter-station.tsx
@@ -211,6 +211,7 @@ interface LccConverterStationProps {
id: string;
stationLabel: string;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
studyUuid: UUID;
}
@@ -219,8 +220,9 @@ export default function LccConverterStation({
stationLabel,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
}: Readonly) {
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id, currentRootNetworkUuid);
const stationIdField = ;
@@ -233,6 +235,7 @@ export default function LccConverterStation({
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
previousValues={undefined}
/>
);
diff --git a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-dialog.tsx b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-dialog.tsx
index 3ab63a1239..75463ba9d3 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-dialog.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-dialog.tsx
@@ -114,6 +114,7 @@ export interface LccCreationDialogProps extends Partial {
editData: LccCreationInfos;
currentNode: CurrentTreeNode;
studyUuid: UUID;
+ currentRootNetworkUuid: UUID;
isUpdate: boolean;
editDataFetchStatus: FetchStatus;
}
@@ -122,6 +123,7 @@ export function LccCreationDialog({
editData,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -159,6 +161,7 @@ export function LccCreationDialog({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: fromSearchCopyToFormValues,
setFormValues: (data: LccCreationSchemaForm) => {
reset(data, { keepDefaultValues: true });
@@ -267,13 +270,19 @@ export function LccCreationDialog({
}}
{...dialogProps}
>
-
+
diff --git a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-form.tsx b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-form.tsx
index c15b9074f3..3e2a84e55f 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-form.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/lcc/creation/lcc-creation-form.tsx
@@ -16,8 +16,14 @@ interface LccCreationFormProps {
tabIndex: number;
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
}
-export default function LccCreationForm({ tabIndex, studyUuid, currentNode }: Readonly) {
+export default function LccCreationForm({
+ tabIndex,
+ studyUuid,
+ currentRootNetworkUuid,
+ currentNode,
+}: Readonly) {
return (
<>
@@ -27,6 +33,7 @@ export default function LccCreationForm({ tabIndex, studyUuid, currentNode }: Re
@@ -35,6 +42,7 @@ export default function LccCreationForm({ tabIndex, studyUuid, currentNode }: Re
diff --git a/src/components/dialogs/network-modifications/hvdc-line/vsc/converter-station/converter-station-pane.tsx b/src/components/dialogs/network-modifications/hvdc-line/vsc/converter-station/converter-station-pane.tsx
index 069b988c18..a43e8b3e19 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/vsc/converter-station/converter-station-pane.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/vsc/converter-station/converter-station-pane.tsx
@@ -40,6 +40,7 @@ interface VscConverterStationPaneProps {
stationLabel: string;
currentNode: CurrentTreeNode;
studyUuid: UUID;
+ currentRootNetworkUuid: UUID;
isModification?: boolean;
previousValues?: ConverterStationElementModificationInfos | null;
updatePreviousReactiveCapabilityCurveTableConverterStation?: UpdateReactiveCapabilityCurveTable;
@@ -50,6 +51,7 @@ const ConverterStationPane: FunctionComponent = ({
stationLabel,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isModification = false,
previousValues,
updatePreviousReactiveCapabilityCurveTableConverterStation,
@@ -68,7 +70,7 @@ const ConverterStationPane: FunctionComponent = ({
}
});
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id, currentRootNetworkUuid);
const generatorIdField = isModification ? (
= ({
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
isEquipmentModification={isModification}
previousValues={previousValues}
/>
diff --git a/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-dialog.jsx b/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-dialog.jsx
index dbbcd3be6f..10c6bc079f 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-dialog.jsx
@@ -86,7 +86,15 @@ export const VSC_CREATION_TABS = {
CONVERTER_STATION_2: 2,
};
-const VscCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, editDataFetchStatus, ...dialogProps }) => {
+const VscCreationDialog = ({
+ editData,
+ currentNode,
+ studyUuid,
+ currentRootNetworkUuid,
+ isUpdate,
+ editDataFetchStatus,
+ ...dialogProps
+}) => {
const currentNodeUuid = currentNode.id;
const { snackError } = useSnackMessage();
const [tabIndex, setTabIndex] = useState(VSC_CREATION_TABS.HVDC_LINE_TAB);
@@ -131,6 +139,7 @@ const VscCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, editDat
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.HVDC_LINE,
@@ -260,6 +269,7 @@ const VscCreationDialog = ({ editData, currentNode, studyUuid, isUpdate, editDat
equipmentType={EQUIPMENT_TYPES.HVDC_LINE}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
diff --git a/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-form.tsx b/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-form.tsx
index 8d5c231fa3..2299023524 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-form.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/vsc/creation/vsc-creation-form.tsx
@@ -17,9 +17,15 @@ import { Box } from '@mui/material';
interface VscCreationFormProps {
tabIndex: number;
studyUuid: UUID;
+ currentRootNetworkUuid: UUID;
currentNode: CurrentTreeNode;
}
-const VscCreationForm: FunctionComponent = ({ tabIndex, studyUuid, currentNode }) => {
+const VscCreationForm: FunctionComponent = ({
+ tabIndex,
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+}) => {
return (
<>
@@ -29,6 +35,7 @@ const VscCreationForm: FunctionComponent = ({ tabIndex, st
@@ -37,6 +44,7 @@ const VscCreationForm: FunctionComponent = ({ tabIndex, st
diff --git a/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-dialog.tsx b/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-dialog.tsx
index 7e315958e3..c619407d2c 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-dialog.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-dialog.tsx
@@ -101,6 +101,7 @@ const VscModificationDialog: React.FC = ({
editData,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -162,6 +163,7 @@ const VscModificationDialog: React.FC = ({
fetchNetworkElementInfos(
studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.HVDC_LINE,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -233,7 +235,16 @@ const VscModificationDialog: React.FC = ({
});
}
},
- [setValuesAndEmptyOthers, studyUuid, currentNode, setValue, reset, getValues, editData?.equipmentId]
+ [
+ setValuesAndEmptyOthers,
+ currentRootNetworkUuid,
+ studyUuid,
+ currentNode,
+ setValue,
+ reset,
+ getValues,
+ editData?.equipmentId,
+ ]
);
useEffect(() => {
@@ -341,6 +352,7 @@ const VscModificationDialog: React.FC = ({
studyUuid={studyUuid}
currentNode={currentNode}
defaultValue={equipmentId}
+ currentRootNetworkUuid={currentRootNetworkUuid}
setSelectedId={setEquipmentId}
equipmentType={EQUIPMENT_TYPES.HVDC_LINE}
fillerHeight={17}
@@ -351,6 +363,7 @@ const VscModificationDialog: React.FC = ({
tabIndex={tabIndex}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
equipmentId={equipmentId}
setTabIndex={setTabIndex}
vscToModify={vscToModify}
diff --git a/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-from.tsx b/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-from.tsx
index 15d9591c25..5d59e50e58 100644
--- a/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-from.tsx
+++ b/src/components/dialogs/network-modifications/hvdc-line/vsc/modification/vsc-modification-from.tsx
@@ -28,6 +28,7 @@ interface VscModificationFormProps {
tabIndex: number;
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
equipmentId: string;
vscToModify: VscModificationInfo | null;
setTabIndex: React.Dispatch>;
@@ -40,6 +41,7 @@ export const VscModificationForm: FunctionComponent =
setTabIndex,
studyUuid,
currentNode,
+ currentRootNetworkUuid,
equipmentId,
vscToModify,
tabIndexesWithError,
@@ -95,6 +97,7 @@ export const VscModificationForm: FunctionComponent =
=
);
@@ -160,6 +162,7 @@ const LineAttachToVoltageLevelForm = ({
onClose={onVoltageLevelDialogClose}
currentNode={currentNode}
studyUuid={studyUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
onCreateVoltageLevel={onVoltageLevelCreationDo}
editData={isVoltageLevelEdit ? voltageLevelToEdit : null}
/>
@@ -170,6 +173,7 @@ const LineAttachToVoltageLevelForm = ({
onClose={onLineDialogClose}
currentNode={currentNode}
studyUuid={studyUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
displayConnectivity={false}
onCreateLine={onLineCreationDo}
editData={lineToEdit}
diff --git a/src/components/dialogs/network-modifications/line-split-with-voltage-level/line-split-with-voltage-level-form.jsx b/src/components/dialogs/network-modifications/line-split-with-voltage-level/line-split-with-voltage-level-form.jsx
index 4058b750b4..74cbbb2de9 100644
--- a/src/components/dialogs/network-modifications/line-split-with-voltage-level/line-split-with-voltage-level-form.jsx
+++ b/src/components/dialogs/network-modifications/line-split-with-voltage-level/line-split-with-voltage-level-form.jsx
@@ -24,6 +24,7 @@ import GridItem from '../../commons/grid-item';
const LineSplitWithVoltageLevelForm = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
onVoltageLevelCreationDo,
voltageLevelToEdit,
allVoltageLevelOptions,
@@ -43,7 +44,12 @@ const LineSplitWithVoltageLevelForm = ({
};
const lineToSplitForm = (
-
+
);
const newLine1IdField = ;
@@ -71,6 +77,7 @@ const LineSplitWithVoltageLevelForm = ({
newBusOrBusbarSectionOptions={busbarSectionOptions}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
);
@@ -110,6 +117,7 @@ const LineSplitWithVoltageLevelForm = ({
onClose={onVoltageLevelDialogClose}
currentNode={currentNode}
studyUuid={studyUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
onCreateVoltageLevel={onVoltageLevelCreationDo}
editData={isVoltageLevelEdit ? voltageLevelToEdit : null}
/>
diff --git a/src/components/dialogs/network-modifications/line-to-attach-or-split-form/line-to-attach-or-split-form.jsx b/src/components/dialogs/network-modifications/line-to-attach-or-split-form/line-to-attach-or-split-form.jsx
index e69c421f78..6905fa43a4 100644
--- a/src/components/dialogs/network-modifications/line-to-attach-or-split-form/line-to-attach-or-split-form.jsx
+++ b/src/components/dialogs/network-modifications/line-to-attach-or-split-form/line-to-attach-or-split-form.jsx
@@ -17,7 +17,7 @@ import { EQUIPMENT_TYPES } from '../../../utils/equipment-types';
import { fetchEquipmentsIds } from '../../../../services/study/network-map';
import GridItem from '../../commons/grid-item';
-export const LineToAttachOrSplitForm = ({ label, studyUuid, currentNode }) => {
+export const LineToAttachOrSplitForm = ({ label, studyUuid, currentNode, currentRootNetworkUuid }) => {
const [line1Substation, setLine1Substation] = useState('');
const [line2Substation, setLine2Substation] = useState('');
const [linesOptions, setLinesOptions] = useState([]);
@@ -27,8 +27,15 @@ export const LineToAttachOrSplitForm = ({ label, studyUuid, currentNode }) => {
});
useEffect(() => {
- if (studyUuid && currentNode?.id) {
- fetchEquipmentsIds(studyUuid, currentNode?.id, undefined, EQUIPMENT_TYPES.LINE, true)
+ if (studyUuid && currentNode?.id && currentRootNetworkUuid) {
+ fetchEquipmentsIds(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ undefined,
+ EQUIPMENT_TYPES.LINE,
+ true
+ )
.then((values) => {
setLinesOptions(values.sort());
})
@@ -39,7 +46,7 @@ export const LineToAttachOrSplitForm = ({ label, studyUuid, currentNode }) => {
});
});
}
- }, [studyUuid, currentNode?.id, watchLineToAttachOrSplit, snackError]);
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid, watchLineToAttachOrSplit, snackError]);
useEffect(() => {
const lineToAttachOrSplit = linesOptions.find((l) => l?.id === watchLineToAttachOrSplit);
diff --git a/src/components/dialogs/network-modifications/line/characteristics-pane/line-characteristics-pane.jsx b/src/components/dialogs/network-modifications/line/characteristics-pane/line-characteristics-pane.jsx
index b4a8e3faf7..38309a5ab5 100644
--- a/src/components/dialogs/network-modifications/line/characteristics-pane/line-characteristics-pane.jsx
+++ b/src/components/dialogs/network-modifications/line/characteristics-pane/line-characteristics-pane.jsx
@@ -37,13 +37,14 @@ const LineCharacteristicsPane = ({
id = CHARACTERISTICS,
studyUuid,
currentNode,
+ currentRootNetworkUuid,
displayConnectivity,
lineToModify,
clearableFields = false,
isModification = false,
}) => {
const currentNodeUuid = currentNode.id;
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid, currentRootNetworkUuid);
const seriesResistanceField = (
@@ -120,6 +122,7 @@ const LineCharacteristicsPane = ({
id={`${id}.${CONNECTIVITY_2}`}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
voltageLevelOptions={voltageLevelOptions}
withPosition={true}
/>
diff --git a/src/components/dialogs/network-modifications/line/creation/line-creation-dialog.jsx b/src/components/dialogs/network-modifications/line/creation/line-creation-dialog.jsx
index 14f013adb4..452f5d4b43 100644
--- a/src/components/dialogs/network-modifications/line/creation/line-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/line/creation/line-creation-dialog.jsx
@@ -104,6 +104,7 @@ const LineCreationDialog = ({
editData,
studyUuid,
currentNode,
+ currentRootNetworkUuid,
onCreateLine = createLine,
displayConnectivity = true,
isUpdate,
@@ -246,6 +247,7 @@ const LineCreationDialog = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.LINE,
@@ -420,6 +422,7 @@ const LineCreationDialog = ({
equipmentType={EQUIPMENT_TYPES.LINE}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
{
+const LineModificationDialogTabs = ({ studyUuid, currentNode, currentRootNetworkUuid, lineToModify, tabIndex }) => {
return (
<>
{
@@ -426,6 +438,7 @@ const LineModificationDialog = ({
{
+const LinesAttachToSplitLinesForm = ({ currentNode, studyUuid, currentRootNetworkUuid }) => {
const currentNodeUuid = currentNode?.id;
const [linesIds, setLinesIds] = useState([]);
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid, currentRootNetworkUuid);
useEffect(() => {
- fetchEquipmentsIds(studyUuid, currentNodeUuid, undefined, 'LINE', true).then((values) => {
- setLinesIds(values?.sort((a, b) => a.localeCompare(b)));
- });
- }, [studyUuid, currentNodeUuid]);
+ fetchEquipmentsIds(studyUuid, currentNodeUuid, currentRootNetworkUuid, undefined, 'LINE', true).then(
+ (values) => {
+ setLinesIds(values?.sort((a, b) => a.localeCompare(b)));
+ }
+ );
+ }, [studyUuid, currentNodeUuid, currentRootNetworkUuid]);
const lineToAttachTo1Field = (
{
voltageLevelOptions={voltageLevelOptions}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
withDirectionsInfos={false}
/>
);
diff --git a/src/components/dialogs/network-modifications/load/creation/load-creation-dialog.tsx b/src/components/dialogs/network-modifications/load/creation/load-creation-dialog.tsx
index fc333d25bb..7347fad699 100644
--- a/src/components/dialogs/network-modifications/load/creation/load-creation-dialog.tsx
+++ b/src/components/dialogs/network-modifications/load/creation/load-creation-dialog.tsx
@@ -75,6 +75,7 @@ export interface LoadCreationDialogProps extends Partial {
editData: LoadCreationInfos;
currentNode: CurrentTreeNode;
studyUuid: UUID;
+ currentRootNetworkUuid: UUID;
isUpdate: boolean;
editDataFetchStatus: FetchStatus;
disabledSave: boolean;
@@ -84,6 +85,7 @@ export function LoadCreationDialog({
editData,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -144,6 +146,7 @@ export function LoadCreationDialog({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: fromSearchCopyToFormValues,
setFormValues: (data: LoadCreationSchemaForm) => {
reset(data, { keepDefaultValues: true });
@@ -209,14 +212,18 @@ export function LoadCreationDialog({
isDataFetching={isUpdate && editDataFetchStatus === FetchStatus.RUNNING}
{...dialogProps}
>
-
-
+
diff --git a/src/components/dialogs/network-modifications/load/creation/load-creation-form.tsx b/src/components/dialogs/network-modifications/load/creation/load-creation-form.tsx
index 2607e5ecf8..15e4fac368 100644
--- a/src/components/dialogs/network-modifications/load/creation/load-creation-form.tsx
+++ b/src/components/dialogs/network-modifications/load/creation/load-creation-form.tsx
@@ -22,10 +22,15 @@ import GridSection from '../../../commons/grid-section';
export interface LoadCreationFormProps {
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
}
-export default function LoadCreationForm({ studyUuid, currentNode }: Readonly) {
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id);
+export default function LoadCreationForm({
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+}: Readonly) {
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id, currentRootNetworkUuid);
const loadIdField = (
@@ -54,6 +59,7 @@ export default function LoadCreationForm({ studyUuid, currentNode }: Readonly
);
diff --git a/src/components/dialogs/network-modifications/load/modification/load-modification-dialog.jsx b/src/components/dialogs/network-modifications/load/modification/load-modification-dialog.jsx
index 16857fb6b1..f378c9231c 100644
--- a/src/components/dialogs/network-modifications/load/modification/load-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/load/modification/load-modification-dialog.jsx
@@ -84,6 +84,7 @@ const LoadModificationDialog = ({
editData, // contains data when we try to edit an existing hypothesis from the current node's list
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the SLD
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -143,6 +144,7 @@ const LoadModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.LOAD,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -169,7 +171,7 @@ const LoadModificationDialog = ({
});
}
},
- [studyUuid, currentNodeUuid, reset, getValues, setValue, editData]
+ [studyUuid, currentRootNetworkUuid, currentNodeUuid, reset, getValues, setValue, editData]
);
useEffect(() => {
@@ -238,6 +240,7 @@ const LoadModificationDialog = ({
{
+const LoadModificationForm = ({ studyUuid, currentNode, currentRootNetworkUuid, loadToModify, equipmentId }) => {
const intl = useIntl();
const loadIdField = (
@@ -86,6 +86,7 @@ const LoadModificationForm = ({ studyUuid, currentNode, loadToModify, equipmentI
withPosition={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
isEquipmentModification={true}
previousValues={loadToModify}
/>
diff --git a/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-dialog.jsx b/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-dialog.jsx
index 6f44c848bc..4509c90e36 100644
--- a/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-dialog.jsx
@@ -88,6 +88,7 @@ const formSchema = yup
const ShuntCompensatorCreationDialog = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
editData,
isUpdate,
editDataFetchStatus,
@@ -162,6 +163,8 @@ const ShuntCompensatorCreationDialog = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
+
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.SHUNT_COMPENSATOR,
@@ -243,6 +246,7 @@ const ShuntCompensatorCreationDialog = ({
equipmentType={EQUIPMENT_TYPES.SHUNT_COMPENSATOR}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
@@ -258,6 +262,7 @@ ShuntCompensatorCreationDialog.propTypes = {
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
isUpdate: PropTypes.bool,
+ currentRootNetworkUuid: PropTypes.string,
editDataFetchStatus: PropTypes.string,
};
diff --git a/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-form.jsx b/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-form.jsx
index d97ea38150..d81762ad5c 100644
--- a/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-form.jsx
+++ b/src/components/dialogs/network-modifications/shunt-compensator/creation/shunt-compensator-creation-form.jsx
@@ -19,16 +19,16 @@ import PropertiesForm from '../../common/properties/properties-form';
import GridItem from '../../../commons/grid-item';
import GridSection from '../../../commons/grid-section';
-const ShuntCompensatorCreationForm = ({ studyUuid, currentNode }) => {
+const ShuntCompensatorCreationForm = ({ studyUuid, currentNode, currentRootNetworkUuid }) => {
const [voltageLevelOptions, setVoltageLevelOptions] = useState([]);
useEffect(() => {
- if (studyUuid && currentNode?.id) {
- fetchVoltageLevelsListInfos(studyUuid, currentNode.id).then((values) => {
+ if (studyUuid && currentNode?.id && currentRootNetworkUuid) {
+ fetchVoltageLevelsListInfos(studyUuid, currentNode.id, currentRootNetworkUuid).then((values) => {
setVoltageLevelOptions(values.sort((a, b) => a?.id?.localeCompare(b?.id)));
});
}
- }, [studyUuid, currentNode?.id]);
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid]);
const shuntCompensatorIdField = (
@@ -42,6 +42,7 @@ const ShuntCompensatorCreationForm = ({ studyUuid, currentNode }) => {
voltageLevelOptions={voltageLevelOptions}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
);
diff --git a/src/components/dialogs/network-modifications/shunt-compensator/modification/shunt-compensator-modification-dialog.jsx b/src/components/dialogs/network-modifications/shunt-compensator/modification/shunt-compensator-modification-dialog.jsx
index 0e405a8fb8..728ad271ec 100644
--- a/src/components/dialogs/network-modifications/shunt-compensator/modification/shunt-compensator-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/shunt-compensator/modification/shunt-compensator-modification-dialog.jsx
@@ -78,6 +78,7 @@ const ShuntCompensatorModificationDialog = ({
editData, // contains data when we try to edit an existing hypothesis from the current node's list
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the network map
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -164,6 +165,7 @@ const ShuntCompensatorModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.SHUNT_COMPENSATOR,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -207,7 +209,7 @@ const ShuntCompensatorModificationDialog = ({
setShuntCompensatorInfos(null);
}
},
- [currentNode.id, snackError, studyUuid, reset, getValues, setValue, editData]
+ [currentNode.id, currentRootNetworkUuid, snackError, studyUuid, reset, getValues, setValue, editData]
);
useEffect(() => {
@@ -281,6 +283,7 @@ const ShuntCompensatorModificationDialog = ({
{
+const ShuntCompensatorModificationForm = ({
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+ shuntCompensatorInfos,
+ equipmentId,
+}) => {
const shuntCompensatorIdField = (
diff --git a/src/components/dialogs/network-modifications/static-var-compensator/creation/set-points-limits-form.tsx b/src/components/dialogs/network-modifications/static-var-compensator/creation/set-points-limits-form.tsx
index 730e3f1bd3..ece0eceaae 100644
--- a/src/components/dialogs/network-modifications/static-var-compensator/creation/set-points-limits-form.tsx
+++ b/src/components/dialogs/network-modifications/static-var-compensator/creation/set-points-limits-form.tsx
@@ -35,11 +35,13 @@ import GridItem from '../../../commons/grid-item';
export interface SetPointsLimitsFormProps {
studyUuid: UUID;
currentNode: { id: UUID };
+ currentRootNetworkUuid: UUID;
voltageLevelOptions: any;
}
export const SetPointsLimitsForm: FunctionComponent = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
voltageLevelOptions,
}) => {
const id = SETPOINTS_LIMITS;
@@ -89,6 +91,7 @@ export const SetPointsLimitsForm: FunctionComponent =
disabled={false}
studyUuid={studyUuid}
currentNodeUuid={currentNode.id}
+ currentRootNetworkUuid={currentRootNetworkUuid}
voltageLevelOptions={voltageLevelOptions}
equipmentSectionTypeDefaultValue={EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR}
previousRegulatingTerminalValue={undefined}
diff --git a/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-dialog.tsx b/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-dialog.tsx
index 4068c85658..f1e60b5307 100644
--- a/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-dialog.tsx
+++ b/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-dialog.tsx
@@ -162,6 +162,7 @@ const formSchema = yup
const StaticVarCompensatorCreationDialog: FC = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
editData,
isUpdate,
editDataFetchStatus,
@@ -286,6 +287,8 @@ const StaticVarCompensatorCreationDialog: FC = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
+
toFormValues: (data: StaticVarCompensatorCreationSchemaForm) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR,
@@ -463,13 +466,19 @@ const StaticVarCompensatorCreationDialog: FC = ({
}}
{...dialogProps}
>
-
+
diff --git a/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-form.tsx b/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-form.tsx
index a029ed153a..70fb1e9d5a 100644
--- a/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-form.tsx
+++ b/src/components/dialogs/network-modifications/static-var-compensator/creation/static-var-compensator-creation-form.tsx
@@ -20,21 +20,24 @@ import GridItem from '../../../commons/grid-item';
export interface StaticVarCompensatorCreationFormProps {
studyUuid: UUID;
currentNode: { id: UUID };
+ currentRootNetworkUuid: UUID;
tabIndex: number;
}
const StaticVarCompensatorCreationForm: FunctionComponent = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
tabIndex,
}) => {
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode.id, currentRootNetworkUuid);
const connectivityForm = (
);
@@ -50,6 +53,7 @@ const StaticVarCompensatorCreationForm: FunctionComponent
diff --git a/src/components/dialogs/network-modifications/substation/creation/substation-creation-dialog.jsx b/src/components/dialogs/network-modifications/substation/creation/substation-creation-dialog.jsx
index 8a9eda91bc..3c3d5317ae 100644
--- a/src/components/dialogs/network-modifications/substation/creation/substation-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/substation/creation/substation-creation-dialog.jsx
@@ -49,6 +49,7 @@ const SubstationCreationDialog = ({
editData,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -78,6 +79,7 @@ const SubstationCreationDialog = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.SUBSTATION,
@@ -158,6 +160,7 @@ const SubstationCreationDialog = ({
equipmentType={EQUIPMENT_TYPES.SUBSTATION}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
diff --git a/src/components/dialogs/network-modifications/substation/modification/substation-modification-dialog.jsx b/src/components/dialogs/network-modifications/substation/modification/substation-modification-dialog.jsx
index e3b220e43c..942aec28fc 100644
--- a/src/components/dialogs/network-modifications/substation/modification/substation-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/substation/modification/substation-modification-dialog.jsx
@@ -57,6 +57,7 @@ const SubstationModificationDialog = ({
editData, // contains data when we try to edit an existing hypothesis from the current node's list
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the network map
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -101,6 +102,7 @@ const SubstationModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.SUBSTATION,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -125,7 +127,7 @@ const SubstationModificationDialog = ({
});
}
},
- [studyUuid, currentNodeUuid, reset, getValues, editData]
+ [studyUuid, currentRootNetworkUuid, currentNodeUuid, reset, getValues, editData]
);
useEffect(() => {
@@ -183,6 +185,7 @@ const SubstationModificationDialog = ({
{
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNode?.id, currentRootNetworkUuid);
const connectivity1Field = (
@@ -47,6 +49,7 @@ const TwoWindingsTransformerCreationCharacteristicsPane = ({
id={`${id}.${CONNECTIVITY_2}`}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
voltageLevelOptions={voltageLevelOptions}
withPosition={true}
/>
@@ -81,6 +84,7 @@ const TwoWindingsTransformerCreationCharacteristicsPane = ({
@@ -89,6 +93,7 @@ const TwoWindingsTransformerCreationCharacteristicsPane = ({
diff --git a/src/components/dialogs/network-modifications/two-windings-transformer/creation/two-windings-transformer-creation-dialog.jsx b/src/components/dialogs/network-modifications/two-windings-transformer/creation/two-windings-transformer-creation-dialog.jsx
index e59cd0ba9d..0172505323 100644
--- a/src/components/dialogs/network-modifications/two-windings-transformer/creation/two-windings-transformer-creation-dialog.jsx
+++ b/src/components/dialogs/network-modifications/two-windings-transformer/creation/two-windings-transformer-creation-dialog.jsx
@@ -152,6 +152,7 @@ const TwoWindingsTransformerCreationDialog = ({
editData,
studyUuid,
currentNode,
+ currentRootNetworkUuid,
isUpdate,
editDataFetchStatus,
...dialogProps
@@ -403,6 +404,7 @@ const TwoWindingsTransformerCreationDialog = ({
const searchCopy = useFormSearchCopy({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
toFormValues: (data) => data,
setFormValues: fromSearchCopyToFormValues,
elementType: EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER,
@@ -673,6 +675,7 @@ const TwoWindingsTransformerCreationDialog = ({
equipmentType={EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER}
onSelectionChange={searchCopy.handleSelectionChange}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
/>
@@ -683,6 +686,8 @@ TwoWindingsTransformerCreationDialog.propTypes = {
editData: PropTypes.object,
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
+ currentRootNetworkUuid: PropTypes.string,
+
isUpdate: PropTypes.bool,
editDataFetchStatus: PropTypes.string,
};
diff --git a/src/components/dialogs/network-modifications/two-windings-transformer/modification/two-windings-transformer-modification-dialog.jsx b/src/components/dialogs/network-modifications/two-windings-transformer/modification/two-windings-transformer-modification-dialog.jsx
index 50b554707d..335174232a 100644
--- a/src/components/dialogs/network-modifications/two-windings-transformer/modification/two-windings-transformer-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/two-windings-transformer/modification/two-windings-transformer-modification-dialog.jsx
@@ -162,6 +162,7 @@ export const TwoWindingsTransformerModificationDialogTab = {
* @param studyUuid the study we are currently working on
* @param defaultIdValue the default two windings transformer id
* @param currentNode The node we are currently working on
+ * @param currentRootNetworkUuid The current root network uuid we are currently working on
* @param isUpdate check if edition form
* @param editData the data to edit
* @param editDataFetchStatus indicates the status of fetching EditData
@@ -171,6 +172,7 @@ const TwoWindingsTransformerModificationDialog = ({
studyUuid,
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the SLD
currentNode,
+ currentRootNetworkUuid,
isUpdate,
editData, // contains data when we try to edit an existing hypothesis from the current node's list
editDataFetchStatus,
@@ -189,7 +191,7 @@ const TwoWindingsTransformerModificationDialog = ({
resolver: yupResolver(formSchema),
});
const { reset, getValues, setValue } = formMethods;
- const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid);
+ const voltageLevelOptions = useVoltageLevelsListInfos(studyUuid, currentNodeUuid, currentRootNetworkUuid);
const computeRatioTapChangerRegulationMode = (ratioTapChangerFormValues) => {
if (ratioTapChangerFormValues?.[REGULATING]?.value == null) {
@@ -581,6 +583,7 @@ const TwoWindingsTransformerModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -633,7 +636,16 @@ const TwoWindingsTransformerModificationDialog = ({
reset(emptyFormData, { keepDefaultValues: true });
}
},
- [studyUuid, currentNodeUuid, selectedId, editData, reset, getValues, setConnectivityValue]
+ [
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ selectedId,
+ editData,
+ reset,
+ getValues,
+ setConnectivityValue,
+ ]
);
useEffect(() => {
@@ -680,6 +692,7 @@ const TwoWindingsTransformerModificationDialog = ({
data,
setFormValues: fromExternalDataToFormValues,
elementType: EQUIPMENT_TYPES.VOLTAGE_LEVEL,
@@ -261,13 +263,18 @@ const VoltageLevelCreationDialog = ({
isDataFetching={isUpdate && editDataFetchStatus === FetchStatus.RUNNING}
{...dialogProps}
>
-
+
@@ -278,6 +285,7 @@ VoltageLevelCreationDialog.propTypes = {
editData: PropTypes.object,
studyUuid: PropTypes.string,
currentNode: PropTypes.object,
+ currentRootNetworkUuid: PropTypes.string,
isUpdate: PropTypes.bool,
onCreateVoltageLevel: PropTypes.func,
editDataFetchStatus: PropTypes.string,
diff --git a/src/components/dialogs/network-modifications/voltage-level/creation/voltage-level-creation-form.jsx b/src/components/dialogs/network-modifications/voltage-level/creation/voltage-level-creation-form.jsx
index aa221b626c..cc77cf57f3 100644
--- a/src/components/dialogs/network-modifications/voltage-level/creation/voltage-level-creation-form.jsx
+++ b/src/components/dialogs/network-modifications/voltage-level/creation/voltage-level-creation-form.jsx
@@ -34,7 +34,7 @@ import { useWatch } from 'react-hook-form';
import GridItem from '../../../commons/grid-item';
import GridSection from '../../../commons/grid-section';
-const VoltageLevelCreationForm = ({ currentNode, studyUuid }) => {
+const VoltageLevelCreationForm = ({ currentNode, studyUuid, currentRootNetworkUuid }) => {
const currentNodeUuid = currentNode?.id;
const [substations, setSubstations] = useState([]);
@@ -42,12 +42,14 @@ const VoltageLevelCreationForm = ({ currentNode, studyUuid }) => {
const watchSectionCount = useWatch({ name: SECTION_COUNT });
useEffect(() => {
- if (studyUuid && currentNodeUuid) {
- fetchEquipmentsIds(studyUuid, currentNodeUuid, undefined, 'SUBSTATION', true).then((values) => {
- setSubstations(values.sort((a, b) => a.localeCompare(b)));
- });
+ if (studyUuid && currentNodeUuid && currentRootNetworkUuid) {
+ fetchEquipmentsIds(studyUuid, currentNodeUuid, currentRootNetworkUuid, undefined, 'SUBSTATION', true).then(
+ (values) => {
+ setSubstations(values.sort((a, b) => a.localeCompare(b)));
+ }
+ );
}
- }, [studyUuid, currentNodeUuid]);
+ }, [studyUuid, currentNodeUuid, currentRootNetworkUuid]);
const voltageLevelIdField = (
diff --git a/src/components/dialogs/network-modifications/voltage-level/modification/voltage-level-modification-dialog.jsx b/src/components/dialogs/network-modifications/voltage-level/modification/voltage-level-modification-dialog.jsx
index cdbb0ab781..c836995db6 100644
--- a/src/components/dialogs/network-modifications/voltage-level/modification/voltage-level-modification-dialog.jsx
+++ b/src/components/dialogs/network-modifications/voltage-level/modification/voltage-level-modification-dialog.jsx
@@ -76,6 +76,7 @@ const VoltageLevelModificationDialog = ({
editData, // contains data when we try to edit an existing hypothesis from the current node's list
defaultIdValue, // Used to pre-select an equipmentId when calling this dialog from the network map
currentNode,
+ currentRootNetworkUuid,
studyUuid,
isUpdate,
editDataFetchStatus,
@@ -119,6 +120,7 @@ const VoltageLevelModificationDialog = ({
fetchNetworkElementInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.VOLTAGE_LEVEL,
EQUIPMENT_INFOS_TYPES.FORM.type,
equipmentId,
@@ -156,7 +158,7 @@ const VoltageLevelModificationDialog = ({
reset(emptyFormData, { keepDefaultValues: true });
}
},
- [studyUuid, currentNodeUuid, reset, getValues, editData]
+ [studyUuid, currentNodeUuid, currentRootNetworkUuid, reset, getValues, editData]
);
useEffect(() => {
@@ -222,6 +224,7 @@ const VoltageLevelModificationDialog = ({
state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetwork = useSelector((state: AppState) => state.currentRootNetwork);
const intl = useIntl();
const equipmentsRef = useRef>(null);
@@ -87,11 +88,11 @@ const EquipmentFilter = forwardRef {
- if (!studyUuid || !currentNode?.id) {
+ if (!currentRootNetwork || !studyUuid || !currentNode?.id) {
return;
}
// Load voltage level IDs
- fetchVoltageLevelsMapInfos(studyUuid, currentNode.id)
+ fetchVoltageLevelsMapInfos(studyUuid, currentNode.id, currentRootNetwork)
.then((voltageLevels: VoltageLevel[]) => {
const vlMap = new Map();
const nvSet = new Set();
@@ -111,7 +112,7 @@ const EquipmentFilter = forwardRef setCountries(countryCodes))
.catch((error) => {
snackError({
@@ -119,11 +120,11 @@ const EquipmentFilter = forwardRef {
- if (!studyUuid || !currentNode?.id) {
+ if (!studyUuid || !currentRootNetwork || !currentNode?.id) {
return;
}
const expertFilter = buildExpertFilter(
@@ -134,10 +135,11 @@ const EquipmentFilter = forwardRef(
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const [allModels, setAllModels] = useState([]);
const [allVariables, setAllVariables] = useState<
@@ -218,22 +219,24 @@ const ModelFilter = forwardRef(
// fetch all associated models and variables for current node and study
useEffect(() => {
- if (!currentNode?.id) {
+ if (!currentNode?.id || !currentRootNetworkUuid) {
return;
}
- fetchDynamicSimulationModels(studyUuid, currentNode.id).then((models: DynamicSimulationModelBack[]) => {
- setAllModels(
- models.map((model) => ({
- name: model.modelName,
- equipmentType: model.equipmentType,
- }))
- );
+ fetchDynamicSimulationModels(studyUuid, currentNode.id, currentRootNetworkUuid).then(
+ (models: DynamicSimulationModelBack[]) => {
+ setAllModels(
+ models.map((model) => ({
+ name: model.modelName,
+ equipmentType: model.equipmentType,
+ }))
+ );
- // transform models to variables tree representation
- const variablesTree = modelsToVariablesTree(models);
- setAllVariables(variablesTree);
- });
- }, [studyUuid, currentNode?.id]);
+ // transform models to variables tree representation
+ const variablesTree = modelsToVariablesTree(models);
+ setAllVariables(variablesTree);
+ }
+ );
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid]);
// expose some api for the component by using ref
useImperativeHandle(
diff --git a/src/components/dialogs/parameters/sensi/sensitivity-analysis-parameters.tsx b/src/components/dialogs/parameters/sensi/sensitivity-analysis-parameters.tsx
index d49e1009fa..fd16f8dc0d 100644
--- a/src/components/dialogs/parameters/sensi/sensitivity-analysis-parameters.tsx
+++ b/src/components/dialogs/parameters/sensi/sensitivity-analysis-parameters.tsx
@@ -143,6 +143,7 @@ export const SensitivityAnalysisParameters: FunctionComponent state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const [sensitivityAnalysisParams, setSensitivityAnalysisParams] = useState(params);
const resetSensitivityAnalysisParameters = useCallback(() => {
@@ -224,13 +225,14 @@ export const SensitivityAnalysisParameters: FunctionComponent {
// TODO: not easy to fix any here since values[SubTabsValues] have each time different type which causes problems with "filter"
// "none of those signatures are compatible with each other
- if (!currentNode) {
+ if (!currentNode || !currentRootNetworkUuid) {
return;
}
setLaunchLoader(true);
getSensitivityAnalysisFactorsCount(
studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
arrayFormName === SENSI_INJECTIONS_SET,
formatFilteredParams(row)
)
@@ -248,7 +250,7 @@ export const SensitivityAnalysisParameters: FunctionComponent {
if (watchVoltageLevelId) {
- fetchVoltageLevelEquipments(studyUuid, currentNodeUuid, undefined, watchVoltageLevelId, true).then(
- (values) => {
- setEquipmentsOptions(values);
- }
- );
+ fetchVoltageLevelEquipments(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ undefined,
+ watchVoltageLevelId,
+ true
+ ).then((values) => {
+ setEquipmentsOptions(values);
+ });
} else {
setEquipmentsOptions([]);
}
- }, [watchVoltageLevelId, id, studyUuid, currentNodeUuid]);
+ }, [watchVoltageLevelId, id, studyUuid, currentNodeUuid, currentRootNetworkUuid]);
const resetEquipment = useCallback(() => {
setValue(`${id}.${EQUIPMENT}`, null);
diff --git a/src/components/dialogs/root-network-creation-dialog.tsx b/src/components/dialogs/root-network-creation-dialog.tsx
new file mode 100644
index 0000000000..a1ed735034
--- /dev/null
+++ b/src/components/dialogs/root-network-creation-dialog.tsx
@@ -0,0 +1,222 @@
+/**
+ * Copyright (c) 2024, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import { FormattedMessage, useIntl } from 'react-intl';
+import {
+ CustomFormProvider,
+ ElementType,
+ fetchDirectoryElementPath,
+ TreeViewFinderNodeProps,
+ useSnackMessage,
+} from '@gridsuite/commons-ui';
+import { UUID } from 'crypto';
+import { useCallback, useEffect, useState } from 'react';
+import { Grid, Button } from '@mui/material';
+import { UniqueNameInput } from './commons/unique-name-input';
+import { CASE_NAME, CASE_ID, NAME } from '../utils/field-constants';
+import { useForm } from 'react-hook-form';
+import { yupResolver } from '@hookform/resolvers/yup';
+import yup from '../utils/yup-config';
+import { useSelector } from 'react-redux';
+import BasicModificationDialog from './commons/basicModificationDialog';
+import { AppState } from 'redux/reducer';
+import ImportCaseDialog from './import-case-dialog';
+
+export interface FormData {
+ [NAME]: string;
+ [CASE_NAME]: string;
+ [CASE_ID]: string;
+}
+
+interface RootNetworkCreationDialogProps {
+ open: boolean;
+ onSave: (data: FormData) => void;
+ onClose: () => void;
+ type: ElementType;
+ titleId: string;
+ dialogProps: any;
+ prefixIdForGeneratedName?: string;
+}
+
+const formSchema = yup
+ .object()
+ .shape({
+ [NAME]: yup.string().trim().required(),
+ [CASE_NAME]: yup.string().required(),
+ [CASE_ID]: yup.string().required(),
+ })
+ .required();
+
+const emptyFormData: FormData = {
+ [NAME]: '',
+ [CASE_NAME]: '',
+ [CASE_ID]: '',
+};
+
+const RootNetworkCreationDialog: React.FC = ({
+ open,
+ onSave,
+ onClose,
+ type,
+ titleId,
+ dialogProps = undefined,
+ prefixIdForGeneratedName,
+}) => {
+ const intl = useIntl();
+ const studyUuid = useSelector((state: AppState) => state.studyUuid);
+ const { snackError } = useSnackMessage();
+
+ const [destinationFolder, setDestinationFolder] = useState();
+ const [selectedCase, setSelectedCase] = useState(null);
+ const [caseSelectorOpen, setCaseSelectorOpen] = useState(false);
+
+ const formMethods = useForm({
+ defaultValues: emptyFormData,
+ resolver: yupResolver(formSchema),
+ });
+
+ const { reset, setValue } = formMethods;
+ const disableSave =
+ // Form validation must pass
+ !selectedCase || // A case must be selected
+ !formMethods.getValues(NAME); // NAME must not be empty
+
+ // Clear form and reset selected case
+ const clear = useCallback(() => {
+ reset(emptyFormData);
+ setSelectedCase(null); // Reset the selected case on clear
+ }, [reset]);
+
+ // Fetch default directory based on study UUID
+ const fetchDefaultDirectoryForStudy = useCallback(() => {
+ if (!studyUuid) {
+ return;
+ }
+ fetchDirectoryElementPath(studyUuid).then((res) => {
+ if (!res || res.length < 2) {
+ snackError({
+ messageTxt: 'unknown study directory',
+ headerId: 'studyDirectoryFetchingError',
+ });
+ return;
+ }
+ const parentFolderIndex = res.length - 2;
+ const { elementUuid, elementName } = res[parentFolderIndex];
+ setDestinationFolder({
+ id: elementUuid,
+ name: elementName,
+ });
+ });
+ }, [studyUuid, snackError]);
+
+ // Auto-generate a name with prefix and current date
+ useEffect(() => {
+ if (prefixIdForGeneratedName) {
+ const getCurrentDateTime = () => new Date().toISOString();
+ const formattedMessage = intl.formatMessage({
+ id: prefixIdForGeneratedName,
+ });
+ const dateTime = getCurrentDateTime();
+ reset(
+ {
+ ...emptyFormData,
+ [NAME]: `${formattedMessage}-${dateTime}`,
+ },
+ { keepDefaultValues: true }
+ );
+ }
+ }, [prefixIdForGeneratedName, intl, reset]);
+
+ useEffect(() => {
+ if (open && studyUuid) {
+ fetchDefaultDirectoryForStudy();
+ }
+ }, [fetchDefaultDirectoryForStudy, studyUuid, open]);
+
+ // Open case selector
+ const handleCaseSelection = () => {
+ setCaseSelectorOpen(true);
+ };
+
+ // Set selected case when a case is selected
+ const onSelectCase = (selectedCase: TreeViewFinderNodeProps) => {
+ setSelectedCase(selectedCase);
+ setValue(NAME, selectedCase.name); // Set the name from the selected case
+ setValue(CASE_NAME, selectedCase.name);
+ setValue(CASE_ID, selectedCase.id as string);
+ setCaseSelectorOpen(false);
+ };
+
+ const handleSave = useCallback(
+ (values: FormData) => {
+ if (selectedCase) {
+ // Save data, including CASE_NAME and CASE_ID
+ const creationData1: FormData = {
+ ...values,
+ [CASE_NAME]: selectedCase.name,
+ [CASE_ID]: selectedCase.id as UUID,
+ };
+ onSave(creationData1);
+ } else {
+ snackError({
+ messageTxt: 'Please select a case before saving.',
+ headerId: 'caseNotSelectedError',
+ });
+ }
+ },
+ [onSave, selectedCase, snackError]
+ );
+
+ // Case selection component
+ const caseSelection = (
+
+
+
+
+
+ );
+
+ return (
+
+
+
+
+
+
+ {type === ElementType.ROOT_NETWORK && caseSelection}
+
+
+ setCaseSelectorOpen(false)}
+ onSelectCase={onSelectCase}
+ />
+
+
+ );
+};
+
+export default RootNetworkCreationDialog;
diff --git a/src/components/dialogs/set-points/voltage-regulation.jsx b/src/components/dialogs/set-points/voltage-regulation.jsx
index 6d239eaeae..4c04c58aea 100644
--- a/src/components/dialogs/set-points/voltage-regulation.jsx
+++ b/src/components/dialogs/set-points/voltage-regulation.jsx
@@ -19,6 +19,7 @@ import GridItem from '../commons/grid-item';
const VoltageRegulation = ({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
voltageLevelOptions,
previousValues,
isEquipmentModification,
@@ -78,6 +79,7 @@ const VoltageRegulation = ({
voltageLevelOptions={voltageLevelOptions}
equipmentSectionTypeDefaultValue={''}
currentNodeUuid={currentNodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
studyUuid={studyUuid}
previousRegulatingTerminalValue={previousValues?.regulatingTerminalVlId}
previousEquipmentSectionTypeValue={
diff --git a/src/components/graph/menus/dynamic-simulation/event-modification-scenario-editor.tsx b/src/components/graph/menus/dynamic-simulation/event-modification-scenario-editor.tsx
index 9941fb1ff3..4ebf6fbdde 100644
--- a/src/components/graph/menus/dynamic-simulation/event-modification-scenario-editor.tsx
+++ b/src/components/graph/menus/dynamic-simulation/event-modification-scenario-editor.tsx
@@ -34,6 +34,7 @@ const EventModificationScenarioEditor = () => {
const { snackError } = useSnackMessage();
const [events, setEvents] = useState([]);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const currentNodeIdRef = useRef(); // initial empty to get first update
const [pendingState, setPendingState] = useState(false);
@@ -92,11 +93,11 @@ const EventModificationScenarioEditor = () => {
const doFetchEvents = useCallback(() => {
// Do not fetch modifications on the root node
- if (currentNode?.type !== 'NETWORK_MODIFICATION' || !studyUuid) {
+ if (currentNode?.type !== 'NETWORK_MODIFICATION' || !studyUuid || !currentRootNetworkUuid) {
return;
}
setLaunchLoader(true);
- fetchDynamicSimulationEvents(studyUuid, currentNode.id)
+ fetchDynamicSimulationEvents(studyUuid, currentNode.id, currentRootNetworkUuid)
.then((res) => {
// Check if during asynchronous request currentNode has already changed
// otherwise accept fetch results
@@ -117,7 +118,15 @@ const EventModificationScenarioEditor = () => {
setLaunchLoader(false);
dispatch(setModificationsInProgress(false));
});
- }, [currentNode?.type, currentNode?.id, studyUuid, updateSelectedItems, snackError, dispatch]);
+ }, [
+ currentNode?.type,
+ currentRootNetworkUuid,
+ currentNode?.id,
+ studyUuid,
+ updateSelectedItems,
+ snackError,
+ dispatch,
+ ]);
useEffect(() => {
// first time with currentNode initialized then fetch events
@@ -164,17 +173,19 @@ const EventModificationScenarioEditor = () => {
const isAnyNodeBuilding = useIsAnyNodeBuilding();
const doDeleteEvent = useCallback(() => {
- if (!studyUuid || !currentNode?.id) {
+ if (!studyUuid || !currentNode?.id || !currentRootNetworkUuid) {
return;
}
const selectedEvents = [...selectedItems];
- deleteDynamicSimulationEvents(studyUuid, currentNode.id, selectedEvents).catch((errMsg) => {
- snackError({
- messageTxt: errMsg,
- headerId: 'DynamicSimulationEventDeleteError',
- });
- });
- }, [currentNode?.id, selectedItems, snackError, studyUuid]);
+ deleteDynamicSimulationEvents(studyUuid, currentNode.id, currentRootNetworkUuid, selectedEvents).catch(
+ (errMsg) => {
+ snackError({
+ messageTxt: errMsg,
+ headerId: 'DynamicSimulationEventDeleteError',
+ });
+ }
+ );
+ }, [currentNode?.id, selectedItems, snackError, studyUuid, currentRootNetworkUuid]);
const doEditEvent = (event: Event) => {
setEditDialogOpen({
diff --git a/src/components/graph/menus/editable-title.tsx b/src/components/graph/menus/editable-title.tsx
index 3a1a4d44a7..7aa4089c61 100644
--- a/src/components/graph/menus/editable-title.tsx
+++ b/src/components/graph/menus/editable-title.tsx
@@ -40,19 +40,30 @@ interface EditableTitleProps {
name: string;
onClose: () => void;
onChange?: (value: string) => void;
+ isCloseIconVisible?: boolean;
}
-export const EditableTitle: FunctionComponent = ({ name, onClose, onChange }) => {
+export const EditableTitle: FunctionComponent = ({
+ name,
+ isCloseIconVisible = true,
+ onClose,
+ onChange,
+}) => {
const [openEditTitle, setOpenEditTitle] = useState(false);
const intl = useIntl();
return (
- setOpenEditTitle(true)} disabled={onChange === undefined}>
+ setOpenEditTitle(true)}
+ disabled={onChange === undefined}
+ >
-
+
{
const [deleteInProgress, setDeleteInProgress] = useState(false);
const [modificationsToRestore, setModificationsToRestore] = useState([]);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const currentNodeIdRef = useRef(); // initial empty to get first update
const [pendingState, setPendingState] = useState(false);
@@ -263,6 +264,7 @@ const NetworkModificationNodeEditor = () => {
onValidated={handleValidatedDialog}
currentNode={currentNode}
studyUuid={studyUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
editData={editData}
isUpdate={isUpdate}
editDataFetchStatus={editDataFetchStatus}
diff --git a/src/components/graph/menus/node-editor.tsx b/src/components/graph/menus/node-editor.tsx
index 6aceda8cfa..462e2a2b22 100644
--- a/src/components/graph/menus/node-editor.tsx
+++ b/src/components/graph/menus/node-editor.tsx
@@ -59,6 +59,7 @@ const NodeEditor = () => {
name={currentTreeNode?.data?.label ?? ''}
onClose={closeModificationsDrawer}
onChange={changeNodeName}
+ isCloseIconVisible={true}
/>
diff --git a/src/components/graph/menus/root-network-editor.tsx b/src/components/graph/menus/root-network-editor.tsx
new file mode 100644
index 0000000000..e16612c4c2
--- /dev/null
+++ b/src/components/graph/menus/root-network-editor.tsx
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2024, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import PropTypes from 'prop-types';
+import { EditableTitle } from './editable-title';
+import { Box } from '@mui/material';
+import { AppState } from '../../../redux/reducer';
+import RootNetworkNodeEditor from './root-network-node-editor';
+import { useSelector } from 'react-redux';
+
+const styles = {
+ paper: () => ({
+ height: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ elevation: 3,
+ }),
+};
+
+const RootNetworkEditor = () => {
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
+
+ const closeModificationsDrawer = () => {};
+
+ return (
+
+
+
+
+ );
+};
+
+RootNetworkEditor.propTypes = {
+ className: PropTypes.string,
+};
+
+export default RootNetworkEditor;
diff --git a/src/components/graph/menus/root-network-node-editor.tsx b/src/components/graph/menus/root-network-node-editor.tsx
new file mode 100644
index 0000000000..1d3038191c
--- /dev/null
+++ b/src/components/graph/menus/root-network-node-editor.tsx
@@ -0,0 +1,456 @@
+/**
+ * Copyright (c) 2024, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import { CheckBoxList, ElementType, Parameter, useSnackMessage } from '@gridsuite/commons-ui';
+
+import FileUpload from '@mui/icons-material/FileUpload';
+
+import DeleteIcon from '@mui/icons-material/Delete';
+import { Box, Checkbox, CircularProgress, Theme, Toolbar, Tooltip, Typography, Badge } from '@mui/material';
+import IconButton from '@mui/material/IconButton';
+
+import { useCallback, useEffect, useState } from 'react';
+import { FormattedMessage, useIntl } from 'react-intl';
+import { useDispatch, useSelector } from 'react-redux';
+
+import { UUID } from 'crypto';
+import { AppState } from 'redux/reducer';
+import { RootNetworkMetadata } from './network-modification-menu.type';
+
+import {
+ CaseImportParameters,
+ GetCaseImportParametersReturn,
+ getCaseImportParameters,
+} from 'services/network-conversion';
+import { createRootNetwork, deleteRootNetworks, fetchRootNetworks } from 'services/root-network';
+import RemoveRedEyeIcon from '@mui/icons-material/RemoveRedEye';
+import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
+import { setCurrentRootNetwork } from 'redux/actions';
+import RootNetworkCreationDialog, { FormData } from 'components/dialogs/root-network-creation-dialog';
+
+export const styles = {
+ listContainer: (theme: Theme) => ({
+ overflowY: 'auto',
+ display: 'flex',
+ flexDirection: 'column',
+ flexGrow: 1,
+ paddingBottom: theme.spacing(8),
+ }),
+ listItem: { paddingLeft: 0, paddingTop: 0, paddingBottom: 0 },
+ checkBoxLabel: { flexGrow: '1' },
+ disabledRootNetwork: { opacity: 0.4 },
+ checkBoxIcon: { minWidth: 0, padding: 0 },
+ checkboxButton: {
+ padding: 0.5,
+ margin: 0,
+ display: 'flex',
+ alignItems: 'center',
+ },
+ rootNetworksTitle: (theme: Theme) => ({
+ display: 'flex',
+ alignItems: 'center',
+ margin: theme.spacing(0),
+ padding: theme.spacing(1),
+ backgroundColor: theme.palette.primary.main,
+ color: theme.palette.primary.contrastText,
+ overflow: 'hidden',
+ }),
+ toolbar: (theme: Theme) => ({
+ '&': {
+ // Necessary to overrides some @media specific styles that are defined elsewhere
+ padding: 0,
+ minHeight: 0,
+ },
+ border: theme.spacing(1),
+ margin: 0,
+ flexShrink: 0,
+ }),
+ toolbarIcon: (theme: Theme) => ({
+ marginRight: theme.spacing(1),
+ }),
+ toolbarCheckbox: (theme: Theme) => ({
+ marginLeft: theme.spacing(1.5),
+ }),
+ filler: {
+ flexGrow: 1,
+ },
+ circularProgress: (theme: Theme) => ({
+ marginRight: theme.spacing(2),
+ color: theme.palette.primary.contrastText,
+ }),
+ toolbarCircularProgress: (theme: Theme) => ({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: theme.spacing(1.25),
+ marginRight: theme.spacing(2),
+ color: theme.palette.secondary.main,
+ }),
+ notification: (theme: Theme) => ({
+ flex: 1,
+ alignContent: 'center',
+ justifyContent: 'center',
+ marginTop: theme.spacing(4),
+ textAlign: 'center',
+ color: theme.palette.primary.main,
+ }),
+ icon: (theme: Theme) => ({
+ width: theme.spacing(3),
+ }),
+ iconEdit: (theme: Theme) => ({
+ marginRight: theme.spacing(1),
+ }),
+};
+
+export function isChecked(s1: number) {
+ return s1 !== 0;
+}
+
+export function isPartial(s1: number, s2: number) {
+ if (s1 === 0) {
+ return false;
+ }
+ return s1 !== s2;
+}
+
+const RootNetworkNodeEditor = () => {
+ const notificationIdList = useSelector((state: AppState) => state.notificationIdList);
+ const studyUuid = useSelector((state: AppState) => state.studyUuid);
+ const { snackInfo, snackError, snackWarning } = useSnackMessage();
+ const [rootNetworks, setRootNetworks] = useState([]);
+ const [createInProgress, setCreateInProgress] = useState(false);
+ const [deleteInProgress, setDeleteInProgress] = useState(false);
+ const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetwork = useSelector((state: AppState) => state.currentRootNetwork);
+
+ const [pendingState, setPendingState] = useState(false);
+
+ const [selectedItems, setSelectedItems] = useState([]);
+
+ const [rootNetworkCreationDialogOpen, setRootNetworkCreationDialogOpen] = useState(false);
+ const dispatch = useDispatch();
+ const studyUpdatedForce = useSelector((state: AppState) => state.studyUpdated);
+ const [messageId, setMessageId] = useState('');
+ const [launchLoader, setLaunchLoader] = useState(false);
+
+ const updateSelectedItems = useCallback((rootNetworks: RootNetworkMetadata[]) => {
+ const toKeepIdsSet = new Set(rootNetworks.map((e) => e.rootNetworkUuid));
+ setSelectedItems((oldselectedItems) => oldselectedItems.filter((s) => toKeepIdsSet.has(s.rootNetworkUuid)));
+ }, []);
+
+ const dofetchRootNetworks = useCallback(() => {
+ setLaunchLoader(true);
+ if (studyUuid) {
+ fetchRootNetworks(studyUuid)
+ .then((res: RootNetworkMetadata[]) => {
+ updateSelectedItems(res);
+ setRootNetworks(res);
+ })
+ .catch((error) => {
+ snackError({
+ messageTxt: error.message,
+ });
+ })
+ .finally(() => {
+ setPendingState(false);
+ setLaunchLoader(false);
+ });
+ }
+ }, [studyUuid, updateSelectedItems, snackError]);
+
+ useEffect(() => {
+ if (studyUpdatedForce.eventData.headers) {
+ if (studyUpdatedForce.eventData.headers['updateType'] === 'rootNetworksUpdated') {
+ setMessageId('updateRootNetworksList');
+ dofetchRootNetworks();
+ }
+ }
+ }, [studyUpdatedForce, dofetchRootNetworks]);
+
+ useEffect(() => {
+ if (rootNetworks.length === 0) {
+ dofetchRootNetworks();
+ }
+ }, [dofetchRootNetworks, rootNetworks]);
+
+ const openRootNetworkCreationDialog = useCallback(() => {
+ setRootNetworkCreationDialogOpen(true);
+ }, []);
+
+ const doDeleteRootNetwork = useCallback(() => {
+ const selectedRootNetworksUuid = selectedItems.map((item) => item.rootNetworkUuid);
+ const itemsToDelete = selectedRootNetworksUuid.filter((uuid) => uuid !== currentRootNetwork);
+
+ // If there are no items to delete, show warning
+ if (itemsToDelete.length === 0) {
+ snackWarning({ headerId: 'warnDeleteCurrentRootNetwork' });
+ return;
+ }
+
+ if (studyUuid && currentRootNetwork) {
+ deleteRootNetworks(studyUuid, itemsToDelete)
+ .then(() => {
+ setDeleteInProgress(true);
+ })
+ .catch((errmsg) => {
+ snackError({
+ messageTxt: errmsg,
+ headerId: 'errDeleteRootNetworkMsg',
+ });
+ })
+ .finally(() => {
+ setDeleteInProgress(false);
+ if (selectedRootNetworksUuid.includes(currentRootNetwork)) {
+ snackWarning({
+ headerId: 'warnDeleteCurrentRootNetwork',
+ });
+ }
+ });
+ }
+ }, [selectedItems, snackError, snackWarning, studyUuid, currentRootNetwork]);
+
+ const toggleSelectAllRootNetworks = useCallback(() => {
+ setSelectedItems((oldVal) => (oldVal.length === 0 ? rootNetworks : []));
+ }, [rootNetworks]);
+
+ const isLoading = useCallback(() => {
+ return notificationIdList.filter((notification) => notification === currentNode?.id).length > 0;
+ }, [notificationIdList, currentNode?.id]);
+
+ const intl = useIntl();
+ const getRootNetworkLabel = (rootNetwork: RootNetworkMetadata): string => {
+ if (!rootNetwork) {
+ return '';
+ }
+ return intl.formatMessage({ id: 'RootNetwork' }) + ': ' + rootNetwork.rootNetworkUuid;
+ };
+
+ const handleSecondaryAction = useCallback(
+ (rootNetwork: RootNetworkMetadata) => {
+ const isCurrentRootNetwork = rootNetwork.rootNetworkUuid === currentRootNetwork;
+
+ return (
+
+ {
+ if (rootNetwork.rootNetworkUuid !== currentRootNetwork) {
+ dispatch(setCurrentRootNetwork(rootNetwork.rootNetworkUuid));
+ }
+ }}
+ >
+ {isCurrentRootNetwork ? (
+
+
+
+ ) : (
+
+ )}
+
+
+ );
+ },
+ [currentRootNetwork, dispatch]
+ );
+
+ const renderRootNetworksList = () => {
+ return (
+ ({
+ label: {
+ ...(rootNetwork.isCreating && { ...styles.disabledRootNetwork }),
+ ...styles.checkBoxLabel,
+ },
+ checkBoxIcon: styles.checkBoxIcon,
+ checkboxButton: styles.checkboxButton,
+ }),
+ }}
+ onItemClick={(rootNetwork) => {
+ console.log(rootNetwork.rootNetworkUuid, 'on click');
+ }}
+ selectedItems={selectedItems}
+ onSelectionChange={setSelectedItems}
+ items={rootNetworks}
+ getItemId={(val) => val.rootNetworkUuid}
+ getItemLabel={getRootNetworkLabel}
+ divider
+ secondaryAction={handleSecondaryAction}
+ />
+ );
+ };
+
+ const renderRootNetworksListTitleLoading = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+ };
+
+ const renderRootNetworksListTitleUpdating = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+ };
+
+ const renderRootNetworksListTitle = () => {
+ return (
+
+
+ {pendingState && }
+
+
+
+
+
+ );
+ };
+
+ const renderRootNetworkCreationDialog = () => {
+ return (
+ setRootNetworkCreationDialogOpen(false)}
+ onSave={doCreateRootNetwork}
+ type={ElementType.ROOT_NETWORK}
+ titleId={'CreateRootNetwork'}
+ dialogProps={undefined}
+ />
+ );
+ };
+
+ function formatCaseImportParameters(params: CaseImportParameters[]): CaseImportParameters[] {
+ // sort possible values alphabetically to display select options sorted
+ return params?.map((parameter) => ({
+ ...parameter,
+ possibleValues: parameter.possibleValues?.sort((a: any, b: any) => a.localeCompare(b)),
+ }));
+ }
+
+ function customizeCurrentParameters(params: Parameter[]): Record {
+ return params.reduce((obj, parameter) => {
+ // we check if the parameter is for extensions. If so, we select all possible values by default.
+ // the only way for the moment to check if the parameter is for extension, is by checking his name.
+ // TODO: implement a cleaner way to determine the extensions field
+ if (parameter.type === 'STRING_LIST' && parameter.name?.endsWith('extensions')) {
+ return { ...obj, [parameter.name]: parameter.possibleValues.toString() };
+ }
+ return obj;
+ }, {} as Record);
+ }
+
+ const doCreateRootNetwork = ({ name, caseName, caseId }: FormData) => {
+ setCreateInProgress(true);
+
+ getCaseImportParameters(caseId as UUID)
+ .then((params: GetCaseImportParametersReturn) => {
+ // Format the parameters
+ const formattedParams = formatCaseImportParameters(params.parameters);
+ const customizedCurrentParameters = customizeCurrentParameters(formattedParams as Parameter[]);
+ // Call createRootNetwork with formatted parameters
+ return createRootNetwork(caseId as UUID, params.formatName, studyUuid, customizedCurrentParameters);
+ })
+ .then(() => {
+ snackInfo({
+ headerId: 'rootNetworkCreated',
+ headerValues: {
+ rootNetworkName: name,
+ },
+ });
+ })
+ .catch((error) => {
+ snackError({
+ messageTxt: error.message,
+ headerId: 'errCreateRootNetworksMsg',
+ });
+ })
+ .finally(() => {
+ setCreateInProgress(false);
+ });
+ };
+ const renderPaneSubtitle = () => {
+ if (isLoading() && messageId) {
+ return renderRootNetworksListTitleLoading();
+ }
+ if (launchLoader) {
+ return renderRootNetworksListTitleUpdating();
+ }
+ return renderRootNetworksListTitle();
+ };
+
+ return (
+ <>
+
+
+
+
+ }>
+
+
+
+
+
+
+
+
+
+
+ {deleteInProgress ?? (
+ }>
+
+
+
+
+ )}
+
+ {rootNetworkCreationDialogOpen && renderRootNetworkCreationDialog()}
+ {renderPaneSubtitle()}
+
+ {renderRootNetworksList()}
+ >
+ );
+};
+
+export default RootNetworkNodeEditor;
diff --git a/src/components/map-viewer.jsx b/src/components/map-viewer.jsx
index 4844d5fd1c..84c9ceef39 100644
--- a/src/components/map-viewer.jsx
+++ b/src/components/map-viewer.jsx
@@ -130,6 +130,7 @@ export const Content = () => (
const MapViewer = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
view,
openDiagramView,
tableEquipment,
@@ -258,7 +259,11 @@ const MapViewer = ({
}}
>
-
+
{/* Map */}
@@ -305,6 +310,7 @@ const MapViewer = ({
lineFlowAlertThreshold={networkVisuParams.mapParameters.lineFlowAlertThreshold}
openVoltageLevel={openVoltageLevel}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
onChangeTab={onChangeTab}
showInSpreadsheet={showInSpreadsheet}
setErrorMessage={setErrorMessage}
@@ -332,6 +338,7 @@ const MapViewer = ({
studyUuid={studyUuid}
showInSpreadsheet={showInSpreadsheet}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
visible={
!isInDrawingMode &&
view === StudyView.MAP &&
diff --git a/src/components/menus/bus-menu.tsx b/src/components/menus/bus-menu.tsx
index d5cfdb9f46..05ecd19d4e 100644
--- a/src/components/menus/bus-menu.tsx
+++ b/src/components/menus/bus-menu.tsx
@@ -75,6 +75,7 @@ export const BusMenu: FunctionComponent = ({
// to check is node editable
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const isAnyNodeBuilding = useIsAnyNodeBuilding();
const isNodeEditable = useMemo(
@@ -86,6 +87,7 @@ export const BusMenu: FunctionComponent = ({
fetchNetworkElementInfos(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
EQUIPMENT_TYPES.BUSBAR_SECTION,
EQUIPMENT_INFOS_TYPES.OPERATING_STATUS.type,
busId,
@@ -95,7 +97,7 @@ export const BusMenu: FunctionComponent = ({
setEquipmentInfos(value);
}
});
- }, [studyUuid, currentNode?.id, busId]);
+ }, [studyUuid, currentRootNetworkUuid, currentNode?.id, busId]);
const computationStarting = useSelector((state: AppState) => state.computationStarting);
diff --git a/src/components/menus/operating-status-menu.tsx b/src/components/menus/operating-status-menu.tsx
index d05f94001e..a164a96d58 100644
--- a/src/components/menus/operating-status-menu.tsx
+++ b/src/components/menus/operating-status-menu.tsx
@@ -63,6 +63,7 @@ export type MenuBranchProps = {
onOpenDynamicSimulationEventDialog?: (id: string, type: EquipmentType | null, dialogTitle: string) => void;
currentNode?: CurrentTreeNode;
studyUuid?: UUID;
+ currentRootNetworkUuid?: UUID;
modificationInProgress?: boolean;
setModificationInProgress?: (progress: boolean) => void;
};
@@ -81,6 +82,7 @@ const withOperatingStatusMenu =
onOpenDynamicSimulationEventDialog,
currentNode,
studyUuid,
+ currentRootNetworkUuid,
modificationInProgress,
setModificationInProgress,
}: MenuBranchProps) => {
@@ -103,6 +105,7 @@ const withOperatingStatusMenu =
fetchNetworkElementInfos(
studyUuid,
currentNode?.id,
+ currentRootNetworkUuid,
equipmentType,
EQUIPMENT_INFOS_TYPES.OPERATING_STATUS.type,
equipment.id,
@@ -113,7 +116,7 @@ const withOperatingStatusMenu =
}
});
}
- }, [studyUuid, currentNode?.id, equipmentType, equipment?.id]);
+ }, [studyUuid, currentNode?.id, currentRootNetworkUuid, equipmentType, equipment?.id]);
const isNodeEditable = useMemo(
function () {
@@ -403,6 +406,7 @@ withOperatingStatusMenu.propTypes = {
onOpenDynamicSimulationEventDialog: PropTypes.func.isRequired,
currentNode: PropTypes.object,
studyUuid: PropTypes.string.isRequired,
+ currentRootNetworkUuid: PropTypes.string.isRequired,
modificationInProgress: PropTypes.func,
setModificationInProgress: PropTypes.func,
};
diff --git a/src/components/network-modification-tree-pane.jsx b/src/components/network-modification-tree-pane.jsx
index 9536aeb095..8edf91e237 100644
--- a/src/components/network-modification-tree-pane.jsx
+++ b/src/components/network-modification-tree-pane.jsx
@@ -51,6 +51,7 @@ const styles = {
height: '100%',
display: 'flex',
flexDirection: 'row',
+ // backgroundColor: 'yellow',
},
};
@@ -75,7 +76,7 @@ const noNodeSelectionForCopy = {
const HTTP_MAX_NODE_BUILDS_EXCEEDED_MESSAGE = 'MAX_NODE_BUILDS_EXCEEDED';
-export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay }) => {
+export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay, currentRootNetworkUuid }) => {
const dispatch = useDispatch();
const intlRef = useIntlRef();
const { snackError, snackWarning, snackInfo } = useSnackMessage();
@@ -137,7 +138,8 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
const currentNode = useSelector((state) => state.currentTreeNode);
const currentNodeRef = useRef();
currentNodeRef.current = currentNode;
-
+ const currentRootNetworkRef = useRef();
+ currentRootNetworkRef.current = currentRootNetworkUuid;
const selectionForCopy = useSelector((state) => state.nodeSelectionForCopy);
const nodeSelectionForCopyRef = useRef();
nodeSelectionForCopyRef.current = selectionForCopy;
@@ -152,13 +154,15 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
const updateNodes = useCallback(
(updatedNodesIds) => {
- Promise.all(updatedNodesIds.map((nodeId) => fetchNetworkModificationTreeNode(studyUuid, nodeId))).then(
- (values) => {
- dispatch(networkModificationTreeNodesUpdated(values));
- }
- );
+ Promise.all(
+ updatedNodesIds.map((nodeId) =>
+ fetchNetworkModificationTreeNode(studyUuid, nodeId, currentRootNetworkUuid)
+ )
+ ).then((values) => {
+ dispatch(networkModificationTreeNodesUpdated(values));
+ });
},
- [studyUuid, dispatch]
+ [studyUuid, currentRootNetworkUuid, dispatch]
);
const isSubtreeImpacted = useCallback(
@@ -213,18 +217,20 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
useEffect(() => {
if (studyUpdatedForce.eventData.headers) {
if (studyUpdatedForce.eventData.headers['updateType'] === UpdateType.NODE_CREATED) {
- fetchNetworkModificationTreeNode(studyUuid, studyUpdatedForce.eventData.headers['newNode']).then(
- (node) => {
- dispatch(
- networkModificationTreeNodeAdded(
- node,
- studyUpdatedForce.eventData.headers['parentNode'],
- studyUpdatedForce.eventData.headers['insertMode'],
- studyUpdatedForce.eventData.headers['referenceNodeUuid']
- )
- );
- }
- );
+ fetchNetworkModificationTreeNode(
+ studyUuid,
+ studyUpdatedForce.eventData.headers['newNode'],
+ currentRootNetworkUuid
+ ).then((node) => {
+ dispatch(
+ networkModificationTreeNodeAdded(
+ node,
+ studyUpdatedForce.eventData.headers['parentNode'],
+ studyUpdatedForce.eventData.headers['insertMode'],
+ studyUpdatedForce.eventData.headers['referenceNodeUuid']
+ )
+ );
+ });
if (isSubtreeImpacted([studyUpdatedForce.eventData.headers['parentNode']])) {
resetNodeClipboard();
@@ -246,18 +252,20 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
JSON.parse(studyUpdatedForce.eventData.payload)
);
} else if (studyUpdatedForce.eventData.headers['updateType'] === 'nodeMoved') {
- fetchNetworkModificationTreeNode(studyUuid, studyUpdatedForce.eventData.headers['movedNode']).then(
- (node) => {
- dispatch(
- networkModificationTreeNodeMoved(
- node,
- studyUpdatedForce.eventData.headers['parentNode'],
- studyUpdatedForce.eventData.headers['insertMode'],
- studyUpdatedForce.eventData.headers['referenceNodeUuid']
- )
- );
- }
- );
+ fetchNetworkModificationTreeNode(
+ studyUuid,
+ studyUpdatedForce.eventData.headers['movedNode'],
+ currentRootNetworkUuid
+ ).then((node) => {
+ dispatch(
+ networkModificationTreeNodeMoved(
+ node,
+ studyUpdatedForce.eventData.headers['parentNode'],
+ studyUpdatedForce.eventData.headers['insertMode'],
+ studyUpdatedForce.eventData.headers['referenceNodeUuid']
+ )
+ );
+ });
} else if (studyUpdatedForce.eventData.headers['updateType'] === 'subtreeMoved') {
fetchNetworkModificationSubtree(studyUuid, studyUpdatedForce.eventData.headers['movedNode']).then(
(nodes) => {
@@ -296,7 +304,10 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
}
} else if (studyUpdatedForce.eventData.headers['updateType'] === 'nodeRenamed') {
updateNodes([studyUpdatedForce.eventData.headers['node']]);
- } else if (studyUpdatedForce.eventData.headers['updateType'] === 'nodeBuildStatusUpdated') {
+ } else if (
+ studyUpdatedForce.eventData.headers['updateType'] === 'nodeBuildStatusUpdated' &&
+ studyUpdatedForce.eventData.headers['rootNetwork'] === currentRootNetworkRef.current
+ ) {
updateNodes(studyUpdatedForce.eventData.headers['nodes']);
if (
studyUpdatedForce.eventData.headers['nodes'].some((nodeId) => nodeId === currentNodeRef.current?.id)
@@ -323,6 +334,7 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
snackInfo,
dispatch,
broadcastChannel,
+ currentRootNetworkUuid,
isSubtreeImpacted,
resetNodeClipboard,
]);
@@ -416,19 +428,19 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
const handleUnbuildNode = useCallback(
(element) => {
- unbuildNode(studyUuid, element.id).catch((error) => {
+ unbuildNode(studyUuid, element.id, currentRootNetworkUuid).catch((error) => {
snackError({
messageTxt: error.message,
headerId: 'NodeUnbuildingError',
});
});
},
- [studyUuid, snackError]
+ [studyUuid, currentRootNetworkUuid, snackError]
);
const handleBuildNode = useCallback(
(element) => {
- buildNode(studyUuid, element.id).catch((error) => {
+ buildNode(studyUuid, element.id, currentRootNetworkUuid).catch((error) => {
if (error.status === 403 && error.message.includes(HTTP_MAX_NODE_BUILDS_EXCEEDED_MESSAGE)) {
// retrieve last word of the message (ex: "MAX_NODE_BUILDS_EXCEEDED max allowed built nodes : 2" -> 2)
let limit = error.message.split(/[: ]+/).pop();
@@ -444,7 +456,7 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
}
});
},
- [studyUuid, snackError]
+ [studyUuid, currentRootNetworkUuid, snackError]
);
const [openExportDialog, setOpenExportDialog] = useState(false);
@@ -587,6 +599,7 @@ export const NetworkModificationTreePane = ({ studyUuid, studyMapTreeDisplay })
onClose={() => setOpenExportDialog(false)}
onClick={handleClickExportStudy}
studyUuid={studyUuid}
+ rootNetworkUuid={currentRootNetworkUuid}
nodeUuid={activeNode?.id}
title={intlRef.current.formatMessage({
id: 'exportNetwork',
diff --git a/src/components/network-modification-tree.jsx b/src/components/network-modification-tree.jsx
index 0f480ffb9f..497d5d7988 100644
--- a/src/components/network-modification-tree.jsx
+++ b/src/components/network-modification-tree.jsx
@@ -28,6 +28,7 @@ import {
snapGrid,
} from './graph/layout';
import TreeControlButton from './graph/util/tree-control-button';
+import RootNetworkPanel from './root-network-panel';
import { updateNodesColumnPositions } from '../services/study/tree-subtree.ts';
import { useSnackMessage } from '@gridsuite/commons-ui';
@@ -355,6 +356,9 @@ const NetworkModificationTree = ({
{isMinimapOpen && }
+
+ {/* root Network Panel */}
+
);
diff --git a/src/components/network/gs-map-equipments.ts b/src/components/network/gs-map-equipments.ts
index 942436232f..b1fd512072 100644
--- a/src/components/network/gs-map-equipments.ts
+++ b/src/components/network/gs-map-equipments.ts
@@ -24,11 +24,35 @@ export default class GSMapEquipments extends MapEquipments {
errHandler?: UseSnackMessageReturn['snackError'];
intlRef: RefObject;
- initEquipments(studyUuid: UUID, currentNodeUuid: UUID) {
- const fetchSubstationsMapInfosPromise = fetchSubstationsMapInfos(studyUuid, currentNodeUuid, undefined, false);
- const fetchLinesMapInfosPromise = fetchLinesMapInfos(studyUuid, currentNodeUuid, undefined, false);
- const fetchTieLinesMapInfosPromise = fetchTieLinesMapInfos(studyUuid, currentNodeUuid, undefined, false);
- const fetchHvdcLinesMapInfosPromise = fetchHvdcLinesMapInfos(studyUuid, currentNodeUuid, undefined, false);
+ initEquipments(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ const fetchSubstationsMapInfosPromise = fetchSubstationsMapInfos(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ undefined,
+ false
+ );
+ const fetchLinesMapInfosPromise = fetchLinesMapInfos(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ undefined,
+ false
+ );
+ const fetchTieLinesMapInfosPromise = fetchTieLinesMapInfos(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ undefined,
+ false
+ );
+ const fetchHvdcLinesMapInfosPromise = fetchHvdcLinesMapInfos(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ undefined,
+ false
+ );
this.dispatch(setMapEquipementsInitialized(false));
@@ -101,6 +125,7 @@ export default class GSMapEquipments extends MapEquipments {
constructor(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
errHandler: UseSnackMessageReturn['snackError'],
dispatch: Dispatch,
intlRef: RefObject
@@ -109,14 +134,43 @@ export default class GSMapEquipments extends MapEquipments {
this.dispatch = dispatch;
this.errHandler = errHandler;
this.intlRef = intlRef;
- this.initEquipments(studyUuid, currentNodeUuid);
+ this.initEquipments(studyUuid, currentNodeUuid, currentRootNetworkUuid);
}
- reloadImpactedSubstationsEquipments(studyUuid: UUID, currentNode: any, substationsIds: string[] | null) {
- const updatedSubstations = fetchSubstationsMapInfos(studyUuid, currentNode?.id, substationsIds, true);
- const updatedLines = fetchLinesMapInfos(studyUuid, currentNode?.id, substationsIds, true);
- const updatedTieLines = fetchTieLinesMapInfos(studyUuid, currentNode?.id, substationsIds, true);
- const updatedHvdcLines = fetchHvdcLinesMapInfos(studyUuid, currentNode?.id, substationsIds, true);
+ reloadImpactedSubstationsEquipments(
+ studyUuid: UUID,
+ currentNode: any,
+ currentRootNetworkUuid: UUID,
+ substationsIds: string[] | null
+ ) {
+ const updatedSubstations = fetchSubstationsMapInfos(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ substationsIds,
+ true
+ );
+ const updatedLines = fetchLinesMapInfos(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ substationsIds,
+ true
+ );
+ const updatedTieLines = fetchTieLinesMapInfos(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ substationsIds,
+ true
+ );
+ const updatedHvdcLines = fetchHvdcLinesMapInfos(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ substationsIds,
+ true
+ );
updatedSubstations.catch((error) => {
console.error(error.message);
if (this.errHandler) {
diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx
index 769a6ffbbd..128f50f019 100644
--- a/src/components/network/network-map-tab.tsx
+++ b/src/components/network/network-map-tab.tsx
@@ -84,6 +84,7 @@ type NetworkMapTabProps = {
networkMapRef: React.RefObject;
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
visible: boolean;
lineFullPath: boolean;
lineParallelPath: boolean;
@@ -105,6 +106,7 @@ export const NetworkMapTab = ({
/* redux can be use as redux*/
studyUuid,
currentNode,
+ currentRootNetworkUuid,
/* visual*/
visible,
lineFullPath,
@@ -155,6 +157,7 @@ export const NetworkMapTab = ({
const basicDataReady = mapEquipments && geoData;
const lineFullPathRef = useRef();
+ const rootNetworkRef = useRef();
/*
This Set stores the geo data that are collected from the server AFTER the initialization.
@@ -209,6 +212,7 @@ export const NetworkMapTab = ({
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
isUpdate={true}
defaultIdValue={equipmentToModify?.id}
onClose={() => closeModificationDialog()}
@@ -222,6 +226,7 @@ export const NetworkMapTab = ({
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
isUpdate={true}
defaultIdValue={equipmentToModify?.id}
onClose={() => closeModificationDialog()}
@@ -235,6 +240,7 @@ export const NetworkMapTab = ({
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
defaultIdValue={equipmentToModify?.id}
isUpdate={true}
onClose={() => closeModificationDialog()}
@@ -255,6 +261,7 @@ export const NetworkMapTab = ({
open={true}
studyUuid={studyUuid}
currentNode={currentNode}
+ currentRootNetworkUuid={currentRootNetworkUuid}
defaultIdValue={equipmentToModify?.id}
isUpdate={true}
onClose={() => closeModificationDialog()}
@@ -418,15 +425,25 @@ export const NetworkMapTab = ({
const getMissingEquipmentsPositions = useCallback(
(
notFoundEquipmentsIds: string[],
- fetchEquipmentCB: (studyUuid: UUID, nodeId: UUID, equipmentIds: string[]) => Promise
+ fetchEquipmentCB: (
+ studyUuid: UUID,
+ nodeId: UUID,
+ currentRootNetworkUuid: UUID,
+ equipmentIds: string[]
+ ) => Promise
) => {
if (notFoundEquipmentsIds.length === 0 || !currentNodeRef.current) {
return Promise.resolve([]);
}
- return fetchEquipmentCB(studyUuid, currentNodeRef.current!.id, notFoundEquipmentsIds);
+ return fetchEquipmentCB(
+ studyUuid,
+ currentNodeRef.current!.id,
+ currentRootNetworkUuid,
+ notFoundEquipmentsIds
+ );
},
- [studyUuid]
+ [studyUuid, currentRootNetworkUuid]
);
const updateSubstationsTemporaryGeoData = useCallback(
@@ -572,23 +589,33 @@ export const NetworkMapTab = ({
updateLinesTemporaryGeoData,
]);
+ const handleChange = useCallback(
+ (newValues: unknown[]) => {
+ setFilteredNominalVoltages(newValues);
+ onNominalVoltagesChange(newValues);
+ },
+ [setFilteredNominalVoltages, onNominalVoltagesChange]
+ );
+
// loads all root node geo-data then saves them in redux
// it will be considered as the source of truth to check whether we need to fetch geo-data for a specific equipment or not
const loadRootNodeGeoData = useCallback(() => {
console.info(`Loading geo data of study '${studyUuid}'...`);
dispatch(setMapDataLoading(true));
-
- const substationPositionsDone = fetchSubstationPositions(studyUuid, rootNodeId).then((data) => {
- console.info(`Received substations of study '${studyUuid}'...`);
- const newGeoData = new GeoData(new Map(), geoDataRef.current?.linePositionsById || new Map());
- newGeoData.setSubstationPositions(data);
- setGeoData(newGeoData);
- geoDataRef.current = newGeoData;
- });
+ geoDataRef.current = null;
+ const substationPositionsDone = fetchSubstationPositions(studyUuid, rootNodeId, currentRootNetworkUuid).then(
+ (data) => {
+ console.info(`Received substations of study '${studyUuid}'...`);
+ const newGeoData = new GeoData(new Map(), geoDataRef.current?.linePositionsById || new Map());
+ newGeoData.setSubstationPositions(data);
+ setGeoData(newGeoData);
+ geoDataRef.current = newGeoData;
+ }
+ );
const linePositionsDone = !lineFullPath
? Promise.resolve()
- : fetchLinePositions(studyUuid, rootNodeId).then((data) => {
+ : fetchLinePositions(studyUuid, rootNodeId, currentRootNetworkUuid).then((data) => {
console.info(`Received lines of study '${studyUuid}'...`);
const newGeoData = new GeoData(geoDataRef.current?.substationPositionsById || new Map(), new Map());
newGeoData.setLinePositions(data);
@@ -599,6 +626,12 @@ export const NetworkMapTab = ({
Promise.all([substationPositionsDone, linePositionsDone])
.then(() => {
temporaryGeoDataIdsRef.current = new Set();
+ networkMapRef.current?.centerMapNetwork();
+ // when reloading root node map equipments (when switching of root network), nominal voltages are reloaded
+ // we check them all in NominalVoltageFilter by default
+ if (mapEquipments) {
+ handleChange(mapEquipments.getNominalVoltages());
+ }
setIsRootNodeGeoDataLoaded(true);
})
.catch(function (error) {
@@ -611,7 +644,17 @@ export const NetworkMapTab = ({
.finally(() => {
dispatch(setMapDataLoading(false));
});
- }, [rootNodeId, lineFullPath, studyUuid, dispatch, snackError]);
+ }, [
+ mapEquipments,
+ rootNodeId,
+ currentRootNetworkUuid,
+ lineFullPath,
+ studyUuid,
+ dispatch,
+ snackError,
+ networkMapRef,
+ handleChange,
+ ]);
const loadGeoData = useCallback(() => {
if (studyUuid && currentNodeRef.current) {
@@ -646,11 +689,18 @@ export const NetworkMapTab = ({
if (!isNodeBuilt(currentNode) || !studyUuid) {
return;
}
- const gSMapEquipments = new GSMapEquipments(studyUuid, currentNode?.id, snackError, dispatch, intlRef);
+ const gSMapEquipments = new GSMapEquipments(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ snackError,
+ dispatch,
+ intlRef
+ );
if (gSMapEquipments) {
dispatch(resetMapReloaded());
}
- }, [currentNode, dispatch, intlRef, snackError, studyUuid]);
+ }, [currentNode, currentRootNetworkUuid, dispatch, intlRef, snackError, studyUuid]);
const reloadMapEquipments = useCallback(
(currentNodeAtReloadCalling: CurrentTreeNode | null, substationsIds: UUID[] | undefined) => {
@@ -663,7 +713,12 @@ export const NetworkMapTab = ({
}
const { updatedSubstations, updatedLines, updatedTieLines, updatedHvdcLines } = mapEquipments
- ? mapEquipments.reloadImpactedSubstationsEquipments(studyUuid, currentNode, substationsIds ?? null)
+ ? mapEquipments.reloadImpactedSubstationsEquipments(
+ studyUuid,
+ currentNode,
+ currentRootNetworkUuid,
+ substationsIds ?? null
+ )
: {
updatedSubstations: Promise.resolve([]),
updatedLines: Promise.resolve([]),
@@ -700,7 +755,7 @@ export const NetworkMapTab = ({
dispatch(setMapDataLoading(false));
});
},
- [currentNode, dispatch, mapEquipments, studyUuid]
+ [currentNode, currentRootNetworkUuid, dispatch, mapEquipments, studyUuid]
);
const updateMapEquipments = useCallback(
@@ -766,7 +821,11 @@ export const NetworkMapTab = ({
useEffect(() => {
if (isInitialized && studyUpdatedForce.eventData.headers) {
- if (studyUpdatedForce.eventData.headers[UPDATE_TYPE_HEADER] === 'loadflowResult') {
+ const currentRootNetwork = studyUpdatedForce.eventData.headers['rootNetwork'];
+ if (
+ studyUpdatedForce.eventData.headers[UPDATE_TYPE_HEADER] === 'loadflowResult' &&
+ currentRootNetwork === currentRootNetworkUuid
+ ) {
reloadMapEquipments(currentNodeRef.current, undefined).catch((e) =>
snackError({
messageTxt: e.message,
@@ -774,7 +833,7 @@ export const NetworkMapTab = ({
);
}
}
- }, [isInitialized, studyUpdatedForce, reloadMapEquipments, snackError]);
+ }, [isInitialized, studyUpdatedForce, currentRootNetworkUuid, reloadMapEquipments, snackError]);
useEffect(() => {
if (!mapEquipments || refIsMapManualRefreshEnabled.current) {
@@ -863,7 +922,21 @@ export const NetworkMapTab = ({
if (isInitialized && lineFullPath && !prevLineFullPath) {
loadGeoData();
}
- }, [isInitialized, lineFullPath, loadGeoData]);
+ }, [isInitialized, lineFullPath, loadGeoData, currentRootNetworkUuid]);
+
+ // Effect to handle changes in currentRootNetworkUuid
+ useEffect(() => {
+ const prevRootNetworkPath = rootNetworkRef.current;
+ rootNetworkRef.current = currentRootNetworkUuid;
+
+ if (currentRootNetworkUuid && currentRootNetworkUuid !== prevRootNetworkPath && rootNodeId) {
+ loadRootNodeGeoData();
+ // set initialized to false to trigger "missing geo-data fetching"
+ setInitialized(false);
+ // set isRootNodeGeoDataLoaded to false so "missing geo-data fetching" waits for root node geo-data to be fully fetched before triggering
+ setIsRootNodeGeoDataLoaded(false);
+ }
+ }, [currentRootNetworkUuid, loadRootNodeGeoData, rootNodeId]);
let choiceVoltageLevelsSubstation: EquipmentMap | null = null;
if (choiceVoltageLevelsSubstationId) {
@@ -983,11 +1056,6 @@ export const NetworkMapTab = ({
/>
);
- function handleChange(newValues: unknown[]) {
- setFilteredNominalVoltages(newValues);
- onNominalVoltagesChange(newValues);
- }
-
function renderNominalVoltageFilter() {
return (
diff --git a/src/components/network/selection-creation-panel/use-save-map.ts b/src/components/network/selection-creation-panel/use-save-map.ts
index b87547dc28..021db245d2 100644
--- a/src/components/network/selection-creation-panel/use-save-map.ts
+++ b/src/components/network/selection-creation-panel/use-save-map.ts
@@ -27,6 +27,7 @@ export const useSaveMap = (): UseSaveMapOutput => {
const intl = useIntl();
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNodeUuid = useSelector((state: AppState) => state.currentTreeNode?.id);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const { snackInfo, snackError, snackWarning } = useSnackMessage();
const [pendingState, setPendingState] = useState(false);
@@ -63,6 +64,7 @@ export const useSaveMap = (): UseSaveMapOutput => {
// @ts-expect-error TODO: manage null case
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
selectedEquipmentsIds,
nominalVoltages
);
@@ -79,6 +81,7 @@ export const useSaveMap = (): UseSaveMapOutput => {
// @ts-expect-error TODO: manage null case
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
equipments,
nominalVoltages
);
@@ -110,7 +113,7 @@ export const useSaveMap = (): UseSaveMapOutput => {
}
return true; // success
},
- [currentNodeUuid, intl, snackError, snackInfo, snackWarning, studyUuid]
+ [currentNodeUuid, currentRootNetworkUuid, intl, snackError, snackInfo, snackWarning, studyUuid]
);
return { pendingState, onSaveSelection };
diff --git a/src/components/report-viewer-tab.jsx b/src/components/report-viewer-tab.jsx
index 2cbdda0805..0bd1c41faa 100644
--- a/src/components/report-viewer-tab.jsx
+++ b/src/components/report-viewer-tab.jsx
@@ -36,6 +36,7 @@ const styles = {
* @param studyId : string study id
* @param visible : boolean window visible
* @param currentNode : object visualized node
+ * @param currentRootNetwork : current rootnetwork uuid
* @param disabled : boolean disabled
* @returns {*} node
* @constructor
diff --git a/src/components/result-view-tab.tsx b/src/components/result-view-tab.tsx
index 5a6ba447d5..6061a10e39 100644
--- a/src/components/result-view-tab.tsx
+++ b/src/components/result-view-tab.tsx
@@ -46,6 +46,7 @@ const styles = {
interface IResultViewTabProps {
studyUuid: UUID;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: UUID;
openVoltageLevelDiagram: (voltageLevelId: string) => void;
disabled: boolean;
view: string;
@@ -62,6 +63,7 @@ export interface IService {
* control results views
* @param studyUuid : string uuid of study
* @param currentNode : object current node
+ * @param currentRootNetworkUuid : uuid of current root network
* @param openVoltageLevelDiagram : function
* @param resultTabIndexRedirection : ResultTabIndexRedirection to specific tab [RootTab, LevelOneTab, ...]
* @param disabled
@@ -71,6 +73,7 @@ export interface IService {
export const ResultViewTab: FunctionComponent = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
openVoltageLevelDiagram,
disabled,
view,
@@ -92,10 +95,14 @@ export const ResultViewTab: FunctionComponent = ({
const renderLoadFlowResult = useMemo(() => {
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const renderSecurityAnalysisResult = useMemo(() => {
return (
@@ -103,59 +110,86 @@ export const ResultViewTab: FunctionComponent = ({
);
- }, [studyUuid, currentNode, openVoltageLevelDiagram]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid, openVoltageLevelDiagram]);
const renderVoltageInitResult = useMemo(() => {
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const renderSensitivityAnalysisResult = useMemo(() => {
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const renderNonEvacuatedEnergyResult = useMemo(() => {
+ console.log('ùùùùùù renderNonEvacuatedEnergyResult ', currentRootNetworkUuid);
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const renderShortCircuitAnalysisResult = useMemo(() => {
return (
-
+
);
- }, [view, currentNode?.id, studyUuid]);
+ }, [view, currentNode?.id, studyUuid, currentRootNetworkUuid]);
const renderDynamicSimulationResult = useMemo(() => {
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const renderStateEstimationResult = useMemo(() => {
return (
-
+
);
- }, [studyUuid, currentNode]);
+ }, [studyUuid, currentNode, currentRootNetworkUuid]);
const services: IService[] = useMemo(() => {
return [
diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx
index e50218199d..cdb3d34192 100644
--- a/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx
+++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx
@@ -42,68 +42,72 @@ const defaultColDef = {
type DynamicSimulationResultSynthesisProps = {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
};
-const DynamicSimulationResultSynthesis = memo(({ nodeUuid, studyUuid }: DynamicSimulationResultSynthesisProps) => {
- const intl = useIntl();
+const DynamicSimulationResultSynthesis = memo(
+ ({ nodeUuid, studyUuid, currentRootNetworkUuid }: DynamicSimulationResultSynthesisProps) => {
+ const intl = useIntl();
- const [result, isLoading] = useNodeData(
- studyUuid,
- nodeUuid,
- fetchDynamicSimulationStatus,
- dynamicSimulationResultInvalidations,
- null,
- (status: RunningStatus) =>
- status && [
- {
- status,
- },
- ]
- );
+ const [result, isLoading] = useNodeData(
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ fetchDynamicSimulationStatus,
+ dynamicSimulationResultInvalidations,
+ null,
+ (status: RunningStatus) =>
+ status && [
+ {
+ status,
+ },
+ ]
+ );
- const columnDefs = useMemo(
- () => [
- makeAgGridCustomHeaderColumn({
- headerName: intl.formatMessage({
+ const columnDefs = useMemo(
+ () => [
+ makeAgGridCustomHeaderColumn({
+ headerName: intl.formatMessage({
+ id: 'status',
+ }),
id: 'status',
+ field: 'status',
+ width: MEDIUM_COLUMN_WIDTH,
+ cellRenderer: StatusCellRender,
}),
- id: 'status',
- field: 'status',
- width: MEDIUM_COLUMN_WIDTH,
- cellRenderer: StatusCellRender,
- }),
- ],
- [intl]
- );
+ ],
+ [intl]
+ );
- // messages to show when no data
- const dynamicSimulationStatus = useSelector(
- (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION]
- );
- const messages = useIntlResultStatusMessages(intl, true);
- const overlayMessage = useMemo(
- () => getNoRowsMessage(messages, result, dynamicSimulationStatus, !isLoading),
- [messages, result, dynamicSimulationStatus, isLoading]
- );
+ // messages to show when no data
+ const dynamicSimulationStatus = useSelector(
+ (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION]
+ );
+ const messages = useIntlResultStatusMessages(intl, true);
+ const overlayMessage = useMemo(
+ () => getNoRowsMessage(messages, result, dynamicSimulationStatus, !isLoading),
+ [messages, result, dynamicSimulationStatus, isLoading]
+ );
- const rowDataToShow = useMemo(() => (overlayMessage ? [] : result), [result, overlayMessage]);
+ const rowDataToShow = useMemo(() => (overlayMessage ? [] : result), [result, overlayMessage]);
- return (
- <>
- {isLoading && (
-
-
-
- )}
-
- >
- );
-});
+ return (
+ <>
+ {isLoading && (
+
+
+
+ )}
+
+ >
+ );
+ }
+);
export default DynamicSimulationResultSynthesis;
diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-tab.jsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-tab.jsx
index 11faf3c179..1e9698ba0c 100644
--- a/src/components/results/dynamicsimulation/dynamic-simulation-result-tab.jsx
+++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-tab.jsx
@@ -25,7 +25,7 @@ const TAB_INDEX_TIMELINE = 'DynamicSimulationTabTimeline';
const TAB_INDEX_STATUS = 'DynamicSimulationTabStatus';
const TAB_INDEX_LOGS = 'ComputationResultsLogs';
-const DynamicSimulationResultTab = ({ studyUuid, nodeUuid }) => {
+const DynamicSimulationResultTab = ({ studyUuid, nodeUuid, currentRootNetworkUuid }) => {
const intl = useIntl();
const [tabIndex, setTabIndex] = useState(TAB_INDEX_TIME_SERIES);
@@ -66,13 +66,25 @@ const DynamicSimulationResultTab = ({ studyUuid, nodeUuid }) => {
-
+
-
+
-
+
diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-time-series.jsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-time-series.jsx
index 9ade8cc765..4ca9633495 100644
--- a/src/components/results/dynamicsimulation/dynamic-simulation-result-time-series.jsx
+++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-time-series.jsx
@@ -36,8 +36,8 @@ const styles = {
},
};
-const DynamicSimulationResultTimeSeries = memo(({ nodeUuid, studyUuid }) => {
- const [result, loadTimeSeries, isLoading] = useResultTimeSeries(nodeUuid, studyUuid);
+const DynamicSimulationResultTimeSeries = memo(({ nodeUuid, studyUuid, currentRootNetworkUuid }) => {
+ const [result, loadTimeSeries, isLoading] = useResultTimeSeries(nodeUuid, studyUuid, currentRootNetworkUuid);
// tab id is automatically increased and reset to zero when there is no tab.
const [tabIncId, setTabIncId] = useState(1);
@@ -182,6 +182,7 @@ const DynamicSimulationResultTimeSeries = memo(({ nodeUuid, studyUuid }) => {
DynamicSimulationResultTimeSeries.propTypes = {
nodeUuid: PropTypes.string,
studyUuid: PropTypes.string,
+ currentRootNetworkUuid: PropTypes.string,
};
export default DynamicSimulationResultTimeSeries;
diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx
index 62e790345c..f452c2b985 100644
--- a/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx
+++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx
@@ -65,138 +65,142 @@ const defaultColDef = {
type DynamicSimulationResultTimelineProps = {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
};
-const DynamicSimulationResultTimeline = memo(({ studyUuid, nodeUuid }: DynamicSimulationResultTimelineProps) => {
- const intl = useIntl();
- const gridRef = useRef(null);
+const DynamicSimulationResultTimeline = memo(
+ ({ studyUuid, nodeUuid, currentRootNetworkUuid }: DynamicSimulationResultTimelineProps) => {
+ const intl = useIntl();
+ const gridRef = useRef(null);
- const [timelines, isLoading] = useNodeData(
- studyUuid,
- nodeUuid,
- fetchDynamicSimulationResultTimeline,
- dynamicSimulationResultInvalidations
- );
+ const [timelines, isLoading] = useNodeData(
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ fetchDynamicSimulationResultTimeline,
+ dynamicSimulationResultInvalidations
+ );
- const { onSortChanged, sortConfig } = useAgGridSort(DYNAMIC_SIMULATION_RESULT_SORT_STORE, TIMELINE);
+ const { onSortChanged, sortConfig } = useAgGridSort(DYNAMIC_SIMULATION_RESULT_SORT_STORE, TIMELINE);
- const { updateFilter, filterSelector } = useAggridLocalRowFilter(gridRef, {
- filterType: DYNAMIC_SIMULATION_RESULT_STORE_FIELD,
- filterTab: TIMELINE,
- // @ts-expect-error TODO: found how to have Action type in props type
- filterStoreAction: setDynamicSimulationResultFilter,
- });
+ const { updateFilter, filterSelector } = useAggridLocalRowFilter(gridRef, {
+ filterType: DYNAMIC_SIMULATION_RESULT_STORE_FIELD,
+ filterTab: TIMELINE,
+ // @ts-expect-error TODO: found how to have Action type in props type
+ filterStoreAction: setDynamicSimulationResultFilter,
+ });
- const sortAndFilterProps = useMemo(
- () => ({
- sortProps: {
- onSortChanged,
- sortConfig,
- },
- filterProps: {
- updateFilter,
- filterSelector,
- },
- }),
- [onSortChanged, sortConfig, updateFilter, filterSelector]
- );
-
- // columns are defined from fields in {@link TimelineEvent} types
- const columnDefs = useMemo(
- () => [
- makeAgGridCustomHeaderColumn({
- headerName: intl.formatMessage({
- id: 'DynamicSimulationTimelineEventTime',
- }),
- field: COL_TIME,
- width: MIN_COLUMN_WIDTH,
- numeric: true,
- fractionDigits: 2,
- id: 'agNumberColumnFilter',
- filter: 'agNumberColumnFilter',
- filterComponent: CustomAggridComparatorFilter,
- filterComponentParams: {
- filterParams: {
- ...sortAndFilterProps.filterProps,
- filterDataType: FILTER_DATA_TYPES.NUMBER,
- filterComparators: Object.values(FILTER_NUMBER_COMPARATORS),
- },
- },
- cellRenderer: NumberCellRenderer,
+ const sortAndFilterProps = useMemo(
+ () => ({
sortProps: {
- ...sortAndFilterProps.sortProps,
+ onSortChanged,
+ sortConfig,
+ },
+ filterProps: {
+ updateFilter,
+ filterSelector,
},
}),
- makeAgGridCustomHeaderColumn({
- headerName: intl.formatMessage({
- id: 'DynamicSimulationTimelineEventModelName',
+ [onSortChanged, sortConfig, updateFilter, filterSelector]
+ );
+
+ // columns are defined from fields in {@link TimelineEvent} types
+ const columnDefs = useMemo(
+ () => [
+ makeAgGridCustomHeaderColumn({
+ headerName: intl.formatMessage({
+ id: 'DynamicSimulationTimelineEventTime',
+ }),
+ field: COL_TIME,
+ width: MIN_COLUMN_WIDTH,
+ numeric: true,
+ fractionDigits: 2,
+ id: 'agNumberColumnFilter',
+ filter: 'agNumberColumnFilter',
+ filterComponent: CustomAggridComparatorFilter,
+ filterComponentParams: {
+ filterParams: {
+ ...sortAndFilterProps.filterProps,
+ filterDataType: FILTER_DATA_TYPES.NUMBER,
+ filterComparators: Object.values(FILTER_NUMBER_COMPARATORS),
+ },
+ },
+ cellRenderer: NumberCellRenderer,
+ sortProps: {
+ ...sortAndFilterProps.sortProps,
+ },
}),
- id: COL_MODEL_NAME,
- field: COL_MODEL_NAME,
- width: MEDIUM_COLUMN_WIDTH,
- filterComponent: CustomAggridComparatorFilter,
- filterComponentParams: {
- filterParams: {
- ...sortAndFilterProps.filterProps,
- filterDataType: FILTER_DATA_TYPES.TEXT,
- filterComparators: [FILTER_TEXT_COMPARATORS.STARTS_WITH, FILTER_TEXT_COMPARATORS.CONTAINS],
+ makeAgGridCustomHeaderColumn({
+ headerName: intl.formatMessage({
+ id: 'DynamicSimulationTimelineEventModelName',
+ }),
+ id: COL_MODEL_NAME,
+ field: COL_MODEL_NAME,
+ width: MEDIUM_COLUMN_WIDTH,
+ filterComponent: CustomAggridComparatorFilter,
+ filterComponentParams: {
+ filterParams: {
+ ...sortAndFilterProps.filterProps,
+ filterDataType: FILTER_DATA_TYPES.TEXT,
+ filterComparators: [FILTER_TEXT_COMPARATORS.STARTS_WITH, FILTER_TEXT_COMPARATORS.CONTAINS],
+ },
+ },
+ sortProps: {
+ ...sortAndFilterProps.sortProps,
},
- },
- sortProps: {
- ...sortAndFilterProps.sortProps,
- },
- }),
- makeAgGridCustomHeaderColumn({
- headerName: intl.formatMessage({
- id: 'DynamicSimulationTimelineEventModelMessage',
}),
- id: COL_MESSAGE,
- field: COL_MESSAGE,
- width: LARGE_COLUMN_WIDTH,
- filterComponent: CustomAggridComparatorFilter,
- filterComponentParams: {
- filterParams: {
- ...sortAndFilterProps.filterProps,
- filterDataType: FILTER_DATA_TYPES.TEXT,
- filterComparators: [FILTER_TEXT_COMPARATORS.STARTS_WITH, FILTER_TEXT_COMPARATORS.CONTAINS],
+ makeAgGridCustomHeaderColumn({
+ headerName: intl.formatMessage({
+ id: 'DynamicSimulationTimelineEventModelMessage',
+ }),
+ id: COL_MESSAGE,
+ field: COL_MESSAGE,
+ width: LARGE_COLUMN_WIDTH,
+ filterComponent: CustomAggridComparatorFilter,
+ filterComponentParams: {
+ filterParams: {
+ ...sortAndFilterProps.filterProps,
+ filterDataType: FILTER_DATA_TYPES.TEXT,
+ filterComparators: [FILTER_TEXT_COMPARATORS.STARTS_WITH, FILTER_TEXT_COMPARATORS.CONTAINS],
+ },
},
- },
- sortProps: {
- ...sortAndFilterProps.sortProps,
- },
- }),
- ],
- [intl, sortAndFilterProps]
- );
+ sortProps: {
+ ...sortAndFilterProps.sortProps,
+ },
+ }),
+ ],
+ [intl, sortAndFilterProps]
+ );
- // messages to show when no data
- const dynamicSimulationStatus = useSelector(
- (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION]
- );
- const messages = useIntlResultStatusMessages(intl, true);
- const overlayMessage = useMemo(
- () => getNoRowsMessage(messages, timelines, dynamicSimulationStatus, !isLoading),
- [messages, timelines, dynamicSimulationStatus, isLoading]
- );
+ // messages to show when no data
+ const dynamicSimulationStatus = useSelector(
+ (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION]
+ );
+ const messages = useIntlResultStatusMessages(intl, true);
+ const overlayMessage = useMemo(
+ () => getNoRowsMessage(messages, timelines, dynamicSimulationStatus, !isLoading),
+ [messages, timelines, dynamicSimulationStatus, isLoading]
+ );
- const rowDataToShow = useMemo(() => (overlayMessage ? [] : timelines), [timelines, overlayMessage]);
+ const rowDataToShow = useMemo(() => (overlayMessage ? [] : timelines), [timelines, overlayMessage]);
- return (
- <>
- {isLoading && (
-
-
-
- )}
-
- >
- );
-});
+ return (
+ <>
+ {isLoading && (
+
+
+
+ )}
+
+ >
+ );
+ }
+);
export default DynamicSimulationResultTimeline;
diff --git a/src/components/results/dynamicsimulation/hooks/useResultTimeSeries.ts b/src/components/results/dynamicsimulation/hooks/useResultTimeSeries.ts
index e02ee41fa3..fa1ba7e9c9 100644
--- a/src/components/results/dynamicsimulation/hooks/useResultTimeSeries.ts
+++ b/src/components/results/dynamicsimulation/hooks/useResultTimeSeries.ts
@@ -14,10 +14,11 @@ import { TimeSeriesMetadata } from '../types/dynamic-simulation-result.type';
import { dynamicSimulationResultInvalidations } from '../utils/dynamic-simulation-result-utils';
import { fetchDynamicSimulationTimeSeriesMetadata } from '../../../../services/dynamic-simulation';
-const useResultTimeSeries = (nodeUuid: UUID, studyUuid: UUID) => {
+const useResultTimeSeries = (nodeUuid: UUID, studyUuid: UUID, currentRootNetworkUuid: UUID) => {
const [result, isLoading] = useNodeData(
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
fetchDynamicSimulationTimeSeriesMetadata,
dynamicSimulationResultInvalidations,
null,
@@ -50,7 +51,12 @@ const useResultTimeSeries = (nodeUuid: UUID, studyUuid: UUID) => {
(indexValue) => result.timeseriesMetadatas[indexValue].name
);
- return fetchDynamicSimulationResultTimeSeries(studyUuid, nodeUuid, timeSeriesNamesToLoad)
+ return fetchDynamicSimulationResultTimeSeries(
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ timeSeriesNamesToLoad
+ )
.then((newlyLoadedTimeSeries) => {
// insert one by one newly loaded timeserie into the cache
for (const newSeries of newlyLoadedTimeSeries) {
@@ -77,7 +83,7 @@ const useResultTimeSeries = (nodeUuid: UUID, studyUuid: UUID) => {
});
}
},
- [studyUuid, nodeUuid, result, snackError]
+ [studyUuid, nodeUuid, currentRootNetworkUuid, result, snackError]
);
return [result, lazyLoadTimeSeriesCb, isLoading];
diff --git a/src/components/results/loadflow/load-flow-result-tab.tsx b/src/components/results/loadflow/load-flow-result-tab.tsx
index 99de33add2..a9ed33be42 100644
--- a/src/components/results/loadflow/load-flow-result-tab.tsx
+++ b/src/components/results/loadflow/load-flow-result-tab.tsx
@@ -68,7 +68,11 @@ export interface GlobalFilter {
limitViolationsTypes?: LimitTypes[];
}
-export const LoadFlowResultTab: FunctionComponent = ({ studyUuid, nodeUuid }) => {
+export const LoadFlowResultTab: FunctionComponent = ({
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+}) => {
const { snackError } = useSnackMessage();
const intl = useIntl();
const loadflowResultInvalidations = ['loadflowResult'];
@@ -94,7 +98,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
// load countries
useEffect(() => {
- fetchAllCountries(studyUuid, nodeUuid)
+ fetchAllCountries(studyUuid, nodeUuid, currentRootNetworkUuid)
.then((countryCodes) => {
setCountriesFilter(
countryCodes.map((countryCode: string) => ({
@@ -109,7 +113,8 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
headerId: 'FetchCountryError',
});
});
- fetchAllNominalVoltages(studyUuid, nodeUuid)
+
+ fetchAllNominalVoltages(studyUuid, nodeUuid, currentRootNetworkUuid)
.then((nominalVoltages) => {
setVoltageLevelsFilter(
nominalVoltages.map((nominalV: number) => ({
@@ -124,7 +129,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
headerId: 'FetchNominalVoltagesError',
});
});
- }, [nodeUuid, studyUuid, snackError, loadFlowStatus]);
+ }, [nodeUuid, studyUuid, currentRootNetworkUuid, snackError, loadFlowStatus]);
const getGlobalFilterParameter = useCallback(
(globalFilter: GlobalFilter | undefined) => {
@@ -174,7 +179,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
value: limitTypeValues,
});
}
- return fetchLimitViolations(studyUuid, nodeUuid, {
+ return fetchLimitViolations(studyUuid, nodeUuid, currentRootNetworkUuid, {
sort: sortConfig.map((sort) => ({
...sort,
colId: FROM_COLUMN_TO_FIELD_LIMIT_VIOLATION_RESULT[sort.colId],
@@ -182,14 +187,24 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
filters: mapFieldsToColumnsFilter(updatedFilters, mappingFields(tabIndex)),
globalFilters: getGlobalFilterParameter(globalFilter),
});
- }, [studyUuid, nodeUuid, sortConfig, filterSelector, tabIndex, globalFilter, getGlobalFilterParameter, intl]);
+ }, [
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ sortConfig,
+ filterSelector,
+ tabIndex,
+ globalFilter,
+ getGlobalFilterParameter,
+ intl,
+ ]);
const fetchloadflowResultWithParameters = useCallback(() => {
- return fetchLoadFlowResult(studyUuid, nodeUuid, {
+ return fetchLoadFlowResult(studyUuid, nodeUuid, currentRootNetworkUuid, {
sort: sortConfig,
filters: filterSelector,
});
- }, [studyUuid, nodeUuid, sortConfig, filterSelector]);
+ }, [studyUuid, nodeUuid, currentRootNetworkUuid, sortConfig, filterSelector]);
const fetchResult = useMemo(() => {
if (tabIndex === 0 || tabIndex === 1) {
@@ -202,6 +217,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ studyUu
const [loadflowResult, isLoadingResult, setResult] = useNodeData(
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
fetchResult,
loadflowResultInvalidations
);
diff --git a/src/components/results/loadflow/load-flow-result-utils.ts b/src/components/results/loadflow/load-flow-result-utils.ts
index 14cdd8588d..cd115a7ae8 100644
--- a/src/components/results/loadflow/load-flow-result-utils.ts
+++ b/src/components/results/loadflow/load-flow-result-utils.ts
@@ -178,17 +178,24 @@ export const useFetchFiltersEnums = (): {
});
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetwork = useSelector((state: AppState) => state.currentRootNetwork);
const loadFlowStatus = useSelector((state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW]);
useEffect(() => {
- if (loadFlowStatus !== RunningStatus.SUCCEED || !studyUuid || !currentNode?.id) {
+ if (loadFlowStatus !== RunningStatus.SUCCEED || !studyUuid || !currentNode?.id || !currentRootNetwork) {
return;
}
const filterTypes = ['computation-status', 'limit-types', 'branch-sides'];
const promises = filterTypes.map((filterType) =>
- fetchAvailableFilterEnumValues(studyUuid, currentNode.id, computingType.LOAD_FLOW, filterType)
+ fetchAvailableFilterEnumValues(
+ studyUuid,
+ currentNode.id,
+ currentRootNetwork,
+ computingType.LOAD_FLOW,
+ filterType
+ )
);
setLoading(true);
@@ -206,7 +213,7 @@ export const useFetchFiltersEnums = (): {
.finally(() => {
setLoading(false);
});
- }, [loadFlowStatus, studyUuid, currentNode?.id]);
+ }, [loadFlowStatus, studyUuid, currentNode?.id, currentRootNetwork]);
return { loading, result, error };
};
diff --git a/src/components/results/loadflow/load-flow-result.type.ts b/src/components/results/loadflow/load-flow-result.type.ts
index 15e0ebe17c..9bf133dafe 100644
--- a/src/components/results/loadflow/load-flow-result.type.ts
+++ b/src/components/results/loadflow/load-flow-result.type.ts
@@ -41,6 +41,7 @@ export enum LimitTypes {
export interface LoadFlowTabProps {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
}
export interface LoadflowResultTap {
diff --git a/src/components/results/securityanalysis/security-analysis-export-button.tsx b/src/components/results/securityanalysis/security-analysis-export-button.tsx
index 24ef42436d..10ff5d2edc 100644
--- a/src/components/results/securityanalysis/security-analysis-export-button.tsx
+++ b/src/components/results/securityanalysis/security-analysis-export-button.tsx
@@ -18,13 +18,14 @@ import { PERMANENT_LIMIT_NAME } from '../common/utils';
interface SecurityAnalysisExportButtonProps {
studyUuid: UUID;
nodeUuid: UUID;
+ rootNetworkUuid: UUID;
csvHeaders?: string[];
resultType: RESULT_TYPE;
disabled?: boolean;
}
export const SecurityAnalysisExportButton: FunctionComponent = (props) => {
- const { studyUuid, nodeUuid, csvHeaders, disabled, resultType } = props;
+ const { studyUuid, nodeUuid, rootNetworkUuid, csvHeaders, disabled, resultType } = props;
const { snackError } = useSnackMessage();
const [isCsvExportLoading, setIsCsvExportLoading] = useState(false);
@@ -70,6 +71,7 @@ export const SecurityAnalysisExportButton: FunctionComponent setIsCsvExportLoading(false));
- }, [resultType, csvHeaders, enumValueTranslations, studyUuid, nodeUuid, snackError, intl]);
+ }, [resultType, csvHeaders, enumValueTranslations, studyUuid, nodeUuid, rootNetworkUuid, snackError, intl]);
return (
= ({
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
openVoltageLevelDiagram,
}) => {
const intl = useIntl();
@@ -164,14 +165,25 @@ export const SecurityAnalysisResultTab: FunctionComponent {
});
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const securityAnalysisStatus = useSelector(
(state: AppState) => state.computingStatus[ComputingType.SECURITY_ANALYSIS]
);
useEffect(() => {
- if (securityAnalysisStatus !== RunningStatus.SUCCEED || !studyUuid || !currentNode?.id) {
+ if (
+ securityAnalysisStatus !== RunningStatus.SUCCEED ||
+ !studyUuid ||
+ !currentNode?.id ||
+ !currentRootNetworkUuid
+ ) {
return;
}
@@ -694,7 +700,13 @@ export const useFetchFiltersEnums = () => {
];
const promises = filterTypes.map((filterType) =>
- fetchAvailableFilterEnumValues(studyUuid, currentNode.id, computingType.SECURITY_ANALYSIS, filterType)
+ fetchAvailableFilterEnumValues(
+ studyUuid,
+ currentNode.id,
+ currentRootNetworkUuid,
+ computingType.SECURITY_ANALYSIS,
+ filterType
+ )
);
setLoading(true);
@@ -726,7 +738,7 @@ export const useFetchFiltersEnums = () => {
.finally(() => {
setLoading(false);
});
- }, [securityAnalysisStatus, studyUuid, currentNode?.id]);
+ }, [securityAnalysisStatus, studyUuid, currentNode?.id, currentRootNetworkUuid]);
return { loading, result, error };
};
diff --git a/src/components/results/securityanalysis/security-analysis.type.ts b/src/components/results/securityanalysis/security-analysis.type.ts
index e72a2b1e09..cad7a24441 100644
--- a/src/components/results/securityanalysis/security-analysis.type.ts
+++ b/src/components/results/securityanalysis/security-analysis.type.ts
@@ -122,6 +122,7 @@ export interface SecurityAnalysisNmkResult {
export interface SecurityAnalysisTabProps {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
openVoltageLevelDiagram: (id: string) => void;
}
diff --git a/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx b/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx
index 5be37f39d3..f448f02ed0 100644
--- a/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx
+++ b/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx
@@ -54,7 +54,7 @@ export const useSecurityAnalysisColumnsDefs: UseSecurityAnalysisColumnsDefsProps
const { snackError } = useSnackMessage();
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
-
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const nodeUuid = currentNode?.id;
const getEnumLabel = useCallback(
@@ -69,7 +69,7 @@ export const useSecurityAnalysisColumnsDefs: UseSecurityAnalysisColumnsDefsProps
// for nmk views, click handler on subjectId cell
const onClickNmKConstraint = useCallback(
(row: SecurityAnalysisNmkTableRow, column?: ColDef) => {
- if (studyUuid && nodeUuid) {
+ if (studyUuid && nodeUuid && currentRootNetworkUuid) {
if (column?.field === 'subjectId') {
let vlId: string | undefined = '';
const { subjectId, side } = row || {};
@@ -86,6 +86,7 @@ export const useSecurityAnalysisColumnsDefs: UseSecurityAnalysisColumnsDefsProps
fetchVoltageLevelIdForLineOrTransformerBySide(
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
subjectId ?? '',
getBranchSide(side) ?? BranchSide.ONE
)
@@ -115,7 +116,7 @@ export const useSecurityAnalysisColumnsDefs: UseSecurityAnalysisColumnsDefsProps
}
}
},
- [nodeUuid, openVoltageLevelDiagram, snackError, studyUuid, intl]
+ [nodeUuid, currentRootNetworkUuid, openVoltageLevelDiagram, snackError, studyUuid, intl]
);
// for nmk views, custom view for subjectId cell
diff --git a/src/components/results/sensitivity-analysis/non-evacuated-energy/non-evacuated-energy-result-tab.tsx b/src/components/results/sensitivity-analysis/non-evacuated-energy/non-evacuated-energy-result-tab.tsx
index 5dd8f96aad..b246242d49 100644
--- a/src/components/results/sensitivity-analysis/non-evacuated-energy/non-evacuated-energy-result-tab.tsx
+++ b/src/components/results/sensitivity-analysis/non-evacuated-energy/non-evacuated-energy-result-tab.tsx
@@ -41,7 +41,11 @@ const styles = {
export const NON_EVACUATED_ENERGY_RESULT_INVALIDATIONS = ['nonEvacuatedEnergyResult'];
-export const NonEvacuatedEnergyResultTab: FunctionComponent = ({ studyUuid, nodeUuid }) => {
+export const NonEvacuatedEnergyResultTab: FunctionComponent = ({
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+}) => {
const [tabIndex, setTabIndex] = useState(0);
const RESULTS_TAB_INDEX = 0;
@@ -54,6 +58,7 @@ export const NonEvacuatedEnergyResultTab: FunctionComponent {
setOptions(res);
})
@@ -122,7 +123,7 @@ const PagedSensitivityAnalysisResult = ({
}),
});
});
- }, [nOrNkIndex, sensiKind, studyUuid, nodeUuid, snackError, intl]);
+ }, [nOrNkIndex, sensiKind, studyUuid, currentRootNetworkUuid, nodeUuid, snackError, intl]);
const fetchResult = useCallback(() => {
const sortSelector = sortConfig?.length
@@ -150,7 +151,7 @@ const PagedSensitivityAnalysisResult = ({
...sortSelector,
};
setIsLoading(true);
- fetchSensitivityAnalysisResult(studyUuid, nodeUuid, selector)
+ fetchSensitivityAnalysisResult(studyUuid, nodeUuid, currentRootNetworkUuid, selector)
.then((res) => {
const { filteredSensitivitiesCount = 0 } = res || {};
@@ -168,7 +169,19 @@ const PagedSensitivityAnalysisResult = ({
.finally(() => {
setIsLoading(false);
});
- }, [nOrNkIndex, sensiKind, page, rowsPerPage, filterSelector, sortConfig, studyUuid, nodeUuid, snackError, intl]);
+ }, [
+ nOrNkIndex,
+ sensiKind,
+ page,
+ rowsPerPage,
+ filterSelector,
+ sortConfig,
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ snackError,
+ intl,
+ ]);
useEffect(() => {
if (sensiStatus === RunningStatus.RUNNING) {
diff --git a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx
index 32b9558ccb..88b7181018 100644
--- a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx
+++ b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx
@@ -46,7 +46,7 @@ function getDisplayedColumns(params) {
return params.api.columnModel.columnDefs.map((c) => c.headerComponentParams.displayName);
}
-const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => {
+const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid, currentRootNetworkUuid }) => {
const { snackError } = useSnackMessage();
const intl = useIntl();
const [nOrNkIndex, setNOrNkIndex] = useState(0);
@@ -111,7 +111,7 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => {
const handleExportResultAsCsv = useCallback(() => {
setIsCsvExportLoading(true);
setIsCsvExportSuccessful(false);
- exportSensitivityResultsAsCsv(studyUuid, nodeUuid, {
+ exportSensitivityResultsAsCsv(studyUuid, nodeUuid, currentRootNetworkUuid, {
csvHeaders: csvHeaders,
resultTab: SensitivityResultTabs[nOrNkIndex].id,
sensitivityFunctionType: FUNCTION_TYPES[sensiKind],
@@ -132,7 +132,7 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => {
setIsCsvExportSuccessful(false);
})
.finally(() => setIsCsvExportLoading(false));
- }, [snackError, studyUuid, nodeUuid, intl, nOrNkIndex, sensiKind, csvHeaders]);
+ }, [snackError, studyUuid, nodeUuid, currentRootNetworkUuid, intl, nOrNkIndex, sensiKind, csvHeaders]);
return (
<>
@@ -163,6 +163,7 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => {
sensiKind={sensiKind}
studyUuid={studyUuid}
nodeUuid={nodeUuid}
+ currentRootNetworkUuid={currentRootNetworkUuid}
page={page}
setPage={setPage}
sortProps={{
@@ -194,6 +195,7 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => {
SensitivityAnalysisResultTab.propTypes = {
studyUuid: PropTypes.string.isRequired,
nodeUuid: PropTypes.string.isRequired,
+ currentRootNetworkUuid: PropTypes.string.isRequired,
};
export default SensitivityAnalysisResultTab;
diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx
index cb4af1de17..c88733ffe5 100644
--- a/src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx
+++ b/src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx
@@ -18,13 +18,14 @@ import { BranchSide } from 'components/utils/constants';
interface ShortCircuitExportButtonProps {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
csvHeaders?: string[];
analysisType: number;
disabled?: boolean;
}
export const ShortCircuitExportButton: FunctionComponent = (props) => {
- const { studyUuid, nodeUuid, csvHeaders, disabled = false, analysisType } = props;
+ const { studyUuid, nodeUuid, currentRootNetworkUuid, csvHeaders, disabled = false, analysisType } = props;
const { snackError } = useSnackMessage();
const [isCsvExportLoading, setIsCsvExportLoading] = useState(false);
@@ -62,7 +63,14 @@ export const ShortCircuitExportButton: FunctionComponent {
setIsCsvExportLoading(true);
setIsCsvExportSuccessful(false);
- downloadShortCircuitResultZippedCsv(studyUuid, nodeUuid, analysisType, csvHeaders, enumValueTranslations)
+ downloadShortCircuitResultZippedCsv(
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ analysisType,
+ csvHeaders,
+ enumValueTranslations
+ )
.then((response) => {
response.blob().then((fileBlob: Blob) => {
downloadZipFile(
@@ -84,7 +92,16 @@ export const ShortCircuitExportButton: FunctionComponent setIsCsvExportLoading(false));
- }, [studyUuid, nodeUuid, intl, snackError, csvHeaders, analysisType, enumValueTranslations]);
+ }, [
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ intl,
+ snackError,
+ csvHeaders,
+ analysisType,
+ enumValueTranslations,
+ ]);
return (
= ({
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
view,
}) => {
const lastCompletedComputation = useSelector((state: AppState) => state.lastCompletedComputation);
@@ -144,6 +146,7 @@ export const ShortCircuitAnalysisResultTab: FunctionComponent state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const isOneBusShortCircuitAnalysisType = analysisType === ShortCircuitAnalysisType.ONE_BUS;
@@ -119,7 +120,9 @@ export const ShortCircuitAnalysisResult: FunctionComponent {
- if (analysisStatus !== RunningStatus.SUCCEED || !studyUuid || !currentNode?.id) {
+ if (analysisStatus !== RunningStatus.SUCCEED || !studyUuid || !currentNode?.id || !currentRootNetworkUuid) {
return;
}
@@ -195,7 +200,13 @@ export const ShortCircuitAnalysisResult: FunctionComponent
- fetchAvailableFilterEnumValues(studyUuid, currentNode.id, currentComputingType, filter)
+ fetchAvailableFilterEnumValues(
+ studyUuid,
+ currentNode.id,
+ currentRootNetworkUuid,
+ currentComputingType,
+ filter
+ )
);
Promise.all(promises)
@@ -219,7 +230,15 @@ export const ShortCircuitAnalysisResult: FunctionComponent = ({ studyUuid, nodeUuid }) => {
+export const StateEstimationResultTab: FunctionComponent = ({
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+}) => {
const intl = useIntl();
const stateEstimationResultInvalidations = ['stateEstimationResult'];
@@ -53,8 +57,8 @@ export const StateEstimationResultTab: FunctionComponent {
- return fetchStateEstimationResult(studyUuid, nodeUuid);
- }, [studyUuid, nodeUuid]);
+ return fetchStateEstimationResult(studyUuid, nodeUuid, currentRootNetworkUuid);
+ }, [studyUuid, nodeUuid, currentRootNetworkUuid]);
const fetchResult = useMemo(() => {
return fetchEstimResults;
@@ -63,6 +67,7 @@ export const StateEstimationResultTab: FunctionComponent ({
+ paper: {
+ position: 'absolute',
+ top: 16,
+ left: 16,
+ width: '40%',
+ height: '40%',
+ display: 'flex',
+ flexDirection: 'column',
+ borderRadius: '8px',
+ boxShadow: '0 6px 15px rgba(0,0,0,0.15)', // Softer shadow
+ zIndex: 10,
+ overflow: 'hidden', // Ensure no overflow
+ },
+ contentBox: {
+ flex: 1, // Take up all available space
+ display: 'flex',
+ flexDirection: 'column',
+ position: 'relative', // Enable absolute positioning for child elements
+ },
+});
+
+const RootNetworkPanel: FunctionComponent = ({ studyId }) => {
+ return (
+ styles(theme).paper}>
+ styles(theme).contentBox}>
+
+
+
+ );
+};
+
+export default RootNetworkPanel;
diff --git a/src/components/run-button-container.jsx b/src/components/run-button-container.jsx
index 58a2610ede..ab943c0bce 100644
--- a/src/components/run-button-container.jsx
+++ b/src/components/run-button-container.jsx
@@ -35,7 +35,7 @@ import { startStateEstimation, stopStateEstimation } from '../services/study/sta
import { OptionalServicesNames, OptionalServicesStatus } from './utils/optional-services';
import { useOptionalServiceStatus } from '../hooks/use-optional-service-status';
-export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
+export function RunButtonContainer({ studyUuid, currentNode, currentRootNetworkUuid, disabled }) {
const loadFlowStatus = useSelector((state) => state.computingStatus[ComputingType.LOAD_FLOW]);
const securityAnalysisStatus = useSelector((state) => state.computingStatus[ComputingType.SECURITY_ANALYSIS]);
@@ -116,7 +116,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
// close the contingency list selection window
setShowContingencyListSelector(false);
},
- () => startSecurityAnalysis(studyUuid, currentNode?.id, contingencyListNames),
+ () => startSecurityAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid, contingencyListNames),
() => {},
null,
null
@@ -130,7 +130,13 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
// close the dialog
setShowDynamicSimulationParametersSelector(false);
},
- () => startDynamicSimulation(studyUuid, currentNode?.id, dynamicSimulationConfiguration),
+ () =>
+ startDynamicSimulation(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ dynamicSimulationConfiguration
+ ),
() => {},
null,
'DynamicSimulationRunError'
@@ -152,7 +158,13 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
startComputationAsync(
ComputingType.LOAD_FLOW,
null,
- () => startLoadFlow(studyUuid, currentNode?.id, limitReductionParam / 100.0),
+ () =>
+ startLoadFlow(
+ studyUuid,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ limitReductionParam / 100.0
+ ),
() => {},
null,
'startLoadFlowError'
@@ -169,7 +181,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.SECURITY_ANALYSIS, () =>
- stopSecurityAnalysis(studyUuid, currentNode?.id)
+ stopSecurityAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -179,7 +191,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
startComputationAsync(
ComputingType.SENSITIVITY_ANALYSIS,
null,
- () => startSensitivityAnalysis(studyUuid, currentNode?.id),
+ () => startSensitivityAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid),
() => {},
null,
'startSensitivityAnalysisError'
@@ -187,7 +199,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.SENSITIVITY_ANALYSIS, () =>
- stopSensitivityAnalysis(studyUuid, currentNode?.id)
+ stopSensitivityAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -198,7 +210,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
ComputingType.NON_EVACUATED_ENERGY_ANALYSIS,
null,
() => {
- return startNonEvacuatedEnergy(studyUuid, currentNode?.id);
+ return startNonEvacuatedEnergy(studyUuid, currentNode?.id, currentRootNetworkUuid);
},
() => {},
null,
@@ -207,7 +219,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.NON_EVACUATED_ENERGY_ANALYSIS, () =>
- stopNonEvacuatedEnergy(studyUuid, currentNode?.id)
+ stopNonEvacuatedEnergy(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -217,7 +229,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
startComputationAsync(
ComputingType.SHORT_CIRCUIT,
null,
- () => startShortCircuitAnalysis(studyUuid, currentNode?.id),
+ () => startShortCircuitAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid),
() => {},
null,
'startShortCircuitError'
@@ -225,7 +237,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.SHORT_CIRCUIT, () =>
- stopShortCircuitAnalysis(studyUuid, currentNode?.id)
+ stopShortCircuitAnalysis(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -239,7 +251,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
setShowDynamicSimulationParametersSelector(true);
} else {
// start server side dynamic simulation directly
- return startDynamicSimulation(studyUuid, currentNode?.id);
+ return startDynamicSimulation(studyUuid, currentNode?.id, currentRootNetworkUuid);
}
})
.catch((error) => {
@@ -251,7 +263,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.DYNAMIC_SIMULATION, () =>
- stopDynamicSimulation(studyUuid, currentNode?.id)
+ stopDynamicSimulation(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -261,7 +273,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
startComputationAsync(
ComputingType.VOLTAGE_INITIALIZATION,
null,
- () => startVoltageInit(studyUuid, currentNode?.id),
+ () => startVoltageInit(studyUuid, currentNode?.id, currentRootNetworkUuid),
() => {},
null,
'startVoltageInitError'
@@ -269,7 +281,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.VOLTAGE_INITIALIZATION, () =>
- stopVoltageInit(studyUuid, currentNode?.id)
+ stopVoltageInit(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
@@ -280,7 +292,7 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
ComputingType.STATE_ESTIMATION,
null,
() => {
- return startStateEstimation(studyUuid, currentNode?.id);
+ return startStateEstimation(studyUuid, currentNode?.id, currentRootNetworkUuid);
},
() => {},
null,
@@ -289,12 +301,20 @@ export function RunButtonContainer({ studyUuid, currentNode, disabled }) {
},
actionOnRunnable() {
actionOnRunnables(ComputingType.STATE_ESTIMATION, () =>
- stopStateEstimation(studyUuid, currentNode?.id)
+ stopStateEstimation(studyUuid, currentNode?.id, currentRootNetworkUuid)
);
},
},
};
- }, [dispatch, snackError, startComputationAsync, studyUuid, limitReductionParam, currentNode?.id]);
+ }, [
+ dispatch,
+ snackError,
+ startComputationAsync,
+ studyUuid,
+ limitReductionParam,
+ currentNode?.id,
+ currentRootNetworkUuid,
+ ]);
// running status is refreshed more often, so we memoize it apart
const getRunningStatus = useCallback(
diff --git a/src/components/spreadsheet/config/spreadsheet.type.ts b/src/components/spreadsheet/config/spreadsheet.type.ts
index 53c1181a45..f8b115365a 100644
--- a/src/components/spreadsheet/config/spreadsheet.type.ts
+++ b/src/components/spreadsheet/config/spreadsheet.type.ts
@@ -9,7 +9,12 @@ import type { UUID } from 'crypto';
import type { EQUIPMENT_TYPES } from '../../utils/equipment-types';
import type { CustomAggridFilterParams, CustomColDef } from '../../custom-aggrid/custom-aggrid-header.type';
-export type EquipmentFetcher = (studyUuid: UUID, currentNodeUuid: UUID, substationsIds: string[]) => Promise;
+export type EquipmentFetcher = (
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds: string[]
+) => Promise;
export type SpreadsheetEquipmentType = Exclude<
EQUIPMENT_TYPES,
diff --git a/src/components/spreadsheet/table-wrapper.tsx b/src/components/spreadsheet/table-wrapper.tsx
index 5b0343d716..3a57ff8554 100644
--- a/src/components/spreadsheet/table-wrapper.tsx
+++ b/src/components/spreadsheet/table-wrapper.tsx
@@ -150,6 +150,7 @@ const styles = {
interface TableWrapperProps {
studyUuid: string;
currentNode: CurrentTreeNode;
+ currentRootNetworkUuid: string;
equipmentId: string;
equipmentType: SpreadsheetEquipmentType;
equipmentChanged: boolean;
@@ -159,6 +160,7 @@ interface TableWrapperProps {
const TableWrapper: FunctionComponent = ({
studyUuid,
currentNode,
+ currentRootNetworkUuid,
equipmentId,
equipmentType,
equipmentChanged,
@@ -1116,6 +1118,7 @@ const TableWrapper: FunctionComponent = ({
fetchNetworkElementInfos(
studyUuid,
currentNode.id,
+ currentRootNetworkUuid,
lastModifiedEquipment.metadata.equipmentType,
EQUIPMENT_INFOS_TYPES.TAB.type,
lastModifiedEquipment.id,
@@ -1135,7 +1138,15 @@ const TableWrapper: FunctionComponent = ({
});
}
}
- }, [lastModifiedEquipment, currentNode.id, studyUuid, studyUpdatedForce, formatFetchedEquipmentHandler, dispatch]);
+ }, [
+ lastModifiedEquipment,
+ currentNode.id,
+ studyUuid,
+ currentRootNetworkUuid,
+ studyUpdatedForce,
+ formatFetchedEquipmentHandler,
+ dispatch,
+ ]);
//this listener is called for each cell modified
const handleCellEditingStopped = useCallback(
diff --git a/src/components/spreadsheet/use-spreadsheet-equipments.ts b/src/components/spreadsheet/use-spreadsheet-equipments.ts
index 2dee4d89d6..9cccdca1cd 100644
--- a/src/components/spreadsheet/use-spreadsheet-equipments.ts
+++ b/src/components/spreadsheet/use-spreadsheet-equipments.ts
@@ -25,7 +25,7 @@ import { fetchAllEquipments } from 'services/study/network-map';
export type EquipmentProps = {
type: SpreadsheetEquipmentType;
- fetchers: Array<(studyUuid: UUID, currentNodeId: UUID) => Promise>;
+ fetchers: Array<(studyUuid: UUID, currentNodeId: UUID, currentRootNetworkUuid: UUID) => Promise>;
};
type FormatFetchedEquipments = (equipments: Identifiable[]) => Identifiable[];
@@ -39,6 +39,7 @@ export const useSpreadsheetEquipments = (
const equipments = allEquipments[equipment.type];
const studyUuid = useSelector((state: AppState) => state.studyUuid);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
const [errorMessage, setErrorMessage] = useState();
const [isFetching, setIsFetching] = useState(false);
@@ -82,11 +83,13 @@ export const useSpreadsheetEquipments = (
}
resetImpactedElementTypes();
}
- if (impactedSubstationsIds.length > 0 && studyUuid && currentNode?.id) {
+ if (impactedSubstationsIds.length > 0 && studyUuid && currentRootNetworkUuid && currentNode?.id) {
// The formatting of the fetched equipments is done in the reducer
- fetchAllEquipments(studyUuid, currentNode.id, impactedSubstationsIds).then((values) => {
- dispatch(updateEquipments(values));
- });
+ fetchAllEquipments(studyUuid, currentRootNetworkUuid, currentNode.id, impactedSubstationsIds).then(
+ (values) => {
+ dispatch(updateEquipments(values));
+ }
+ );
resetImpactedSubstationsIds();
}
if (deletedEquipments.length > 0) {
@@ -118,6 +121,7 @@ export const useSpreadsheetEquipments = (
deletedEquipments,
impactedElementTypes,
studyUuid,
+ currentRootNetworkUuid,
currentNode?.id,
dispatch,
allEquipments,
@@ -127,10 +131,12 @@ export const useSpreadsheetEquipments = (
]);
useEffect(() => {
- if (shouldFetchEquipments && studyUuid && currentNode?.id) {
+ if (shouldFetchEquipments && studyUuid && currentRootNetworkUuid && currentNode?.id) {
setErrorMessage(null);
setIsFetching(true);
- Promise.all(equipment.fetchers.map((fetcher) => fetcher(studyUuid, currentNode?.id)))
+ Promise.all(
+ equipment.fetchers.map((fetcher) => fetcher(studyUuid, currentNode?.id, currentRootNetworkUuid))
+ )
.then((results) => {
let fetchedEquipments = results.flat();
if (formatFetchedEquipments) {
@@ -144,7 +150,15 @@ export const useSpreadsheetEquipments = (
setIsFetching(false);
});
}
- }, [equipment, shouldFetchEquipments, studyUuid, currentNode?.id, dispatch, formatFetchedEquipments]);
+ }, [
+ equipment,
+ shouldFetchEquipments,
+ studyUuid,
+ currentRootNetworkUuid,
+ currentNode?.id,
+ dispatch,
+ formatFetchedEquipments,
+ ]);
return { equipments, errorMessage, isFetching };
};
diff --git a/src/components/spreadsheet/utils/equipment-table-editors.tsx b/src/components/spreadsheet/utils/equipment-table-editors.tsx
index 4610128193..2ff665cda2 100644
--- a/src/components/spreadsheet/utils/equipment-table-editors.tsx
+++ b/src/components/spreadsheet/utils/equipment-table-editors.tsx
@@ -111,6 +111,7 @@ export const GeneratorRegulatingTerminalEditor = forwardRef(
open={openGeneratorPopup}
onClose={handleCancelRegulatingTerminalPopup}
currentNode={gridContext.currentNode}
+ currentRootNetworkUuid={gridContext.currentRootNetworkUuid}
studyUuid={gridContext.studyUuid}
onModifyRegulatingTerminalGenerator={(updatedRegulatedTerminal: any) => {
handleSaveRegulatingTerminalPopup(updatedRegulatedTerminal);
@@ -188,6 +189,7 @@ export const TWTRegulatingTerminalEditor = forwardRef(
open={openTWTRegulatingTerminalPopup}
onClose={handleCancelRegulatingTerminalPopup}
currentNode={gridContext.currentNode}
+ currentRootNetworkUuid={gridContext.currentRootNetworkUuid}
studyUuid={gridContext.studyUuid}
onModifyRegulatingTerminalGenerator={(updatedRegulatedTerminal: any) => {
handleSaveRegulatingTerminalPopup(updatedRegulatedTerminal);
diff --git a/src/components/study-container.jsx b/src/components/study-container.jsx
index 65ed6b1c93..459294497f 100644
--- a/src/components/study-container.jsx
+++ b/src/components/study-container.jsx
@@ -21,7 +21,10 @@ import {
resetEquipmentsPostLoadflow,
setStudyIndexationStatus,
limitReductionModified,
+ setCurrentRootNetwork,
} from '../redux/actions';
+import { fetchRootNetworks } from 'services/root-network';
+
import WaitingLoader from './utils/waiting-loader';
import { useIntlRef, useSnackMessage } from '@gridsuite/commons-ui';
import NetworkModificationTreeModel from './graph/network-modification-tree-model';
@@ -48,14 +51,27 @@ import { StudyIndexationStatus } from 'redux/reducer';
import { fetchDirectoryElementPath } from '@gridsuite/commons-ui';
import { NodeType } from './graph/tree-node.type';
-function isWorthUpdate(studyUpdatedForce, fetcher, lastUpdateRef, nodeUuidRef, nodeUuid, invalidations) {
+function isWorthUpdate(
+ studyUpdatedForce,
+ fetcher,
+ lastUpdateRef,
+ nodeUuidRef,
+ rootNetworkUuidRef,
+ nodeUuid,
+ rootNetworkUuid,
+ invalidations
+) {
const headers = studyUpdatedForce?.eventData?.headers;
const updateType = headers?.[UPDATE_TYPE_HEADER];
const node = headers?.['node'];
const nodes = headers?.['nodes'];
+
if (nodeUuidRef.current !== nodeUuid) {
return true;
}
+ if (rootNetworkUuidRef.current !== rootNetworkUuid) {
+ return true;
+ }
if (fetcher && lastUpdateRef.current?.fetcher !== fetcher) {
return true;
}
@@ -78,21 +94,31 @@ function isWorthUpdate(studyUpdatedForce, fetcher, lastUpdateRef, nodeUuidRef, n
return false;
}
-export function useNodeData(studyUuid, nodeUuid, fetcher, invalidations, defaultValue, resultConversion) {
+export function useNodeData(
+ studyUuid,
+ nodeUuid,
+ currentRootNetworkUuid,
+ fetcher,
+ invalidations,
+ defaultValue,
+ resultConversion
+) {
const [result, setResult] = useState(defaultValue);
const [isPending, setIsPending] = useState(false);
const [errorMessage, setErrorMessage] = useState(undefined);
const nodeUuidRef = useRef();
+ const rootNetworkUuidRef = useRef();
const studyUpdatedForce = useSelector((state) => state.studyUpdated);
const lastUpdateRef = useRef();
const update = useCallback(() => {
nodeUuidRef.current = nodeUuid;
+ rootNetworkUuidRef.current = currentRootNetworkUuid;
setIsPending(true);
setErrorMessage(undefined);
- fetcher(studyUuid, nodeUuid)
+ fetcher(studyUuid, nodeUuid, currentRootNetworkUuid)
.then((res) => {
- if (nodeUuidRef.current === nodeUuid) {
+ if (nodeUuidRef.current === nodeUuid && rootNetworkUuidRef.current === currentRootNetworkUuid) {
setResult(resultConversion ? resultConversion(res) : res);
}
})
@@ -101,11 +127,11 @@ export function useNodeData(studyUuid, nodeUuid, fetcher, invalidations, default
setResult(RunningStatus.FAILED);
})
.finally(() => setIsPending(false));
- }, [nodeUuid, fetcher, studyUuid, resultConversion]);
+ }, [nodeUuid, fetcher, currentRootNetworkUuid, studyUuid, resultConversion]);
/* initial fetch and update */
useEffect(() => {
- if (!studyUuid || !nodeUuid || !fetcher) {
+ if (!studyUuid || !nodeUuid || !currentRootNetworkUuid || !fetcher) {
return;
}
const isUpdateForUs = isWorthUpdate(
@@ -113,19 +139,26 @@ export function useNodeData(studyUuid, nodeUuid, fetcher, invalidations, default
fetcher,
lastUpdateRef,
nodeUuidRef,
+ rootNetworkUuidRef,
nodeUuid,
+ currentRootNetworkUuid,
invalidations
);
lastUpdateRef.current = { studyUpdatedForce, fetcher };
- if (nodeUuidRef.current !== nodeUuid || isUpdateForUs) {
+ if (
+ nodeUuidRef.current !== nodeUuid ||
+ rootNetworkUuidRef.current !== currentRootNetworkUuid ||
+ isUpdateForUs
+ ) {
update();
}
- }, [update, fetcher, nodeUuid, invalidations, studyUpdatedForce, studyUuid]);
+ }, [update, fetcher, nodeUuid, invalidations, currentRootNetworkUuid, studyUpdatedForce, studyUuid]);
return [result, isPending, setResult, errorMessage, update];
}
function useStudy(studyUuidRequest) {
+ const dispatch = useDispatch();
const [studyUuid, setStudyUuid] = useState(undefined);
const [pending, setPending] = useState(true);
const [errMessage, setErrMessage] = useState(undefined);
@@ -135,8 +168,32 @@ function useStudy(studyUuidRequest) {
fetchStudyExists(studyUuidRequest)
.then(() => {
setStudyUuid(studyUuidRequest);
+
+ // Fetch root networks and set the first one as the current root network
+ fetchRootNetworks(studyUuidRequest)
+ .then((rootNetworks) => {
+ if (rootNetworks && rootNetworks.length > 0) {
+ // Validate that currentRootNetwork is set
+ dispatch(setCurrentRootNetwork(rootNetworks[0].rootNetworkUuid));
+ } else {
+ // Handle case where no root networks are available
+ setErrMessage(
+ intlRef.current.formatMessage(
+ { id: 'rootNetworkNotFound' },
+ { studyUuid: studyUuidRequest }
+ )
+ );
+ }
+ })
+ .catch((error) => {
+ // Handle errors when fetching root networks
+ setErrMessage(
+ intlRef.current.formatMessage({ id: 'rootNetworkNotFound' }, { error: error.message })
+ );
+ });
})
.catch((error) => {
+ // Handle errors when fetching study existence
if (error.status === HttpStatusCode.NOT_FOUND) {
setErrMessage(
intlRef.current.formatMessage({ id: 'studyNotFound' }, { studyUuid: studyUuidRequest })
@@ -146,7 +203,7 @@ function useStudy(studyUuidRequest) {
}
})
.finally(() => setPending(false));
- }, [studyUuidRequest, intlRef]);
+ }, [studyUuidRequest, dispatch, intlRef]);
return [studyUuid, pending, errMessage];
}
@@ -191,10 +248,12 @@ export function StudyContainer({ view, onChangeTab }) {
const dispatch = useDispatch();
const currentNode = useSelector((state) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state) => state.currentRootNetwork);
const currentNodeRef = useRef();
+ const currentRootNetworkRef = useRef();
- useAllComputingStatus(studyUuid, currentNode?.id);
+ useAllComputingStatus(studyUuid, currentNode?.id, currentRootNetworkUuid);
const studyUpdatedForce = useSelector((state) => state.studyUpdated);
@@ -210,10 +269,16 @@ export function StudyContainer({ view, onChangeTab }) {
(eventData) => {
const updateTypeHeader = eventData.headers[UPDATE_TYPE_HEADER];
const errorMessage = eventData.headers[ERROR_HEADER];
+ const currentRootNetwork = eventData.headers['rootNetwork'];
+
const userId = eventData.headers[USER_HEADER];
if (userId != null && userId !== userName) {
return;
}
+ if (currentRootNetwork !== currentRootNetworkRef.current) {
+ return;
+ }
+
if (updateTypeHeader === 'loadflow_failed') {
snackError({
headerId: 'LoadFlowError',
@@ -283,6 +348,10 @@ export function StudyContainer({ view, onChangeTab }) {
const sendAlert = useCallback(
(eventData) => {
const userId = eventData.headers[USER_HEADER];
+ const currentRootNetwork = eventData.headers['rootNetwork'];
+ if (currentRootNetworkRef.current !== currentRootNetwork && currentRootNetwork) {
+ return;
+ }
if (userId !== userName) {
return;
}
@@ -437,14 +506,14 @@ export function StudyContainer({ view, onChangeTab }) {
(initIndexationStatus) => {
console.info(`Loading network modification tree of study '${studyUuid}'...`);
- const networkModificationTree = fetchNetworkModificationTree(studyUuid);
+ const networkModificationTree = fetchNetworkModificationTree(studyUuid, currentRootNetworkUuid);
networkModificationTree
.then((tree) => {
const networkModificationTreeModel = new NetworkModificationTreeModel();
networkModificationTreeModel.setTreeElements(tree);
- fetchCaseName(studyUuid)
+ fetchCaseName(studyUuid, currentRootNetworkUuid)
.then((res) => {
if (res) {
networkModificationTreeModel.setCaseName(res);
@@ -486,12 +555,12 @@ export function StudyContainer({ view, onChangeTab }) {
.finally(() => console.debug('Network modification tree loading finished'));
// Note: studyUuid and dispatch don't change
},
- [studyUuid, dispatch, snackError, snackWarning]
+ [studyUuid, currentRootNetworkUuid, dispatch, snackError, snackWarning]
);
const checkStudyIndexation = useCallback(() => {
setIsStudyIndexationPending(true);
- return fetchStudyIndexationStatus(studyUuid)
+ return fetchStudyIndexationStatus(studyUuid, currentRootNetworkUuid)
.then((status) => {
switch (status) {
case StudyIndexationStatus.INDEXED: {
@@ -505,7 +574,7 @@ export function StudyContainer({ view, onChangeTab }) {
}
case StudyIndexationStatus.NOT_INDEXED: {
dispatch(setStudyIndexationStatus(status));
- reindexAllStudy(studyUuid)
+ reindexAllStudy(studyUuid, currentRootNetworkUuid)
.catch((error) => {
// unknown error when trying to reindex study
snackError({
@@ -536,11 +605,11 @@ export function StudyContainer({ view, onChangeTab }) {
headerId: 'checkstudyIndexationError',
});
});
- }, [studyUuid, dispatch, snackError]);
+ }, [studyUuid, currentRootNetworkUuid, dispatch, snackError]);
const checkNetworkExistenceAndRecreateIfNotFound = useCallback(
(successCallback) => {
- fetchNetworkExistence(studyUuid)
+ fetchNetworkExistence(studyUuid, currentRootNetworkUuid)
.then((response) => {
if (response.status === HttpStatusCode.OK) {
successCallback && successCallback();
@@ -550,7 +619,7 @@ export function StudyContainer({ view, onChangeTab }) {
// response.state === NO_CONTENT
// if network is not found, we try to recreate study network from existing case
setIsStudyNetworkFound(false);
- recreateStudyNetwork(studyUuid)
+ recreateStudyNetwork(studyUuid, currentRootNetworkUuid)
.then(() => {
snackWarning({
headerId: 'recreatingNetworkStudy',
@@ -584,14 +653,17 @@ export function StudyContainer({ view, onChangeTab }) {
);
});
},
- [studyUuid, checkStudyIndexation, loadTree, snackWarning, intlRef]
+ [studyUuid, currentRootNetworkUuid, checkStudyIndexation, loadTree, snackWarning, intlRef]
);
useEffect(() => {
- if (studyUuid && !isStudyNetworkFound) {
+ if (
+ (studyUuid && currentRootNetworkUuid && !isStudyNetworkFound) ||
+ (currentRootNetworkRef.current && currentRootNetworkRef.current !== currentRootNetworkUuid)
+ ) {
checkNetworkExistenceAndRecreateIfNotFound();
}
- }, [isStudyNetworkFound, checkNetworkExistenceAndRecreateIfNotFound, studyUuid]);
+ }, [isStudyNetworkFound, currentRootNetworkUuid, checkNetworkExistenceAndRecreateIfNotFound, studyUuid]);
// study_network_recreation_done notification
// checking another time if we can find network, if we do, we display a snackbar info
@@ -626,6 +698,9 @@ export function StudyContainer({ view, onChangeTab }) {
}
let previousCurrentNode = currentNodeRef.current;
currentNodeRef.current = currentNode;
+
+ let previousCurrentRootNetwork = currentRootNetworkRef.current;
+ currentRootNetworkRef.current = currentRootNetworkUuid;
// if only node renaming, do not reload network
if (isNodeRenamed(previousCurrentNode, currentNode)) {
return;
@@ -635,15 +710,23 @@ export function StudyContainer({ view, onChangeTab }) {
}
// A modification has been added to the currentNode and this one has been built incrementally.
// No need to load the network because reloadImpactedSubstationsEquipments will be executed in the notification useEffect.
- if (isSameNode(previousCurrentNode, currentNode) && isNodeBuilt(previousCurrentNode)) {
+ if (
+ previousCurrentRootNetwork === currentRootNetworkUuid &&
+ isSameNode(previousCurrentNode, currentNode) &&
+ isNodeBuilt(previousCurrentNode)
+ ) {
return;
}
dispatch(resetEquipments());
- }, [currentNode, wsConnected, dispatch]);
+ }, [currentNode, currentRootNetworkUuid, wsConnected, dispatch]);
useEffect(() => {
if (studyUpdatedForce.eventData.headers) {
- if (studyUpdatedForce.eventData.headers[UPDATE_TYPE_HEADER] === 'loadflowResult') {
+ const currentRootNetwork = studyUpdatedForce.eventData.headers['rootNetwork'];
+ if (
+ studyUpdatedForce.eventData.headers[UPDATE_TYPE_HEADER] === 'loadflowResult' &&
+ currentRootNetwork === currentRootNetworkRef.current
+ ) {
dispatch(resetEquipmentsPostLoadflow());
}
}
@@ -740,6 +823,7 @@ export function StudyContainer({ view, onChangeTab }) {
{
+const StudyPane = ({ studyUuid, currentRootNetworkUuid, currentNode, setErrorMessage, ...props }) => {
const [tableEquipment, setTableEquipment] = useState({
id: null,
type: null,
@@ -82,6 +82,7 @@ const StudyPane = ({ studyUuid, currentNode, setErrorMessage, ...props }) => {
{
{
/>
-
{
{
const currentNode = useSelector((state) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state) => state.currentRootNetwork);
const [equipmentInfo, setEquipmentInfo] = useState(null);
const intl = useIntl();
const [localAnchorEl, setLocalAnchorEl] = useState(null);
const [localAnchorPosition, setLocalAnchorPosition] = useState(null);
const getNetworkElementInfos = useCallback(
- (equipmentId, equipmentType, currentNodeId, studyUuid) => {
+ (equipmentId, equipmentType, currentRootNetworkUuid, currentNodeId, studyUuid) => {
fetchNetworkElementInfos(
studyUuid,
currentNodeId,
+ currentRootNetworkUuid,
equipmentType,
EQUIPMENT_INFOS_TYPES.TOOLTIP.type,
equipmentId,
@@ -67,11 +69,11 @@ const EquipmentPopover = ({ studyUuid, anchorEl, anchorPosition, equipmentId, eq
useEffect(() => {
if (equipmentId && equipmentId !== '') {
- debouncedNetworkElementInfos(equipmentId, equipmentType, currentNode.id, studyUuid);
+ debouncedNetworkElementInfos(equipmentId, equipmentType, currentRootNetworkUuid, currentNode.id, studyUuid);
} else {
setEquipmentInfo(null);
}
- }, [debouncedNetworkElementInfos, equipmentId, equipmentType, currentNode.id, studyUuid]);
+ }, [debouncedNetworkElementInfos, equipmentId, equipmentType, currentNode.id, studyUuid, currentRootNetworkUuid]);
const handlePopoverClose = () => {
setEquipmentInfo(null);
diff --git a/src/components/top-bar-equipment-seach-dialog/custom-suffix-renderer.tsx b/src/components/top-bar-equipment-seach-dialog/custom-suffix-renderer.tsx
index 4106782cb7..258f7fb209 100644
--- a/src/components/top-bar-equipment-seach-dialog/custom-suffix-renderer.tsx
+++ b/src/components/top-bar-equipment-seach-dialog/custom-suffix-renderer.tsx
@@ -28,13 +28,14 @@ export const CustomSuffixRenderer: FunctionComponent
const dispatch = useDispatch();
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const networkAreaDiagramNbVoltageLevels = useSelector((state: AppState) => state.networkAreaDiagramNbVoltageLevels);
const networkAreaDiagramDepth = useSelector((state: AppState) => state.networkAreaDiagramDepth);
const centerOnSubstationCB = useCallback(
(e: ReactMouseEvent) => {
e.stopPropagation();
- if (!studyUuid || !currentNode) {
+ if (!studyUuid || !currentNode || !currentRootNetworkUuid) {
return;
}
let substationIdPromise;
@@ -42,7 +43,12 @@ export const CustomSuffixRenderer: FunctionComponent
if (element.type === EQUIPMENT_TYPES.SUBSTATION) {
substationIdPromise = Promise.resolve(element.id);
} else {
- substationIdPromise = fetchSubstationIdForVoltageLevel(studyUuid, currentNode.id, element.id);
+ substationIdPromise = fetchSubstationIdForVoltageLevel(
+ studyUuid,
+ currentNode.id,
+ currentRootNetworkUuid,
+ element.id
+ );
}
substationIdPromise.then((substationId) => {
dispatch(centerOnSubstation(substationId));
@@ -50,7 +56,7 @@ export const CustomSuffixRenderer: FunctionComponent
e.stopPropagation();
});
},
- [studyUuid, currentNode, element.type, element.id, dispatch, onClose]
+ [studyUuid, currentNode, currentRootNetworkUuid, element.type, element.id, dispatch, onClose]
);
const openNetworkAreaDiagramCB = useCallback(
diff --git a/src/components/top-bar-equipment-seach-dialog/top-bar-equipment-search-dialog.tsx b/src/components/top-bar-equipment-seach-dialog/top-bar-equipment-search-dialog.tsx
index 77b163c459..0151cde13f 100644
--- a/src/components/top-bar-equipment-seach-dialog/top-bar-equipment-search-dialog.tsx
+++ b/src/components/top-bar-equipment-seach-dialog/top-bar-equipment-search-dialog.tsx
@@ -42,6 +42,7 @@ export const TopBarEquipmentSearchDialog: FunctionComponent state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetworkUuid = useSelector((state: AppState) => state.currentRootNetwork);
const [equipmentTypeFilter, setEquipmentTypeFilter] = useState(null);
const { searchTerm, updateSearchTerm, equipmentsFound, isLoading } = useTopBarSearchMatchingEquipment({
@@ -49,6 +50,9 @@ export const TopBarEquipmentSearchDialog: FunctionComponent {
- const { studyUuid, nodeUuid, inUpstreamBuiltParentNode, equipmentType } = props;
+ const { studyUuid, nodeUuid, currentRootNetworkUuid, inUpstreamBuiltParentNode, equipmentType } = props;
const { getUseNameParameterKey, getNameOrId } = useNameOrId();
@@ -28,12 +29,13 @@ export const useSearchMatchingEquipments = (props: UseSearchMatchingEquipmentsPr
searchEquipmentsInfos(
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
newSearchTerm,
getUseNameParameterKey,
inUpstreamBuiltParentNode,
equipmentType
),
- [equipmentType, getUseNameParameterKey, inUpstreamBuiltParentNode, nodeUuid, studyUuid]
+ [equipmentType, getUseNameParameterKey, inUpstreamBuiltParentNode, nodeUuid, studyUuid, currentRootNetworkUuid]
);
const { elementsFound, isLoading, searchTerm, updateSearchTerm } = useElementSearch({
diff --git a/src/components/top-bar-equipment-seach-dialog/use-top-bar-search-matching-equipments.tsx b/src/components/top-bar-equipment-seach-dialog/use-top-bar-search-matching-equipments.tsx
index 3475adf117..1aec61fe8b 100644
--- a/src/components/top-bar-equipment-seach-dialog/use-top-bar-search-matching-equipments.tsx
+++ b/src/components/top-bar-equipment-seach-dialog/use-top-bar-search-matching-equipments.tsx
@@ -13,14 +13,16 @@ import { EquipmentType } from '@gridsuite/commons-ui';
interface UseTopBarSearchMatchingEquipmentProps {
studyUuid: UUID;
nodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
equipmentType?: EquipmentType;
}
export const useTopBarSearchMatchingEquipment = (props: UseTopBarSearchMatchingEquipmentProps) => {
- const { nodeUuid, studyUuid, equipmentType } = props;
+ const { nodeUuid, studyUuid, currentRootNetworkUuid, equipmentType } = props;
const { equipmentsFound, searchTerm, ...otherStates } = useSearchMatchingEquipments({
studyUuid: studyUuid,
nodeUuid: nodeUuid,
+ currentRootNetworkUuid: currentRootNetworkUuid,
equipmentType: equipmentType ?? undefined,
});
diff --git a/src/components/utils/field-constants.ts b/src/components/utils/field-constants.ts
index 8bf2123b68..067a72f02f 100644
--- a/src/components/utils/field-constants.ts
+++ b/src/components/utils/field-constants.ts
@@ -19,6 +19,8 @@ export const DESTINATION_FOLDER = 'destinationFolder';
export const FOLDER_NAME = 'folderName';
export const FOLDER_ID = 'folderId';
export const DESCRIPTION = 'description';
+export const CASE_NAME = 'caseName';
+export const CASE_ID = 'caseId';
export const SUBSTATION_ID = 'substationId';
export const NOMINAL_VOLTAGE = 'nominalVoltage';
export const NOMINAL_V = 'nominalV';
diff --git a/src/components/voltage-init-result-tab.jsx b/src/components/voltage-init-result-tab.jsx
index 9d2fdd288f..bfa4dc2491 100644
--- a/src/components/voltage-init-result-tab.jsx
+++ b/src/components/voltage-init-result-tab.jsx
@@ -15,12 +15,13 @@ import RunningStatus from './utils/running-status';
const voltageInitResultInvalidations = ['voltageInitResult'];
-export const VoltageInitResultTab = ({ studyUuid, nodeUuid }) => {
+export const VoltageInitResultTab = ({ studyUuid, nodeUuid, currentRootNetworkUuid }) => {
const voltageInitStatus = useSelector((state) => state.computingStatus[ComputingType.VOLTAGE_INITIALIZATION]);
const [voltageInitResult, isWaiting] = useNodeData(
studyUuid,
nodeUuid,
+ currentRootNetworkUuid,
fetchVoltageInitResult,
voltageInitResultInvalidations
);
diff --git a/src/hooks/use-get-study-impacts.ts b/src/hooks/use-get-study-impacts.ts
index f6c31ad8da..090f7d3050 100644
--- a/src/hooks/use-get-study-impacts.ts
+++ b/src/hooks/use-get-study-impacts.ts
@@ -40,6 +40,7 @@ export const useGetStudyImpacts = (): StudyImpactsWithReset => {
useEffect(() => {
if (studyUpdatedForce.type === NotificationType.STUDY) {
+ console.log('TEST ====== ', studyUpdatedForce);
const {
impactedSubstationsIds: substationsIds,
deletedEquipments,
diff --git a/src/hooks/use-report-fetcher.tsx b/src/hooks/use-report-fetcher.tsx
index 0c48ef6c70..99ad7222e0 100644
--- a/src/hooks/use-report-fetcher.tsx
+++ b/src/hooks/use-report-fetcher.tsx
@@ -81,6 +81,7 @@ export const useReportFetcher = (
const [isLoading, setIsLoading] = useState(false);
const studyUuid = useSelector((state: AppState) => state.studyUuid);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
+ const currentRootNetwork = useSelector((state: AppState) => state.currentRootNetwork);
const treeModel = useSelector((state: AppState) => state.networkModificationTreeModel);
const { snackError } = useSnackMessage();
@@ -116,11 +117,12 @@ export const useReportFetcher = (
const fetchRawParentReport = useCallback(
(nodeOnlyReport?: boolean) => {
- if (currentNode !== null && studyUuid) {
+ if (currentNode !== null && studyUuid && currentRootNetwork) {
return fetch(() =>
fetchParentNodesReport(
studyUuid,
currentNode.id,
+ currentRootNetwork,
nodeOnlyReport ?? true,
getContainerDefaultSeverityList(),
computingAndNetworkModificationType
@@ -129,27 +131,43 @@ export const useReportFetcher = (
}
return Promise.resolve(undefined);
},
- [currentNode, fetch, computingAndNetworkModificationType, studyUuid]
+ [currentNode, currentRootNetwork, fetch, computingAndNetworkModificationType, studyUuid]
);
const fetchReportLogs = useCallback(
(reportId: string, severityList: string[], reportType: ReportType, messageFilter: string) => {
- if (!studyUuid) {
+ if (!studyUuid || !currentRootNetwork) {
return;
}
let fetchPromise: (severityList: string[], reportId: string) => Promise;
if (reportType === ReportType.GLOBAL) {
fetchPromise = (severityList: string[]) =>
- fetchNodeReportLogs(studyUuid, currentNode!.id, null, severityList, messageFilter, true);
+ fetchNodeReportLogs(
+ studyUuid,
+ currentNode!.id,
+ currentRootNetwork,
+ null,
+ severityList,
+ messageFilter,
+ true
+ );
} else {
fetchPromise = (severityList: string[], reportId: string) =>
- fetchNodeReportLogs(studyUuid, currentNode!.id, reportId, severityList, messageFilter, false);
+ fetchNodeReportLogs(
+ studyUuid,
+ currentNode!.id,
+ currentRootNetwork,
+ reportId,
+ severityList,
+ messageFilter,
+ false
+ );
}
return fetchPromise(severityList, reportId).then((r) => {
return mapReportLogs(prettifyReportLogMessage(r, nodesNames));
});
},
- [currentNode, studyUuid, nodesNames]
+ [currentNode, currentRootNetwork, studyUuid, nodesNames]
);
const fetchReportSeverities = useCallback(
diff --git a/src/hooks/use-voltage-levels-list-infos.ts b/src/hooks/use-voltage-levels-list-infos.ts
index ee4d2f4362..0a4fd827b7 100644
--- a/src/hooks/use-voltage-levels-list-infos.ts
+++ b/src/hooks/use-voltage-levels-list-infos.ts
@@ -9,16 +9,16 @@ import { UUID } from 'crypto';
import { useEffect, useState } from 'react';
import { fetchVoltageLevelsListInfos } from '../services/study/network';
-export default function useVoltageLevelsListInfos(studyUuid: UUID, nodeUuid: UUID) {
+export default function useVoltageLevelsListInfos(studyUuid: UUID, nodeUuid: UUID, currentRootNetworkUuid: UUID) {
const [voltageLevelsListInfos, setVoltageLevelsListInfos] = useState([]);
useEffect(() => {
- if (studyUuid && nodeUuid) {
- fetchVoltageLevelsListInfos(studyUuid, nodeUuid).then((values) => {
+ if (studyUuid && nodeUuid && currentRootNetworkUuid) {
+ fetchVoltageLevelsListInfos(studyUuid, nodeUuid, currentRootNetworkUuid).then((values) => {
setVoltageLevelsListInfos(
values.sort((a: { id: string }, b: { id: string }) => a.id.localeCompare(b.id))
);
});
}
- }, [studyUuid, nodeUuid]);
+ }, [studyUuid, nodeUuid, currentRootNetworkUuid]);
return voltageLevelsListInfos;
}
diff --git a/src/redux/actions.ts b/src/redux/actions.ts
index 58ed64eee1..33e88f423f 100644
--- a/src/redux/actions.ts
+++ b/src/redux/actions.ts
@@ -609,6 +609,17 @@ export function setCurrentTreeNode(currentTreeNode: CurrentTreeNode): CurrentTre
};
}
+export const CURRENT_ROOT_NETWORK = 'CURRENT_ROOT_NETWORK';
+export type CurrentRootNetworkAction = Readonly> & {
+ currentRootNetwork: UUID;
+};
+export function setCurrentRootNetwork(currentRootNetwork: UUID): CurrentRootNetworkAction {
+ return {
+ type: CURRENT_ROOT_NETWORK,
+ currentRootNetwork: currentRootNetwork,
+ };
+}
+
export const NODE_SELECTION_FOR_COPY = 'NODE_SELECTION_FOR_COPY';
export type NodeSelectionForCopyAction = Readonly> & {
nodeSelectionForCopy: NonNullable;
diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts
index 18ca908f9b..63468cedfc 100644
--- a/src/redux/reducer.ts
+++ b/src/redux/reducer.ts
@@ -184,6 +184,8 @@ import {
UseNameAction,
STATEESTIMATION_RESULT_FILTER,
StateEstimationResultFilterAction,
+ CURRENT_ROOT_NETWORK,
+ CurrentRootNetworkAction,
UPDATE_NETWORK_VISUALIZATION_PARAMETERS,
UpdateNetworkVisualizationParametersAction,
} from './actions';
@@ -314,6 +316,7 @@ export interface OneBusShortCircuitAnalysisDiagram {
export interface StudyUpdatedEventDataHeader {
studyUuid: UUID;
parentNode: UUID;
+ rootNetwork: UUID;
timestamp: number;
updateType?: string;
node?: UUID;
@@ -443,6 +446,7 @@ export interface AppState extends CommonStoreState {
studyUpdated: StudyUpdated;
studyUuid: UUID | null;
currentTreeNode: CurrentTreeNode | null;
+ currentRootNetwork: UUID | null;
computingStatus: ComputingStatus;
lastCompletedComputation: ComputingType | null;
computationStarting: boolean;
@@ -606,6 +610,7 @@ const initialTablesState: TablesState = {
const initialState: AppState = {
studyUuid: null,
currentTreeNode: null,
+ currentRootNetwork: null,
nodeSelectionForCopy: {
sourceStudyUuid: null,
nodeId: null,
@@ -1144,6 +1149,11 @@ export const reducer = createReducer(initialState, (builder) => {
state.reloadMap = true;
});
+ builder.addCase(CURRENT_ROOT_NETWORK, (state, action: CurrentRootNetworkAction) => {
+ state.currentRootNetwork = action.currentRootNetwork;
+ state.reloadMap = true;
+ });
+
builder.addCase(NODE_SELECTION_FOR_COPY, (state, action: NodeSelectionForCopyAction) => {
const nodeSelectionForCopy = action.nodeSelectionForCopy;
if (
diff --git a/src/services/dynamic-simulation.ts b/src/services/dynamic-simulation.ts
index 7998bd9fb7..e7a2a398a1 100644
--- a/src/services/dynamic-simulation.ts
+++ b/src/services/dynamic-simulation.ts
@@ -7,7 +7,7 @@
import { Event } from '../components/dialogs/dynamicsimulation/event/types/event.type';
import { backendFetch, backendFetchJson, getRequestParamFromList } from './utils';
-import { getStudyUrlWithNodeUuid } from './study';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid } from './study';
import { UUID } from 'crypto';
import {
TimelineEvent,
@@ -30,55 +30,83 @@ export function fetchDynamicSimulationProviders() {
export function fetchDynamicSimulationTimeSeriesMetadata(
studyUuid: UUID,
- currentNodeUuid: UUID
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID
): Promise {
console.info(
- `Fetching dynamic simulation time series's metadata on '${studyUuid}' and node '${currentNodeUuid}' ...`
+ `Fetching dynamic simulation time series's metadata on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/dynamic-simulation/result/timeseries/metadata';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/dynamic-simulation/result/timeseries/metadata';
console.debug(url);
return backendFetchJson(url);
}
export function fetchDynamicSimulationResultTimeline(
studyUuid: UUID,
- currentNodeUuid: UUID
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID
): Promise {
- console.info(`Fetching dynamic simulation timeline result on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/dynamic-simulation/result/timeline';
+ console.info(
+ `Fetching dynamic simulation timeline result on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/dynamic-simulation/result/timeline';
console.debug(url);
return backendFetchJson(url);
}
// --- Event API - BEGIN
-
-export function fetchDynamicSimulationEvents(studyUuid: UUID, nodeUuid: UUID): Promise {
+//TODO: should not be linked to rootnetworkUUID
+export function fetchDynamicSimulationEvents(
+ studyUuid: UUID,
+ nodeUuid: UUID,
+ currentRootNetworkUuid: UUID
+): Promise {
console.info(`Fetching dynamic simulation events on '${studyUuid}' and node '${nodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + '/dynamic-simulation/events';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ '/dynamic-simulation/events';
console.debug(url);
return backendFetchJson(url);
}
-export function fetchDynamicSimulationEvent(studyUuid: UUID, nodeUuid: UUID, equipmentId: string): Promise {
+export function fetchDynamicSimulationEvent(
+ studyUuid: UUID,
+ nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ equipmentId: string
+): Promise {
console.info(
`Fetching dynamic simulation event with '${equipmentId}' on '${studyUuid}' and node '${nodeUuid}' ...`
);
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + `/dynamic-simulation/events?equipmentId=${equipmentId}`;
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ `/dynamic-simulation/events?equipmentId=${equipmentId}`;
console.debug(url);
return backendFetchJson(url);
}
-export function saveDynamicSimulationEvent(studyUuid: UUID, nodeUuid: UUID, event: Event) {
+export function saveDynamicSimulationEvent(
+ studyUuid: UUID,
+ nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ event: Event
+) {
console.info(`Saving dynamic simulation event on '${studyUuid}' and node '${nodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + `/dynamic-simulation/events`;
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ `/dynamic-simulation/events`;
console.debug(url);
return backendFetch(url, {
@@ -91,7 +119,12 @@ export function saveDynamicSimulationEvent(studyUuid: UUID, nodeUuid: UUID, even
});
}
-export function deleteDynamicSimulationEvents(studyUuid: UUID, nodeUuid: UUID, events: Event[]) {
+export function deleteDynamicSimulationEvents(
+ studyUuid: UUID,
+ nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ events: Event[]
+) {
console.info(`Delete dynamic simulation events on '${studyUuid}' and node '${nodeUuid}' ...`);
const eventIdsParams = getRequestParamFromList(
@@ -99,7 +132,9 @@ export function deleteDynamicSimulationEvents(studyUuid: UUID, nodeUuid: UUID, e
'eventUuids'
);
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + `/dynamic-simulation/events?${eventIdsParams}`;
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ `/dynamic-simulation/events?${eventIdsParams}`;
console.debug(url);
diff --git a/src/services/network-conversion.ts b/src/services/network-conversion.ts
index ffa815c369..4f497df213 100644
--- a/src/services/network-conversion.ts
+++ b/src/services/network-conversion.ts
@@ -23,7 +23,7 @@ export interface GetCaseImportParametersReturn {
parameters: CaseImportParameters[];
}
-export function getCaseImportParameters(caseUuid: UUID): Promise {
+export function getCaseImportParameters(caseUuid: UUID | undefined): Promise {
console.info(`get import parameters for case '${caseUuid}' ...`);
const getExportFormatsUrl =
PREFIX_NETWORK_CONVERSION_SERVER_QUERIES + '/v1/cases/' + caseUuid + '/import-parameters';
diff --git a/src/services/root-network.ts b/src/services/root-network.ts
new file mode 100644
index 0000000000..4d31ced499
--- /dev/null
+++ b/src/services/root-network.ts
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2024, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import { backendFetch, backendFetchJson } from './utils';
+import { UUID } from 'crypto';
+
+export const PREFIX_STUDY_QUERIES = import.meta.env.VITE_API_GATEWAY + '/study';
+
+export function fetchRootNetworks(studyUuid: UUID) {
+ console.info('Fetching root network for studyUuid : ', studyUuid);
+ const urlSearchParams = new URLSearchParams();
+ const rootNetworkssGetUrl =
+ `${PREFIX_STUDY_QUERIES}/v1/studies/${encodeURIComponent(studyUuid)}/root-networks` +
+ urlSearchParams.toString();
+
+ console.debug(rootNetworkssGetUrl);
+ return backendFetchJson(rootNetworkssGetUrl);
+}
+
+export const createRootNetwork = (
+ caseUuid: UUID | undefined,
+ caseFormat: string,
+ studyUuid: UUID | null,
+ importParameters: Record
+) => {
+ if (!studyUuid || !caseUuid) {
+ throw new Error('studyUuid and caseUuid are required parameters.');
+ }
+
+ const createRootNetworkUrl =
+ PREFIX_STUDY_QUERIES +
+ `/v1/studies/${encodeURIComponent(studyUuid)}/root-networks?` +
+ `caseUuid=${encodeURIComponent(caseUuid)}&` +
+ `caseFormat=${encodeURIComponent(caseFormat)}`;
+
+ console.debug(createRootNetworkUrl);
+ return backendFetch(createRootNetworkUrl, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: importParameters ? JSON.stringify(importParameters) : '',
+ });
+};
+
+export function deleteRootNetworks(studyUuid: UUID, rootNetworkUuids: UUID[]) {
+ const rootNetworkDeleteUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${encodeURIComponent(studyUuid)}/root-networks`;
+
+ console.debug(rootNetworkDeleteUrl);
+ return backendFetch(rootNetworkDeleteUrl, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(rootNetworkUuids),
+ });
+}
diff --git a/src/services/study/dynamic-simulation.ts b/src/services/study/dynamic-simulation.ts
index 7ec438166d..177d06dd87 100644
--- a/src/services/study/dynamic-simulation.ts
+++ b/src/services/study/dynamic-simulation.ts
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid, PREFIX_STUDY_QUERIES } from './index';
import { backendFetch, backendFetchJson, backendFetchText, getRequestParamFromList } from '../utils';
import { UUID } from 'crypto';
@@ -17,11 +17,20 @@ export function getDynamicMappings(studyUuid: UUID) {
return backendFetchJson(url);
}
-export function startDynamicSimulation(studyUuid: UUID, currentNodeUuid: UUID, dynamicSimulationConfiguration?: any) {
- console.info(`Running dynamic simulation on '${studyUuid}' and node '${currentNodeUuid}' ...`);
-
- const startDynamicSimulationUrl = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/dynamic-simulation/run`;
-
+export function startDynamicSimulation(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ dynamicSimulationConfiguration?: any
+) {
+ console.info(
+ `Running dynamic simulation on '${studyUuid}' on root nerwork '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const startDynamicSimulationUrl = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/dynamic-simulation/run`;
// add body
const body = JSON.stringify(dynamicSimulationConfiguration ?? {});
@@ -37,16 +46,24 @@ export function startDynamicSimulation(studyUuid: UUID, currentNodeUuid: UUID, d
});
}
-export function stopDynamicSimulation(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping dynamic simulation on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const stopDynamicSimulationUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/dynamic-simulation/stop';
+export function stopDynamicSimulation(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping dynamic simulation on '${studyUuid}' for root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const stopDynamicSimulationUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/dynamic-simulation/stop';
console.debug(stopDynamicSimulationUrl);
return backendFetch(stopDynamicSimulationUrl, { method: 'put' });
}
-export function fetchDynamicSimulationStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching dynamic simulation status on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/dynamic-simulation/status';
+export function fetchDynamicSimulationStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching dynamic simulation status on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/dynamic-simulation/status';
console.debug(url);
return backendFetchJson(url);
}
@@ -54,6 +71,7 @@ export function fetchDynamicSimulationStatus(studyUuid: UUID, currentNodeUuid: U
export function fetchDynamicSimulationResultTimeSeries(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
timeSeriesNames: string[]
) {
console.info(`Fetching dynamic simulation time series result on '${studyUuid}' and node '${currentNodeUuid}' ...`);
@@ -62,19 +80,22 @@ export function fetchDynamicSimulationResultTimeSeries(
const timeSeriesParams = getRequestParamFromList(timeSeriesNames, 'timeSeriesNames');
const urlSearchParams = new URLSearchParams(timeSeriesParams);
- const url = `${getStudyUrlWithNodeUuid(
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
studyUuid,
- currentNodeUuid
+ currentNodeUuid,
+ currentRootNetworkUuid
)}/dynamic-simulation/result/timeseries?${urlSearchParams}`;
console.debug(url);
return backendFetchJson(url);
}
-export function fetchDynamicSimulationModels(studyUuid: UUID | null, nodeUuid: UUID) {
- console.info(`Fetching dynamic simulation models on '${studyUuid}' and node '${nodeUuid}' ...`);
-
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + '/dynamic-simulation/models';
+export function fetchDynamicSimulationModels(studyUuid: UUID | null, nodeUuid: UUID, rootNetworkUuid: UUID) {
+ console.info(
+ `Fetching dynamic simulation models on '${studyUuid}' on root network '${rootNetworkUuid}' and node '${nodeUuid}' ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, rootNetworkUuid) + '/dynamic-simulation/models';
console.debug(url);
return backendFetchJson(url);
}
diff --git a/src/services/study/filter.ts b/src/services/study/filter.ts
index 9718e4be24..4694948c34 100644
--- a/src/services/study/filter.ts
+++ b/src/services/study/filter.ts
@@ -7,7 +7,7 @@
import { backendFetchJson } from '../utils';
import { UUID } from 'crypto';
-import { getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { RuleGroupTypeExport } from '../../components/dialogs/filter/expert/expert-filter.type';
import { EQUIPMENT_TYPES } from 'components/utils/equipment-types';
@@ -28,12 +28,16 @@ export interface IdentifiableAttributes {
export function evaluateJsonFilter(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
filter: ExpertFilter // at moment only ExpertFilter but in futur may add others filter types to compose a union type
): Promise {
- console.info(`Get matched elements of study '${studyUuid}' and node '${currentNodeUuid}' ...`);
+ console.info(
+ `Get matched elements of study '${studyUuid}' with a root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
const evaluateFilterUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/filters/evaluate?inUpstreamBuiltParentNode=true';
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/filters/evaluate?inUpstreamBuiltParentNode=true';
console.debug(evaluateFilterUrl);
return backendFetchJson(evaluateFilterUrl, {
method: 'post',
diff --git a/src/services/study/geo-data.ts b/src/services/study/geo-data.ts
index 05a2032b58..0c07c072dd 100644
--- a/src/services/study/geo-data.ts
+++ b/src/services/study/geo-data.ts
@@ -6,31 +6,46 @@
*/
import { backendFetchJson, getQueryParamsList } from '../utils';
-import { getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { UUID } from 'crypto';
-export function fetchSubstationPositions(studyUuid: UUID, currentNodeUuid?: UUID, substationsIds?: string[]) {
+export function fetchSubstationPositions(
+ studyUuid: UUID,
+ currentNodeUuid?: UUID,
+ currentRootNetworkUuid?: UUID,
+ substationsIds?: string[]
+) {
console.info(
- `Fetching substation positions of study '${studyUuid}' and node '${currentNodeUuid}' with ids '${substationsIds}'...`
+ `Fetching substation positions of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' with ids '${substationsIds}'...`
);
const paramsList =
substationsIds && substationsIds.length > 0 ? '?' + getQueryParamsList(substationsIds, 'substationId') : '';
const fetchSubstationPositionsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/geo-data/substations' + paramsList;
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/geo-data/substations' +
+ paramsList;
console.debug(fetchSubstationPositionsUrl);
return backendFetchJson(fetchSubstationPositionsUrl);
}
-export function fetchLinePositions(studyUuid: UUID, currentNodeUuid: UUID | undefined, linesIds?: string[]) {
+export function fetchLinePositions(
+ studyUuid: UUID,
+ currentNodeUuid: UUID | undefined,
+ currentRootNetworkUuid: UUID | undefined,
+ linesIds?: string[]
+) {
console.info(
- `Fetching line positions of study '${studyUuid}' and node '${currentNodeUuid}' with ids '${linesIds}'...`
+ `Fetching line positions of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' with ids '${linesIds}'...`
);
const paramsList = linesIds && linesIds.length > 0 ? '?' + getQueryParamsList(linesIds, 'lineId') : '';
- const fetchLinePositionsUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/geo-data/lines' + paramsList;
+ const fetchLinePositionsUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/geo-data/lines' +
+ paramsList;
console.debug(fetchLinePositionsUrl);
return backendFetchJson(fetchLinePositionsUrl);
diff --git a/src/services/study/index.ts b/src/services/study/index.ts
index 06bf8b943c..ba80e168fb 100644
--- a/src/services/study/index.ts
+++ b/src/services/study/index.ts
@@ -26,6 +26,15 @@ export const PREFIX_STUDY_QUERIES = import.meta.env.VITE_API_GATEWAY + '/study';
export const getStudyUrl = (studyUuid: UUID | null) =>
`${PREFIX_STUDY_QUERIES}/v1/studies/${safeEncodeURIComponent(studyUuid)}`;
+export const getStudyUrlWithNodeUuidAndRootNetworkUuid = (
+ studyUuid: string | null | undefined,
+ nodeUuid: string | undefined,
+ rootNetworkUuid: string | undefined | null
+) =>
+ `${PREFIX_STUDY_QUERIES}/v1/studies/${safeEncodeURIComponent(studyUuid)}/root-networks/${safeEncodeURIComponent(
+ rootNetworkUuid
+ )}/nodes/${safeEncodeURIComponent(nodeUuid)}`;
+
export const getStudyUrlWithNodeUuid = (studyUuid: string | null | undefined, nodeUuid: string | undefined) =>
`${PREFIX_STUDY_QUERIES}/v1/studies/${safeEncodeURIComponent(studyUuid)}/nodes/${safeEncodeURIComponent(nodeUuid)}`;
@@ -46,13 +55,16 @@ export const fetchStudyExists = (studyUuid: UUID) => {
export function getNetworkAreaDiagramUrl(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
voltageLevelsIds: UUID[],
depth: number,
withGeoData: boolean
) {
- console.info(`Getting url of network area diagram of study '${studyUuid}' and node '${currentNodeUuid}'...`);
+ console.info(
+ `Getting url of network area diagram of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}'...`
+ );
return (
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-area-diagram?' +
new URLSearchParams({
depth: depth.toString(),
@@ -66,6 +78,7 @@ export function getNetworkAreaDiagramUrl(
export function fetchParentNodesReport(
studyUuid: UUID | null,
nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
nodeOnlyReport: boolean,
severityFilterList: string[],
reportType: keyof typeof COMPUTING_AND_NETWORK_MODIFICATION_TYPE
@@ -82,7 +95,7 @@ export function fetchParentNodesReport(
);
let url =
- getStudyUrlWithNodeUuid(studyUuid, nodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
'/parent-nodes-report?nodeOnlyReport=' +
(nodeOnlyReport ? 'true' : 'false') +
'&reportType=' +
@@ -97,6 +110,7 @@ export function fetchParentNodesReport(
export function fetchNodeReportLogs(
studyUuid: UUID | null,
nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
reportId: string | null,
severityFilterList: string[],
messageFilter: string,
@@ -104,9 +118,13 @@ export function fetchNodeReportLogs(
) {
let url;
if (isGlobalLogs) {
- url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + '/report/logs?';
+ url = getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) + '/report/logs?';
} else {
- url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + '/report/' + reportId + '/logs?';
+ url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ '/report/' +
+ reportId +
+ '/logs?';
}
if (severityFilterList?.length) {
url += '&' + getRequestParamFromList(severityFilterList, 'severityLevels');
@@ -136,6 +154,7 @@ export function fetchSvg(svgUrl: string) {
export function searchEquipmentsInfos(
studyUuid: UUID,
nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
searchTerm: string,
getUseNameParameterKey: () => 'name' | 'id',
inUpstreamBuiltParentNode?: boolean,
@@ -152,11 +171,18 @@ export function searchEquipmentsInfos(
urlSearchParams.append('equipmentType', equipmentType);
}
return backendFetchJson(
- getStudyUrl(studyUuid) + '/nodes/' + encodeURIComponent(nodeUuid) + '/search?' + urlSearchParams.toString()
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ '/search?' +
+ urlSearchParams.toString()
);
}
-export function fetchContingencyCount(studyUuid: UUID, currentNodeUuid: UUID, contingencyListNames: string[]) {
+export function fetchContingencyCount(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ contingencyListNames: string[]
+) {
console.info(
`Fetching contingency count for ${contingencyListNames} on '${studyUuid}' and node '${currentNodeUuid}'...`
);
@@ -164,7 +190,10 @@ export function fetchContingencyCount(studyUuid: UUID, currentNodeUuid: UUID, co
const contingencyListNamesParams = getRequestParamFromList(contingencyListNames, 'contingencyListName');
const urlSearchParams = new URLSearchParams(contingencyListNamesParams);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/contingency-count?' + urlSearchParams;
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/contingency-count?' +
+ urlSearchParams;
console.debug(url);
return backendFetchJson(url);
@@ -213,23 +242,33 @@ export function getAvailableComponentLibraries(): Promise {
return backendFetchJson(getAvailableComponentLibrariesUrl);
}
-export function unbuildNode(studyUuid: UUID, currentNodeUuid: UUID) {
+export function unbuildNode(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
console.info('Unbuild node ' + currentNodeUuid + ' of study ' + studyUuid + ' ...');
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/unbuild';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) + '/unbuild';
console.debug(url);
return backendFetchText(url, { method: 'post' });
}
-export function buildNode(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info('Build node ' + currentNodeUuid + ' of study ' + studyUuid + ' ...');
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/build';
+export function buildNode(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ 'Build node ' +
+ currentNodeUuid +
+ ' on root network ' +
+ currentRootNetworkUuid +
+ ' of study ' +
+ studyUuid +
+ ' ...'
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) + '/build';
console.debug(url);
return backendFetchText(url, { method: 'post' });
}
-export function fetchCaseName(studyUuid: UUID) {
+export function fetchCaseName(studyUuid: UUID, rootNetworkUuid: UUID) {
console.info('Fetching case name');
- const url = getStudyUrl(studyUuid) + '/case/name';
+ const url = getStudyUrl(studyUuid) + '/root-networks/' + encodeURIComponent(rootNetworkUuid) + '/case/name';
console.debug(url);
return backendFetchText(url);
@@ -270,13 +309,15 @@ export function getServersInfos() {
export function fetchAvailableFilterEnumValues(
studyUuid: UUID,
nodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
computingType: ComputingType,
filterEnum: string
) {
console.info('fetch available filter values');
- const url = `${getStudyUrlWithNodeUuid(
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
studyUuid,
- nodeUuid
+ nodeUuid,
+ currentRootNetworkUuid
)}/computation/result/enum-values?computingType=${encodeURIComponent(computingType)}&enumName=${encodeURIComponent(
filterEnum
)}`;
diff --git a/src/services/study/loadflow.ts b/src/services/study/loadflow.ts
index 08f6572a4e..1c39b0c86b 100644
--- a/src/services/study/loadflow.ts
+++ b/src/services/study/loadflow.ts
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid, PREFIX_STUDY_QUERIES } from './index';
import { backendFetch, backendFetchJson, backendFetchText } from '../utils';
import { UUID } from 'crypto';
import { FilterSelectorType } from 'components/custom-aggrid/custom-aggrid-header.type';
@@ -60,33 +60,58 @@ export function setLoadFlowProvider(studyUuid: UUID, newProvider: string) {
});
}
-export function startLoadFlow(studyUuid: UUID, currentNodeUuid: UUID, limitReduction: number) {
+export function startLoadFlow(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ limitReduction: number
+) {
console.info(
- 'Running loadflow on ' + studyUuid + ' and node ' + currentNodeUuid + ' with limit reduction ' + limitReduction
+ 'Running loadflow on ' +
+ studyUuid +
+ ' on root network ' +
+ currentRootNetworkUuid +
+ ' and node ' +
+ currentNodeUuid +
+ ' with limit reduction ' +
+ limitReduction
);
const startLoadFlowUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/loadflow/run?limitReduction=' +
limitReduction.toString();
console.debug(startLoadFlowUrl);
return backendFetch(startLoadFlowUrl, { method: 'put' });
}
-export function stopLoadFlow(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping loadFlow on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const stopLoadFlowUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/loadflow/stop';
+export function stopLoadFlow(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping loadFlow on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const stopLoadFlowUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/loadflow/stop';
console.debug(stopLoadFlowUrl);
return backendFetch(stopLoadFlowUrl, { method: 'put' });
}
-export function fetchLoadFlowStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching loadFlow status on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/loadflow/status';
+export function fetchLoadFlowStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching loadFlow status on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/loadflow/status';
console.debug(url);
return backendFetchText(url);
}
-export function fetchLoadFlowResult(studyUuid: UUID, currentNodeUuid: UUID, queryParams: QueryParams) {
+export function fetchLoadFlowResult(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ queryParams: QueryParams
+) {
console.info(`Fetching loadflow result on '${studyUuid}' and node '${currentNodeUuid}' ...`);
const { sort, filters } = queryParams || {};
const params = new URLSearchParams({});
@@ -96,13 +121,20 @@ export function fetchLoadFlowResult(studyUuid: UUID, currentNodeUuid: UUID, quer
if (filters?.length) {
params.append('filters', JSON.stringify(filters));
}
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/loadflow/result';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/loadflow/result';
const urlWithParams = `${url}?${params.toString()}`;
console.debug(urlWithParams);
return backendFetchJson(urlWithParams);
}
-export function fetchLimitViolations(studyUuid: UUID, currentNodeUuid: UUID, queryParams: QueryParams) {
+export function fetchLimitViolations(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ queryParams: QueryParams
+) {
console.info(`Fetching limit violations ...`);
const { sort, filters, globalFilters } = queryParams || {};
const params = new URLSearchParams({});
@@ -117,7 +149,9 @@ export function fetchLimitViolations(studyUuid: UUID, currentNodeUuid: UUID, que
params.append('globalFilters', JSON.stringify(globalFilters));
}
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/limit-violations';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/limit-violations';
const urlWithParams = `${url}?${params.toString()}`;
console.debug(urlWithParams);
return backendFetchJson(urlWithParams);
diff --git a/src/services/study/network-map.ts b/src/services/study/network-map.ts
index acc7467796..1dd26113f9 100644
--- a/src/services/study/network-map.ts
+++ b/src/services/study/network-map.ts
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { backendFetchJson, backendFetchText, getQueryParamsList } from '../utils';
import { EQUIPMENT_INFOS_TYPES } from '../../components/utils/equipment-types';
import { EquipmentInfos, EquipmentType, createFilter } from '@gridsuite/commons-ui';
@@ -14,14 +14,19 @@ import { createContingencyList } from 'services/explore';
import { ContingencyList, createIdentifierContingencyList } from './contingency-list';
import { UUID } from 'crypto';
-export function fetchHvdcLineWithShuntCompensators(studyUuid: UUID, currentNodeUuid: UUID, hvdcLineId: string) {
+export function fetchHvdcLineWithShuntCompensators(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ hvdcLineId: string
+) {
console.info(
- `Fetching HVDC Line '${hvdcLineId}' with Shunt Compensators of study '${studyUuid}' and node '${currentNodeUuid}'...`
+ `Fetching HVDC Line '${hvdcLineId}' with Shunt Compensators of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}'...`
);
const urlSearchParams = new URLSearchParams();
urlSearchParams.append('inUpstreamBuiltParentNode', 'true');
const fetchEquipmentsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-map' +
'/hvdc-lines/' +
hvdcLineId +
@@ -31,13 +36,18 @@ export function fetchHvdcLineWithShuntCompensators(studyUuid: UUID, currentNodeU
return backendFetchJson(fetchEquipmentsUrl);
}
-export function fetchAllEquipments(studyUuid: UUID, currentNodeUuid: UUID, substationsIds: string[]) {
+export function fetchAllEquipments(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds: string[]
+) {
console.info(
- `Fetching all equipments of study '${studyUuid}' and node '${currentNodeUuid}' with substations ids '${substationsIds}'...`
+ `Fetching all equipments of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' with substations ids '${substationsIds}'...`
);
const fetchEquipmentsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-map/all' +
'?' +
getQueryParamsList(substationsIds, 'substationId');
@@ -48,12 +58,13 @@ export function fetchAllEquipments(studyUuid: UUID, currentNodeUuid: UUID, subst
export function fetchVoltageLevelEquipments(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[],
voltageLevelId: string,
inUpstreamBuiltParentNode: boolean
) {
console.info(
- `Fetching equipments of study '${studyUuid}' and node '${currentNodeUuid}' and voltage level '${voltageLevelId}' with substations ids '${substationsIds}'...`
+ `Fetching equipments of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' and voltage level '${voltageLevelId}' with substations ids '${substationsIds}'...`
);
const urlSearchParams = new URLSearchParams();
if (inUpstreamBuiltParentNode !== undefined) {
@@ -61,7 +72,7 @@ export function fetchVoltageLevelEquipments(
}
const fetchEquipmentsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-map' +
'/voltage-levels/' +
encodeURIComponent(voltageLevelId) +
@@ -76,6 +87,7 @@ export function fetchVoltageLevelEquipments(
export function fetchEquipmentsIds(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[],
equipmentType: EquipmentType,
inUpstreamBuiltParentNode: boolean,
@@ -93,7 +105,7 @@ export function fetchEquipmentsIds(
const nominalVoltagesParamsList = nominalVoltages && nominalVoltages.length > 0 ? '&' + nominalVoltagesParams : '';
let fetchEquipmentsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-map/' +
'equipments-ids' +
'?' +
@@ -115,6 +127,7 @@ export function fetchEquipmentsIds(
export function fetchVoltageLevelIdForLineOrTransformerBySide(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
equipmentId: string,
side: string
) {
@@ -126,20 +139,22 @@ export function fetchVoltageLevelIdForLineOrTransformerBySide(
urlSearchParams.append('inUpstreamBuiltParentNode', 'true');
urlSearchParams.append('side', side);
- const fetchEquipmentInfosUrl = `${getStudyUrlWithNodeUuid(
+ const fetchEquipmentInfosUrl = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
studyUuid,
- currentNodeUuid
+ currentNodeUuid,
+ currentRootNetworkUuid
)}/network-map/branch-or-3wt/${encodeURIComponent(equipmentId)}/voltage-level-id?${urlSearchParams.toString()}`;
console.debug(fetchEquipmentInfosUrl);
return backendFetchText(fetchEquipmentInfosUrl);
}
-export function fetchAllCountries(studyUuid: UUID, currentNodeUuid: UUID) {
+export function fetchAllCountries(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
console.info(`Fetching all countries of study '${studyUuid}' and node '${currentNodeUuid}' ...`);
const fetchCountriesUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/network-map/countries?inUpstreamBuiltParentNode=true';
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/network-map/countries?inUpstreamBuiltParentNode=true';
console.debug(fetchCountriesUrl);
return backendFetchJson(fetchCountriesUrl);
}
@@ -171,6 +186,7 @@ export async function createMapFilter(
destinationDirectoryId: UUID,
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
selectedEquipmentsIds: string[],
nominalVoltages: number[]
) {
@@ -195,6 +211,7 @@ export async function createMapFilter(
const elementsIds = await fetchEquipmentsIds(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
selectedEquipmentsIds,
equipmentType,
false,
@@ -220,6 +237,7 @@ export async function createMapContingencyList(
destinationDirectoryId: UUID,
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
selectedEquipments: EquipmentInfos[],
nominalVoltages: number[]
) {
@@ -240,6 +258,7 @@ export async function createMapContingencyList(
const elementsIds = await fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
selectedEquipmentsIds,
equipmentType,
EQUIPMENT_INFOS_TYPES.LIST.type,
@@ -263,11 +282,11 @@ export async function createMapContingencyList(
return createContingencyList(equipmentContingencyList, elementName, '', destinationDirectoryId);
}
-export function fetchAllNominalVoltages(studyUuid: UUID, currentNodeUuid: UUID) {
+export function fetchAllNominalVoltages(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
console.info(`Fetching all nominal voltages of study '${studyUuid}' and node '${currentNodeUuid}' ...`);
const fetchNominalVoltagesUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network-map/nominal-voltages?inUpstreamBuiltParentNode=true';
console.debug(fetchNominalVoltagesUrl);
return backendFetchJson(fetchNominalVoltagesUrl);
diff --git a/src/services/study/network.ts b/src/services/study/network.ts
index 951bcf737d..02cae2faa2 100644
--- a/src/services/study/network.ts
+++ b/src/services/study/network.ts
@@ -5,7 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES, safeEncodeURIComponent } from './index';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid, PREFIX_STUDY_QUERIES, safeEncodeURIComponent } from './index';
+
import { EQUIPMENT_INFOS_TYPES, EQUIPMENT_TYPES } from '../../components/utils/equipment-types';
import { backendFetch, backendFetchJson, backendFetchText, getQueryParamsList, getUrlWithToken } from '../utils';
import { UUID } from 'crypto';
@@ -14,6 +15,7 @@ import { EquipmentType, GsLang } from '@gridsuite/commons-ui';
interface VoltageLevelSingleLineDiagram {
studyUuid: UUID;
currentNodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
voltageLevelId?: UUID;
useName: boolean;
centerLabel: boolean;
@@ -26,6 +28,7 @@ interface VoltageLevelSingleLineDiagram {
interface SubstationSingleLineDiagram {
studyUuid: UUID;
currentNodeUuid: UUID;
+ currentRootNetworkUuid: UUID;
substationId: UUID;
useName: boolean;
centerLabel: boolean;
@@ -39,6 +42,7 @@ interface SubstationSingleLineDiagram {
export function getVoltageLevelSingleLineDiagram({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
voltageLevelId,
useName,
centerLabel,
@@ -63,7 +67,7 @@ export function getVoltageLevelSingleLineDiagram({
queryParams.append('componentLibrary', String(componentLibrary));
}
return (
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/voltage-levels/' +
safeEncodeURIComponent(voltageLevelId) +
'/svg-and-metadata?' +
@@ -71,15 +75,20 @@ export function getVoltageLevelSingleLineDiagram({
);
}
-export function fetchSubstationIdForVoltageLevel(studyUuid: UUID, currentNodeUuid: UUID, voltageLevelId: string) {
+export function fetchSubstationIdForVoltageLevel(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ voltageLevelId: string
+) {
console.info(
- `Fetching substation ID for the voltage level '${voltageLevelId}' of study '${studyUuid}' and node '${currentNodeUuid}' + ' for voltage level '${voltageLevelId}'...`
+ `Fetching substation ID for the voltage level '${voltageLevelId}' of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' + ' for voltage level '${voltageLevelId}'...`
);
const urlSearchParams = new URLSearchParams();
urlSearchParams.append('inUpstreamBuiltParentNode', 'true');
const fetchSubstationIdUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/voltage-levels/' +
encodeURIComponent(voltageLevelId) +
'/substation-id' +
@@ -94,16 +103,17 @@ export function fetchSubstationIdForVoltageLevel(studyUuid: UUID, currentNodeUui
export function fetchBusesOrBusbarSectionsForVoltageLevel(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
voltageLevelId: UUID
) {
console.info(
- `Fetching buses or busbar sections of study '${studyUuid}' and node '${currentNodeUuid}' + ' for voltage level '${voltageLevelId}'...`
+ `Fetching buses or busbar sections of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' + ' for voltage level '${voltageLevelId}'...`
);
const urlSearchParams = new URLSearchParams();
urlSearchParams.append('inUpstreamBuiltParentNode', 'true');
const fetchBusbarSectionsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/voltage-levels/' +
encodeURIComponent(voltageLevelId) +
'/buses-or-busbar-sections' +
@@ -118,6 +128,7 @@ export function fetchBusesOrBusbarSectionsForVoltageLevel(
export function getSubstationSingleLineDiagram({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationId,
useName,
centerLabel,
@@ -141,7 +152,7 @@ export function getSubstationSingleLineDiagram({
queryParams.append('componentLibrary', String(componentLibrary));
}
return (
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/substations/' +
encodeURIComponent(substationId) +
'/svg-and-metadata?' +
@@ -153,6 +164,7 @@ export function getSubstationSingleLineDiagram({
export function fetchNetworkElementsInfos(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[] | undefined | null,
elementType: string,
infoType: string,
@@ -163,7 +175,7 @@ export function fetchNetworkElementsInfos(
const nominalVoltagesStr = nominalVoltages ? `[${nominalVoltages}]` : '[]';
console.info(
- `Fetching network '${elementType}' elements '${infoType}' infos of study '${studyUuid}' and node '${currentNodeUuid}' with ${substationsCount} substations ids and ${nominalVoltagesStr} nominal voltages.`
+ `Fetching network '${elementType}' elements '${infoType}' infos of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' with ${substationsCount} substations ids and ${nominalVoltagesStr} nominal voltages.`
);
const nominalVoltagesParams = getQueryParamsList(nominalVoltages, 'nominalVoltages');
@@ -178,7 +190,7 @@ export function fetchNetworkElementsInfos(
urlSearchParams.append('elementType', elementType);
const fetchElementsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/elements' +
'?' +
urlSearchParams +
@@ -195,13 +207,14 @@ export function fetchNetworkElementsInfos(
export function fetchNetworkElementInfos(
studyUuid: string | undefined | null,
currentNodeUuid: UUID | undefined,
+ currentRootNetworkUuid: string | undefined | null,
elementType: EquipmentType | EQUIPMENT_TYPES,
infoType: string,
elementId: string,
inUpstreamBuiltParentNode: boolean
) {
console.info(
- `Fetching specific network element '${elementId}' of type '${elementType}' of study '${studyUuid}' and node '${currentNodeUuid}' ...`
+ `Fetching specific network element '${elementId}' of type '${elementType}' of study '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
);
const urlSearchParams = new URLSearchParams();
if (inUpstreamBuiltParentNode !== undefined) {
@@ -211,7 +224,7 @@ export function fetchNetworkElementInfos(
urlSearchParams.append('infoType', infoType);
const fetchElementsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) +
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
'/network/elements/' +
encodeURIComponent(elementId) +
'?' +
@@ -224,12 +237,14 @@ export function fetchNetworkElementInfos(
export function fetchSubstationsMapInfos(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[] | null | undefined,
inUpstreamBuiltParentNode: boolean
) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.SUBSTATION,
EQUIPMENT_INFOS_TYPES.MAP.type,
@@ -240,12 +255,14 @@ export function fetchSubstationsMapInfos(
export function fetchLinesMapInfos(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[] | undefined | null,
inUpstreamBuiltParentNode: boolean
) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.LINE,
EQUIPMENT_INFOS_TYPES.MAP.type,
@@ -256,12 +273,14 @@ export function fetchLinesMapInfos(
export function fetchTieLinesMapInfos(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[] | undefined | null,
inUpstreamBuiltParentNode: boolean
) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.TIE_LINE,
EQUIPMENT_INFOS_TYPES.MAP.type,
@@ -272,12 +291,14 @@ export function fetchTieLinesMapInfos(
export function fetchHvdcLinesMapInfos(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
substationsIds: string[] | undefined | null,
inUpstreamBuiltParentNode: boolean
) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.HVDC_LINE,
EQUIPMENT_INFOS_TYPES.MAP.type,
@@ -285,10 +306,16 @@ export function fetchHvdcLinesMapInfos(
);
}
-export function fetchSubstations(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchSubstations(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.SUBSTATION,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -296,10 +323,16 @@ export function fetchSubstations(studyUuid: UUID, currentNodeUuid: UUID, substat
);
}
-export function fetchLines(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchLines(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.LINE,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -307,10 +340,16 @@ export function fetchLines(studyUuid: UUID, currentNodeUuid: UUID, substationsId
);
}
-export function fetchVoltageLevels(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchVoltageLevels(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.VOLTAGE_LEVEL,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -318,10 +357,16 @@ export function fetchVoltageLevels(studyUuid: UUID, currentNodeUuid: UUID, subst
);
}
-export function fetchVoltageLevelsListInfos(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchVoltageLevelsListInfos(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.VOLTAGE_LEVEL,
EQUIPMENT_INFOS_TYPES.LIST.type,
@@ -329,10 +374,16 @@ export function fetchVoltageLevelsListInfos(studyUuid: UUID, currentNodeUuid: UU
);
}
-export function fetchVoltageLevelsMapInfos(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchVoltageLevelsMapInfos(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.VOLTAGE_LEVEL,
EQUIPMENT_INFOS_TYPES.MAP.type,
@@ -340,10 +391,16 @@ export function fetchVoltageLevelsMapInfos(studyUuid: UUID, currentNodeUuid: UUI
);
}
-export function fetchTwoWindingsTransformers(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchTwoWindingsTransformers(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -351,10 +408,16 @@ export function fetchTwoWindingsTransformers(studyUuid: UUID, currentNodeUuid: U
);
}
-export function fetchThreeWindingsTransformers(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchThreeWindingsTransformers(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -362,20 +425,32 @@ export function fetchThreeWindingsTransformers(studyUuid: UUID, currentNodeUuid:
);
}
-export function fetchGenerators(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchGenerators(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.GENERATOR,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchLoads(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchLoads(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.LOAD,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -383,30 +458,48 @@ export function fetchLoads(studyUuid: UUID, currentNodeUuid: UUID, substationsId
);
}
-export function fetchDanglingLines(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchDanglingLines(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.DANGLING_LINE,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchBatteries(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchBatteries(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.BATTERY,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchHvdcLines(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchHvdcLines(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.HVDC_LINE,
EQUIPMENT_INFOS_TYPES.TAB.type,
@@ -414,75 +507,125 @@ export function fetchHvdcLines(studyUuid: UUID, currentNodeUuid: UUID, substatio
);
}
-export function fetchLccConverterStations(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchLccConverterStations(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.LCC_CONVERTER_STATION,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchVscConverterStations(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchVscConverterStations(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.VSC_CONVERTER_STATION,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchShuntCompensators(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchShuntCompensators(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.SHUNT_COMPENSATOR,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchStaticVarCompensators(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchStaticVarCompensators(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchBuses(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchBuses(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.BUS,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-export function fetchBusbarSections(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
+export function fetchBusbarSections(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
return fetchNetworkElementsInfos(
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
substationsIds,
EQUIPMENT_TYPES.BUSBAR_SECTION,
EQUIPMENT_INFOS_TYPES.TAB.type
);
}
-
-export const fetchNetworkExistence = (studyUuid: UUID) => {
- const fetchNetworkExistenceUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${studyUuid}/network`;
+export function fetchTieLines(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ substationsIds?: string[]
+) {
+ return fetchNetworkElementsInfos(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ substationsIds,
+ EQUIPMENT_TYPES.TIE_LINE,
+ EQUIPMENT_INFOS_TYPES.TAB.type
+ );
+}
+export const fetchNetworkExistence = (studyUuid: UUID, rootNetworkUuid: UUID) => {
+ const fetchNetworkExistenceUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${studyUuid}/root-networks/${rootNetworkUuid}/network`;
return backendFetch(fetchNetworkExistenceUrl, { method: 'HEAD' });
};
-export const fetchStudyIndexationStatus = (studyUuid: UUID) => {
+export const fetchStudyIndexationStatus = (studyUuid: UUID, rootNetworkUuid: UUID) => {
console.info(`Fetching study indexation status of study '${studyUuid}' ...`);
- const fetchStudyIndexationUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${studyUuid}/indexation/status`;
+ const fetchStudyIndexationUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${studyUuid}/root-networks/${rootNetworkUuid}/indexation/status`;
console.debug(fetchStudyIndexationUrl);
@@ -490,17 +633,16 @@ export const fetchStudyIndexationStatus = (studyUuid: UUID) => {
};
/* export-network */
-export function getExportUrl(studyUuid: UUID, nodeUuid: UUID, exportFormat: string) {
- const url = getStudyUrlWithNodeUuid(studyUuid, nodeUuid) + '/export-network/' + exportFormat;
- return getUrlWithToken(url);
-}
-export function fetchTieLines(studyUuid: UUID, currentNodeUuid: UUID, substationsIds?: string[]) {
- return fetchNetworkElementsInfos(
- studyUuid,
- currentNodeUuid,
- substationsIds,
- EQUIPMENT_TYPES.TIE_LINE,
- EQUIPMENT_INFOS_TYPES.TAB.type
- );
+export function getExportUrl(studyUuid: UUID, nodeUuid: UUID, rootNetworkUuid: UUID, exportFormat: string) {
+ // getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, currentRootNetworkUuid) +
+ // '/root-networks/' +
+ // rootNetworkUuid +
+ // '/export-network/' +
+ // exportFormat;
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, nodeUuid, rootNetworkUuid) +
+ '/export-network/' +
+ exportFormat;
+ return getUrlWithToken(url);
}
diff --git a/src/services/study/non-evacuated-energy.ts b/src/services/study/non-evacuated-energy.ts
index 71e84a8d90..db51075954 100644
--- a/src/services/study/non-evacuated-energy.ts
+++ b/src/services/study/non-evacuated-energy.ts
@@ -5,36 +5,57 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid, PREFIX_STUDY_QUERIES } from './index';
import { backendFetch, backendFetchJson, backendFetchText } from '../utils';
import { UUID } from 'crypto';
-export function startNonEvacuatedEnergy(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Running non evacuated energy analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/non-evacuated-energy/run';
-
+export function startNonEvacuatedEnergy(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Running non evacuated energy analysis on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/non-evacuated-energy/run';
console.debug(url);
return backendFetch(url, { method: 'post' });
}
-export function stopNonEvacuatedEnergy(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping non evacuated energy analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/non-evacuated-energy/stop`;
+export function stopNonEvacuatedEnergy(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping non evacuated energy analysis on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/non-evacuated-energy/stop`;
console.debug(url);
return backendFetch(url, { method: 'put' });
}
-export function fetchNonEvacuatedEnergyStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching non evacuated energy analysis status on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/non-evacuated-energy/status`;
+export function fetchNonEvacuatedEnergyStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching non evacuated energy analysis status on ${studyUuid} on root network '${currentRootNetworkUuid}' on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/non-evacuated-energy/status`;
console.debug(url);
return backendFetchText(url);
}
-export function fetchNonEvacuatedEnergyResult(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching non evacuated energy analysis result on ${studyUuid} and node ${currentNodeUuid} ...`);
+export function fetchNonEvacuatedEnergyResult(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching non evacuated energy analysis result on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/non-evacuated-energy/result`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/non-evacuated-energy/result`;
console.debug(url);
return backendFetchJson(url);
}
diff --git a/src/services/study/security-analysis.ts b/src/services/study/security-analysis.ts
index 1a6a8f1058..929d6364d6 100644
--- a/src/services/study/security-analysis.ts
+++ b/src/services/study/security-analysis.ts
@@ -5,34 +5,55 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid, PREFIX_STUDY_QUERIES } from './index';
import { backendFetch, backendFetchFile, backendFetchJson, backendFetchText, getRequestParamFromList } from '../utils';
import { UUID } from 'crypto';
import { RESULT_TYPE } from '../../components/results/securityanalysis/security-analysis-result-utils';
-export function startSecurityAnalysis(studyUuid: UUID, currentNodeUuid: UUID, contingencyListNames: string[]) {
- console.info(`Running security analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
-
+export function startSecurityAnalysis(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ contingencyListNames: string[]
+) {
+ console.info(
+ `Running security analysis on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
// Add params to Url
const contingencyListsQueryParams = getRequestParamFromList(contingencyListNames, 'contingencyListName');
const urlSearchParams = new URLSearchParams(contingencyListsQueryParams);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/security-analysis/run?${urlSearchParams}`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/security-analysis/run?${urlSearchParams}`;
console.debug(url);
return backendFetch(url, { method: 'post' });
}
-export function stopSecurityAnalysis(studyUuid: UUID, currentNodeUuid: UUID) {
+export function stopSecurityAnalysis(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
console.info('Stopping security analysis on ' + studyUuid + ' and node ' + currentNodeUuid + ' ...');
- const stopSecurityAnalysisUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/security-analysis/stop';
+ const stopSecurityAnalysisUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/security-analysis/stop';
console.debug(stopSecurityAnalysisUrl);
return backendFetch(stopSecurityAnalysisUrl, { method: 'put' });
}
-export function fetchSecurityAnalysisResult(studyUuid: string, currentNodeUuid: string, queryParams: any) {
+export function fetchSecurityAnalysisResult(
+ studyUuid: string,
+ currentNodeUuid: string,
+ currentRootNetworkUuid: string,
+ queryParams: any
+) {
console.info(`Fetching security analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/security-analysis/result`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/security-analysis/result`;
const { resultType, page, size, sort, filters } = queryParams || {};
@@ -57,12 +78,19 @@ export function fetchSecurityAnalysisResult(studyUuid: string, currentNodeUuid:
export function downloadSecurityAnalysisResultZippedCsv(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
queryParams: { resultType: RESULT_TYPE },
headers: string[] | undefined,
enumValueTranslations: Record
) {
- console.info(`Fetching security analysis zipped csv on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/security-analysis/result/csv`;
+ console.info(
+ `Fetching security analysis zipped csv on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/security-analysis/result/csv`;
const { resultType } = queryParams || {};
@@ -83,10 +111,13 @@ export function downloadSecurityAnalysisResultZippedCsv(
});
}
-export function fetchSecurityAnalysisStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching security analysis status on ${studyUuid} and node ${currentNodeUuid} ...`);
-
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/security-analysis/status';
+export function fetchSecurityAnalysisStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching security analysis status on ${studyUuid} on root network '${currentRootNetworkUuid}' and node ${currentNodeUuid} ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/security-analysis/status';
console.debug(url);
return backendFetchText(url);
}
diff --git a/src/services/study/sensitivity-analysis.ts b/src/services/study/sensitivity-analysis.ts
index 13bee0145b..cbe0ee733e 100644
--- a/src/services/study/sensitivity-analysis.ts
+++ b/src/services/study/sensitivity-analysis.ts
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { PREFIX_STUDY_QUERIES, getStudyUrl, getStudyUrlWithNodeUuid } from './index';
+import { PREFIX_STUDY_QUERIES, getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { backendFetch, backendFetchJson, backendFetchText } from '../utils';
import { UUID } from 'crypto';
import { SensitivityAnalysisParametersInfos } from './sensitivity-analysis.type';
@@ -31,40 +31,62 @@ interface CsvConfig {
sensitivityFunctionType: string;
}
-export function startSensitivityAnalysis(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Running sensi on ${studyUuid} and node ${currentNodeUuid} ...`);
- const startSensiAnalysisUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/sensitivity-analysis/run';
-
+export function startSensitivityAnalysis(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Running sensi on ${studyUuid} for root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const startSensiAnalysisUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/sensitivity-analysis/run';
console.debug(startSensiAnalysisUrl);
return backendFetch(startSensiAnalysisUrl, { method: 'post' });
}
-export function stopSensitivityAnalysis(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping sensitivity analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
- const stopSensitivityAnalysisUrl = `${getStudyUrlWithNodeUuid(
+export function stopSensitivityAnalysis(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping sensitivity analysis on ${studyUuid} for root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
+ const stopSensitivityAnalysisUrl = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
studyUuid,
- currentNodeUuid
+ currentNodeUuid,
+ currentRootNetworkUuid
)}/sensitivity-analysis/stop`;
console.debug(stopSensitivityAnalysisUrl);
return backendFetch(stopSensitivityAnalysisUrl, { method: 'put' });
}
-export function fetchSensitivityAnalysisStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching sensitivity analysis status on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/sensitivity-analysis/status`;
+export function fetchSensitivityAnalysisStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching sensitivity analysis status on ${studyUuid} on root network '${currentRootNetworkUuid}' and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/sensitivity-analysis/status`;
console.debug(url);
return backendFetchText(url);
}
-export function fetchSensitivityAnalysisResult(studyUuid: UUID, currentNodeUuid: UUID, selector: any) {
- console.info(`Fetching sensitivity analysis on ${studyUuid} and node ${currentNodeUuid} ...`);
-
+export function fetchSensitivityAnalysisResult(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ selector: any
+) {
+ console.info(
+ `Fetching sensitivity analysis on ${studyUuid} for root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
// Add params to Url
const urlSearchParams = new URLSearchParams();
const jsoned = JSON.stringify(selector);
urlSearchParams.append('selector', jsoned);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/sensitivity-analysis/result?${urlSearchParams}`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/sensitivity-analysis/result?${urlSearchParams}`;
console.debug(url);
return backendFetchJson(url);
}
@@ -72,18 +94,21 @@ export function fetchSensitivityAnalysisResult(studyUuid: UUID, currentNodeUuid:
export function fetchSensitivityAnalysisFilterOptions(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
selector: SelectorFilterOptions
) {
- console.info(`Fetching sensitivity analysis filter options on ${studyUuid} and node ${currentNodeUuid} ...`);
-
+ console.info(
+ `Fetching sensitivity analysis filter options on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
// Add params to Url
const urlSearchParams = new URLSearchParams();
const jsoned = JSON.stringify(selector);
urlSearchParams.append('selector', jsoned);
- const url = `${getStudyUrlWithNodeUuid(
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
studyUuid,
- currentNodeUuid
+ currentNodeUuid,
+ currentRootNetworkUuid
)}/sensitivity-analysis/result/filter-options?${urlSearchParams}`;
console.debug(url);
return backendFetchJson(url);
@@ -130,6 +155,7 @@ export function setSensitivityAnalysisParameters(
export function getSensitivityAnalysisFactorsCount(
studyUuid: UUID | null,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
isInjectionsSet: boolean,
newParams: SensitivityAnalysisFactorsCountParameters
) {
@@ -143,7 +169,7 @@ export function getSensitivityAnalysisFactorsCount(
// @ts-ignore
.forEach((key) => urlSearchParams.append(`ids[${key}]`, newParams[key]));
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid)}
/sensitivity-analysis/factors-count?${urlSearchParams}`;
console.debug(url);
return backendFetch(url, {
@@ -151,10 +177,21 @@ export function getSensitivityAnalysisFactorsCount(
});
}
-export function exportSensitivityResultsAsCsv(studyUuid: UUID, currentNodeUuid: UUID, csvConfig: CsvConfig) {
- console.info(`Exporting sensitivity analysis on ${studyUuid} and node ${currentNodeUuid} as CSV ...`);
+export function exportSensitivityResultsAsCsv(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
+ csvConfig: CsvConfig
+) {
+ console.info(
+ `Exporting sensitivity analysis on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} as CSV ...`
+ );
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/sensitivity-analysis/result/csv`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/sensitivity-analysis/result/csv`;
console.debug(url);
return backendFetch(url, {
method: 'POST',
diff --git a/src/services/study/short-circuit-analysis.ts b/src/services/study/short-circuit-analysis.ts
index 2f1a7b1424..a1444c9583 100644
--- a/src/services/study/short-circuit-analysis.ts
+++ b/src/services/study/short-circuit-analysis.ts
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import {
getShortCircuitAnalysisTypeFromEnum,
ShortCircuitAnalysisType,
@@ -21,6 +21,7 @@ const PREFIX_SHORT_CIRCUIT_SERVER_QUERIES = import.meta.env.VITE_API_GATEWAY + '
interface ShortCircuitAnalysisResult {
studyUuid: UUID | null;
currentNodeUuid?: UUID;
+ currentRootNetworkUuid?: UUID;
type: ShortCircuitAnalysisType;
}
interface Selector {
@@ -55,21 +56,37 @@ function getShortCircuitUrl() {
return `${PREFIX_SHORT_CIRCUIT_SERVER_QUERIES}/v1/`;
}
-export function startShortCircuitAnalysis(studyUuid: string, currentNodeUuid: UUID | undefined, busId: string) {
- console.info(`Running short circuit analysis on '${studyUuid}' and node '${currentNodeUuid}' ...`);
-
+export function startShortCircuitAnalysis(
+ studyUuid: string,
+ currentNodeUuid: UUID | undefined,
+ currentRootNetworkUuid: UUID | null,
+ busId: string
+) {
+ console.info(
+ `Running short circuit analysis on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
const urlSearchParams = new URLSearchParams();
busId && urlSearchParams.append('busId', busId);
const startShortCircuitAnalysisUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/shortcircuit/run?' + urlSearchParams.toString();
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/shortcircuit/run?' +
+ urlSearchParams.toString();
console.debug(startShortCircuitAnalysisUrl);
return backendFetch(startShortCircuitAnalysisUrl, { method: 'put' });
}
-export function stopShortCircuitAnalysis(studyUuid: string, currentNodeUuid: UUID | undefined) {
- console.info(`Stopping short circuit analysis on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const stopShortCircuitAnalysisUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/shortcircuit/stop';
+export function stopShortCircuitAnalysis(
+ studyUuid: string,
+ currentNodeUuid: UUID | undefined,
+ currentRootNetworkUuid: UUID | undefined
+) {
+ console.info(
+ `Stopping short circuit analysis on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const stopShortCircuitAnalysisUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/shortcircuit/stop';
console.debug(stopShortCircuitAnalysisUrl);
return backendFetch(stopShortCircuitAnalysisUrl, { method: 'put' });
}
@@ -77,31 +94,48 @@ export function stopShortCircuitAnalysis(studyUuid: string, currentNodeUuid: UUI
export function fetchShortCircuitAnalysisStatus(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
type = ShortCircuitAnalysisType.ALL_BUSES
) {
const analysisType = getShortCircuitAnalysisTypeFromEnum(type);
console.info(
- `Fetching ${analysisType} short circuit analysis status on '${studyUuid}' and node '${currentNodeUuid}' ...`
+ `Fetching ${analysisType} short circuit analysis status on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
);
const urlSearchParams = new URLSearchParams();
if (analysisType !== null) {
urlSearchParams.append('type', analysisType);
}
const url =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/shortcircuit/status?' + urlSearchParams.toString();
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/shortcircuit/status?' +
+ urlSearchParams.toString();
console.debug(url);
return backendFetchText(url);
}
-export function fetchOneBusShortCircuitAnalysisStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- return fetchShortCircuitAnalysisStatus(studyUuid, currentNodeUuid, ShortCircuitAnalysisType.ONE_BUS);
+export function fetchOneBusShortCircuitAnalysisStatus(
+ studyUuid: UUID,
+ currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID
+) {
+ return fetchShortCircuitAnalysisStatus(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ ShortCircuitAnalysisType.ONE_BUS
+ );
}
-export function fetchShortCircuitAnalysisResult({ studyUuid, currentNodeUuid, type }: ShortCircuitAnalysisResult) {
+export function fetchShortCircuitAnalysisResult({
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid,
+ type,
+}: ShortCircuitAnalysisResult) {
const analysisType = getShortCircuitAnalysisTypeFromEnum(type);
console.info(
- `Fetching ${analysisType} short circuit analysis result on '${studyUuid}' and node '${currentNodeUuid}' ...`
+ `Fetching ${analysisType} short circuit analysis result on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
);
const urlSearchParams = new URLSearchParams();
if (analysisType) {
@@ -109,7 +143,9 @@ export function fetchShortCircuitAnalysisResult({ studyUuid, currentNodeUuid, ty
}
const url =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/shortcircuit/result?' + urlSearchParams.toString();
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/shortcircuit/result?' +
+ urlSearchParams.toString();
console.debug(url);
return backendFetchJson(url);
}
@@ -117,6 +153,7 @@ export function fetchShortCircuitAnalysisResult({ studyUuid, currentNodeUuid, ty
export function fetchShortCircuitAnalysisPagedResults({
studyUuid,
currentNodeUuid,
+ currentRootNetworkUuid,
selector = {},
type = ShortCircuitAnalysisType.ALL_BUSES,
}: ShortCircuitAnalysisPagedResults) {
@@ -149,7 +186,9 @@ export function fetchShortCircuitAnalysisPagedResults({
}
const url =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/shortcircuit/result?' + urlSearchParams.toString();
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/shortcircuit/result?' +
+ urlSearchParams.toString();
console.debug(url);
return backendFetchJson(url);
}
@@ -194,12 +233,17 @@ export function invalidateShortCircuitStatus(studyUuid: UUID | null) {
export function downloadShortCircuitResultZippedCsv(
studyUuid: UUID,
currentNodeUuid: UUID,
+ currentRootNetworkUuid: UUID,
analysisType: number,
headersCsv: string[] | undefined,
enumValueTranslations: Record
) {
console.info(`Fetching short-circuit analysis export csv on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/shortcircuit/result/csv`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/shortcircuit/result/csv`;
const type = getShortCircuitAnalysisTypeFromEnum(analysisType);
const param = new URLSearchParams();
if (type) {
diff --git a/src/services/study/state-estimation.ts b/src/services/study/state-estimation.ts
index e9ec1a9469..41c2611fc6 100644
--- a/src/services/study/state-estimation.ts
+++ b/src/services/study/state-estimation.ts
@@ -5,36 +5,58 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { backendFetch, backendFetchJson, backendFetchText } from '../utils';
import { UUID } from 'crypto';
-export function startStateEstimation(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Running state estimation on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/state-estimation/run';
+export function startStateEstimation(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Running state estimation on ${studyUuid} on root network '${currentRootNetworkUuid}' and node ${currentNodeUuid} ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/state-estimation/run';
console.debug(url);
return backendFetch(url, { method: 'post' });
}
-export function stopStateEstimation(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping state estimation on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/state-estimation/stop`;
+export function stopStateEstimation(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping state estimation on ${studyUuid} on root network '${currentRootNetworkUuid}' and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/state-estimation/stop`;
console.debug(url);
return backendFetch(url, { method: 'put' });
}
-export function fetchStateEstimationStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching state estimation status on ${studyUuid} and node ${currentNodeUuid} ...`);
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/state-estimation/status`;
+export function fetchStateEstimationStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching state estimation status on ${studyUuid} on root network '${currentRootNetworkUuid}' and node ${currentNodeUuid} ...`
+ );
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/state-estimation/status`;
console.debug(url);
return backendFetchText(url);
}
-export function fetchStateEstimationResult(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching state estimation result on ${studyUuid} and node ${currentNodeUuid} ...`);
+export function fetchStateEstimationResult(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching state estimation result on ${studyUuid} on root network ${currentRootNetworkUuid} and node ${currentNodeUuid} ...`
+ );
- const url = `${getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid)}/state-estimation/result`;
+ const url = `${getStudyUrlWithNodeUuidAndRootNetworkUuid(
+ studyUuid,
+ currentNodeUuid,
+ currentRootNetworkUuid
+ )}/state-estimation/result`;
console.debug(url);
return backendFetchJson(url);
}
diff --git a/src/services/study/study.ts b/src/services/study/study.ts
index 9824a94af3..f6ca25392d 100644
--- a/src/services/study/study.ts
+++ b/src/services/study/study.ts
@@ -18,6 +18,7 @@ interface BasicStudyInfos {
export const recreateStudyNetworkFromExistingCase = (
caseUuid: UUID,
studyUuid: UUID,
+ currentRootNetworkUuid: UUID,
importParameters: Record
): Promise => {
const urlSearchParams = new URLSearchParams();
@@ -27,6 +28,8 @@ export const recreateStudyNetworkFromExistingCase = (
PREFIX_STUDY_QUERIES +
'/v1/studies/' +
encodeURIComponent(studyUuid) +
+ '/root-networks/' +
+ encodeURIComponent(currentRootNetworkUuid) +
'/network?' +
urlSearchParams.toString();
@@ -39,8 +42,14 @@ export const recreateStudyNetworkFromExistingCase = (
});
};
-export const recreateStudyNetwork = (studyUuid: UUID): Promise => {
- const recreateStudyNetworkUrl = PREFIX_STUDY_QUERIES + '/v1/studies/' + encodeURIComponent(studyUuid) + '/network';
+export const recreateStudyNetwork = (studyUuid: UUID, currentRootNetworkUuid: UUID): Promise => {
+ const recreateStudyNetworkUrl =
+ PREFIX_STUDY_QUERIES +
+ '/v1/studies/' +
+ encodeURIComponent(studyUuid) +
+ '/root-networks/' +
+ encodeURIComponent(currentRootNetworkUuid) +
+ '/network';
console.debug(recreateStudyNetworkUrl);
@@ -50,8 +59,14 @@ export const recreateStudyNetwork = (studyUuid: UUID): Promise
});
};
-export const reindexAllStudy = (studyUuid: UUID): Promise => {
- const reindexAllStudyUrl = PREFIX_STUDY_QUERIES + '/v1/studies/' + encodeURIComponent(studyUuid) + '/reindex-all';
+export const reindexAllStudy = (studyUuid: UUID, currentRootNetworkUuid: UUID): Promise => {
+ const reindexAllStudyUrl =
+ PREFIX_STUDY_QUERIES +
+ '/v1/studies/' +
+ encodeURIComponent(studyUuid) +
+ '/root-networks/' +
+ encodeURIComponent(currentRootNetworkUuid) +
+ '/reindex-all';
console.debug(reindexAllStudyUrl);
diff --git a/src/services/study/tree-subtree.ts b/src/services/study/tree-subtree.ts
index 222278becf..f9576f0c59 100644
--- a/src/services/study/tree-subtree.ts
+++ b/src/services/study/tree-subtree.ts
@@ -177,16 +177,21 @@ export function updateNodesColumnPositions(studyUuid: UUID, parentNodeId: UUID,
});
}
-export function fetchNetworkModificationTreeNode(studyUuid: UUID, nodeUuid: UUID) {
+export function fetchNetworkModificationTreeNode(studyUuid: UUID, nodeUuid: UUID, rootNetworkUuid: UUID) {
console.info('Fetching network modification tree node : ', nodeUuid);
- const url = getStudyUrl(studyUuid) + '/tree/nodes/' + encodeURIComponent(nodeUuid);
+ const urlSearchParams = new URLSearchParams();
+ urlSearchParams.set('rootNetworkUuid', rootNetworkUuid);
+ const url =
+ getStudyUrl(studyUuid) + '/tree/nodes/' + encodeURIComponent(nodeUuid) + '?' + urlSearchParams.toString();
console.debug(url);
return backendFetchJson(url);
}
-export function fetchNetworkModificationTree(studyUuid: UUID) {
+export function fetchNetworkModificationTree(studyUuid: UUID, rootNetworkUuid: UUID) {
console.info('Fetching network modification tree');
- const url = getStudyUrl(studyUuid) + '/tree';
+ const urlSearchParams = new URLSearchParams();
+ urlSearchParams.set('rootNetworkUuid', rootNetworkUuid);
+ const url = getStudyUrl(studyUuid) + '/tree?' + urlSearchParams.toString();
console.debug(url);
return backendFetchJson(url);
}
diff --git a/src/services/study/voltage-init.ts b/src/services/study/voltage-init.ts
index 24ba1afc27..9ee411495b 100644
--- a/src/services/study/voltage-init.ts
+++ b/src/services/study/voltage-init.ts
@@ -5,36 +5,51 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-import { getStudyUrl, getStudyUrlWithNodeUuid } from './index';
+import { getStudyUrl, getStudyUrlWithNodeUuidAndRootNetworkUuid } from './index';
import { backendFetch, backendFetchJson, backendFetchText } from '../utils';
import { UUID } from 'crypto';
import { VoltageInitParam } from '../../components/dialogs/parameters/voltageinit/voltage-init-utils';
-export function startVoltageInit(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Running voltage init on '${studyUuid}' and node '${currentNodeUuid}' ...`);
+export function startVoltageInit(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Running voltage init on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
- const startVoltageInitUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/voltage-init/run';
+ const startVoltageInitUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/voltage-init/run';
console.debug(startVoltageInitUrl);
return backendFetch(startVoltageInitUrl, { method: 'put' });
}
-export function stopVoltageInit(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Stopping voltage init on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const stopVoltageInitUrl = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/voltage-init/stop';
+export function stopVoltageInit(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Stopping voltage init on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const stopVoltageInitUrl =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/voltage-init/stop';
console.debug(stopVoltageInitUrl);
return backendFetch(stopVoltageInitUrl, { method: 'put' });
}
-export function fetchVoltageInitStatus(studyUuid: UUID, currentNodeUuid: UUID) {
- console.info(`Fetching voltage init status on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/voltage-init/status';
+export function fetchVoltageInitStatus(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
+ console.info(
+ `Fetching voltage init status on '${studyUuid}' on root network '${currentRootNetworkUuid}' and node '${currentNodeUuid}' ...`
+ );
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/voltage-init/status';
+
console.debug(url);
return backendFetchText(url);
}
-export function fetchVoltageInitResult(studyUuid: UUID, currentNodeUuid: UUID) {
+export function fetchVoltageInitResult(studyUuid: UUID, currentNodeUuid: UUID, currentRootNetworkUuid: UUID) {
console.info(`Fetching voltage init result on '${studyUuid}' and node '${currentNodeUuid}' ...`);
- const url = getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + '/voltage-init/result';
+ const url =
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeUuid, currentRootNetworkUuid) +
+ '/voltage-init/result';
console.debug(url);
return backendFetchJson(url);
}
@@ -66,18 +81,20 @@ export function getVoltageInitStudyParameters(studyUuid: UUID) {
return backendFetchJson(getVoltageInitParams);
}
-export function getVoltageInitModifications(studyUuid: UUID, currentNodeId: UUID) {
+export function getVoltageInitModifications(studyUuid: UUID, currentNodeId: UUID, currentRootNetworkUuid: UUID) {
console.info('get voltage init modifications');
const getVoltageInitModifications =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeId) + '/voltage-init/modifications';
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeId, currentRootNetworkUuid) +
+ '/voltage-init/modifications';
console.debug(getVoltageInitModifications);
return backendFetchJson(getVoltageInitModifications);
}
-export function cloneVoltageInitModifications(studyUuid: UUID, currentNodeId: UUID) {
+export function cloneVoltageInitModifications(studyUuid: UUID, currentNodeId: UUID, currentRootNetworkUuid: UUID) {
console.info('cloning voltage init modifications');
const cloneVoltageInitModificationsUrl =
- getStudyUrlWithNodeUuid(studyUuid, currentNodeId) + '/voltage-init/modifications';
+ getStudyUrlWithNodeUuidAndRootNetworkUuid(studyUuid, currentNodeId, currentRootNetworkUuid) +
+ '/voltage-init/modifications';
return backendFetch(cloneVoltageInitModificationsUrl, {
method: 'PUT',
diff --git a/src/translations/en.json b/src/translations/en.json
index 7eb5e121e2..ea93ddc5eb 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -55,6 +55,8 @@
"SingleLineDiagram": "Single line diagram",
"NetworkAreaDiagram": "Network area diagram",
"studyNotFound": "Study with id \"{studyUuid}\" has not been found",
+ "rootNetworkNotFound": "No root network was not found for the study with ID \"{studyUuid}\"",
+
"svgNotFound": "Diagram has not been found: {error}; {svgUrl}",
"svgLoadingFail": "The diagram couldn't be loaded",
"networkLoadingFail": "Network of study with id \"{studyUuid}\" couldn't be loaded",
@@ -371,6 +373,9 @@
"TwoSides.ONE": "Origin side",
"TwoSides.TWO": "Extremity side",
+ "selectCase": "Select case",
+ "ChooseSituation": "Select a case",
+
"ContingencyListsSelection": "Contingency lists selection",
"Execute": "Execute",
"AddContingencyList": "Add",
@@ -566,6 +571,8 @@
"HideMinimap": "Hide minimap",
"DisplayTheWholeTree": "Display the whole tree",
+ "CreateRootNetwork": "Configure root network",
+
"Logs": "Logs",
"logsTitle": "Logs : {title}",
"showReport": "Show logs",
@@ -603,6 +610,7 @@
"NodeBuildingError": "An error occurred while building node",
"NodeUnbuildingError": "An error occurred while unbuilding node",
"NetworkModifications": "Network modifications",
+ "RootNetwork": "Root Network",
"CreateLoad": "Create load",
"ModifyLoad": "Modify load",
"NameOptional": "Name (optional)",
@@ -1230,6 +1238,7 @@
"SaveModificationTo": "Save to GridExplore",
"ModificationsSelection": "Modification selection",
"errCreateModificationsMsg": "Network modifications creation error",
+ "errCreateRootNetworksMsg": "Root Networks creation error",
"infoCreateModificationsMsg": "Composite modification of {nbModifications} unitary network modifications created in {studyDirectory}",
"idSelector.idNeeded": "Please select an ID",
"SpreadsheetFetchError": "An error occurred while fetching equipments in the spreadsheet",
@@ -1446,5 +1455,14 @@
"qualityPerRegionResults": "Quality region",
"StateEstimationStatus": "Status : ",
"StateEstimationQuality": "Quality : ",
- "Or": "or"
+ "Or": "or",
+ "rootNetworksCount":"{hide, select, false {{count, plural, =0 {aucun réseau racine} =1 {# réseau racine} other {# réseaux racine}}} other {...}}",
+ "updateRootNetworksList": "Updating root network list ...",
+ "deletingRootNetwork": "Deleting root network ...",
+ "creatingRootNetwork": "Creating root network ...",
+ "rootNetworkCreated": "Root Network has been created successfully",
+ "errDeleteRootNetworkMsg": "Root Networks deletion error",
+ "warnDeleteCurrentRootNetwork" : "Current root network can not be delete"
+
+
}
diff --git a/src/translations/fr.json b/src/translations/fr.json
index fde58cc42e..c8cc0bdd92 100644
--- a/src/translations/fr.json
+++ b/src/translations/fr.json
@@ -56,6 +56,8 @@
"NetworkAreaDiagram": "Image nodale de zone",
"studyNotFound": "L'étude avec l'identifiant \"{studyUuid}\" n'a pas été trouvée",
+ "RootNetworkNotFound": "Aucun réseau racine n'a été trouvé pour l'étude avec l'ID \"{studyUuid}\"",
+
"svgNotFound": "L'image poste n'a pas été trouvée : {error}; {svgUrl}",
"svgLoadingFail": "L'image n'a pas pu être chargée",
"networkLoadingFail": "Le réseau de l'étude avec l'identifiant \"{studyUuid}\" n'a pas pu être chargé",
@@ -372,6 +374,9 @@
"TwoSides.ONE": "Côté 1",
"TwoSides.TWO": "Côté 2",
+ "selectCase": "Sélectionner une situation",
+ "ChooseSituation": "Choisir une situation",
+
"ContingencyListsSelection": "Sélection des listes d'aléas",
"Execute": "Exécuter",
"AddContingencyList": "Ajouter",
@@ -568,6 +573,8 @@
"HideMinimap": "Masquer la mini-carte",
"DisplayTheWholeTree": "Visualiser l'arbre en entier",
+ "CreateRootNetwork": "Configurer un réseau racine",
+
"Logs": "Logs",
"logsTitle": "Logs : {title}",
"showReport": "Afficher logs",
@@ -606,6 +613,8 @@
"NodeBuildingError": "Une erreur est survenue lors de la réalisation du nœud",
"NodeUnbuildingError": "Une erreur est survenue lors de la déréalisation du nœud",
"NetworkModifications": "Modifications de réseau",
+ "RootNetwork": "Réseau racine",
+
"CreateLoad": "Créer une consommation",
"ModifyLoad": "Modifier une consommation",
"NameOptional": "Nom (optionnel)",
@@ -1230,6 +1239,8 @@
"SaveModificationTo": "Enregistrer dans GridExplore",
"ModificationsSelection": "Sélection des modifications",
"errCreateModificationsMsg": "Une erreur est survenue lors de la création des modifications",
+ "errCreateRootNetworksMsg": "Une erreur est survenue lors de la création du réseau racine",
+
"infoCreateModificationsMsg": "Création d'une modification composite de {nbModifications} modifications unitaires dans {studyDirectory}",
"idSelector.idNeeded": "Veuillez sélectionner un ID",
"SpreadsheetFetchError": "Une erreur est survenue lors du chargement des ouvrages dans le tableur",
@@ -1446,5 +1457,14 @@
"qualityPerRegionResults": "Qualité par région",
"StateEstimationStatus": "Statut : ",
"StateEstimationQuality": "Qualité: ",
- "Or": "ou"
+ "Or": "ou",
+ "rootNetworksCount":"{hide, select, false {{count, plural, =0 {no root network} =1 {{count} root network} other {{count} root networks}}} other {...}}",
+ "updateRootNetworksList": "Mise à jour de la liste des réseaux racine cours ...",
+ "deletingRootNetwork": "Suppression du réseau racine en cours ...",
+ "creatingRootNetwork": "Création du réseau racine en cours ...",
+ "rootNetworkCreated": "Le réseau racine a été créé avec succès",
+ "errDeleteRootNetworkMsg": "Une erreur est survenue lors de la suppression des réseaux racine",
+ "warnDeleteCurrentRootNetwork": "Le réseau racine actuel ne peut pas être supprimé"
+
+
}
\ No newline at end of file