From a770a57ff7263128d9f5c7254e8e155adf4ee9a2 Mon Sep 17 00:00:00 2001 From: Franck LECUYER Date: Fri, 22 Nov 2024 13:36:55 +0100 Subject: [PATCH 01/13] Upgrade to powsybl-network-viewer 1.2.0 Signed-off-by: Franck LECUYER --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c30b88fb20..ed4f36e903 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.1.1", + "@powsybl/network-viewer": "1.2.0", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", @@ -5178,9 +5178,9 @@ } }, "node_modules/@powsybl/network-viewer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@powsybl/network-viewer/-/network-viewer-1.1.1.tgz", - "integrity": "sha512-spXy3EnRlbvPbsq4ue3ECA+Dz7z/9WEOOaXoGtPyMyZtbHlDJCpWUoVwg7iVbr33uYMAY8oDvqu+sLszZ9aNCw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@powsybl/network-viewer/-/network-viewer-1.2.0.tgz", + "integrity": "sha512-AHnAa7fLMYsHPr1ZUKpj9VI6QvL4JRx57Fcv6KtKkT1xKKEoS40CuQ+EgRBMaorDkwxLhibutVmskIOzD5AVdA==", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", "@svgdotjs/svg.js": "^3.2.0", diff --git a/package.json b/package.json index 6fc193ad7d..9562f5aa11 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.1.1", + "@powsybl/network-viewer": "1.2.0", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", From af20e7d776245d21609af9539b33156562c9502c Mon Sep 17 00:00:00 2001 From: Franck LECUYER Date: Tue, 26 Nov 2024 14:30:28 +0100 Subject: [PATCH 02/13] Build GridStudy app with new powsybl-network-viewer release 1.2.0 Signed-off-by: Franck LECUYER --- src/components/network/gs-map-equipments.ts | 7 +-- src/components/network/network-map-tab.tsx | 47 +++++++++++++++------ src/redux/reducer.ts | 4 ++ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/components/network/gs-map-equipments.ts b/src/components/network/gs-map-equipments.ts index 942436232f..62c88cd4a1 100644 --- a/src/components/network/gs-map-equipments.ts +++ b/src/components/network/gs-map-equipments.ts @@ -6,8 +6,6 @@ */ import { UUID } from 'crypto'; -import { RefObject } from 'react'; -import { IntlShape } from 'react-intl'; import { Dispatch } from 'redux'; import { UseSnackMessageReturn } from '@gridsuite/commons-ui'; import { mapEquipmentsCreated, setMapEquipementsInitialized } from '../../redux/actions'; @@ -22,7 +20,6 @@ import { MapEquipments } from '@powsybl/network-viewer'; export default class GSMapEquipments extends MapEquipments { dispatch: Dispatch; errHandler?: UseSnackMessageReturn['snackError']; - intlRef: RefObject; initEquipments(studyUuid: UUID, currentNodeUuid: UUID) { const fetchSubstationsMapInfosPromise = fetchSubstationsMapInfos(studyUuid, currentNodeUuid, undefined, false); @@ -102,13 +99,11 @@ export default class GSMapEquipments extends MapEquipments { studyUuid: UUID, currentNodeUuid: UUID, errHandler: UseSnackMessageReturn['snackError'], - dispatch: Dispatch, - intlRef: RefObject + dispatch: Dispatch ) { super(); this.dispatch = dispatch; this.errHandler = errHandler; - this.intlRef = intlRef; this.initEquipments(studyUuid, currentNodeUuid); } diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index fa73988e2d..d79432c4fc 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -21,7 +21,7 @@ import VoltageLevelChoice from '../voltage-level-choice'; import NominalVoltageFilter from './nominal-voltage-filter'; import { useDispatch, useSelector } from 'react-redux'; import { PARAM_MAP_BASEMAP, PARAM_MAP_MANUAL_REFRESH, PARAM_USE_NAME } from '../../utils/config-params'; -import { Equipment, EquipmentType, useIntlRef, useSnackMessage } from '@gridsuite/commons-ui'; +import { Equipment, EquipmentType, useSnackMessage } from '@gridsuite/commons-ui'; import { isNodeBuilt, isNodeRenamed, isSameNode, isSameNodeAndBuilt } from '../graph/util/model-functions'; import { resetMapReloaded, setMapDataLoading } from '../../redux/actions'; import GSMapEquipments from './gs-map-equipments'; @@ -55,6 +55,11 @@ import { Line as LineMap, VoltageLevel as VoltageLevelMap, } from '@powsybl/network-viewer/dist/components/network-map-viewer/network/map-equipments'; +import { + Substation as SubstationEq, + Equipment as EquipmentEq, + Line as LineEq, +} from '@powsybl/network-viewer/dist/components/network-map-viewer/utils/equipment-types'; import { Box, useTheme } from '@mui/material'; const INITIAL_POSITION = [0, 0] as [number, number]; const INITIAL_ZOOM = 9; @@ -141,14 +146,13 @@ export const NetworkMapTab = ({ const dispatch = useDispatch(); - const intlRef = useIntlRef(); const [isRootNodeGeoDataLoaded, setIsRootNodeGeoDataLoaded] = useState(false); const [isInitialized, setInitialized] = useState(false); const mapBoxToken = useMapBoxToken(); const { snackError } = useSnackMessage(); - const [filteredNominalVoltages, setFilteredNominalVoltages] = useState(); + const [filteredNominalVoltages, setFilteredNominalVoltages] = useState([]); const [geoData, setGeoData] = useState(); const geoDataRef = useRef(); @@ -339,7 +343,7 @@ export const NetworkMapTab = ({ const handleDeleteEquipment = useCallback( (equipmentType: EquipmentType | null, equipmentId: string) => { - const equipment = mapEquipments?.hvdcLinesById?.get(equipmentId) as Equipment; + const equipment = mapEquipments?.hvdcLinesById?.get(equipmentId) as LineEq; if ( equipmentType === EquipmentType.HVDC_LINE && equipment && @@ -494,11 +498,11 @@ export const NetworkMapTab = ({ const loadMissingGeoData = useCallback(() => { const notFoundSubstationIds = getEquipmentsNotFoundIds( geoDataRef.current.substationPositionsById, - mapEquipments?.substations as Substation[] + mapEquipments?.substations as SubstationEq[] ); const notFoundLineIds = lineFullPath - ? getEquipmentsNotFoundIds(geoDataRef.current.linePositionsById, mapEquipments?.lines as Line[]) + ? getEquipmentsNotFoundIds(geoDataRef.current.linePositionsById, mapEquipments?.lines as EquipmentGeoData[]) : []; if (notFoundSubstationIds.length > 0 || notFoundLineIds.length > 0) { @@ -649,11 +653,11 @@ 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, snackError, dispatch); if (gSMapEquipments) { dispatch(resetMapReloaded()); } - }, [currentNode, dispatch, intlRef, snackError, studyUuid]); + }, [currentNode, dispatch, snackError, studyUuid]); const reloadMapEquipments = useCallback( (currentNodeAtReloadCalling: CurrentTreeNode | null, substationsIds: UUID[] | undefined) => { @@ -674,24 +678,36 @@ export const NetworkMapTab = ({ updatedSubstations.then((values) => { if (currentNodeAtReloadCalling?.id === currentNodeRef.current?.id) { - mapEquipments.updateSubstations(mapEquipments.checkAndGetValues(values), isFullReload); + mapEquipments.updateSubstations( + mapEquipments.checkAndGetValues(values as EquipmentEq[]) as SubstationEq[], + isFullReload + ); } }); updatedLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateLines(mapEquipments.checkAndGetValues(values), isFullReload); + mapEquipments.updateLines( + mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], + isFullReload + ); setUpdatedLines(values); } }); updatedTieLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateTieLines(mapEquipments.checkAndGetValues(values), isFullReload); + mapEquipments.updateTieLines( + mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], + isFullReload + ); setUpdatedTieLines(values); } }); updatedHvdcLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateHvdcLines(mapEquipments.checkAndGetValues(values), isFullReload); + mapEquipments.updateHvdcLines( + mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], + isFullReload + ); setUpdatedHvdcLines(values); } }); @@ -775,6 +791,7 @@ export const NetworkMapTab = ({ } if (deletedEquipments?.length > 0 && mapEquipments) { deletedEquipments.forEach((deletedEquipment) => { + // @ts-expect-error TODO type conversion string to enum mapEquipments.removeEquipment(deletedEquipment?.equipmentType, deletedEquipment?.equipmentId); }); resetDeletedEquipments(); @@ -948,6 +965,7 @@ export const NetworkMapTab = ({ } onVoltageLevelMenuClick={voltageLevelMenuClick} mapBoxToken={mapBoxToken} + // @ts-expect-error TODO type conversion centerOnSubstation={centerOnSubstation} isManualRefreshBackdropDisplayed={mapManualRefresh && reloadMapNeeded && isNodeBuilt(currentNode)} // only 2 things need this to ensure the map keeps the correct size: @@ -957,6 +975,7 @@ export const NetworkMapTab = ({ // it causes a render with the map container having display:none onManualRefreshClick={updateMapEquipmentsAndGeoData} triggerMapResizeOnChange={[studyDisplayMode, visible]} + // @ts-expect-error TODO type conversion renderPopover={renderLinePopover} mapLibrary={basemap} mapTheme={theme?.palette.mode} @@ -974,7 +993,7 @@ export const NetworkMapTab = ({ /> ); - function handleChange(newValues: unknown[]) { + function handleChange(newValues: number[]) { setFilteredNominalVoltages(newValues); onNominalVoltagesChange(newValues); } @@ -984,7 +1003,7 @@ export const NetworkMapTab = ({ diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index 0edfba4ce3..bd0246cc01 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -814,18 +814,22 @@ export const reducer = createReducer(initialState, (builder) => { newMapEquipments = state.mapEquipments.newMapEquipmentForUpdate() as GSMapEquipments; } if (action.newLines) { + // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.lines = action.newLines; newMapEquipments.completeLinesInfos([]); } if (action.newTieLines) { + // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.tieLines = action.newTieLines; newMapEquipments.completeTieLinesInfos([]); } if (action.newSubstations) { + // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.substations = action.newSubstations; newMapEquipments.completeSubstationsInfos([]); } if (action.newHvdcLines) { + // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.hvdcLines = action.newHvdcLines; newMapEquipments.completeHvdcLinesInfos([]); } From cae75376edac187d8a7dcabd4033f942dd523696 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 01:43:57 +0100 Subject: [PATCH 03/13] revert 1.1.1 --- package-lock.json | 8 ++--- package.json | 4 +-- src/components/network/network-map-tab.tsx | 41 +++++++--------------- src/redux/reducer.ts | 4 --- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index ed4f36e903..c30b88fb20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.2.0", + "@powsybl/network-viewer": "1.1.1", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", @@ -5178,9 +5178,9 @@ } }, "node_modules/@powsybl/network-viewer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@powsybl/network-viewer/-/network-viewer-1.2.0.tgz", - "integrity": "sha512-AHnAa7fLMYsHPr1ZUKpj9VI6QvL4JRx57Fcv6KtKkT1xKKEoS40CuQ+EgRBMaorDkwxLhibutVmskIOzD5AVdA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@powsybl/network-viewer/-/network-viewer-1.1.1.tgz", + "integrity": "sha512-spXy3EnRlbvPbsq4ue3ECA+Dz7z/9WEOOaXoGtPyMyZtbHlDJCpWUoVwg7iVbr33uYMAY8oDvqu+sLszZ9aNCw==", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", "@svgdotjs/svg.js": "^3.2.0", diff --git a/package.json b/package.json index 9562f5aa11..f0bf614dcd 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,11 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.2.0", + "@powsybl/network-viewer": "1.1.1", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", + "@xyflow/react": "^12.3.2", "ag-grid-community": "^31.0.0", "ag-grid-react": "^31.2.0", "cheap-ruler": "^3.0.2", @@ -36,7 +37,6 @@ "react-beautiful-dnd": "^13.1.1", "react-csv-downloader": "^3.1.0", "react-dom": "^18.2.0", - "@xyflow/react": "^12.3.2", "react-grid-layout": "^1.4.4", "react-hook-form": "^7.51.2", "react-intl": "^6.6.4", diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index d79432c4fc..e4978ac7e6 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -55,11 +55,6 @@ import { Line as LineMap, VoltageLevel as VoltageLevelMap, } from '@powsybl/network-viewer/dist/components/network-map-viewer/network/map-equipments'; -import { - Substation as SubstationEq, - Equipment as EquipmentEq, - Line as LineEq, -} from '@powsybl/network-viewer/dist/components/network-map-viewer/utils/equipment-types'; import { Box, useTheme } from '@mui/material'; const INITIAL_POSITION = [0, 0] as [number, number]; const INITIAL_ZOOM = 9; @@ -343,10 +338,12 @@ export const NetworkMapTab = ({ const handleDeleteEquipment = useCallback( (equipmentType: EquipmentType | null, equipmentId: string) => { - const equipment = mapEquipments?.hvdcLinesById?.get(equipmentId) as LineEq; + const equipment = mapEquipments?.hvdcLinesById?.get(equipmentId); if ( equipmentType === EquipmentType.HVDC_LINE && + // mapEquipments?.hvdcLinesById?.get(equipmentId)?.hvdcType === 'LCC' equipment && + // @ts-expect-error TODO: ??? 'hvdcType' in equipment && equipment.hvdcType === 'LCC' ) { @@ -498,7 +495,8 @@ export const NetworkMapTab = ({ const loadMissingGeoData = useCallback(() => { const notFoundSubstationIds = getEquipmentsNotFoundIds( geoDataRef.current.substationPositionsById, - mapEquipments?.substations as SubstationEq[] + //@ts-expect-error TODO: manage undefined case + mapEquipments?.substations ); const notFoundLineIds = lineFullPath @@ -678,36 +676,24 @@ export const NetworkMapTab = ({ updatedSubstations.then((values) => { if (currentNodeAtReloadCalling?.id === currentNodeRef.current?.id) { - mapEquipments.updateSubstations( - mapEquipments.checkAndGetValues(values as EquipmentEq[]) as SubstationEq[], - isFullReload - ); + mapEquipments.updateSubstations(mapEquipments.checkAndGetValues(values), isFullReload); } }); updatedLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateLines( - mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], - isFullReload - ); + mapEquipments.updateLines(mapEquipments.checkAndGetValues(values), isFullReload); setUpdatedLines(values); } }); updatedTieLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateTieLines( - mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], - isFullReload - ); + mapEquipments.updateTieLines(mapEquipments.checkAndGetValues(values), isFullReload); setUpdatedTieLines(values); } }); updatedHvdcLines.then((values) => { if (checkNodeConsistency(currentNodeAtReloadCalling)) { - mapEquipments.updateHvdcLines( - mapEquipments.checkAndGetValues(values as EquipmentEq[]) as LineEq[], - isFullReload - ); + mapEquipments.updateHvdcLines(mapEquipments.checkAndGetValues(values), isFullReload); setUpdatedHvdcLines(values); } }); @@ -790,10 +776,9 @@ export const NetworkMapTab = ({ return; } if (deletedEquipments?.length > 0 && mapEquipments) { - deletedEquipments.forEach((deletedEquipment) => { - // @ts-expect-error TODO type conversion string to enum - mapEquipments.removeEquipment(deletedEquipment?.equipmentType, deletedEquipment?.equipmentId); - }); + deletedEquipments.forEach((deletedEquipment) => + mapEquipments.removeEquipment(deletedEquipment?.equipmentType, deletedEquipment?.equipmentId) + ); resetDeletedEquipments(); } }, [deletedEquipments, mapEquipments, resetDeletedEquipments]); @@ -965,7 +950,6 @@ export const NetworkMapTab = ({ } onVoltageLevelMenuClick={voltageLevelMenuClick} mapBoxToken={mapBoxToken} - // @ts-expect-error TODO type conversion centerOnSubstation={centerOnSubstation} isManualRefreshBackdropDisplayed={mapManualRefresh && reloadMapNeeded && isNodeBuilt(currentNode)} // only 2 things need this to ensure the map keeps the correct size: @@ -975,7 +959,6 @@ export const NetworkMapTab = ({ // it causes a render with the map container having display:none onManualRefreshClick={updateMapEquipmentsAndGeoData} triggerMapResizeOnChange={[studyDisplayMode, visible]} - // @ts-expect-error TODO type conversion renderPopover={renderLinePopover} mapLibrary={basemap} mapTheme={theme?.palette.mode} diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index bd0246cc01..0edfba4ce3 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -814,22 +814,18 @@ export const reducer = createReducer(initialState, (builder) => { newMapEquipments = state.mapEquipments.newMapEquipmentForUpdate() as GSMapEquipments; } if (action.newLines) { - // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.lines = action.newLines; newMapEquipments.completeLinesInfos([]); } if (action.newTieLines) { - // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.tieLines = action.newTieLines; newMapEquipments.completeTieLinesInfos([]); } if (action.newSubstations) { - // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.substations = action.newSubstations; newMapEquipments.completeSubstationsInfos([]); } if (action.newHvdcLines) { - // @ts-expect-error TODO: find how to convert MutableUnknownArray to proper type newMapEquipments.hvdcLines = action.newHvdcLines; newMapEquipments.completeHvdcLinesInfos([]); } From e331ac6531fefc6eecbcda28752f814f6a15702e Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 02:28:16 +0100 Subject: [PATCH 04/13] Step 1 --- package-lock.json | 9 ++- package.json | 2 +- src/components/menus/base-equipment-menu.tsx | 2 +- src/components/network/network-map-tab.tsx | 85 +++++++++++--------- 4 files changed, 56 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index c30b88fb20..dbe9963b43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.1.1", + "@powsybl/network-viewer": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", @@ -5178,9 +5178,10 @@ } }, "node_modules/@powsybl/network-viewer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@powsybl/network-viewer/-/network-viewer-1.1.1.tgz", - "integrity": "sha512-spXy3EnRlbvPbsq4ue3ECA+Dz7z/9WEOOaXoGtPyMyZtbHlDJCpWUoVwg7iVbr33uYMAY8oDvqu+sLszZ9aNCw==", + "version": "1.2.0", + "resolved": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", + "integrity": "sha512-zr6xP55LJGOSwpxPUPBuj00M7ArP/f1W0ZyxHVAkwAt8vAB2t908YS/TH/t2bXbIHWdzgmbAJ6E/yMqz4WHhXQ==", + "license": "MPL-2.0", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", "@svgdotjs/svg.js": "^3.2.0", diff --git a/package.json b/package.json index f0bf614dcd..4074a54391 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@mui/lab": "5.0.0-alpha.169", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", - "@powsybl/network-viewer": "1.1.1", + "@powsybl/network-viewer": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", "@reduxjs/toolkit": "^2.2.3", "@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.panzoom.js": "^2.1.2", diff --git a/src/components/menus/base-equipment-menu.tsx b/src/components/menus/base-equipment-menu.tsx index 58d9ce8167..b4917e8cbb 100644 --- a/src/components/menus/base-equipment-menu.tsx +++ b/src/components/menus/base-equipment-menu.tsx @@ -145,7 +145,7 @@ const ItemViewInForm = ({ ); }; -// Temporary type definition for VoltageLevel Equipment, pending a more comprehensive Equipment typing in diagramViewer +// TODO: Temporary type definition for VoltageLevel Equipment, pending a more comprehensive Equipment typing in diagramViewer export type MapEquipment = Equipment & { substationId: string; substationName: string; diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index e4978ac7e6..0eda1882f8 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -5,17 +5,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import type { Writable } from 'type-fest'; import { - NetworkMap, + type Coordinate, + DRAW_MODES, GeoData, - NetworkMapRef, - LineFlowMode, LineFlowColorMode, - DRAW_MODES, + LineFlowMode, + type MapEquipment, + type MapLine, + type MapSubstation, + type MapVoltageLevel, + NetworkMap, + type NetworkMapRef, } from '@powsybl/network-viewer'; -import { useCallback, useEffect, useState, useRef, useMemo, RefObject } from 'react'; +import { type FunctionComponent, type RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import withOperatingStatusMenu, { MenuBranchProps } from '../menus/operating-status-menu'; -import BaseEquipmentMenu, { MapEquipment } from '../menus/base-equipment-menu'; +import BaseEquipmentMenu, { MapEquipment as BaseEquipment } from '../menus/base-equipment-menu'; import withEquipmentMenu from '../menus/equipment-menu'; import VoltageLevelChoice from '../voltage-level-choice'; import NominalVoltageFilter from './nominal-voltage-filter'; @@ -25,7 +31,7 @@ import { Equipment, EquipmentType, useSnackMessage } from '@gridsuite/commons-ui import { isNodeBuilt, isNodeRenamed, isSameNode, isSameNodeAndBuilt } from '../graph/util/model-functions'; import { resetMapReloaded, setMapDataLoading } from '../../redux/actions'; import GSMapEquipments from './gs-map-equipments'; -import LinearProgress from '@mui/material/LinearProgress'; +import { Box, LinearProgress, useTheme } from '@mui/material'; import { UPDATE_TYPE_HEADER } from '../study-container'; import SubstationModificationDialog from '../dialogs/network-modifications/substation/modification/substation-modification-dialog'; import VoltageLevelModificationDialog from '../dialogs/network-modifications/voltage-level/modification/voltage-level-modification-dialog'; @@ -34,7 +40,6 @@ import LineModificationDialog from '../dialogs/network-modifications/line/modifi import { deleteEquipment } from '../../services/study/network-modifications'; import EquipmentDeletionDialog from '../dialogs/network-modifications/equipment-deletion/equipment-deletion-dialog'; import { fetchLinePositions, fetchSubstationPositions } from '../../services/study/geo-data'; - import { useMapBoxToken } from './network-map/use-mapbox-token'; import EquipmentPopover from '../tooltips/equipment-popover'; import RunningStatus from 'components/utils/running-status'; @@ -44,19 +49,12 @@ import { ROOT_NODE_LABEL } from '../../constants/node.constant'; import { UUID } from 'crypto'; import { AppState, CurrentTreeNode } from 'redux/reducer'; import { - Coordinate, + Equipment as EquipmentGeoData, Line, Substation, - Equipment as EquipmentGeoData, } from '@powsybl/network-viewer/dist/components/network-map-viewer/network/geo-data'; -import { - Equipment as EquipmentMap, - Substation as SubstationMap, - Line as LineMap, - VoltageLevel as VoltageLevelMap, -} from '@powsybl/network-viewer/dist/components/network-map-viewer/network/map-equipments'; -import { Box, useTheme } from '@mui/material'; -const INITIAL_POSITION = [0, 0] as [number, number]; + +const INITIAL_POSITION = [0, 0] as const; const INITIAL_ZOOM = 9; const LABELS_ZOOM_THRESHOLD = 9; const ARROWS_ZOOM_THRESHOLD = 7; @@ -81,7 +79,7 @@ const styles = { const NODE_CHANGED_ERROR = 'Node has changed or is not built anymore. The Promise is rejected.'; type NetworkMapTabProps = { - networkMapRef: React.RefObject; + networkMapRef: RefObject; studyUuid: UUID; currentNode: CurrentTreeNode; visible: boolean; @@ -179,7 +177,7 @@ export const NetworkMapTab = ({ type EquipmentMenuProps = { position?: [number, number] | null; - equipment?: MapEquipment; + equipment?: BaseEquipment; equipmentType?: EquipmentType; display: boolean; }; @@ -288,7 +286,7 @@ export const NetworkMapTab = ({ studyUuid: UUID; equipmentType: EquipmentType; }; - function withEquipment(Menu: React.FC, props: MenuProps | null) { + function withEquipment(Menu: FunctionComponent, props: MenuProps | null) { return ( equipmentMenu?.equipment && equipmentMenu.position && @@ -313,7 +311,7 @@ export const NetworkMapTab = ({ const MenuVoltageLevel = withEquipmentMenu(BaseEquipmentMenu, EquipmentType.VOLTAGE_LEVEL, 'voltage-level-menus'); - function showEquipmentMenu(equipment: MapEquipment, x: number, y: number, type: EquipmentType) { + function showEquipmentMenu(equipment: BaseEquipment, x: number, y: number, type: EquipmentType) { setEquipmentMenu({ position: [x, y], equipment: equipment, @@ -371,10 +369,10 @@ export const NetworkMapTab = ({ closeChoiceVoltageLevelMenu(); } - const voltageLevelMenuClick = (equipment: VoltageLevelMap, x: number, y: number) => { + const voltageLevelMenuClick = (equipment: MapVoltageLevel, x: number, y: number) => { // don't display the voltage level menu in drawing mode. if (!isInDrawingMode) { - showEquipmentMenu(equipment as MapEquipment, x, y, EquipmentType.VOLTAGE_LEVEL); + showEquipmentMenu(equipment as unknown as BaseEquipment, x, y, EquipmentType.VOLTAGE_LEVEL); } }; @@ -860,13 +858,12 @@ export const NetworkMapTab = ({ } }, [isInitialized, lineFullPath, loadGeoData]); - let choiceVoltageLevelsSubstation: EquipmentMap | null = null; - if (choiceVoltageLevelsSubstationId) { - choiceVoltageLevelsSubstation = mapEquipments?.getSubstation(choiceVoltageLevelsSubstationId); - } + const choiceVoltageLevelsSubstation = choiceVoltageLevelsSubstationId + ? mapEquipments?.getSubstation(choiceVoltageLevelsSubstationId) + : null; const displayEquipmentMenu = ( - equipment: MapEquipment, + equipment: BaseEquipment, x: number, y: number, equipmentType: EquipmentType, @@ -927,7 +924,7 @@ export const NetworkMapTab = ({ filteredNominalVoltages={filteredNominalVoltages} labelsZoomThreshold={LABELS_ZOOM_THRESHOLD} arrowsZoomThreshold={ARROWS_ZOOM_THRESHOLD} - initialPosition={INITIAL_POSITION} + initialPosition={INITIAL_POSITION as Writable} initialZoom={INITIAL_ZOOM} lineFullPath={lineFullPath} lineParallelPath={lineParallelPath} @@ -939,15 +936,31 @@ export const NetworkMapTab = ({ disabled={disabled} onSubstationClick={openVoltageLevel} onSubstationClickChooseVoltageLevel={chooseVoltageLevelForSubstation} - onSubstationMenuClick={(equipment: SubstationMap, x: number, y: number) => - displayEquipmentMenu(equipment as MapEquipment, x, y, EquipmentType.SUBSTATION, isInDrawingMode) + // @ts-expect-error TODO tmp + onSubstationMenuClick={(equipment: MapSubstation, x: number, y: number) => + displayEquipmentMenu( + equipment as unknown as BaseEquipment, + x, + y, + EquipmentType.SUBSTATION, + isInDrawingMode + ) } - onLineMenuClick={(equipment: LineMap, x: number, y: number) => - displayEquipmentMenu(equipment as MapEquipment, x, y, EquipmentType.LINE, isInDrawingMode) + // @ts-expect-error TODO tmp + onLineMenuClick={(equipment: MapLine, x: number, y: number) => + displayEquipmentMenu(equipment as unknown as BaseEquipment, x, y, EquipmentType.LINE, isInDrawingMode) } - onHvdcLineMenuClick={(equipment: EquipmentMap, x: number, y: number) => - displayEquipmentMenu(equipment as MapEquipment, x, y, EquipmentType.HVDC_LINE, isInDrawingMode) + // @ts-expect-error TODO tmp + onHvdcLineMenuClick={(equipment: MapEquipment, x: number, y: number) => + displayEquipmentMenu( + equipment as unknown as BaseEquipment, + x, + y, + EquipmentType.HVDC_LINE, + isInDrawingMode + ) } + // @ts-expect-error TODO tmp onVoltageLevelMenuClick={voltageLevelMenuClick} mapBoxToken={mapBoxToken} centerOnSubstation={centerOnSubstation} From 8b0716fac4b0378547ab5a36ced34b611c355cb4 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 02:41:11 +0100 Subject: [PATCH 05/13] Step 2 --- package-lock.json | 2 +- src/components/network/network-map-tab.tsx | 41 ++++++++++++---------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index dbe9963b43..b0cacbe12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5180,7 +5180,7 @@ "node_modules/@powsybl/network-viewer": { "version": "1.2.0", "resolved": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", - "integrity": "sha512-zr6xP55LJGOSwpxPUPBuj00M7ArP/f1W0ZyxHVAkwAt8vAB2t908YS/TH/t2bXbIHWdzgmbAJ6E/yMqz4WHhXQ==", + "integrity": "sha512-8OTEqPQTxIOzm++wuz64AO66er/xN5RGJL+SAiW0UwTYgA/DvxnRzpPqFXTmaohbDkX3PiztE9B0UCCYHpKkPg==", "license": "MPL-2.0", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index 0eda1882f8..0ee28091d1 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -10,11 +10,16 @@ import { type Coordinate, DRAW_MODES, GeoData, + type GeoDataEquipment, + type GeoDataLine, + type GeoDataSubstation, LineFlowColorMode, LineFlowMode, type MapEquipment, + type MapHvdcLine, type MapLine, type MapSubstation, + type MapTieLine, type MapVoltageLevel, NetworkMap, type NetworkMapRef, @@ -48,11 +53,6 @@ import { useGetStudyImpacts } from 'hooks/use-get-study-impacts'; import { ROOT_NODE_LABEL } from '../../constants/node.constant'; import { UUID } from 'crypto'; import { AppState, CurrentTreeNode } from 'redux/reducer'; -import { - Equipment as EquipmentGeoData, - Line, - Substation, -} from '@powsybl/network-viewer/dist/components/network-map-viewer/network/geo-data'; const INITIAL_POSITION = [0, 0] as const; const INITIAL_ZOOM = 9; @@ -188,9 +188,9 @@ export const NetworkMapTab = ({ const [position, setPosition] = useState([-1, -1]); const currentNodeRef = useRef(null); - const [updatedLines, setUpdatedLines] = useState([]); - const [updatedTieLines, setUpdatedTieLines] = useState([]); - const [updatedHvdcLines, setUpdatedHvdcLines] = useState([]); + const [updatedLines, setUpdatedLines] = useState([]); + const [updatedTieLines, setUpdatedTieLines] = useState([]); + const [updatedHvdcLines, setUpdatedHvdcLines] = useState([]); const [equipmentToModify, setEquipmentToModify] = useState(); const [modificationDialogOpen, setModificationDialogOpen] = useState(false); const [deletionDialogOpen, setDeletionDialogOpen] = useState(false); @@ -387,7 +387,7 @@ export const NetworkMapTab = ({ ); const getEquipmentsNotFoundIds = useCallback( - (foundEquipmentPositions: Map, allEquipments: EquipmentGeoData[]) => { + (foundEquipmentPositions: Map, allEquipments: GeoDataEquipment[]) => { return allEquipments .filter((s) => !foundEquipmentPositions.has(s.id) || temporaryGeoDataIdsRef?.current?.has(s.id)) .map((s) => s.id); @@ -399,14 +399,17 @@ export const NetworkMapTab = ({ return coordinate1?.lat === coordinate2?.lat && coordinate1?.lon === coordinate2?.lon; }; - const substationPositionsAreEqual = useCallback((substationPos1: Substation, substationPos2: Substation) => { - return ( - latLonEqual(substationPos1?.coordinate, substationPos2?.coordinate) && - substationPos1?.country === substationPos2?.country - ); - }, []); + const substationPositionsAreEqual = useCallback( + (substationPos1: GeoDataSubstation, substationPos2: GeoDataSubstation) => { + return ( + latLonEqual(substationPos1?.coordinate, substationPos2?.coordinate) && + substationPos1?.country === substationPos2?.country + ); + }, + [] + ); - const linePositionsAreEqual = useCallback((linePos1: Line, linePos2: Line) => { + const linePositionsAreEqual = useCallback((linePos1: GeoDataLine, linePos2: GeoDataLine) => { return ( latLonEqual(linePos1?.coordinates?.[0], linePos2?.coordinates?.[0]) && latLonEqual(linePos1?.coordinates?.[1], linePos2?.coordinates?.[1]) && @@ -432,7 +435,7 @@ export const NetworkMapTab = ({ ); const updateSubstationsTemporaryGeoData = useCallback( - (requestedPositions: string[], fetchedPositions: Substation[]) => { + (requestedPositions: string[], fetchedPositions: GeoDataSubstation[]) => { let someDataHasChanged = false; fetchedPositions.forEach((pos) => { // If the geo data is the same in the geoData and in the server response, it's not updated @@ -458,7 +461,7 @@ export const NetworkMapTab = ({ ); const updateLinesTemporaryGeoData = useCallback( - (requestedPositions: string[], fetchedPositions: Line[]) => { + (requestedPositions: string[], fetchedPositions: GeoDataLine[]) => { let someDataHasChanged = false; fetchedPositions.forEach((pos) => { // If the geo data is the same in the geoData and in the server response, it's not updated @@ -498,7 +501,7 @@ export const NetworkMapTab = ({ ); const notFoundLineIds = lineFullPath - ? getEquipmentsNotFoundIds(geoDataRef.current.linePositionsById, mapEquipments?.lines as EquipmentGeoData[]) + ? getEquipmentsNotFoundIds(geoDataRef.current.linePositionsById, mapEquipments?.lines as GeoDataEquipment[]) : []; if (notFoundSubstationIds.length > 0 || notFoundLineIds.length > 0) { From 1eceaf32fa22dc05f94018f94e121fff38ee9dcc Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 12:42:42 +0100 Subject: [PATCH 06/13] Step 3 --- package-lock.json | 2 +- src/components/network/network-map-tab.tsx | 15 +++---------- src/redux/actions.ts | 25 ++++++++++++++-------- src/redux/reducer.ts | 14 +++++++----- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index b0cacbe12b..b521200ea4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5180,7 +5180,7 @@ "node_modules/@powsybl/network-viewer": { "version": "1.2.0", "resolved": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", - "integrity": "sha512-8OTEqPQTxIOzm++wuz64AO66er/xN5RGJL+SAiW0UwTYgA/DvxnRzpPqFXTmaohbDkX3PiztE9B0UCCYHpKkPg==", + "integrity": "sha512-5E+Br1pyRuh5j5XBZlKJPSOvmPxkIacV5OkT1JHdyVSQqHxmIl5OORjwk51f3CENUBHa7jl3umhRHuWTkfbFHg==", "license": "MPL-2.0", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index 0ee28091d1..e5b2f2a6bb 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -15,7 +15,6 @@ import { type GeoDataSubstation, LineFlowColorMode, LineFlowMode, - type MapEquipment, type MapHvdcLine, type MapLine, type MapSubstation, @@ -286,6 +285,7 @@ export const NetworkMapTab = ({ studyUuid: UUID; equipmentType: EquipmentType; }; + function withEquipment(Menu: FunctionComponent, props: MenuProps | null) { return ( equipmentMenu?.equipment && @@ -336,14 +336,9 @@ export const NetworkMapTab = ({ const handleDeleteEquipment = useCallback( (equipmentType: EquipmentType | null, equipmentId: string) => { - const equipment = mapEquipments?.hvdcLinesById?.get(equipmentId); if ( equipmentType === EquipmentType.HVDC_LINE && - // mapEquipments?.hvdcLinesById?.get(equipmentId)?.hvdcType === 'LCC' - equipment && - // @ts-expect-error TODO: ??? - 'hvdcType' in equipment && - equipment.hvdcType === 'LCC' + mapEquipments?.hvdcLinesById?.get(equipmentId)?.hvdcType === 'LCC' ) { // only hvdc line with LCC requires a Dialog (to select MCS) handleOpenDeletionDialog(equipmentId, EquipmentType.HVDC_LINE); @@ -939,7 +934,6 @@ export const NetworkMapTab = ({ disabled={disabled} onSubstationClick={openVoltageLevel} onSubstationClickChooseVoltageLevel={chooseVoltageLevelForSubstation} - // @ts-expect-error TODO tmp onSubstationMenuClick={(equipment: MapSubstation, x: number, y: number) => displayEquipmentMenu( equipment as unknown as BaseEquipment, @@ -949,12 +943,10 @@ export const NetworkMapTab = ({ isInDrawingMode ) } - // @ts-expect-error TODO tmp onLineMenuClick={(equipment: MapLine, x: number, y: number) => displayEquipmentMenu(equipment as unknown as BaseEquipment, x, y, EquipmentType.LINE, isInDrawingMode) } - // @ts-expect-error TODO tmp - onHvdcLineMenuClick={(equipment: MapEquipment, x: number, y: number) => + onHvdcLineMenuClick={(equipment: MapHvdcLine, x: number, y: number) => displayEquipmentMenu( equipment as unknown as BaseEquipment, x, @@ -963,7 +955,6 @@ export const NetworkMapTab = ({ isInDrawingMode ) } - // @ts-expect-error TODO tmp onVoltageLevelMenuClick={voltageLevelMenuClick} mapBoxToken={mapBoxToken} centerOnSubstation={centerOnSubstation} diff --git a/src/redux/actions.ts b/src/redux/actions.ts index 2ece4faec3..05abebc8ad 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -36,7 +36,14 @@ import { UUID } from 'crypto'; import type { LiteralUnion, UnknownArray } from 'type-fest'; import NetworkModificationTreeModel from '../components/graph/network-modification-tree-model'; import { NodeInsertModes } from '../components/graph/nodes/node-insert-modes'; -import { LineFlowColorMode, LineFlowMode } from '@powsybl/network-viewer'; +import { + LineFlowColorMode, + LineFlowMode, + type MapHvdcLine, + type MapLine, + type MapSubstation, + type MapTieLine, +} from '@powsybl/network-viewer'; import { AppState, CurrentTreeNode, @@ -232,17 +239,17 @@ export function resetEquipmentsPostLoadflow(): ResetEquipmentsPostLoadflowAction export const MAP_EQUIPMENTS_CREATED = 'MAP_EQUIPMENTS_CREATED'; export type MapEquipmentsCreatedAction = Readonly> & { mapEquipments: GSMapEquipments; - newLines?: MutableUnknownArray; - newTieLines?: MutableUnknownArray; - newSubstations?: MutableUnknownArray; - newHvdcLines?: MutableUnknownArray; + newLines?: MapLine[]; + newTieLines?: MapTieLine[]; + newSubstations?: MapSubstation[]; + newHvdcLines?: MapHvdcLine[]; }; export function mapEquipmentsCreated( mapEquipments: GSMapEquipments, - newLines?: MutableUnknownArray, - newTieLines?: MutableUnknownArray, - newSubstations?: MutableUnknownArray, - newHvdcLines?: MutableUnknownArray + newLines?: MapLine[], + newTieLines?: MapTieLine[], + newSubstations?: MapSubstation[], + newHvdcLines?: MapHvdcLine[] ): MapEquipmentsCreatedAction { return { type: MAP_EQUIPMENTS_CREATED, diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index 0edfba4ce3..a6ee88dba4 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -292,7 +292,11 @@ import { } from '../utils/store-sort-filter-fields'; import { UUID } from 'crypto'; import { Filter } from '../components/results/common/results-global-filter'; -import { LineFlowColorMode, LineFlowMode } from '@powsybl/network-viewer'; +import { + LineFlowColorMode, + LineFlowMode, + EQUIPMENT_TYPES as NetworkViewerEquipmentType, +} from '@powsybl/network-viewer'; import type { UnknownArray, ValueOf, WritableDeep } from 'type-fest'; import { Node } from '@xyflow/react'; import { SortConfigType, SortWay } from '../hooks/use-aggrid-sort'; @@ -336,7 +340,7 @@ export interface StudyUpdatedEventDataHeader { // Payloads export interface DeletedEquipment { equipmentId: string; - equipmentType: string; + equipmentType: NetworkViewerEquipmentType; } export interface NetworkImpactsInfos { @@ -806,12 +810,12 @@ export const reducer = createReducer(initialState, (builder) => { }); builder.addCase(MAP_EQUIPMENTS_CREATED, (state, action: MapEquipmentsCreatedAction) => { - let newMapEquipments; + let newMapEquipments: GSMapEquipments; //if it's not initialised yet we take the empty one given in action if (!state.mapEquipments) { - newMapEquipments = action.mapEquipments.newMapEquipmentForUpdate() as GSMapEquipments; + newMapEquipments = action.mapEquipments.newMapEquipmentForUpdate(); } else { - newMapEquipments = state.mapEquipments.newMapEquipmentForUpdate() as GSMapEquipments; + newMapEquipments = state.mapEquipments.newMapEquipmentForUpdate(); } if (action.newLines) { newMapEquipments.lines = action.newLines; From 96e374efb220481250bfe590a5081d0572323595 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 13:18:44 +0100 Subject: [PATCH 07/13] Step 4 --- package-lock.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index b521200ea4..a105597cd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5180,7 +5180,8 @@ "node_modules/@powsybl/network-viewer": { "version": "1.2.0", "resolved": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", - "integrity": "sha512-5E+Br1pyRuh5j5XBZlKJPSOvmPxkIacV5OkT1JHdyVSQqHxmIl5OORjwk51f3CENUBHa7jl3umhRHuWTkfbFHg==", + "integrity": "sha512-A3YKWhYkOs+cu2fG7I9JFrlo50l+p79PVhJ65ebTotrjKssnE6sUsbLqraOkebHk5KCSDN5/lUDonKvVXYC+Mg==", + "hasInstallScript": true, "license": "MPL-2.0", "dependencies": { "@mapbox/mapbox-gl-draw": "^1.4.3", From ba2b23e0dfdc084307b72dee97c1205d7e5e6946 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 14:55:18 +0100 Subject: [PATCH 08/13] Step 5 --- package-lock.json | 2 +- src/components/network/network-map-tab.tsx | 20 ++++++++++++-------- src/redux/actions.ts | 4 ++-- src/redux/reducer.ts | 21 +++++++++------------ 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index a105597cd4..4293a47c51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5180,7 +5180,7 @@ "node_modules/@powsybl/network-viewer": { "version": "1.2.0", "resolved": "file:../../../~powsybl/powsybl-diagram-viewer/powsybl-network-viewer-1.2.0.tgz", - "integrity": "sha512-A3YKWhYkOs+cu2fG7I9JFrlo50l+p79PVhJ65ebTotrjKssnE6sUsbLqraOkebHk5KCSDN5/lUDonKvVXYC+Mg==", + "integrity": "sha512-UbZ6jmVym8bfkYKgMBh1N9h+Y2B38J2F7r7xKqM0zDHCafSn9867sJIWselTCy5hzEzFmBunAfTjFRMcUMiulA==", "hasInstallScript": true, "license": "MPL-2.0", "dependencies": { diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index e5b2f2a6bb..4ea87fe85a 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -21,6 +21,7 @@ import { type MapTieLine, type MapVoltageLevel, NetworkMap, + type NetworkMapProps, type NetworkMapRef, } from '@powsybl/network-viewer'; import { type FunctionComponent, type RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'; @@ -902,14 +903,17 @@ export const NetworkMapTab = ({ ); } - const renderLinePopover = (elementId: string, ref: RefObject) => ( - + const renderLinePopover = useCallback>( + (elementId, ref) => ( + + ), + [loadFlowStatus, studyUuid] ); const renderMap = () => ( diff --git a/src/redux/actions.ts b/src/redux/actions.ts index 05abebc8ad..59062f9b9e 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -761,9 +761,9 @@ export function setEventScenarioDrawerOpen(isEventScenarioDrawerOpen: boolean): export const CENTER_ON_SUBSTATION = 'CENTER_ON_SUBSTATION'; export type CenterOnSubstationAction = Readonly> & { - centerOnSubstation: { to: unknown }; + centerOnSubstation: { to: string }; }; -export function centerOnSubstation(substationId: unknown): CenterOnSubstationAction { +export function centerOnSubstation(substationId: string): CenterOnSubstationAction { return { type: CENTER_ON_SUBSTATION, centerOnSubstation: { to: substationId }, diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index a6ee88dba4..52fcf92e5f 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -462,7 +462,7 @@ export interface AppState extends CommonStoreState { notificationIdList: UUID[]; nonEvacuatedEnergyNotif: boolean; recentGlobalFilters: Filter[]; - mapEquipments: GSMapEquipments | null; + mapEquipments: GSMapEquipments | undefined; networkAreaDiagramNbVoltageLevels: number; networkAreaDiagramDepth: number; studyDisplayMode: StudyDisplayMode; @@ -486,9 +486,11 @@ export interface AppState extends CommonStoreState { isExplorerDrawerOpen: boolean; isModificationsDrawerOpen: boolean; isEventScenarioDrawerOpen: boolean; - centerOnSubstation: null | { - to: unknown; - }; + centerOnSubstation: + | undefined + | { + to: string; + }; isModificationsInProgress: boolean; reloadMap: boolean; isMapEquipmentsInitialized: boolean; @@ -620,7 +622,7 @@ const initialState: AppState = { allChildrenIds: null, }, tables: initialTablesState, - mapEquipments: null, + mapEquipments: undefined, geoData: null, networkModificationTreeModel: new NetworkModificationTreeModel(), computedLanguage: getLocalStorageComputedLanguage(), @@ -637,7 +639,7 @@ const initialState: AppState = { isExplorerDrawerOpen: true, isModificationsDrawerOpen: false, isEventScenarioDrawerOpen: false, - centerOnSubstation: null, + centerOnSubstation: undefined, notificationIdList: [], isModificationsInProgress: false, studyDisplayMode: StudyDisplayMode.HYBRID, @@ -810,13 +812,8 @@ export const reducer = createReducer(initialState, (builder) => { }); builder.addCase(MAP_EQUIPMENTS_CREATED, (state, action: MapEquipmentsCreatedAction) => { - let newMapEquipments: GSMapEquipments; //if it's not initialised yet we take the empty one given in action - if (!state.mapEquipments) { - newMapEquipments = action.mapEquipments.newMapEquipmentForUpdate(); - } else { - newMapEquipments = state.mapEquipments.newMapEquipmentForUpdate(); - } + const newMapEquipments = (state.mapEquipments ?? action.mapEquipments).newMapEquipmentForUpdate(); if (action.newLines) { newMapEquipments.lines = action.newLines; newMapEquipments.completeLinesInfos([]); From ce196e74470c5f8ffda6c30bc9b08ac51cb1e3ae Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 5 Dec 2024 14:55:33 +0100 Subject: [PATCH 09/13] remove unused parameter --- src/components/map-viewer.jsx | 2 -- src/components/network/network-map-tab.tsx | 2 -- src/components/study-container.jsx | 8 +------- src/components/study-pane.jsx | 3 +-- 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/components/map-viewer.jsx b/src/components/map-viewer.jsx index c54b65fc93..32c31acb67 100644 --- a/src/components/map-viewer.jsx +++ b/src/components/map-viewer.jsx @@ -142,7 +142,6 @@ const MapViewer = ({ tableEquipment, onTableEquipementChanged, onChangeTab, - setErrorMessage, }) => { const networkMapref = useRef(null); // hold the reference to the network map (from powsybl-network-viewer) const dispatch = useDispatch(); @@ -323,7 +322,6 @@ const MapViewer = ({ currentNode={currentNode} onChangeTab={onChangeTab} showInSpreadsheet={showInSpreadsheet} - setErrorMessage={setErrorMessage} onDrawPolygonModeActive={onDrawingModeEnter} onPolygonChanged={() => {}} onDrawEvent={onDrawEvent} diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index 4ea87fe85a..be7fff5e3b 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -90,7 +90,6 @@ type NetworkMapTabProps = { lineFlowAlertThreshold: number; openVoltageLevel: (idVoltageLevel: string) => void; showInSpreadsheet: (equipment: { equipmentType: EquipmentType; equipmentId: string }) => void; - setErrorMessage: (message: string) => void; onDrawPolygonModeActive: (active: DRAW_MODES) => void; onPolygonChanged: (polygoneFeature: any) => void; onDrawEvent: (drawEvent: number) => void; @@ -113,7 +112,6 @@ export const NetworkMapTab = ({ /* callbacks */ openVoltageLevel, showInSpreadsheet, - setErrorMessage, onDrawPolygonModeActive, onPolygonChanged, onDrawEvent, diff --git a/src/components/study-container.jsx b/src/components/study-container.jsx index 151b85df23..5d16ade554 100644 --- a/src/components/study-container.jsx +++ b/src/components/study-container.jsx @@ -738,13 +738,7 @@ export function StudyContainer({ view, onChangeTab }) { } // we wait for the user params to be loaded because it can cause some bugs (e.g. with lineFullPath for the map) message={'LoadingRemoteData'} > - + ); diff --git a/src/components/study-pane.jsx b/src/components/study-pane.jsx index d9f2ea899c..579ac17d74 100644 --- a/src/components/study-pane.jsx +++ b/src/components/study-pane.jsx @@ -51,7 +51,7 @@ export const StudyView = { PARAMETERS: 'Parameters', }; -const StudyPane = ({ studyUuid, currentNode, setErrorMessage, ...props }) => { +const StudyPane = ({ studyUuid, currentNode, ...props }) => { const [tableEquipment, setTableEquipment] = useState({ id: null, type: null, @@ -87,7 +87,6 @@ const StudyPane = ({ studyUuid, currentNode, setErrorMessage, ...props }) => { tableEquipment={tableEquipment} onTableEquipementChanged={(newTableEquipment) => setTableEquipment(newTableEquipment)} onChangeTab={props.onChangeTab} - setErrorMessage={setErrorMessage} > {/* using a key in these TabPanelLazy because we can change the nodeUuid in this component */} From ba546db181853906196faf40d700201c3a779b5c Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 6 Dec 2024 11:39:18 +0100 Subject: [PATCH 10/13] set correct type in API --- src/components/network/gs-map-equipments.ts | 6 +- src/components/network/network-map-tab.tsx | 6 +- src/hooks/use-voltage-levels-list-infos.ts | 2 +- .../study/{geo-data.js => geo-data.ts} | 14 +- src/services/study/network-map.ts | 4 +- src/services/study/network-ts.ts | 124 ++++++++++++++++++ src/services/study/network.js | 90 +------------ 7 files changed, 148 insertions(+), 98 deletions(-) rename src/services/study/{geo-data.js => geo-data.ts} (77%) create mode 100644 src/services/study/network-ts.ts diff --git a/src/components/network/gs-map-equipments.ts b/src/components/network/gs-map-equipments.ts index 62c88cd4a1..0695ade24a 100644 --- a/src/components/network/gs-map-equipments.ts +++ b/src/components/network/gs-map-equipments.ts @@ -9,13 +9,13 @@ import { UUID } from 'crypto'; import { Dispatch } from 'redux'; import { UseSnackMessageReturn } from '@gridsuite/commons-ui'; import { mapEquipmentsCreated, setMapEquipementsInitialized } from '../../redux/actions'; +import { MapEquipments } from '@powsybl/network-viewer'; import { fetchHvdcLinesMapInfos, fetchLinesMapInfos, fetchSubstationsMapInfos, fetchTieLinesMapInfos, -} from '../../services/study/network'; -import { MapEquipments } from '@powsybl/network-viewer'; +} from '../../services/study/network-ts'; export default class GSMapEquipments extends MapEquipments { dispatch: Dispatch; @@ -107,7 +107,7 @@ export default class GSMapEquipments extends MapEquipments { this.initEquipments(studyUuid, currentNodeUuid); } - reloadImpactedSubstationsEquipments(studyUuid: UUID, currentNode: any, substationsIds: string[] | null) { + reloadImpactedSubstationsEquipments(studyUuid: UUID, currentNode: any, substationsIds: string[] | undefined) { const updatedSubstations = fetchSubstationsMapInfos(studyUuid, currentNode?.id, substationsIds, true); const updatedLines = fetchLinesMapInfos(studyUuid, currentNode?.id, substationsIds, true); const updatedTieLines = fetchTieLinesMapInfos(studyUuid, currentNode?.id, substationsIds, true); diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index ce9c682614..6d8b79791b 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -578,6 +578,7 @@ export const NetworkMapTab = ({ console.info(`Loading geo data of study '${studyUuid}'...`); dispatch(setMapDataLoading(true)); + // @ts-expect-error TODO: manage rootNodeId undefined case 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()); @@ -588,7 +589,8 @@ export const NetworkMapTab = ({ const linePositionsDone = !lineFullPath ? Promise.resolve() - : fetchLinePositions(studyUuid, rootNodeId).then((data) => { + : // @ts-expect-error TODO: manage rootNodeId undefined case + fetchLinePositions(studyUuid, rootNodeId).then((data) => { console.info(`Received lines of study '${studyUuid}'...`); const newGeoData = new GeoData(geoDataRef.current?.substationPositionsById || new Map(), new Map()); newGeoData.setLinePositions(data); @@ -659,7 +661,7 @@ export const NetworkMapTab = ({ } const { updatedSubstations, updatedLines, updatedTieLines, updatedHvdcLines } = mapEquipments - ? mapEquipments.reloadImpactedSubstationsEquipments(studyUuid, currentNode, substationsIds ?? null) + ? mapEquipments.reloadImpactedSubstationsEquipments(studyUuid, currentNode, substationsIds) : { updatedSubstations: Promise.resolve([]), updatedLines: Promise.resolve([]), diff --git a/src/hooks/use-voltage-levels-list-infos.ts b/src/hooks/use-voltage-levels-list-infos.ts index ee4d2f4362..f0c3b0528b 100644 --- a/src/hooks/use-voltage-levels-list-infos.ts +++ b/src/hooks/use-voltage-levels-list-infos.ts @@ -13,7 +13,7 @@ export default function useVoltageLevelsListInfos(studyUuid: UUID, nodeUuid: UUI const [voltageLevelsListInfos, setVoltageLevelsListInfos] = useState([]); useEffect(() => { if (studyUuid && nodeUuid) { - fetchVoltageLevelsListInfos(studyUuid, nodeUuid).then((values) => { + fetchVoltageLevelsListInfos(studyUuid, nodeUuid).then((values: any) => { setVoltageLevelsListInfos( values.sort((a: { id: string }, b: { id: string }) => a.id.localeCompare(b.id)) ); diff --git a/src/services/study/geo-data.js b/src/services/study/geo-data.ts similarity index 77% rename from src/services/study/geo-data.js rename to src/services/study/geo-data.ts index a960fae9e3..d0af0d9990 100644 --- a/src/services/study/geo-data.js +++ b/src/services/study/geo-data.ts @@ -5,10 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import type { UUID } from 'crypto'; +import type { GeoDataLine, GeoDataSubstation } from '@powsybl/network-viewer'; import { backendFetchJson, getQueryParamsList } from '../utils'; import { getStudyUrlWithNodeUuid } from './index'; -export function fetchSubstationPositions(studyUuid, currentNodeUuid, substationsIds) { +export function fetchSubstationPositions( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds?: string[] +): Promise { console.info( `Fetching substation positions of study '${studyUuid}' and node '${currentNodeUuid}' with ids '${substationsIds}'...` ); @@ -22,7 +28,11 @@ export function fetchSubstationPositions(studyUuid, currentNodeUuid, substations return backendFetchJson(fetchSubstationPositionsUrl); } -export function fetchLinePositions(studyUuid, currentNodeUuid, linesIds) { +export function fetchLinePositions( + studyUuid: UUID, + currentNodeUuid: UUID, + linesIds?: string[] +): Promise { console.info( `Fetching line positions of study '${studyUuid}' and node '${currentNodeUuid}' with ids '${linesIds}'...` ); diff --git a/src/services/study/network-map.ts b/src/services/study/network-map.ts index acc7467796..85824dcf10 100644 --- a/src/services/study/network-map.ts +++ b/src/services/study/network-map.ts @@ -9,7 +9,7 @@ import { getStudyUrlWithNodeUuid } 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'; -import { fetchNetworkElementsInfos } from './network'; +import { fetchNetworkElementsInfos } from './network-ts'; import { createContingencyList } from 'services/explore'; import { ContingencyList, createIdentifierContingencyList } from './contingency-list'; import { UUID } from 'crypto'; @@ -237,7 +237,7 @@ export async function createMapContingencyList( } const selectedEquipmentsIds = selectedEquipments.map((element) => element.id); - const elementsIds = await fetchNetworkElementsInfos( + const elementsIds = await fetchNetworkElementsInfos( studyUuid, currentNodeUuid, selectedEquipmentsIds, diff --git a/src/services/study/network-ts.ts b/src/services/study/network-ts.ts new file mode 100644 index 0000000000..43634cf6bd --- /dev/null +++ b/src/services/study/network-ts.ts @@ -0,0 +1,124 @@ +/* + * Copyright © 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 type { UnknownArray } from 'type-fest'; +import type { UUID } from 'crypto'; +import type { MapHvdcLine, MapLine, MapSubstation, MapTieLine } from '@powsybl/network-viewer'; +import { EQUIPMENT_INFOS_TYPES, EQUIPMENT_TYPES } from '../../components/utils/equipment-types'; +import { backendFetchJson, getQueryParamsList } from '../utils'; +import { getStudyUrlWithNodeUuid } from './index'; + +/* + * NOTE: this file is temporary until network.js is fully migrated to TS + */ + +/* elements */ +export async function fetchNetworkElementsInfos( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds: string[] | undefined, + elementType: string, //TODO found which EQUIPMENT_TYPES enum to use + infoType: string, // TODO migrate to EquipmentInfosTypes + inUpstreamBuiltParentNode?: boolean, + nominalVoltages?: UnknownArray +): Promise { + const substationsCount = substationsIds ? substationsIds.length : 0; + 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.` + ); + + const nominalVoltagesParams = getQueryParamsList(nominalVoltages, 'nominalVoltages'); + + const nominalVoltagesParamsList = nominalVoltages && nominalVoltages?.length > 0 ? '&' + nominalVoltagesParams : ''; + + const urlSearchParams = new URLSearchParams(); + if (inUpstreamBuiltParentNode !== undefined) { + urlSearchParams.append('inUpstreamBuiltParentNode', String(inUpstreamBuiltParentNode)); + } + urlSearchParams.append('infoType', infoType); + urlSearchParams.append('elementType', elementType); + + const fetchElementsUrl = + getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + + '/network/elements' + + '?' + + urlSearchParams + + nominalVoltagesParamsList; + console.debug(fetchElementsUrl); + + return await backendFetchJson(fetchElementsUrl, { + method: 'post', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(substationsIds ?? null), + }); +} + +export function fetchSubstationsMapInfos( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds: string[] | undefined, + inUpstreamBuiltParentNode: boolean +) { + return fetchNetworkElementsInfos( + studyUuid, + currentNodeUuid, + substationsIds, + EQUIPMENT_TYPES.SUBSTATION, + EQUIPMENT_INFOS_TYPES.MAP.type, + inUpstreamBuiltParentNode + ); +} + +export function fetchLinesMapInfos( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds: string[] | undefined, + inUpstreamBuiltParentNode: boolean +) { + return fetchNetworkElementsInfos( + studyUuid, + currentNodeUuid, + substationsIds, + EQUIPMENT_TYPES.LINE, + EQUIPMENT_INFOS_TYPES.MAP.type, + inUpstreamBuiltParentNode + ); +} + +export function fetchTieLinesMapInfos( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds: string[] | undefined, + inUpstreamBuiltParentNode: boolean +) { + return fetchNetworkElementsInfos( + studyUuid, + currentNodeUuid, + substationsIds, + EQUIPMENT_TYPES.TIE_LINE, + EQUIPMENT_INFOS_TYPES.MAP.type, + inUpstreamBuiltParentNode + ); +} + +export function fetchHvdcLinesMapInfos( + studyUuid: UUID, + currentNodeUuid: UUID, + substationsIds: string[] | undefined, + inUpstreamBuiltParentNode: boolean +) { + return fetchNetworkElementsInfos( + studyUuid, + currentNodeUuid, + substationsIds, + EQUIPMENT_TYPES.HVDC_LINE, + EQUIPMENT_INFOS_TYPES.MAP.type, + inUpstreamBuiltParentNode + ); +} diff --git a/src/services/study/network.js b/src/services/study/network.js index 2e5c664e06..01d80d12f0 100644 --- a/src/services/study/network.js +++ b/src/services/study/network.js @@ -7,7 +7,8 @@ import { getStudyUrlWithNodeUuid, PREFIX_STUDY_QUERIES } from './index'; import { EQUIPMENT_INFOS_TYPES, EQUIPMENT_TYPES } from '../../components/utils/equipment-types'; -import { backendFetch, backendFetchJson, backendFetchText, getQueryParamsList, getUrlWithToken } from '../utils'; +import { backendFetch, backendFetchJson, backendFetchText, getUrlWithToken } from '../utils'; +import { fetchNetworkElementsInfos } from './network-ts'; /* voltage-levels */ export function getVoltageLevelSingleLineDiagram( @@ -117,49 +118,6 @@ export function getSubstationSingleLineDiagram( ); } -/* elements */ -export function fetchNetworkElementsInfos( - studyUuid, - currentNodeUuid, - substationsIds, - elementType, - infoType, - inUpstreamBuiltParentNode, - nominalVoltages -) { - const substationsCount = substationsIds ? substationsIds.length : 0; - 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.` - ); - - const nominalVoltagesParams = getQueryParamsList(nominalVoltages, 'nominalVoltages'); - - const nominalVoltagesParamsList = nominalVoltages && nominalVoltages?.length > 0 ? '&' + nominalVoltagesParams : ''; - - const urlSearchParams = new URLSearchParams(); - if (inUpstreamBuiltParentNode !== undefined) { - urlSearchParams.append('inUpstreamBuiltParentNode', inUpstreamBuiltParentNode); - } - urlSearchParams.append('infoType', infoType); - urlSearchParams.append('elementType', elementType); - - const fetchElementsUrl = - getStudyUrlWithNodeUuid(studyUuid, currentNodeUuid) + - '/network/elements' + - '?' + - urlSearchParams + - nominalVoltagesParamsList; - console.debug(fetchElementsUrl); - - return backendFetchJson(fetchElementsUrl, { - method: 'post', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(substationsIds ?? null), - }); -} - export function fetchNetworkElementInfos( studyUuid, currentNodeUuid, @@ -191,50 +149,6 @@ export function fetchNetworkElementInfos( return backendFetchJson(fetchElementsUrl); } -export function fetchSubstationsMapInfos(studyUuid, currentNodeUuid, substationsIds, inUpstreamBuiltParentNode) { - return fetchNetworkElementsInfos( - studyUuid, - currentNodeUuid, - substationsIds, - EQUIPMENT_TYPES.SUBSTATION, - EQUIPMENT_INFOS_TYPES.MAP.type, - inUpstreamBuiltParentNode - ); -} - -export function fetchLinesMapInfos(studyUuid, currentNodeUuid, substationsIds, inUpstreamBuiltParentNode) { - return fetchNetworkElementsInfos( - studyUuid, - currentNodeUuid, - substationsIds, - EQUIPMENT_TYPES.LINE, - EQUIPMENT_INFOS_TYPES.MAP.type, - inUpstreamBuiltParentNode - ); -} - -export function fetchTieLinesMapInfos(studyUuid, currentNodeUuid, substationsIds, inUpstreamBuiltParentNode) { - return fetchNetworkElementsInfos( - studyUuid, - currentNodeUuid, - substationsIds, - EQUIPMENT_TYPES.TIE_LINE, - EQUIPMENT_INFOS_TYPES.MAP.type, - inUpstreamBuiltParentNode - ); -} - -export function fetchHvdcLinesMapInfos(studyUuid, currentNodeUuid, substationsIds, inUpstreamBuiltParentNode) { - return fetchNetworkElementsInfos( - studyUuid, - currentNodeUuid, - substationsIds, - EQUIPMENT_TYPES.HVDC_LINE, - EQUIPMENT_INFOS_TYPES.MAP.type, - inUpstreamBuiltParentNode - ); -} - export function fetchSubstations(studyUuid, currentNodeUuid, substationsIds) { return fetchNetworkElementsInfos( studyUuid, From e5c89e3a267984f6bda144b86101c324b13d166d Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 6 Dec 2024 10:52:05 +0100 Subject: [PATCH 11/13] fix type --- .../singleLineDiagram/single-line-diagram-content.tsx | 10 +++------- src/components/network/gs-map-equipments.ts | 3 ++- src/redux/reducer.ts | 6 +----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx b/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx index 28821528ab..74c35904f4 100644 --- a/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx +++ b/src/components/diagrams/singleLineDiagram/single-line-diagram-content.tsx @@ -63,7 +63,7 @@ type EquipmentMenuState = { }; interface SingleLineDiagramContentProps { readonly showInSpreadsheet: (menu: { equipmentId: string | null; equipmentType: EquipmentType | null }) => void; - readonly studyUuid: string; + readonly studyUuid: UUID; readonly svgType: DiagramType; readonly svg?: string; readonly svgMetadata?: SLDMetadata; @@ -393,7 +393,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) { handleOpenModificationDialog={handleOpenModificationDialog} onOpenDynamicSimulationEventDialog={handleOpenDynamicSimulationEventDialog} currentNode={currentNode} - studyUuid={studyUuid as UUID} + studyUuid={studyUuid} modificationInProgress={modificationInProgress} setModificationInProgress={setModificationInProgress} /> @@ -412,11 +412,7 @@ function SingleLineDiagramContent(props: SingleLineDiagramContentProps) { equipmentMenu.equipmentId && equipmentMenu.equipmentType === equipmentType && ( Date: Fri, 6 Dec 2024 21:40:30 +0100 Subject: [PATCH 12/13] Fix regression --- src/components/network/network-map-tab.tsx | 18 +-- .../network/nominal-voltage-filter.tsx | 115 +++++++++--------- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index 6d8b79791b..1d1f53f092 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -29,7 +29,7 @@ import withOperatingStatusMenu, { MenuBranchProps } from '../menus/operating-sta import BaseEquipmentMenu, { MapEquipment as BaseEquipment } from '../menus/base-equipment-menu'; import withEquipmentMenu from '../menus/equipment-menu'; import VoltageLevelChoice from '../voltage-level-choice'; -import NominalVoltageFilter from './nominal-voltage-filter'; +import NominalVoltageFilter, { type NominalVoltageFilterProps } from './nominal-voltage-filter'; import { useDispatch, useSelector } from 'react-redux'; import { PARAM_MAP_BASEMAP, PARAM_MAP_MANUAL_REFRESH, PARAM_USE_NAME } from '../../utils/config-params'; import { Equipment, EquipmentType, useSnackMessage } from '@gridsuite/commons-ui'; @@ -58,6 +58,7 @@ const INITIAL_POSITION = [0, 0] as const; const INITIAL_ZOOM = 9; const LABELS_ZOOM_THRESHOLD = 9; const ARROWS_ZOOM_THRESHOLD = 7; +const EMPTY_ARRAY: any[] = []; const styles = { divNominalVoltageFilter: { @@ -94,7 +95,7 @@ type NetworkMapTabProps = { onPolygonChanged: (polygoneFeature: any) => void; onDrawEvent: (drawEvent: number) => void; isInDrawingMode: boolean; - onNominalVoltagesChange: (nominalVoltages: unknown[]) => void; + onNominalVoltagesChange: (nominalVoltages: number[]) => void; }; export const NetworkMapTab = ({ @@ -987,16 +988,19 @@ export const NetworkMapTab = ({ /> ); - function handleChange(newValues: number[]) { - setFilteredNominalVoltages(newValues); - onNominalVoltagesChange(newValues); - } + const handleChange = useCallback( + (newValues) => { + setFilteredNominalVoltages(newValues); + onNominalVoltagesChange(newValues); + }, + [onNominalVoltagesChange] + ); function renderNominalVoltageFilter() { return ( diff --git a/src/components/network/nominal-voltage-filter.tsx b/src/components/network/nominal-voltage-filter.tsx index c0a13fb7e1..b0cf2fdbe3 100644 --- a/src/components/network/nominal-voltage-filter.tsx +++ b/src/components/network/nominal-voltage-filter.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Checkbox from '@mui/material/Checkbox'; @@ -43,83 +43,88 @@ const styles = { }, }; -type NominalVoltageFilterProps = { +export type NominalVoltageFilterProps = { nominalVoltages: number[]; filteredNominalVoltages: number[]; onChange: (filteredNominalVoltages: number[]) => void; }; -const NominalVoltageFilter = ({ nominalVoltages, filteredNominalVoltages, onChange }: NominalVoltageFilterProps) => { +export default function NominalVoltageFilter({ + nominalVoltages, + filteredNominalVoltages, + onChange, +}: Readonly) { // Set up filteredNominalVoltages useEffect(() => { - if (nominalVoltages && !filteredNominalVoltages) { - onChange(nominalVoltages as number[]); + if (nominalVoltages.length > 0 && filteredNominalVoltages.length <= 0) { + onChange(nominalVoltages); } }, [nominalVoltages, filteredNominalVoltages, onChange]); - const handleToggle = (vnoms: number[], isToggle: boolean) => () => { - // filter on nominal voltage - let newFiltered = [...filteredNominalVoltages]; - if (isToggle) { - vnoms.forEach((vnom) => { - const currentIndex = filteredNominalVoltages.indexOf(vnom); - if (currentIndex === -1) { - newFiltered.push(vnom); - } else { - newFiltered.splice(currentIndex, 1); - } - }); - } else { - newFiltered = [...vnoms]; - } - onChange(newFiltered); - }; + const handleToggle = useCallback( + (vnoms: number[], isToggle: boolean) => { + let newFiltered: number[]; + if (isToggle) { + // we "inverse" the selection for vnoms values + newFiltered = [...filteredNominalVoltages]; + vnoms.forEach((vnom) => { + const currentIndex = filteredNominalVoltages.indexOf(vnom); + if (currentIndex === -1) { + newFiltered.push(vnom); //not previously present, we add it + } else { + newFiltered.splice(currentIndex, 1); // previously present, we remove it + } + }); + } else { + // it's just the new selection + newFiltered = [...vnoms]; + } + onChange(newFiltered); + }, + [filteredNominalVoltages, onChange] + ); + const handleSelectAll = useCallback(() => handleToggle(nominalVoltages, false), [handleToggle, nominalVoltages]); + const handleSelectNone = useCallback(() => handleToggle([], false), [handleToggle]); + + const nominalVoltagesList = useMemo( + () => + nominalVoltages.map((value) => ( + + handleToggle([value], true)} + disabled={!filteredNominalVoltages} + > + + + + + )), + [filteredNominalVoltages, handleToggle, nominalVoltages] + ); - if (!(nominalVoltages?.length > 0)) { + if (nominalVoltages.length <= 0) { return false; } return ( - - - {nominalVoltages.map((value) => { - return ( - - - - - - - ); - })} + {nominalVoltagesList} ); -}; - -export default NominalVoltageFilter; +} From 65db90196ecfb5b16d753f8dc194c0490b20407e Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 13 Dec 2024 01:13:17 +0100 Subject: [PATCH 13/13] fix nominal voltage filter component --- src/components/network/network-map-tab.tsx | 19 +++++++++++---- .../network/nominal-voltage-filter.tsx | 23 ++++--------------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/components/network/network-map-tab.tsx b/src/components/network/network-map-tab.tsx index 1d1f53f092..31df3c1114 100644 --- a/src/components/network/network-map-tab.tsx +++ b/src/components/network/network-map-tab.tsx @@ -144,7 +144,7 @@ export const NetworkMapTab = ({ const { snackError } = useSnackMessage(); - const [filteredNominalVoltages, setFilteredNominalVoltages] = useState([]); + const [filteredNominalVoltages, setFilteredNominalVoltages] = useState(); const [geoData, setGeoData] = useState(); const geoDataRef = useRef(); @@ -988,7 +988,7 @@ export const NetworkMapTab = ({ /> ); - const handleChange = useCallback( + const handleFilteredNominalVoltagesChange = useCallback( (newValues) => { setFilteredNominalVoltages(newValues); onNominalVoltagesChange(newValues); @@ -996,13 +996,22 @@ export const NetworkMapTab = ({ [onNominalVoltagesChange] ); + // Set up filteredNominalVoltages once at map initialization + // TODO: how do we must manage case where voltages change (like when changing node), as filters are already initialized? + const nominalVoltages = mapEquipments?.getNominalVoltages(); + useEffect(() => { + if (nominalVoltages !== undefined && nominalVoltages.length > 0 && filteredNominalVoltages === undefined) { + handleFilteredNominalVoltagesChange(nominalVoltages); + } + }, [filteredNominalVoltages, handleFilteredNominalVoltagesChange, nominalVoltages]); + function renderNominalVoltageFilter() { return ( ); diff --git a/src/components/network/nominal-voltage-filter.tsx b/src/components/network/nominal-voltage-filter.tsx index b0cf2fdbe3..6d10c54dff 100644 --- a/src/components/network/nominal-voltage-filter.tsx +++ b/src/components/network/nominal-voltage-filter.tsx @@ -5,15 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { useCallback, useEffect, useMemo } from 'react'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import Checkbox from '@mui/material/Checkbox'; -import ListItemText from '@mui/material/ListItemText'; -import Paper from '@mui/material/Paper'; +import { useCallback, useMemo } from 'react'; +import { Button, Checkbox, List, ListItem, ListItemButton, ListItemText, Paper } from '@mui/material'; import { FormattedMessage } from 'react-intl'; -import Button from '@mui/material/Button'; -import { ListItemButton } from '@mui/material'; const styles = { nominalVoltageZone: { @@ -54,15 +48,8 @@ export default function NominalVoltageFilter({ filteredNominalVoltages, onChange, }: Readonly) { - // Set up filteredNominalVoltages - useEffect(() => { - if (nominalVoltages.length > 0 && filteredNominalVoltages.length <= 0) { - onChange(nominalVoltages); - } - }, [nominalVoltages, filteredNominalVoltages, onChange]); - const handleToggle = useCallback( - (vnoms: number[], isToggle: boolean) => { + (vnoms: number[], isToggle = false) => { let newFiltered: number[]; if (isToggle) { // we "inverse" the selection for vnoms values @@ -83,8 +70,8 @@ export default function NominalVoltageFilter({ }, [filteredNominalVoltages, onChange] ); - const handleSelectAll = useCallback(() => handleToggle(nominalVoltages, false), [handleToggle, nominalVoltages]); - const handleSelectNone = useCallback(() => handleToggle([], false), [handleToggle]); + const handleSelectAll = useCallback(() => handleToggle(nominalVoltages), [handleToggle, nominalVoltages]); + const handleSelectNone = useCallback(() => handleToggle([]), [handleToggle]); const nominalVoltagesList = useMemo( () =>