Skip to content
Open
8 changes: 7 additions & 1 deletion src/components/grid-layout/dialog/map-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { UUID } from 'node:crypto';
import { EquipmentType, LineFlowMode, NetworkVisualizationParameters, useStateBoolean } from '@gridsuite/commons-ui';
import { useDispatch, useSelector } from 'react-redux';
import { AppState } from 'redux/reducer';
import { resetMapEquipment, setMapDataLoading, setOpenMap, setReloadMapNeeded } from 'redux/actions';
import { resetMapEquipment, setMapDataLoading, setMapState, setOpenMap, setReloadMapNeeded } from 'redux/actions';
import NetworkMapPanel, { NetworkMapPanelRef } from 'components/network/network-map-panel';
import { Close } from '@mui/icons-material';
import { FormattedMessage } from 'react-intl';
Expand Down Expand Up @@ -61,6 +61,12 @@ export const MapDialog = (props: MapDialogProps) => {
return; // Do not close the map but only the drawing mode
}
}
if (networkMapPanelRef.current) {
const currentMapState = networkMapPanelRef.current.getCurrentMapState?.();
if (currentMapState) {
dispatch(setMapState(currentMapState));
}
}
dispatch(setOpenMap(false));
dispatch(resetMapEquipment());
dispatch(setMapDataLoading(false));
Expand Down
55 changes: 43 additions & 12 deletions src/components/network/network-map-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
import { useGetStudyImpacts } from 'hooks/use-get-study-impacts';
import { ROOT_NODE_LABEL } from '../../constants/node.constant';
import type { UUID } from 'node:crypto';
import { AppState } from 'redux/reducer';
import { AppState, MapState } from 'redux/reducer';
import { isReactFlowRootNodeData } from 'redux/utils';
import { isLoadflowResultNotification, isRootNetworksUpdatedNotification } from 'types/notification-types';
import { CurrentTreeNode } from 'components/graph/tree-node.type';
Expand All @@ -70,8 +70,6 @@
import { useEquipmentMenu } from '../../hooks/use-equipment-menu';
import useEquipmentDialogs from 'hooks/use-equipment-dialogs';

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[] = [];
Expand Down Expand Up @@ -132,6 +130,7 @@

export type NetworkMapPanelRef = {
leaveDrawingMode: () => void;
getCurrentMapState: () => MapState;
};

export const NetworkMapPanel = forwardRef<NetworkMapPanelRef, NetworkMapPanelProps>(
Expand Down Expand Up @@ -166,6 +165,7 @@
const isNetworkModificationTreeUpToDate = useSelector(
(state: AppState) => state.isNetworkModificationTreeModelUpToDate
);
const mapState = useSelector((state: AppState) => state.mapState);
const theme = useTheme();
const { snackInfo } = useSnackMessage();

Expand All @@ -182,7 +182,9 @@

const { snackError } = useSnackMessage();

const [filteredNominalVoltages, setFilteredNominalVoltages] = useState<number[]>();
const [filteredNominalVoltages, setFilteredNominalVoltages] = useState<number[]>(
mapState?.filteredNominalVoltages ?? []
);
const [geoData, setGeoData] = useState<GeoData>();
const geoDataRef = useRef<any>();

Expand Down Expand Up @@ -703,13 +705,21 @@
});
return Promise.all([updatedSubstations, updatedLines, updatedTieLines, updatedHvdcLines]).finally(
() => {
if (isFullReload) {
if (isFullReload && !mapState?.filteredNominalVoltages) {
// Only reset filters if no saved state exists
handleFilteredNominalVoltagesChange(mapEquipments.getNominalVoltages());
}
}
);
},
[currentNode, handleFilteredNominalVoltagesChange, currentRootNetworkUuid, mapEquipments, studyUuid]
[
currentNode,
handleFilteredNominalVoltagesChange,
currentRootNetworkUuid,
mapEquipments,
studyUuid,
mapState?.filteredNominalVoltages,
]
);

const updateMapEquipments = useCallback(
Expand Down Expand Up @@ -912,7 +922,8 @@
// we check if equipments are done initializing because they are checked to fetch accurate missing geo data
if (isRootNodeGeoDataLoaded && isMapEquipmentsInitialized && !isInitialized) {
// when root networks are changed, mapEquipments are recreated. when they are done recreating, the map is zoomed around the new network
if (mapEquipments) {
if (mapEquipments && !mapState?.filteredNominalVoltages) {
// Only initialize filters if no saved state exists
handleFilteredNominalVoltagesChange(mapEquipments.getNominalVoltages());
}
if (currentNodeRef.current && !isReactFlowRootNodeData(currentNodeRef.current)) {
Expand All @@ -931,6 +942,7 @@
isInitialized,
loadMissingGeoData,
dispatch,
mapState?.filteredNominalVoltages,
]);

// Reload geo data (if necessary) when we switch on full path
Expand Down Expand Up @@ -1016,12 +1028,24 @@
setShouldOpenSelectionCreationPanel(false);
}, [isInDrawingMode]);

const getCurrentMapState = useCallback(() => {
return {
zoom: networkMapRef.current?.getCurrentViewState()?.zoom,

Check failure on line 1033 in src/components/network/network-map-panel.tsx

View workflow job for this annotation

GitHub Actions / build / build

Property 'getCurrentViewState' does not exist on type 'NetworkMapRef'.
center: [
networkMapRef.current?.getCurrentViewState()?.center.lng,

Check failure on line 1035 in src/components/network/network-map-panel.tsx

View workflow job for this annotation

GitHub Actions / build / build

Property 'getCurrentViewState' does not exist on type 'NetworkMapRef'.
networkMapRef.current?.getCurrentViewState()?.center.lat,

Check failure on line 1036 in src/components/network/network-map-panel.tsx

View workflow job for this annotation

GitHub Actions / build / build

Property 'getCurrentViewState' does not exist on type 'NetworkMapRef'.
] as [number, number],
filteredNominalVoltages: filteredNominalVoltages,
};
Comment on lines 1071 to 1075
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call getCurrentViewState() only once

Plus, casting "as [number, number]" here is hiding the problem where "networkMapRef.current?.getCurrentViewState()" is nullish, handle it properly ?
Maybe reset to default positions if no ref is found (should not happen though)

}, [filteredNominalVoltages]);

useImperativeHandle(
ref,
() => ({
leaveDrawingMode,
getCurrentMapState,
}),
[leaveDrawingMode]
[leaveDrawingMode, getCurrentMapState]
);

const handleDrawingModeChange = useCallback(
Expand Down Expand Up @@ -1120,8 +1144,9 @@
filteredNominalVoltages={filteredNominalVoltages}
labelsZoomThreshold={LABELS_ZOOM_THRESHOLD}
arrowsZoomThreshold={ARROWS_ZOOM_THRESHOLD}
initialPosition={INITIAL_POSITION as Writable<typeof INITIAL_POSITION>}
initialZoom={INITIAL_ZOOM}
// Use saved state for initial position and zoom
initialPosition={mapState?.center}
initialZoom={mapState?.zoom}
lineFullPath={lineFullPath}
lineParallelPath={lineParallelPath}
lineFlowMode={lineFlowMode}
Expand Down Expand Up @@ -1219,11 +1244,17 @@
if (
nominalVoltagesFromMapEquipments !== undefined &&
nominalVoltagesFromMapEquipments.length > 0 &&
filteredNominalVoltages === undefined
filteredNominalVoltages.length === 0 &&
!mapState?.filteredNominalVoltages // Only initialize if no saved map state exists
) {
handleFilteredNominalVoltagesChange(nominalVoltagesFromMapEquipments);
}
}, [filteredNominalVoltages, handleFilteredNominalVoltagesChange, nominalVoltagesFromMapEquipments]);
}, [
filteredNominalVoltages,
handleFilteredNominalVoltagesChange,
nominalVoltagesFromMapEquipments,
mapState?.filteredNominalVoltages,
]);

function renderNominalVoltageFilter() {
return (
Expand Down
13 changes: 13 additions & 0 deletions src/redux/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type {
ComputingStatusParameters,
DiagramGridLayoutConfig,
GlobalFilterSpreadsheetState,
MapState,
NodeSelectionForCopy,
OneBusShortCircuitAnalysisDiagram,
SpreadsheetFilterState,
Expand Down Expand Up @@ -1550,3 +1551,15 @@ export function updateNodeAliases(nodeAliases: NodeAlias[]): UpdateNodeAliasesAc
nodeAliases,
};
}

export const SET_MAP_STATE = 'SET_MAP_STATE';
export type SetMapStateAction = Readonly<Action<typeof SET_MAP_STATE>> & {
mapState: Partial<MapState>;
};

export function setMapState(mapState: Partial<MapState>): SetMapStateAction {
return {
type: SET_MAP_STATE,
mapState,
};
}
17 changes: 17 additions & 0 deletions src/redux/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ import {
type UpdateTableDefinitionAction,
USE_NAME,
type UseNameAction,
SetMapStateAction,
SET_MAP_STATE,
} from './actions';
import {
getLocalStorageComputedLanguage,
Expand Down Expand Up @@ -559,6 +561,12 @@ export interface DiagramGridLayoutConfig {

export type LogsPaginationState = Record<string, LogsPaginationConfig>;

export interface MapState {
zoom?: number;
center?: [number, number];
filteredNominalVoltages?: number[];
}

export interface AppState extends CommonStoreState, AppConfigState {
signInCallbackError: Error | null;
authenticationRouterError: AuthenticationRouterErrorState | null;
Expand Down Expand Up @@ -650,6 +658,7 @@ export interface AppState extends CommonStoreState, AppConfigState {
toggleOptions: StudyDisplayMode[];
highlightedModificationUuid: UUID | null;
mapOpen: boolean;
mapState: MapState;
}

export type LogsFilterState = Record<string, FilterConfig[]>;
Expand Down Expand Up @@ -775,6 +784,7 @@ const initialState: AppState = {
freezeMapUpdates: false,
isMapEquipmentsInitialized: false,
networkAreaDiagramDepth: 0,
mapState: {},
spreadsheetNetwork: { ...initialSpreadsheetNetworkState },
globalFilterSpreadsheetState: {},
spreadsheetOptionalLoadingParameters: {
Expand Down Expand Up @@ -1958,6 +1968,13 @@ export const reducer = createReducer(initialState, (builder) => {
builder.addCase(UPDATE_NODE_ALIASES, (state, action: UpdateNodeAliasesAction) => {
state.nodeAliases = action.nodeAliases;
});

builder.addCase(SET_MAP_STATE, (state, action: SetMapStateAction) => {
state.mapState = {
...state.mapState,
...action.mapState,
};
});
});

function updateSubstationAfterVLDeletion(
Expand Down
Loading