From dd86299b28048d99b0a8535d4eed63ce531db2ab Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Jul 2024 19:55:00 +0200 Subject: [PATCH 1/9] remove file extension in imports --- .../voltageinit/voltage-init-parameters.tsx | 2 +- .../network-modification-node-editor.jsx | 2 +- src/components/map-viewer.jsx | 20 +++++++++---------- src/services/study/network-map.js | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx b/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx index 2a2a6a66da..3a2776198d 100644 --- a/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx +++ b/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx @@ -50,7 +50,7 @@ import { TabValue, VoltageInitParametersForm, voltageInitParametersFormSchema, -} from './voltage-init-parameters-form.js'; +} from './voltage-init-parameters-form'; import { ReduxState } from '../../../../redux/reducer.type'; import { UUID } from 'crypto'; import { useGetVoltageInitParameters } from './use-get-voltage-init-parameters'; diff --git a/src/components/graph/menus/network-modification-node-editor.jsx b/src/components/graph/menus/network-modification-node-editor.jsx index 1c559cdde1..3e84cd4bde 100644 --- a/src/components/graph/menus/network-modification-node-editor.jsx +++ b/src/components/graph/menus/network-modification-node-editor.jsx @@ -84,7 +84,7 @@ import { RestoreFromTrash } from '@mui/icons-material'; import ByFilterDeletionDialog from '../../dialogs/network-modifications/by-filter-deletion/by-filter-deletion-dialog'; import { createCompositeModifications } from '../../../services/explore'; import { areUuidsEqual } from 'components/utils/utils'; -import CreateCompositeModificationDialog from '../../dialogs/create-composite-modification-dialog.tsx'; +import CreateCompositeModificationDialog from '../../dialogs/create-composite-modification-dialog'; export const styles = { listContainer: (theme) => ({ diff --git a/src/components/map-viewer.jsx b/src/components/map-viewer.jsx index 982f08f519..e7758543ed 100644 --- a/src/components/map-viewer.jsx +++ b/src/components/map-viewer.jsx @@ -13,25 +13,25 @@ import { PARAM_LINE_FLOW_MODE, PARAM_LINE_FULL_PATH, PARAM_LINE_PARALLEL_PATH, -} from '../utils/config-params.js'; -import { setStudyDisplayMode } from '../redux/actions.js'; +} from '../utils/config-params'; +import { setStudyDisplayMode } from '../redux/actions'; import { DRAW_EVENT, DRAW_MODES } from '@powsybl/diagram-viewer'; -import { DiagramType } from './diagrams/diagram-common.js'; +import { DiagramType } from './diagrams/diagram-common'; import { ReactFlowProvider } from 'react-flow-renderer'; import { Box } from '@mui/system'; -import HorizontalToolbar from './horizontal-toolbar.jsx'; -import NetworkModificationTreePane from './network-modification-tree-pane.jsx'; -import NetworkMapTab from './network/network-map-tab.jsx'; -import { DiagramPane } from './diagrams/diagram-pane.jsx'; -import { StudyView } from './study-pane.jsx'; +import HorizontalToolbar from './horizontal-toolbar'; +import NetworkModificationTreePane from './network-modification-tree-pane'; +import NetworkMapTab from './network/network-map-tab'; +import { DiagramPane } from './diagrams/diagram-pane'; +import { StudyView } from './study-pane'; import { darken } from '@mui/material/styles'; import ComputingType from './computing-status/computing-type'; import { useIntl } from 'react-intl'; import { useSnackMessage } from '@gridsuite/commons-ui'; -import { StudyDisplayMode } from 'redux/reducer.type.ts'; +import { StudyDisplayMode } from 'redux/reducer.type'; import { Global, css } from '@emotion/react'; -import { EQUIPMENT_TYPES } from './utils/equipment-types.js'; +import { EQUIPMENT_TYPES } from './utils/equipment-types'; import SelectionCreationPanel from './network/selection-creation-panel'; const styles = { map: { diff --git a/src/services/study/network-map.js b/src/services/study/network-map.js index 568044c866..344be4e02d 100644 --- a/src/services/study/network-map.js +++ b/src/services/study/network-map.js @@ -7,7 +7,7 @@ import { getStudyUrlWithNodeUuid } from './index'; import { backendFetchJson, getQueryParamsList } from '../utils'; -import { NAME } from '../../components/utils/field-constants.js'; +import { NAME } from '../../components/utils/field-constants'; import { EQUIPMENT_INFOS_TYPES, EQUIPMENT_TYPES, From 38e3e92ba3129d24ce5fe89302478ae0fe5eafd1 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Jul 2024 19:55:48 +0200 Subject: [PATCH 2/9] migrate session-storage to ts --- src/components/diagrams/diagram-pane.jsx | 2 +- .../graph/nodes/network-modification-node.jsx | 2 +- .../top-bar-equipment-search-dialog.tsx | 2 +- ...use-top-bar-search-matching-equipments.tsx | 2 +- src/redux/session-storage.js | 36 ------------------- src/redux/session-storage/diagram-state.ts | 36 +++++++++++++++++++ .../local-storage.ts} | 36 ++++++++++++------- .../search-equipment-history.ts} | 0 8 files changed, 63 insertions(+), 53 deletions(-) delete mode 100644 src/redux/session-storage.js create mode 100644 src/redux/session-storage/diagram-state.ts rename src/redux/{local-storage/local-storage.tsx => session-storage/local-storage.ts} (55%) rename src/redux/{local-storage/search-equipment-history.tsx => session-storage/search-equipment-history.ts} (100%) diff --git a/src/components/diagrams/diagram-pane.jsx b/src/components/diagrams/diagram-pane.jsx index 34241cf1d4..255edd8c47 100644 --- a/src/components/diagrams/diagram-pane.jsx +++ b/src/components/diagrams/diagram-pane.jsx @@ -46,7 +46,7 @@ import { AutoSizer } from 'react-virtualized'; import Diagram from './diagram'; import { SLD_DISPLAY_MODE } from '../network/constants'; import { useNameOrId } from '../utils/equipmentInfosHandler'; -import { syncDiagramStateWithSessionStorage } from '../../redux/session-storage'; +import { syncDiagramStateWithSessionStorage } from '../../redux/session-storage/diagram-state'; import SingleLineDiagramContent from './singleLineDiagram/single-line-diagram-content'; import NetworkAreaDiagramContent from './networkAreaDiagram/network-area-diagram-content'; import { useDebounce, useSnackMessage } from '@gridsuite/commons-ui'; diff --git a/src/components/graph/nodes/network-modification-node.jsx b/src/components/graph/nodes/network-modification-node.jsx index 37f8f0964f..640c40b321 100644 --- a/src/components/graph/nodes/network-modification-node.jsx +++ b/src/components/graph/nodes/network-modification-node.jsx @@ -13,7 +13,7 @@ import CircularProgress from '@mui/material/CircularProgress'; import LockIcon from '@mui/icons-material/Lock'; import { OverflowableText } from '@gridsuite/commons-ui'; import { CopyType } from '../../network-modification-tree-pane'; -import { getLocalStorageTheme } from '../../../redux/local-storage/local-storage'; +import { getLocalStorageTheme } from '../../../redux/session-storage/local-storage'; import { LIGHT_THEME } from '@gridsuite/commons-ui'; import { BUILD_STATUS } from '../../network/constants'; import { Box } from '@mui/system'; 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 25bda6757a..91b08f8669 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 @@ -25,7 +25,7 @@ import { useTopBarSearchMatchingEquipment } from './use-top-bar-search-matching- import { addToLocalStorageSearchEquipmentHistory, excludeElementFromCurrentSearchHistory, -} from 'redux/local-storage/search-equipment-history'; +} from 'redux/session-storage/search-equipment-history'; import { fetchNetworkElementInfos } from 'services/study/network'; import { EQUIPMENT_INFOS_TYPES } from 'components/utils/equipment-types'; import { TopBarEquipmentSearchInput } from './top-bar-equipment-search-input'; 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 a902120051..8f2df6d7fe 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 @@ -7,7 +7,7 @@ import { UUID } from 'crypto'; import { useSearchMatchingEquipments } from './use-search-matching-equipments'; import { useMemo } from 'react'; -import { getLocalStorageSearchEquipmentHistory } from 'redux/local-storage/search-equipment-history'; +import { getLocalStorageSearchEquipmentHistory } from 'redux/session-storage/search-equipment-history'; import { EquipmentType } from '@gridsuite/commons-ui'; interface UseTopBarSearchMatchingEquipmentProps { diff --git a/src/redux/session-storage.js b/src/redux/session-storage.js deleted file mode 100644 index 6082c8291e..0000000000 --- a/src/redux/session-storage.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2022, 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 { APP_NAME } from '../utils/config-params'; - -export const SESSION_STORAGE_DIAGRAM_STATE_KEY_PREFIX = ( - APP_NAME + '_DIAGRAM_STATE_' -).toUpperCase(); - -const getDiagramStateKeyPrefixFromStudyUuid = (studyUuid) => { - return SESSION_STORAGE_DIAGRAM_STATE_KEY_PREFIX + studyUuid; -}; - -export const syncDiagramStateWithSessionStorage = (diagramState, studyUuid) => { - if (studyUuid == null) { - return; - } - sessionStorage.setItem( - getDiagramStateKeyPrefixFromStudyUuid(studyUuid), - JSON.stringify(diagramState) - ); -}; - -export const loadDiagramStateFromSessionStorage = (studyUuid) => { - const diagramState = JSON.parse( - sessionStorage.getItem(getDiagramStateKeyPrefixFromStudyUuid(studyUuid)) - ); - if (diagramState === null) { - return []; - } - return diagramState; -}; diff --git a/src/redux/session-storage/diagram-state.ts b/src/redux/session-storage/diagram-state.ts new file mode 100644 index 0000000000..ffbe1f7dac --- /dev/null +++ b/src/redux/session-storage/diagram-state.ts @@ -0,0 +1,36 @@ +/* + * 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 { APP_NAME } from '../../utils/config-params'; +import { UUID } from 'crypto'; + +const SESSION_STORAGE_DIAGRAM_STATE_KEY_PREFIX = + APP_NAME.toUpperCase() + '_DIAGRAM_STATE_'; + +function getDiagramStateKeyPrefixFromStudyUuid(studyUuid: UUID) { + return SESSION_STORAGE_DIAGRAM_STATE_KEY_PREFIX + studyUuid; +} + +export function syncDiagramStateWithSessionStorage( + diagramState: unknown, + studyUuid: UUID +) { + if (studyUuid == null) { + return; + } + sessionStorage.setItem( + getDiagramStateKeyPrefixFromStudyUuid(studyUuid), + JSON.stringify(diagramState) + ); +} + +export function loadDiagramStateFromSessionStorage(studyUuid: UUID) { + const raw = sessionStorage.getItem( + getDiagramStateKeyPrefixFromStudyUuid(studyUuid) + ); + return (raw && JSON.parse(raw)) ?? []; +} diff --git a/src/redux/local-storage/local-storage.tsx b/src/redux/session-storage/local-storage.ts similarity index 55% rename from src/redux/local-storage/local-storage.tsx rename to src/redux/session-storage/local-storage.ts index 9f0f8ec9ef..fe60f5105d 100644 --- a/src/redux/local-storage/local-storage.tsx +++ b/src/redux/session-storage/local-storage.ts @@ -5,29 +5,39 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { DARK_THEME, LANG_SYSTEM } from '@gridsuite/commons-ui'; +import { + DARK_THEME, + GsLang, + GsTheme, + LANG_SYSTEM, +} from '@gridsuite/commons-ui'; import { getComputedLanguage } from '../../utils/language'; import { APP_NAME } from '../../utils/config-params'; const LOCAL_STORAGE_THEME_KEY = (APP_NAME + '_THEME').toUpperCase(); const LOCAL_STORAGE_LANGUAGE_KEY = (APP_NAME + '_LANGUAGE').toUpperCase(); -export const getLocalStorageTheme = () => { - return localStorage.getItem(LOCAL_STORAGE_THEME_KEY) || DARK_THEME; -}; +export function getLocalStorageTheme() { + return ( + (localStorage.getItem(LOCAL_STORAGE_THEME_KEY) as GsTheme) || DARK_THEME + ); +} -export const saveLocalStorageTheme = (theme: string) => { +export function saveLocalStorageTheme(theme: GsTheme) { localStorage.setItem(LOCAL_STORAGE_THEME_KEY, theme); -}; +} -export const getLocalStorageLanguage = () => { - return localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) || LANG_SYSTEM; -}; +export function getLocalStorageLanguage() { + return ( + (localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) as GsLang) || + LANG_SYSTEM + ); +} -export const saveLocalStorageLanguage = (language: string) => { +export function saveLocalStorageLanguage(language: GsLang) { localStorage.setItem(LOCAL_STORAGE_LANGUAGE_KEY, language); -}; +} -export const getLocalStorageComputedLanguage = () => { +export function getLocalStorageComputedLanguage() { return getComputedLanguage(getLocalStorageLanguage()); -}; +} diff --git a/src/redux/local-storage/search-equipment-history.tsx b/src/redux/session-storage/search-equipment-history.ts similarity index 100% rename from src/redux/local-storage/search-equipment-history.tsx rename to src/redux/session-storage/search-equipment-history.ts From 97570b5fab3eec760f8dc49229f4a1c9c02a1302 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Mon, 22 Jul 2024 20:05:47 +0200 Subject: [PATCH 3/9] prepare --- .../{diagram-common.js => diagram-common.ts} | 62 +++++++++-------- ...-parameters.jsx => network-parameters.tsx} | 8 +-- .../graph/menus/create-node-menu.jsx | 5 +- .../graph/network-modification-tree-model.js | 2 +- .../graph/nodes/network-modification-node.jsx | 5 +- .../nodes}/node-insert-modes.ts | 0 src/components/graph/nodes/root-node.jsx | 4 +- src/components/network/constants.ts | 13 ++-- .../network/selection-creation-panel.tsx | 4 +- .../utils/equipment-table-utils.ts | 9 +-- ...{equipment-types.js => equipment-types.ts} | 68 +++++++++++-------- .../utils/{feederType.js => feederType.ts} | 5 +- 12 files changed, 101 insertions(+), 84 deletions(-) rename src/components/diagrams/{diagram-common.js => diagram-common.ts} (86%) rename src/components/dialogs/parameters/{network-parameters.jsx => network-parameters.tsx} (97%) rename src/components/{utils => graph/nodes}/node-insert-modes.ts (100%) rename src/components/utils/{equipment-types.js => equipment-types.ts} (50%) rename src/components/utils/{feederType.js => feederType.ts} (79%) diff --git a/src/components/diagrams/diagram-common.js b/src/components/diagrams/diagram-common.ts similarity index 86% rename from src/components/diagrams/diagram-common.js rename to src/components/diagrams/diagram-common.ts index 539a97f73d..fb4801d554 100644 --- a/src/components/diagrams/diagram-common.js +++ b/src/components/diagrams/diagram-common.ts @@ -18,8 +18,10 @@ import { INVALID_LOADFLOW_OPACITY, NAD_INVALID_LOADFLOW_OPACITY, } from '../../utils/colors'; -import { FEEDER_TYPES } from 'components/utils/feederType'; +import { FEEDER_TYPES, FeederTypes } from 'components/utils/feederType'; import { EQUIPMENT_TYPES } from 'components/utils/equipment-types'; +import { Theme } from '@mui/material'; +import { AppDispatch } from '../../redux/store'; export const LOADING_WIDTH = 300; export const LOADING_HEIGHT = 300; @@ -46,7 +48,7 @@ export const DEFAULT_HEIGHT_NETWORK_AREA_DIAGRAM = 400; export const MAP_BOTTOM_OFFSET = 80; // Percentage of the diagram pane's total height that correspond to the minimum -// height of opened diagrams : diagrams should not be smaller than 25% of the +// height of opened diagrams: diagrams should not be smaller than 25% of the // diagram pane's height. export const DIAGRAM_MAP_RATIO_MIN_PERCENTAGE = 0.25; @@ -62,7 +64,7 @@ export const styles = { }, overflow: 'hidden', }, - divNetworkAreaDiagram: (theme) => ({ + divNetworkAreaDiagram: (theme: Theme) => ({ '& .nad-label-box': { color: theme.palette.text.primary, fontFamily: theme.typography.fontFamily, @@ -71,7 +73,7 @@ export const styles = { stroke: theme.palette.text.primary, }, }), - divSingleLineDiagram: (theme) => ({ + divSingleLineDiagram: (theme: Theme) => ({ '& polyline': { pointerEvents: 'none', }, @@ -116,35 +118,35 @@ export const styles = { opacity: NAD_INVALID_LOADFLOW_OPACITY, }, }, - paperBorders: (theme) => ({ + paperBorders: (theme: Theme) => ({ borderLeft: '1px solid ' + theme.palette.action.disabled, borderBottom: '1px solid ' + theme.palette.action.disabledBackground, borderRight: '1px solid ' + theme.palette.action.hover, }), }; -export const ViewState = { - PINNED: 'pinned', - MINIMIZED: 'minimized', - OPENED: 'opened', -}; +export enum ViewState { + PINNED = 'pinned', + MINIMIZED = 'minimized', + OPENED = 'opened', +} -export const SubstationLayout = { - HORIZONTAL: 'horizontal', - VERTICAL: 'vertical', - SMART: 'smart', - SMARTHORIZONTALCOMPACTION: 'smartHorizontalCompaction', - SMARTVERTICALCOMPACTION: 'smartVerticalCompaction', -}; +export enum SubstationLayout { + HORIZONTAL = 'horizontal', + VERTICAL = 'vertical', + SMART = 'smart', + SMARTHORIZONTALCOMPACTION = 'smartHorizontalCompaction', + SMARTVERTICALCOMPACTION = 'smartVerticalCompaction', +} -export const DiagramType = { - VOLTAGE_LEVEL: 'voltage-level', - SUBSTATION: 'substation', - NETWORK_AREA_DIAGRAM: 'network-area-diagram', -}; +export enum DiagramType { + VOLTAGE_LEVEL = 'voltage-level', + SUBSTATION = 'substation', + NETWORK_AREA_DIAGRAM = 'network-area-diagram', +} // be careful when using this method because there are treatments made on purpose -export function getEquipmentTypeFromFeederType(feederType) { +export function getEquipmentTypeFromFeederType(feederType: FeederTypes) { switch (feederType) { case FEEDER_TYPES.LINE: return EQUIPMENT_TYPES.LINE; @@ -181,7 +183,7 @@ export function getEquipmentTypeFromFeederType(feederType) { } } -export function getFeederTypeFromEquipmentType(equipmentType) { +export function getFeederTypeFromEquipmentType(equipmentType: EQUIPMENT_TYPES) { switch (equipmentType) { case EQUIPMENT_TYPES.SUBSTATION: return FEEDER_TYPES.SUBSTATION; @@ -220,38 +222,38 @@ export function getFeederTypeFromEquipmentType(equipmentType) { } export const useDiagram = () => { - const dispatch = useDispatch(); + const dispatch = useDispatch(); const openDiagramView = useCallback( - (id, type) => { + (id: unknown, type: unknown) => { dispatch(openDiagram(id, type)); }, [dispatch] ); const togglePinDiagramView = useCallback( - (id, type) => { + (id: unknown, type: unknown) => { dispatch(togglePinDiagram(id, type)); }, [dispatch] ); const minimizeDiagramView = useCallback( - (id, type) => { + (id: unknown, type: unknown) => { dispatch(minimizeDiagram(id, type)); }, [dispatch] ); const closeDiagramView = useCallback( - (id, type) => { + (id: unknown, type: unknown) => { dispatch(closeDiagram(id, type)); }, [dispatch] ); const closeDiagramViews = useCallback( - (idsToRemove) => { + (idsToRemove: UnknownArray) => { dispatch(closeDiagrams(idsToRemove)); }, [dispatch] diff --git a/src/components/dialogs/parameters/network-parameters.jsx b/src/components/dialogs/parameters/network-parameters.tsx similarity index 97% rename from src/components/dialogs/parameters/network-parameters.jsx rename to src/components/dialogs/parameters/network-parameters.tsx index f82ad5a9f6..85ab343446 100644 --- a/src/components/dialogs/parameters/network-parameters.jsx +++ b/src/components/dialogs/parameters/network-parameters.tsx @@ -19,10 +19,10 @@ import { LabelledButton, styles, useParameterState } from './parameters'; import ParameterLineDropdown from './widget/parameter-line-dropdown'; import ParameterLineSwitch from './widget/parameter-line-switch'; -export const FluxConventions = { - IIDM: 'iidm', - TARGET: 'target', -}; +export enum FluxConventions { + IIDM = 'iidm', + TARGET = 'target', +} export const NetworkParameters = () => { const [, handleChangeFluxConvention] = useParameterState( diff --git a/src/components/graph/menus/create-node-menu.jsx b/src/components/graph/menus/create-node-menu.jsx index 7e70a0f563..5e294d32b7 100644 --- a/src/components/graph/menus/create-node-menu.jsx +++ b/src/components/graph/menus/create-node-menu.jsx @@ -13,9 +13,10 @@ import { useIsAnyNodeBuilding } from '../../utils/is-any-node-building-hook'; import { useSelector } from 'react-redux'; import { CopyType } from '../../network-modification-tree-pane'; import ChildMenuItem from './create-child-menu-item'; -import { NodeInsertModes } from '../../utils/node-insert-modes'; +import { NodeInsertModes } from '../nodes/node-insert-modes'; import { CustomDialog } from '../../utils/custom-dialog'; import { CustomNestedMenuItem } from '../../utils/custom-nested-menu'; +import { BUILD_STATUS } from '../../network/constants'; export const NodeActions = { REMOVE_NODE: 'REMOVE_NODE', @@ -226,7 +227,7 @@ const CreateNodeMenu = ({ id: 'buildNode', disabled: activeNode?.data?.globalBuildStatus?.startsWith('BUILT') || - activeNode?.data?.globalBuildStatus === 'BUILDING' || + activeNode?.data?.globalBuildStatus === BUILD_STATUS.BUILDING || isModificationsInProgress, }, CREATE_MODIFICATION_NODE: { diff --git a/src/components/graph/network-modification-tree-model.js b/src/components/graph/network-modification-tree-model.js index ac39adb889..d9d7d4a63b 100644 --- a/src/components/graph/network-modification-tree-model.js +++ b/src/components/graph/network-modification-tree-model.js @@ -7,7 +7,7 @@ import { getLayoutedNodes } from './layout'; import { convertNodetoReactFlowModelNode } from './util/model-functions'; -import { NodeInsertModes } from '../utils/node-insert-modes'; +import { NodeInsertModes } from '../../components/graph/nodes/node-insert-modes'; // Function to count children nodes for a given parentId recursively in an array of nodes. // TODO refactoring when changing NetworkModificationTreeModel as it becomes an object containing nodes diff --git a/src/components/graph/nodes/network-modification-node.jsx b/src/components/graph/nodes/network-modification-node.jsx index 640c40b321..22ef6c066d 100644 --- a/src/components/graph/nodes/network-modification-node.jsx +++ b/src/components/graph/nodes/network-modification-node.jsx @@ -11,10 +11,9 @@ import { Handle } from 'react-flow-renderer'; import { useSelector } from 'react-redux'; import CircularProgress from '@mui/material/CircularProgress'; import LockIcon from '@mui/icons-material/Lock'; -import { OverflowableText } from '@gridsuite/commons-ui'; +import { LIGHT_THEME, OverflowableText } from '@gridsuite/commons-ui'; import { CopyType } from '../../network-modification-tree-pane'; import { getLocalStorageTheme } from '../../../redux/session-storage/local-storage'; -import { LIGHT_THEME } from '@gridsuite/commons-ui'; import { BUILD_STATUS } from '../../network/constants'; import { Box } from '@mui/system'; @@ -204,7 +203,7 @@ const NetworkModificationNode = (props) => { } > - {props.data.localBuildStatus === 'BUILDING' && ( + {props.data.localBuildStatus === BUILD_STATUS.BUILDING && ( ({ @@ -62,7 +63,8 @@ const RootNode = (props) => { variant="outlined" sx={isSelectedNode() ? styles.rootSelected : styles.root} > - {(props.data.globalBuildStatus === 'BUILDING' && ( + {(props.data.globalBuildStatus === + BUILD_STATUS.BUILDING && ( )) || } diff --git a/src/components/network/constants.ts b/src/components/network/constants.ts index 6c5ab2fd90..ce0634ee6a 100644 --- a/src/components/network/constants.ts +++ b/src/components/network/constants.ts @@ -149,12 +149,13 @@ export const VOLTAGE_LEVEL_COMPONENTS = { BUS_BAR_SECTION_CONNECTION: 'BusBarSectionConnection', }; -export const BUILD_STATUS = { - NOT_BUILT: 'NOT_BUILT', - BUILT: 'BUILT', - BUILT_WITH_WARNING: 'BUILT_WITH_WARNING', - BUILT_WITH_ERROR: 'BUILT_WITH_ERROR', -}; +export enum BUILD_STATUS { + NOT_BUILT = 'NOT_BUILT', + BUILDING = 'BUILDING', + BUILT = 'BUILT', + BUILT_WITH_WARNING = 'BUILT_WITH_WARNING', + BUILT_WITH_ERROR = 'BUILT_WITH_ERROR', +} export const SWITCH_TYPE = { BREAKER: { id: 'BREAKER', label: 'Breaker' }, diff --git a/src/components/network/selection-creation-panel.tsx b/src/components/network/selection-creation-panel.tsx index 53804fc26a..5262e2e508 100644 --- a/src/components/network/selection-creation-panel.tsx +++ b/src/components/network/selection-creation-panel.tsx @@ -29,7 +29,7 @@ import { FormattedMessage, useIntl } from 'react-intl'; import { UniqueNameInput } from 'components/dialogs/commons/unique-name-input'; import { useSelector } from 'react-redux'; import { - equipementTypeToLabel, + equipmentTypeToLabel, EQUIPMENT_TYPES, } from '../utils/equipment-types'; import { UUID } from 'crypto'; @@ -147,7 +147,7 @@ const SelectionCreationPanel: React.FC = ({ .map((value) => { return { id: value, - label: equipementTypeToLabel(value), + label: equipmentTypeToLabel(value), }; }); } diff --git a/src/components/spreadsheet/utils/equipment-table-utils.ts b/src/components/spreadsheet/utils/equipment-table-utils.ts index 6154b2dd4f..f18e26dba6 100644 --- a/src/components/spreadsheet/utils/equipment-table-utils.ts +++ b/src/components/spreadsheet/utils/equipment-table-utils.ts @@ -33,6 +33,7 @@ import { getPhaseTapRegulationSideId, } from 'components/dialogs/network-modifications/two-windings-transformer/tap-changer-pane/phase-tap-changer-pane/phase-tap-changer-pane-utils'; import { EQUIPMENT_TYPES } from 'components/utils/equipment-types'; +import { IEquipment } from '../../../services/study/contingency-list'; type DynamicValidation = Record; @@ -211,8 +212,8 @@ const formatShuntCompensatorDataForTable = (shuntCompensator: any) => { }; export const formatFetchedEquipments = ( - equipmentType: string, - equipments: any + equipmentType: EQUIPMENT_TYPES, + equipments: IEquipment[] ) => { if (equipments && equipments?.length > 0) { return equipments.map((equipment: any) => { @@ -223,8 +224,8 @@ export const formatFetchedEquipments = ( }; export const formatFetchedEquipment = ( - equipmentType: string, - equipment: any + equipmentType: EQUIPMENT_TYPES, + equipment: IEquipment ) => { switch (equipmentType) { case EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER: diff --git a/src/components/utils/equipment-types.js b/src/components/utils/equipment-types.ts similarity index 50% rename from src/components/utils/equipment-types.js rename to src/components/utils/equipment-types.ts index 9b8c0655bb..b32d7d1341 100644 --- a/src/components/utils/equipment-types.js +++ b/src/components/utils/equipment-types.ts @@ -5,38 +5,46 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -export const EQUIPMENT_INFOS_TYPES = { - LIST: { type: 'LIST' }, - MAP: { type: 'MAP' }, - FORM: { type: 'FORM' }, - TAB: { type: 'TAB' }, - TOOLTIP: { type: 'TOOLTIP' }, -}; +type EquipmentInfosTypesStruct = { type: T }; +//TODO: rename to PascalCase +export const EQUIPMENT_INFOS_TYPES: Record = + { + LIST: { type: 'LIST' }, + MAP: { type: 'MAP' }, + FORM: { type: 'FORM' }, + TAB: { type: 'TAB' }, + TOOLTIP: { type: 'TOOLTIP' }, + }; +export type EquipmentInfosTypes = EquipmentInfosTypesStruct< + 'LIST' | 'MAP' | 'FORM' | 'TAB' | 'TOOLTIP' +>; -export const EQUIPMENT_TYPES = { - SUBSTATION: 'SUBSTATION', - VOLTAGE_LEVEL: 'VOLTAGE_LEVEL', - LINE: 'LINE', - TIE_LINE: 'TIE_LINE', - TWO_WINDINGS_TRANSFORMER: 'TWO_WINDINGS_TRANSFORMER', - THREE_WINDINGS_TRANSFORMER: 'THREE_WINDINGS_TRANSFORMER', - HVDC_LINE: 'HVDC_LINE', - BUS: 'BUS', - BUSBAR_SECTION: 'BUSBAR_SECTION', - GENERATOR: 'GENERATOR', - BATTERY: 'BATTERY', - LOAD: 'LOAD', - SHUNT_COMPENSATOR: 'SHUNT_COMPENSATOR', - DANGLING_LINE: 'DANGLING_LINE', - STATIC_VAR_COMPENSATOR: 'STATIC_VAR_COMPENSATOR', - HVDC_CONVERTER_STATION: 'HVDC_CONVERTER_STATION', - VSC_CONVERTER_STATION: 'VSC_CONVERTER_STATION', - LCC_CONVERTER_STATION: 'LCC_CONVERTER_STATION', - SWITCH: 'SWITCH', -}; +//TODO: Compare with commons-ui's EquipmentType enum (miss TIE_LINE and not same order) +//TODO: rename to PascalCase +export enum EQUIPMENT_TYPES { + SUBSTATION = 'SUBSTATION', + VOLTAGE_LEVEL = 'VOLTAGE_LEVEL', + LINE = 'LINE', + TIE_LINE = 'TIE_LINE', + TWO_WINDINGS_TRANSFORMER = 'TWO_WINDINGS_TRANSFORMER', + THREE_WINDINGS_TRANSFORMER = 'THREE_WINDINGS_TRANSFORMER', + HVDC_LINE = 'HVDC_LINE', + BUS = 'BUS', + BUSBAR_SECTION = 'BUSBAR_SECTION', + GENERATOR = 'GENERATOR', + BATTERY = 'BATTERY', + LOAD = 'LOAD', + SHUNT_COMPENSATOR = 'SHUNT_COMPENSATOR', + DANGLING_LINE = 'DANGLING_LINE', + STATIC_VAR_COMPENSATOR = 'STATIC_VAR_COMPENSATOR', + HVDC_CONVERTER_STATION = 'HVDC_CONVERTER_STATION', + VSC_CONVERTER_STATION = 'VSC_CONVERTER_STATION', + LCC_CONVERTER_STATION = 'LCC_CONVERTER_STATION', + SWITCH = 'SWITCH', +} -//TODO merge the labels with the equipement types -export function equipementTypeToLabel(equipmentType) { +//TODO merge the labels with the equipment types +export function equipmentTypeToLabel(equipmentType: EQUIPMENT_TYPES) { switch (equipmentType) { case EQUIPMENT_TYPES.GENERATOR: return 'Generators'; diff --git a/src/components/utils/feederType.js b/src/components/utils/feederType.ts similarity index 79% rename from src/components/utils/feederType.js rename to src/components/utils/feederType.ts index 2cf215dce0..6aaa297799 100644 --- a/src/components/utils/feederType.js +++ b/src/components/utils/feederType.ts @@ -6,11 +6,13 @@ */ import { EQUIPMENT_TYPES } from './equipment-types'; +import { ValueOf } from 'type-fest'; export const FEEDER_TYPES = { ...EQUIPMENT_TYPES, /** - * these are ComponentTypeNames from powsybl-single-line-diagram but we put them here because some ComponentTypeNames are also EquipmentsNames + * these are ComponentTypeNames from powsybl-single-line-diagram, + * but we put them here because some ComponentTypeNames are also EquipmentsNames */ CAPACITOR: 'CAPACITOR', INDUCTOR: 'INDUCTOR', @@ -18,3 +20,4 @@ export const FEEDER_TYPES = { PHASE_SHIFT_TRANSFORMER: 'PHASE_SHIFT_TRANSFORMER', THREE_WINDINGS_TRANSFORMER_LEG: 'THREE_WINDINGS_TRANSFORMER_LEG', }; +export type FeederTypes = ValueOf; From 2baf2365870750effb661b636eef6f8316019e65 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Jul 2024 20:18:50 +0200 Subject: [PATCH 4/9] migrate redux store to ts --- package-lock.json | 32 +- package.json | 4 +- src/components/app.jsx | 9 +- .../computing-status/use-computing-status.ts | 7 +- src/components/diagrams/diagram-common.ts | 10 +- src/components/diagrams/diagram-pane.jsx | 6 +- ...e-one-bus-shortcircuit-analysis-loader.tsx | 9 +- .../create-composite-modification-dialog.tsx | 4 +- .../event/dynamic-simulation-event-dialog.tsx | 3 +- .../event/dynamic-simulation-event-form.tsx | 3 +- .../event/model/event.model.ts | 2 +- .../event/types/event.type.ts | 5 +- .../dialogs/equipment-search-dialog.tsx | 5 +- ...eric-Illustration-network-modification.tsx | 4 +- .../by-formula/formula/formula-form.tsx | 4 +- .../by-formula/formula/formula-utils.tsx | 3 +- .../converter-station-pane.tsx | 2 +- .../vsc/creation/vsc-creation-form.tsx | 2 +- .../modification/vsc-modification-from.tsx | 2 +- .../common/parameters-creation-dialog.tsx | 5 +- .../use-get-voltage-init-parameters.tsx | 4 +- .../voltageinit/voltage-init-parameters.tsx | 4 +- .../dynamic-simulation/event-list-item.tsx | 9 +- .../event-modification-scenario-editor.tsx | 25 +- .../dynamic-simulation/scenario-editor.tsx | 7 +- src/components/horizontal-toolbar.jsx | 2 +- src/components/map-viewer.jsx | 2 +- src/components/menus/bus-menu.tsx | 10 +- .../dynamic-simulation-event-menu-item.tsx | 2 + .../network-modification-tree-pane.jsx | 2 +- src/components/network-modification-tree.jsx | 2 +- .../network/selection-creation-panel.tsx | 5 +- src/components/network/use-save-map.ts | 6 +- src/components/parameters-tabs.tsx | 4 +- src/components/result-view-tab.tsx | 4 +- .../common/computation-report-viewer.tsx | 14 +- .../results/common/results-global-filter.tsx | 7 +- .../dynamic-simulation-result-logs.tsx | 4 +- .../dynamic-simulation-result-synthesis.tsx | 4 +- .../dynamic-simulation-result-timeline.tsx | 5 +- .../loadflow/limit-violation-result.tsx | 4 +- .../results/loadflow/load-flow-result-tab.tsx | 5 +- .../loadflow/load-flow-result-utils.ts | 14 +- .../results/loadflow/load-flow-result.tsx | 4 +- .../security-analysis-result-tab.tsx | 5 +- .../security-analysis-result-utils.ts | 14 +- .../security-analysis-table.tsx | 4 +- .../use-security-analysis-column-defs.tsx | 8 +- .../non-evacuated-energy-result-tab.tsx | 4 +- .../sensitivity-analysis-result-tab.jsx | 1 + ...shortcircuit-analysis-all-buses-result.tsx | 5 +- .../shortcircuit-analysis-one-bus-result.tsx | 10 +- .../shortcircuit-analysis-result-tab.tsx | 10 +- .../shortcircuit-analysis-result-table.tsx | 4 +- .../shortcircuit-analysis-result.tsx | 11 +- src/components/results/use-results-tab.ts | 14 +- src/components/spreadsheet/table-wrapper.jsx | 1 + src/components/study-container.jsx | 2 +- .../custom-suffix-renderer.tsx | 18 +- .../top-bar-equipment-search-dialog.tsx | 12 +- .../use-disabled-search-reason.tsx | 12 +- .../use-search-event.tsx | 4 +- src/hooks/use-aggrid-row-filter.ts | 8 +- src/hooks/use-computation-results-count.ts | 19 +- src/hooks/use-get-study-impacts.ts | 10 +- src/hooks/use-optional-service-status.ts | 4 +- src/redux/actions.js | 755 ------- src/redux/actions.ts | 1307 +++++++++++ src/redux/reducer.js | 1339 ------------ .../{reducer.test.js => reducer.test.ts} | 403 ++-- src/redux/reducer.ts | 1929 +++++++++++++++++ src/redux/reducer.type.ts | 152 -- src/redux/{store.js => store.ts} | 5 +- src/utils/config-params.js | 1 + 74 files changed, 3692 insertions(+), 2649 deletions(-) delete mode 100644 src/redux/actions.js create mode 100644 src/redux/actions.ts delete mode 100644 src/redux/reducer.js rename src/redux/{reducer.test.js => reducer.test.ts} (80%) create mode 100644 src/redux/reducer.ts delete mode 100644 src/redux/reducer.type.ts rename src/redux/{store.js => store.ts} (77%) diff --git a/package-lock.json b/package-lock.json index 69d532b716..3142397c23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,6 +67,7 @@ "@types/eslint": "^8.56.9", "@types/eslint-config-prettier": "^6.11.3", "@types/identity-obj-proxy": "^3.0.2", + "@types/jest": "^29.5.12", "@types/license-checker": "^25.0.6", "@types/localized-countries": "^2.0.3", "@types/lucene-escape-query": "^1.0.2", @@ -102,6 +103,7 @@ "license-checker": "^25.0.1", "prettier": "^2.8.8", "ts-node": "^10.9.2", + "type-fest": "^4.22.1", "typescript": "5.1.6", "vite": "^5.2.7", "vite-plugin-eslint": "^1.8.1", @@ -6396,6 +6398,16 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/jsdom": { "version": "20.0.1", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", @@ -7300,6 +7312,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -18632,12 +18656,12 @@ } }, "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz", + "integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/package.json b/package.json index 5f748d7d2b..1ea84f20b6 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "@types/eslint": "^8.56.9", "@types/eslint-config-prettier": "^6.11.3", "@types/identity-obj-proxy": "^3.0.2", + "@types/jest": "^29.5.12", "@types/license-checker": "^25.0.6", "@types/localized-countries": "^2.0.3", "@types/lucene-escape-query": "^1.0.2", @@ -106,8 +107,9 @@ "jest-environment-jsdom": "^29.7.0", "license-checker": "^25.0.1", "prettier": "^2.8.8", - "typescript": "5.1.6", "ts-node": "^10.9.2", + "type-fest": "^4.22.1", + "typescript": "5.1.6", "vite": "^5.2.7", "vite-plugin-eslint": "^1.8.1", "vite-plugin-svgr": "^4.2.0", diff --git a/src/components/app.jsx b/src/components/app.jsx index 2328e93e99..7123cb4b99 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -10,6 +10,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { getOptionalServiceByServerName, + OptionalServicesNames, OptionalServicesStatus, } from './utils/optional-services'; import { @@ -104,7 +105,6 @@ import { setOptionalServices, setParamsLoaded, } from '../redux/actions'; -import { defaultOptionalServicesState } from '../redux/reducer'; const noUserManager = { instance: null, error: null }; @@ -476,10 +476,9 @@ const App = () => { }; }); // get all potentially optional services - const optionalServicesNames = - defaultOptionalServicesState.map( - (service) => service.name - ); + const optionalServicesNames = Object.keys( + OptionalServicesNames + ); // if one of those services was not returned by "getOptionalServices", it means it was defined as "not optional" // in that case, we consider it is UP diff --git a/src/components/computing-status/use-computing-status.ts b/src/components/computing-status/use-computing-status.ts index 5f04083f8a..dca7c6c08e 100644 --- a/src/components/computing-status/use-computing-status.ts +++ b/src/components/computing-status/use-computing-status.ts @@ -11,12 +11,13 @@ import { UUID } from 'crypto'; import { RefObject, useCallback, useEffect, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { ComputingType } from './computing-type'; -import { ReduxState, StudyUpdated } from 'redux/reducer.type'; +import { AppState, StudyUpdated } from 'redux/reducer'; import { OptionalServicesStatus } from '../utils/optional-services'; import { setComputingStatus, setLastCompletedComputation, } from '../../redux/actions'; +import { AppDispatch } from '../../redux/store'; interface UseComputingStatusProps { ( @@ -98,10 +99,10 @@ export const useComputingStatus: UseComputingStatusProps = ( ) => { const nodeUuidRef = useRef(null); const studyUpdatedForce = useSelector( - (state: ReduxState) => state.studyUpdated + (state: AppState) => state.studyUpdated ); const lastUpdateRef = useRef(null); - const dispatch = useDispatch(); + const dispatch = useDispatch(); //the callback crosschecks the computation status and the content of the last update reference //in order to determine which computation just ended diff --git a/src/components/diagrams/diagram-common.ts b/src/components/diagrams/diagram-common.ts index fb4801d554..4ee60d2dcc 100644 --- a/src/components/diagrams/diagram-common.ts +++ b/src/components/diagrams/diagram-common.ts @@ -225,35 +225,35 @@ export const useDiagram = () => { const dispatch = useDispatch(); const openDiagramView = useCallback( - (id: unknown, type: unknown) => { + (id: string, type: DiagramType) => { dispatch(openDiagram(id, type)); }, [dispatch] ); const togglePinDiagramView = useCallback( - (id: unknown, type: unknown) => { + (id: string, type: DiagramType) => { dispatch(togglePinDiagram(id, type)); }, [dispatch] ); const minimizeDiagramView = useCallback( - (id: unknown, type: unknown) => { + (id: string, type: DiagramType) => { dispatch(minimizeDiagram(id, type)); }, [dispatch] ); const closeDiagramView = useCallback( - (id: unknown, type: unknown) => { + (id: string, type: DiagramType) => { dispatch(closeDiagram(id, type)); }, [dispatch] ); const closeDiagramViews = useCallback( - (idsToRemove: UnknownArray) => { + (idsToRemove: string[]) => { dispatch(closeDiagrams(idsToRemove)); }, [dispatch] diff --git a/src/components/diagrams/diagram-pane.jsx b/src/components/diagrams/diagram-pane.jsx index 255edd8c47..d81dedd433 100644 --- a/src/components/diagrams/diagram-pane.jsx +++ b/src/components/diagrams/diagram-pane.jsx @@ -60,7 +60,6 @@ import { fetchSvg, getNetworkAreaDiagramUrl } from '../../services/study'; import { mergeSx } from '../utils/functions'; import { Box } from '@mui/system'; import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; -import { UpdateTypes } from '../../redux/reducer.type'; // Returns a callback that returns a promise const useDisplayView = (studyUuid, currentNode) => { @@ -837,10 +836,9 @@ export function DiagramPane({ //TODO reload data more intelligently updateDiagramsByCurrentNode(); } else if ( - studyUpdatedForce.eventData.headers['updateType'] === - UpdateTypes.STUDY + studyUpdatedForce.eventData.headers['updateType'] === 'study' ) { - // FM if we want to reload data more precisely we need more information from notifications + // FM if we want to reload data more precisely, we need more information from notifications updateDiagramsByCurrentNode(); } else if ( studyUpdatedForce.eventData.headers['updateType'] === 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 049b384ada..a8b48a3c17 100644 --- a/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx +++ b/src/components/diagrams/use-one-bus-shortcircuit-analysis-loader.tsx @@ -9,9 +9,10 @@ import { UUID } from 'crypto'; import { ReactElement, useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { Chip, darken, lighten, Theme } from '@mui/material'; import { setOneBusShortcircuitAnalysisDiagram } from '../../redux/actions'; +import { AppDispatch } from '../../redux/store'; /** * A hook that handles the logic behind the diagram one bus shortcircuit analysis loader @@ -52,13 +53,13 @@ export function useOneBusShortcircuitAnalysisLoader( nodeId: UUID ): oneBusShortcircuitAnalysisLoader { const studyUpdatedForce = useSelector( - (state: ReduxState) => state.studyUpdated + (state: AppState) => state.studyUpdated ); const oneBusShortCircuitAnalysisDiagram = useSelector( - (state: ReduxState) => state.oneBusShortCircuitAnalysisDiagram + (state: AppState) => state.oneBusShortCircuitAnalysisDiagram ); - const dispatch = useDispatch(); + const dispatch = useDispatch(); const intl = useIntl(); const displayOneBusShortcircuitAnalysisLoader = useCallback(() => { diff --git a/src/components/dialogs/create-composite-modification-dialog.tsx b/src/components/dialogs/create-composite-modification-dialog.tsx index 130349a361..6bbb04c39e 100644 --- a/src/components/dialogs/create-composite-modification-dialog.tsx +++ b/src/components/dialogs/create-composite-modification-dialog.tsx @@ -33,6 +33,7 @@ import { useSelector } from 'react-redux'; import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; +import { AppState } from '../../redux/reducer'; interface ICompositeCreateModificationDialog { [NAME]: string; @@ -66,7 +67,7 @@ const CreateCompositeModificationDialog: React.FC< CreateCompositeModificationDialogProps > = ({ open, onSave, onClose }) => { const intl = useIntl(); - const studyUuid = useSelector((state: any) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const { snackError } = useSnackMessage(); const formMethods = useForm({ defaultValues: emptyFormData, @@ -76,6 +77,7 @@ const CreateCompositeModificationDialog: React.FC< const [destinationFolder, setDestinationFolder] = useState(); const fetchDefaultDirectoryForStudy = useCallback(() => { + // @ts-expect-error TODO: manage null case fetchDirectoryElementPath(studyUuid).then((res) => { if (!res || res.length < 2) { snackError({ 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 4c6b8d5e66..43c69518d2 100644 --- a/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx +++ b/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-dialog.tsx @@ -28,12 +28,13 @@ import { } from '../../../../services/dynamic-simulation'; import { CustomFormProvider, useSnackMessage } from '@gridsuite/commons-ui'; import { FetchStatus } from '../../../../services/utils'; +import { EQUIPMENT_TYPES } from '../../../utils/equipment-types'; export type DynamicSimulationEventDialogProps = { studyUuid: string; currentNodeId: string; equipmentId: string; - equipmentType: string; // must be a string enum + equipmentType: EQUIPMENT_TYPES; onClose: () => void; title: string; open?: boolean; diff --git a/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-form.tsx b/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-form.tsx index 4a093cdc53..c3496c6c26 100644 --- a/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-form.tsx +++ b/src/components/dialogs/dynamicsimulation/event/dynamic-simulation-event-form.tsx @@ -10,10 +10,11 @@ import { Event, EventDefinition, EventPropertyName } from './types/event.type'; import React from 'react'; import { makeComponentFor } from './util/event-rhf'; import { useIntl } from 'react-intl'; +import { EQUIPMENT_TYPES } from '../../../utils/equipment-types'; export type DynamicSimulationBasicEventFormProps = { equipmentId: string; - equipmentType: string; + equipmentType: EQUIPMENT_TYPES; eventDefinition?: EventDefinition; event?: Event; }; diff --git a/src/components/dialogs/dynamicsimulation/event/model/event.model.ts b/src/components/dialogs/dynamicsimulation/event/model/event.model.ts index 1cc350c2b3..302e9c8a2d 100644 --- a/src/components/dialogs/dynamicsimulation/event/model/event.model.ts +++ b/src/components/dialogs/dynamicsimulation/event/model/event.model.ts @@ -37,7 +37,7 @@ export const DISCONNECT_EVENT_DEFINITION: EventDefinition = { id: 'TwoSides.TWO', }, ], - acceptOnly: (equipmentType: string) => { + acceptOnly: (equipmentType: EQUIPMENT_TYPES) => { return BRANCH_EQUIPMENT_TYPES.includes(equipmentType); }, default: null, // TODO remove when corrected in rhf SelectInput diff --git a/src/components/dialogs/dynamicsimulation/event/types/event.type.ts b/src/components/dialogs/dynamicsimulation/event/types/event.type.ts index efbddb6c59..4ff51bba08 100644 --- a/src/components/dialogs/dynamicsimulation/event/types/event.type.ts +++ b/src/components/dialogs/dynamicsimulation/event/types/event.type.ts @@ -4,6 +4,7 @@ * 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 { EQUIPMENT_TYPES } from '../../../../utils/equipment-types'; export enum EventType { DISCONNECT = 'Disconnect', @@ -38,7 +39,7 @@ export type EventPropertyDefinition = { label: string; }[]; unit?: string; - acceptOnly?: (equipmentType: string) => boolean; + acceptOnly?: (equipmentType: EQUIPMENT_TYPES) => boolean; }; export type EventDefinition = { @@ -56,7 +57,7 @@ export interface Event { uuid?: string; nodeId: string; equipmentId: string; - equipmentType: string; + equipmentType: EQUIPMENT_TYPES; eventType?: EventType; properties: EventProperty[]; } diff --git a/src/components/dialogs/equipment-search-dialog.tsx b/src/components/dialogs/equipment-search-dialog.tsx index 18150fe23d..b8ec2371d7 100644 --- a/src/components/dialogs/equipment-search-dialog.tsx +++ b/src/components/dialogs/equipment-search-dialog.tsx @@ -17,7 +17,7 @@ import { FC } from 'react'; import { useSearchMatchingEquipments } from '../top-bar-equipment-seach-dialog/use-search-matching-equipments'; import { UUID } from 'crypto'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { TextField } from '@mui/material'; import { Search } from '@mui/icons-material'; @@ -45,9 +45,10 @@ const EquipmentSearchDialog: FC = ({ currentNodeUuid, }) => { const intl = useIntl(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const { searchTerm, updateSearchTerm, equipmentsFound, isLoading } = useSearchMatchingEquipments({ + // @ts-expect-error TODO: manage null case studyUuid: studyUuid, nodeUuid: currentNodeUuid, inUpstreamBuiltParentNode: true, diff --git a/src/components/dialogs/illustrations/generic-Illustration-network-modification.tsx b/src/components/dialogs/illustrations/generic-Illustration-network-modification.tsx index 1cdc4ce435..3d50c27404 100644 --- a/src/components/dialogs/illustrations/generic-Illustration-network-modification.tsx +++ b/src/components/dialogs/illustrations/generic-Illustration-network-modification.tsx @@ -12,7 +12,7 @@ import Paper from '@mui/material/Paper'; import { LIGHT_THEME } from '@gridsuite/commons-ui'; import { AccordionIllustration } from './AccordionIllustration'; import { PARAM_THEME } from 'utils/config-params'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; interface ReplacedText { eltId: string; @@ -32,7 +32,7 @@ const GenericIllustrationNetworkModification: React.FC< > = ({ svgComponent: SvgComponent, replacedTexts, backgroundElementId }) => { const [showDiagram, setShowDiagram] = useState(true); const intl = useIntl(); - const theme = useSelector((state: ReduxState) => state[PARAM_THEME]); + const theme = useSelector((state: AppState) => state[PARAM_THEME]); useEffect(() => { // dynamically modify the text inside the svg : diff --git a/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx b/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx index 1634ac76d2..f140ca68a7 100644 --- a/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx +++ b/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx @@ -44,7 +44,9 @@ const FormulaForm: FunctionComponent = ({ name, index }) => { const intl = useIntl(); - const equipmentFields = EQUIPMENTS_FIELDS?.[equipmentTypeWatch] ?? []; + const equipmentFields: { id: string; label: string }[] = + // @ts-expect-error TODO: conflicts types + EQUIPMENTS_FIELDS?.[equipmentTypeWatch] ?? []; const filtersField = ( , value: any) { const parent = context.from?.[context.from.length - 1]; const equipmentType = parent?.value?.[EQUIPMENT_TYPE_FIELD]; return parent - ? EQUIPMENTS_FIELDS[equipmentType]?.some( + ? // @ts-expect-error TODO: conflicts types + EQUIPMENTS_FIELDS[equipmentType]?.some( (field: { id: string; label: string }) => field.id === value ) : false; diff --git a/src/components/dialogs/network-modifications/vsc/converter-station/converter-station-pane.tsx b/src/components/dialogs/network-modifications/vsc/converter-station/converter-station-pane.tsx index 93e72ba983..8304e3cabd 100644 --- a/src/components/dialogs/network-modifications/vsc/converter-station/converter-station-pane.tsx +++ b/src/components/dialogs/network-modifications/vsc/converter-station/converter-station-pane.tsx @@ -25,7 +25,7 @@ import { VoltageAdornment, } from '../../../dialogUtils'; import { fetchVoltageLevelsListInfos } from '../../../../../services/study/network'; -import { CurrentTreeNode } from '../../../../../redux/reducer.type'; +import { CurrentTreeNode } from '../../../../../redux/reducer'; import { UUID } from 'crypto'; import { ConnectivityForm } from '../../../connectivity/connectivity-form'; import Grid from '@mui/material/Grid'; diff --git a/src/components/dialogs/network-modifications/vsc/creation/vsc-creation-form.tsx b/src/components/dialogs/network-modifications/vsc/creation/vsc-creation-form.tsx index f092e1170d..ac70aec248 100644 --- a/src/components/dialogs/network-modifications/vsc/creation/vsc-creation-form.tsx +++ b/src/components/dialogs/network-modifications/vsc/creation/vsc-creation-form.tsx @@ -16,7 +16,7 @@ import VscHvdcLinePane from '../hvdc-line-pane/vsc-hvdc-line-pane'; import ConverterStationPane from '../converter-station/converter-station-pane'; import { VSC_CREATION_TABS } from './vsc-creation-dialog'; import { UUID } from 'crypto'; -import { CurrentTreeNode } from '../../../../../redux/reducer.type'; +import { CurrentTreeNode } from '../../../../../redux/reducer'; interface VscCreationFormProps { tabIndex: number; diff --git a/src/components/dialogs/network-modifications/vsc/modification/vsc-modification-from.tsx b/src/components/dialogs/network-modifications/vsc/modification/vsc-modification-from.tsx index 33c44313d1..b9838e9db8 100644 --- a/src/components/dialogs/network-modifications/vsc/modification/vsc-modification-from.tsx +++ b/src/components/dialogs/network-modifications/vsc/modification/vsc-modification-from.tsx @@ -15,7 +15,7 @@ import React, { FunctionComponent } from 'react'; import VscHvdcLinePane from '../hvdc-line-pane/vsc-hvdc-line-pane'; import ConverterStationPane from '../converter-station/converter-station-pane'; import { UUID } from 'crypto'; -import { CurrentTreeNode } from '../../../../../redux/reducer.type'; +import { CurrentTreeNode } from '../../../../../redux/reducer'; import { VscModificationInfo } from 'services/network-modification-types'; import { TextInput } from '@gridsuite/commons-ui'; import { Box, TextField } from '@mui/material'; diff --git a/src/components/dialogs/parameters/common/parameters-creation-dialog.tsx b/src/components/dialogs/parameters/common/parameters-creation-dialog.tsx index 09420c950a..df8a20514f 100644 --- a/src/components/dialogs/parameters/common/parameters-creation-dialog.tsx +++ b/src/components/dialogs/parameters/common/parameters-creation-dialog.tsx @@ -23,7 +23,7 @@ import { import ModificationDialog from 'components/dialogs/commons/modificationDialog'; import { createParameter } from 'services/explore'; import { UniqueNameInput } from 'components/dialogs/commons/unique-name-input'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { UUID } from 'crypto'; interface FormData { @@ -60,7 +60,7 @@ const CreateParameterDialog = ({ const [defaultFolder, setDefaultFolder] = useState(); const [openDirectoryFolders, setOpenDirectoryFolders] = useState(false); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const formMethods = useForm({ defaultValues: emptyFormData, @@ -74,6 +74,7 @@ const CreateParameterDialog = ({ const nameError = errors[NAME]; const fetchDefaultDirectoryForStudy = useCallback(() => { + // @ts-expect-error TODO: manage null case fetchDirectoryElementPath(studyUuid).then((studyPath) => { if (studyPath && studyPath.length >= 2) { // studyPath contains [RootDirectoryElement, directoryElement, ..., directoryElement, studyElement] diff --git a/src/components/dialogs/parameters/voltageinit/use-get-voltage-init-parameters.tsx b/src/components/dialogs/parameters/voltageinit/use-get-voltage-init-parameters.tsx index 98434ac0bc..404b199f03 100644 --- a/src/components/dialogs/parameters/voltageinit/use-get-voltage-init-parameters.tsx +++ b/src/components/dialogs/parameters/voltageinit/use-get-voltage-init-parameters.tsx @@ -8,7 +8,7 @@ import { VoltageInitParam } from './voltage-init-utils'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../../redux/reducer.type'; +import { AppState } from '../../../../redux/reducer'; import { useSnackMessage } from '@gridsuite/commons-ui'; import { useOptionalServiceStatus } from '../../../../hooks/use-optional-service-status'; import { @@ -21,7 +21,7 @@ export const useGetVoltageInitParameters = (): [ VoltageInitParam | null, Dispatch> ] => { - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const { snackError } = useSnackMessage(); const [voltageInitParams, setVoltageInitParams] = useState(null); diff --git a/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx b/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx index 3a2776198d..da1d90175c 100644 --- a/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx +++ b/src/components/dialogs/parameters/voltageinit/voltage-init-parameters.tsx @@ -51,7 +51,7 @@ import { VoltageInitParametersForm, voltageInitParametersFormSchema, } from './voltage-init-parameters-form'; -import { ReduxState } from '../../../../redux/reducer.type'; +import { AppState } from '../../../../redux/reducer'; import { UUID } from 'crypto'; import { useGetVoltageInitParameters } from './use-get-voltage-init-parameters'; @@ -75,7 +75,7 @@ export const VoltageInitParameters = ({ }); const { reset, handleSubmit, getValues, trigger, formState } = formMethods; - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const [voltageInitParams, setVoltageInitParams] = useGetVoltageInitParameters(); diff --git a/src/components/graph/menus/dynamic-simulation/event-list-item.tsx b/src/components/graph/menus/dynamic-simulation/event-list-item.tsx index 8a6f8a2d5f..6c99557015 100644 --- a/src/components/graph/menus/dynamic-simulation/event-list-item.tsx +++ b/src/components/graph/menus/dynamic-simulation/event-list-item.tsx @@ -15,7 +15,7 @@ import IconButton from '@mui/material/IconButton'; import { useSelector } from 'react-redux'; import { Theme } from '@mui/material/styles'; import { Event } from '../../../dialogs/dynamicsimulation/event/types/event.type'; -import { ReduxState } from '../../../../redux/reducer.type'; +import { AppState } from '../../../../redux/reducer'; import { ListItemProps } from '@mui/material/ListItem/ListItem'; import { getStartTime, @@ -59,10 +59,8 @@ export const EventListItem = ({ ...props }: EventListItemProps) => { const intl = useIntl(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const toggle = useCallback(() => handleToggle(item), [item, handleToggle]); @@ -85,6 +83,7 @@ export const EventListItem = ({ return intl.formatMessage( { id: `Event${item.eventType}${ + // @ts-expect-error TODO: conflicts types EQUIPMENT_TYPE_LABEL_KEYS[item.equipmentType] }`, }, 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 c479a41352..2214d88b50 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 @@ -30,8 +30,7 @@ import { EVENT_CRUD_FINISHED, EventCrudType, } from 'components/network/constants.type'; -import { ReduxState, StudyUpdated } from '../../../../redux/reducer.type'; -import { UUID } from 'crypto'; +import { AppState, StudyUpdated } from '../../../../redux/reducer'; import { Event, EventType, @@ -50,11 +49,12 @@ import { } from '../network-modification-node-editor'; import { EQUIPMENT_TYPE_LABEL_KEYS } from '../../util/model-constants'; import { areUuidsEqual } from 'components/utils/utils'; +import { AppDispatch } from '../../../../redux/store'; const EventModificationScenarioEditor = () => { const intl = useIntl(); const notificationIdList = useSelector( - (state: ReduxState) => state.notificationIdList + (state: AppState) => state.notificationIdList ); const params = useParams(); const studyUuid = params?.studyUuid @@ -62,11 +62,9 @@ const EventModificationScenarioEditor = () => { : undefined; const { snackError } = useSnackMessage(); const [events, setEvents] = useState([]); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); - const currentNodeIdRef = useRef(); // initial empty to get first update + const currentNodeIdRef = useRef(); // initial empty to get first update const [pendingState, setPendingState] = useState(false); const [selectedItems, setSelectedItems] = useState([]); @@ -75,14 +73,14 @@ const EventModificationScenarioEditor = () => { | { eventType?: EventType; equipmentId: string; - equipmentType: string; + equipmentType: keyof typeof EQUIPMENT_TYPE_LABEL_KEYS; } | undefined >(); - const dispatch = useDispatch(); + const dispatch = useDispatch(); const studyUpdatedForce = useSelector( - (state: ReduxState) => state.studyUpdated + (state: AppState) => state.studyUpdated ); const [messageId, setMessageId] = useState(''); const [launchLoader, setLaunchLoader] = useState(false); @@ -168,7 +166,7 @@ const EventModificationScenarioEditor = () => { }); }, [ currentNode?.type, - currentNode.id, + currentNode?.id, studyUuid, updateSelectedItems, snackError, @@ -235,7 +233,8 @@ const EventModificationScenarioEditor = () => { const selectedEvents = [...selectedItems]; deleteDynamicSimulationEvents( studyUuid ?? '', - currentNode.id, + // @ts-expect-error TODO: manage null case + currentNode?.id, selectedEvents ).catch((errMsg) => { snackError({ @@ -249,6 +248,7 @@ const EventModificationScenarioEditor = () => { setEditDialogOpen({ eventType: event.eventType, equipmentId: event.equipmentId, + // @ts-expect-error TODO: sub range of equipments types equipmentType: event.equipmentType, }); }; @@ -392,6 +392,7 @@ const EventModificationScenarioEditor = () => { {editDialogOpen && ( { - const dispatch = useDispatch(); + const dispatch = useDispatch(); const currentTreeNode = useSelector( - (state: ReduxState) => state.currentTreeNode + (state: AppState) => state.currentTreeNode ); const intl = useIntl(); diff --git a/src/components/horizontal-toolbar.jsx b/src/components/horizontal-toolbar.jsx index 89746ad00b..8e3048d956 100644 --- a/src/components/horizontal-toolbar.jsx +++ b/src/components/horizontal-toolbar.jsx @@ -23,7 +23,7 @@ import { TOOLTIP_DELAY } from '../utils/UIconstants'; import OfflineBoltOutlinedIcon from '@mui/icons-material/OfflineBoltOutlined'; import { useParameterState } from './dialogs/parameters/parameters'; import { PARAM_DEVELOPER_MODE } from '../utils/config-params'; -import { StudyDisplayMode } from 'redux/reducer.type'; +import { StudyDisplayMode } from 'redux/reducer'; const styles = { selected: (theme) => ({ diff --git a/src/components/map-viewer.jsx b/src/components/map-viewer.jsx index e7758543ed..e49a5dc9cd 100644 --- a/src/components/map-viewer.jsx +++ b/src/components/map-viewer.jsx @@ -28,7 +28,7 @@ import { darken } from '@mui/material/styles'; import ComputingType from './computing-status/computing-type'; import { useIntl } from 'react-intl'; import { useSnackMessage } from '@gridsuite/commons-ui'; -import { StudyDisplayMode } from 'redux/reducer.type'; +import { StudyDisplayMode } from 'redux/reducer'; import { Global, css } from '@emotion/react'; import { EQUIPMENT_TYPES } from './utils/equipment-types'; diff --git a/src/components/menus/bus-menu.tsx b/src/components/menus/bus-menu.tsx index ce165dfa57..b6902c5d72 100644 --- a/src/components/menus/bus-menu.tsx +++ b/src/components/menus/bus-menu.tsx @@ -14,7 +14,7 @@ import { isNodeReadOnly, } from 'components/graph/util/model-functions'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { useIsAnyNodeBuilding } from 'components/utils/is-any-node-building-hook'; import { ComputingType } from 'components/computing-status/computing-type'; import { RunningStatus } from 'components/utils/running-status'; @@ -61,9 +61,7 @@ export const BusMenu: FunctionComponent = ({ const [enableDeveloperMode] = useParameterState(PARAM_DEVELOPER_MODE); // to check is node editable - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const isAnyNodeBuilding = useIsAnyNodeBuilding(); const isNodeEditable = useMemo( () => @@ -74,11 +72,11 @@ export const BusMenu: FunctionComponent = ({ ); const computationStarting = useSelector( - (state: ReduxState) => state.computationStarting + (state: AppState) => state.computationStarting ); const oneBusShortcircuitAnalysisState = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT_ONE_BUS] ); diff --git a/src/components/menus/dynamic-simulation/dynamic-simulation-event-menu-item.tsx b/src/components/menus/dynamic-simulation/dynamic-simulation-event-menu-item.tsx index 67ed1616da..4d5d975848 100644 --- a/src/components/menus/dynamic-simulation/dynamic-simulation-event-menu-item.tsx +++ b/src/components/menus/dynamic-simulation/dynamic-simulation-event-menu-item.tsx @@ -52,6 +52,7 @@ const DynamicSimulationEventMenuItem = ( equipmentId, equipmentType, `${getEventType(equipmentType)}${ + // @ts-expect-error TODO: conflicts types EQUIPMENT_TYPE_LABEL_KEYS[equipmentType] }` ) @@ -66,6 +67,7 @@ const DynamicSimulationEventMenuItem = ( {intl.formatMessage({ id: `${getEventType(equipmentType)}${ + // @ts-expect-error TODO: conflicts types EQUIPMENT_TYPE_LABEL_KEYS[equipmentType] }`, })} diff --git a/src/components/network-modification-tree-pane.jsx b/src/components/network-modification-tree-pane.jsx index 7569398c3d..59cad25185 100644 --- a/src/components/network-modification-tree-pane.jsx +++ b/src/components/network-modification-tree-pane.jsx @@ -41,7 +41,7 @@ import { import { buildNode, getUniqueNodeName, unbuildNode } from '../services/study'; import RestoreNodesDialog from './dialogs/restore-node-dialog'; import ScenarioEditor from './graph/menus/dynamic-simulation/scenario-editor'; -import { StudyDisplayMode } from '../redux/reducer.type'; +import { StudyDisplayMode } from '../redux/reducer'; const styles = { container: { diff --git a/src/components/network-modification-tree.jsx b/src/components/network-modification-tree.jsx index 2e2a51c445..2c4d41df29 100644 --- a/src/components/network-modification-tree.jsx +++ b/src/components/network-modification-tree.jsx @@ -28,7 +28,7 @@ import { useIntl } from 'react-intl'; import CropFreeIcon from '@mui/icons-material/CropFree'; import { nodeTypes } from './graph/util/model-constants'; import { BUILD_STATUS } from './network/constants'; -import { StudyDisplayMode } from '../redux/reducer.type'; +import { StudyDisplayMode } from '../redux/reducer'; // snapGrid value set to [15, 15] which is the default value for ReactFlow // it has to be explicitly set as prop of the ReactFlow component, even if snapToGrid option is set to false diff --git a/src/components/network/selection-creation-panel.tsx b/src/components/network/selection-creation-panel.tsx index 5262e2e508..ebf71cc3d5 100644 --- a/src/components/network/selection-creation-panel.tsx +++ b/src/components/network/selection-creation-panel.tsx @@ -36,7 +36,7 @@ import { UUID } from 'crypto'; import { fetchDirectoryElementPath } from '@gridsuite/commons-ui'; import CircularProgress from '@mui/material/CircularProgress'; import FolderOutlined from '@mui/icons-material/FolderOutlined'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { SELECTION_TYPES, selectionTypeToLabel, @@ -70,7 +70,7 @@ const SelectionCreationPanel: React.FC = ({ onCancel, nominalVoltages, }) => { - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const [openDirectorySelector, setOpenDirectorySelector] = useState(false); const intl = useIntl(); const { pendingState, onSaveSelection } = useSaveMap(); @@ -91,6 +91,7 @@ const SelectionCreationPanel: React.FC = ({ useState(); const fetchDefaultDirectoryForStudy = useCallback(() => { + // @ts-expect-error TODO: manage null case fetchDirectoryElementPath(studyUuid).then((res) => { if (res) { const parentFolderIndex = res.length - 2; diff --git a/src/components/network/use-save-map.ts b/src/components/network/use-save-map.ts index 8000e71a58..ceb3c1bdfc 100644 --- a/src/components/network/use-save-map.ts +++ b/src/components/network/use-save-map.ts @@ -12,7 +12,7 @@ import { import { useCallback, useState } from 'react'; import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { SELECTION_TYPES } from '../utils/selection-types'; import { createMapContingencyList, @@ -35,9 +35,9 @@ export type UseSaveMapOutput = { export const useSaveMap = (): UseSaveMapOutput => { const intl = useIntl(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const currentNodeUuid = useSelector( - (state: ReduxState) => state.currentTreeNode.id + (state: AppState) => state.currentTreeNode?.id ); const { snackInfo, snackError, snackWarning } = useSnackMessage(); const [pendingState, setPendingState] = useState(false); diff --git a/src/components/parameters-tabs.tsx b/src/components/parameters-tabs.tsx index 8f6c9fb2cd..e173bea459 100644 --- a/src/components/parameters-tabs.tsx +++ b/src/components/parameters-tabs.tsx @@ -35,7 +35,7 @@ import { OptionalServicesNames, OptionalServicesStatus, } from './utils/optional-services'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { getLoadFlowProviders, getLoadFlowSpecificParametersDescription, @@ -170,7 +170,7 @@ type OwnProps = { }; const ParametersTabs: FunctionComponent = (props) => { - const user = useSelector((state: ReduxState) => state.user); + const user = useSelector((state: AppState) => state.user); const [tabValue, setTabValue] = useState( TAB_VALUES.sldParamsTabValue diff --git a/src/components/result-view-tab.tsx b/src/components/result-view-tab.tsx index c3e3184d83..b4857b5d70 100644 --- a/src/components/result-view-tab.tsx +++ b/src/components/result-view-tab.tsx @@ -34,7 +34,7 @@ import { OptionalServicesNames, OptionalServicesStatus, } from './utils/optional-services'; -import { CurrentTreeNode, ReduxState } from '../redux/reducer.type'; +import { CurrentTreeNode, AppState } from '../redux/reducer'; import { UUID } from 'crypto'; import { useOptionalServiceStatus } from '../hooks/use-optional-service-status'; import { SecurityAnalysisResultTab } from './results/securityanalysis/security-analysis-result-tab'; @@ -95,7 +95,7 @@ export const ResultViewTab: FunctionComponent = ({ const [enableDeveloperMode] = useParameterState(PARAM_DEVELOPER_MODE); const lastCompletedComputation = useSelector( - (state: ReduxState) => state.lastCompletedComputation + (state: AppState) => state.lastCompletedComputation ); const securityAnalysisAvailability = useOptionalServiceStatus( diff --git a/src/components/results/common/computation-report-viewer.tsx b/src/components/results/common/computation-report-viewer.tsx index 354ec095c6..bb75ab65fa 100644 --- a/src/components/results/common/computation-report-viewer.tsx +++ b/src/components/results/common/computation-report-viewer.tsx @@ -15,7 +15,7 @@ import { useSnackMessage } from '@gridsuite/commons-ui'; import ReportViewer from '../../report-viewer/report-viewer'; import LogReportItem from '../../report-viewer/log-report-item'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { ComputingType } from '../../computing-status/computing-type'; import WaitingLoader from '../../utils/waiting-loader'; @@ -28,10 +28,8 @@ export const ComputationReportViewer: FunctionComponent< > = ({ reportType }) => { const [report, setReport] = useState(undefined); const { snackError } = useSnackMessage(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const [waitingLoadReport, setWaitingLoadReport] = useState(false); const makeReport = useCallback( @@ -86,8 +84,8 @@ export const ComputationReportViewer: FunctionComponent< severityFilterList: string[] ) => { return fetchSubReport( - studyUuid.toString(), - currentNode.id.toString(), + studyUuid?.toString(), + currentNode?.id.toString(), reportId, severityFilterList ); @@ -99,7 +97,7 @@ export const ComputationReportViewer: FunctionComponent< severityFilterList: string[] ) => { return fetchNodeReport( - studyUuid.toString(), + studyUuid?.toString(), nodeId, reportId, severityFilterList, diff --git a/src/components/results/common/results-global-filter.tsx b/src/components/results/common/results-global-filter.tsx index d133d65556..9557ea7534 100644 --- a/src/components/results/common/results-global-filter.tsx +++ b/src/components/results/common/results-global-filter.tsx @@ -15,7 +15,8 @@ import { useLocalizedCountries } from 'components/utils/localized-countries-hook import { useDispatch, useSelector } from 'react-redux'; import { addToRecentGlobalFilters } from '../../../redux/actions'; import { Theme } from '@mui/material'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; +import { AppDispatch } from '../../../redux/store'; const styles = { autocomplete: (theme: Theme) => ({ @@ -121,9 +122,9 @@ const ResultsGlobalFilter: FunctionComponent = ({ }) => { const intl = useIntl(); const { translate } = useLocalizedCountries(); - const dispatch = useDispatch(); + const dispatch = useDispatch(); const recentGlobalFilters = useSelector( - (state: ReduxState) => state.recentGlobalFilters + (state: AppState) => state.recentGlobalFilters ); const getOptionLabel = useCallback( diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-logs.tsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-logs.tsx index 14e34d59aa..867be58b96 100644 --- a/src/components/results/dynamicsimulation/dynamic-simulation-result-logs.tsx +++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-logs.tsx @@ -9,7 +9,7 @@ import { ComputationReportViewer } from '../common/computation-report-viewer'; import { REPORT_TYPES } from '../../utils/report-type'; import React, { memo, useMemo } from 'react'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import ComputingType from '../../computing-status/computing-type'; import RunningStatus from '../../utils/running-status'; import { useIntlResultStatusMessages } from '../../utils/aggrid-rows-handler'; @@ -18,7 +18,7 @@ import Overlay from '../common/Overlay'; const DynamicSimulationResultLogs = memo(() => { const dynamicSimulationStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION] ); diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx index c1a258d12d..8af0be246f 100644 --- a/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx +++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-synthesis.tsx @@ -25,7 +25,7 @@ import { DefaultCellRenderer } from '../../spreadsheet/utils/cell-renderers'; import { StatusCellRender } from '../common/result-cell-renderers'; import { UUID } from 'crypto'; import RunningStatus from '../../utils/running-status'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { CustomAGGrid } from '@gridsuite/commons-ui'; const styles = { @@ -84,7 +84,7 @@ const DynamicSimulationResultSynthesis = memo( // messages to show when no data const dynamicSimulationStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION] ); const messages = useIntlResultStatusMessages(intl, true); diff --git a/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx b/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx index c8692cb41b..59c544bc89 100644 --- a/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx +++ b/src/components/results/dynamicsimulation/dynamic-simulation-result-timeline.tsx @@ -20,7 +20,7 @@ import { useIntlResultStatusMessages, } from '../../utils/aggrid-rows-handler'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import ComputingType from '../../computing-status/computing-type'; import { useAgGridLocalSort } from '../../../hooks/use-aggrid-local-sort'; import { SortWay } from '../../../hooks/use-aggrid-sort'; @@ -91,6 +91,7 @@ const DynamicSimulationResultTimeline = memo( { filterType: DYNAMIC_SIMULATION_RESULT_STORE_FIELD, filterTab: TIMELINE, + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setDynamicSimulationResultFilter, } ); @@ -166,7 +167,7 @@ const DynamicSimulationResultTimeline = memo( // messages to show when no data const dynamicSimulationStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION] ); const messages = useIntlResultStatusMessages(intl, true); diff --git a/src/components/results/loadflow/limit-violation-result.tsx b/src/components/results/loadflow/limit-violation-result.tsx index e8cbd6e342..a68890a88b 100644 --- a/src/components/results/loadflow/limit-violation-result.tsx +++ b/src/components/results/loadflow/limit-violation-result.tsx @@ -19,7 +19,7 @@ import { useTheme } from '@mui/material'; import { GridReadyEvent, RowClassParams } from 'ag-grid-community'; import { ComputingType } from '../../computing-status/computing-type'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { LimitViolationResultProps } from './load-flow-result.type'; import { @@ -43,7 +43,7 @@ export const LimitViolationResult: FunctionComponent< const gridRef = useRef(); const loadFlowStatus = useSelector( - (state: ReduxState) => state.computingStatus[ComputingType.LOAD_FLOW] + (state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW] ); const [isOverloadedEquipmentsReady, setIsOverloadedEquipmentsReady] = diff --git a/src/components/results/loadflow/load-flow-result-tab.tsx b/src/components/results/loadflow/load-flow-result-tab.tsx index 44be7e747d..cbedef0376 100644 --- a/src/components/results/loadflow/load-flow-result-tab.tsx +++ b/src/components/results/loadflow/load-flow-result-tab.tsx @@ -26,7 +26,7 @@ import { } from '../../../services/study/loadflow'; import { REPORT_TYPES } from 'components/utils/report-type'; import RunningStatus from 'components/utils/running-status'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import ComputingType from 'components/computing-status/computing-type'; import { useSelector } from 'react-redux'; import { ComputationReportViewer } from '../common/computation-report-viewer'; @@ -102,7 +102,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ const [tabIndex, setTabIndex] = useState(0); const loadFlowStatus = useSelector( - (state: ReduxState) => state.computingStatus[ComputingType.LOAD_FLOW] + (state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW] ); const { onSortChanged, sortConfig, initSort } = useAgGridSort({ @@ -113,6 +113,7 @@ export const LoadFlowResultTab: FunctionComponent = ({ const { updateFilter, filterSelector } = useAggridRowFilter({ filterType: LOADFLOW_RESULT_STORE_FIELD, filterTab: mappingTabs(tabIndex), + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setLoadflowResultFilter, }); diff --git a/src/components/results/loadflow/load-flow-result-utils.ts b/src/components/results/loadflow/load-flow-result-utils.ts index de4ae9c8df..f02cc721fb 100644 --- a/src/components/results/loadflow/load-flow-result-utils.ts +++ b/src/components/results/loadflow/load-flow-result-utils.ts @@ -48,7 +48,7 @@ import computingType, { ComputingType, } from '../../computing-status/computing-type'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import RunningStatus from 'components/utils/running-status'; export const convertMillisecondsToMinutesSeconds = ( @@ -202,12 +202,10 @@ export const useFetchFiltersEnums = (): { limitType: null, side: null, }); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const loadFlowStatus = useSelector( - (state: ReduxState) => state.computingStatus[ComputingType.LOAD_FLOW] + (state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW] ); useEffect(() => { @@ -224,7 +222,7 @@ export const useFetchFiltersEnums = (): { const promises = filterTypes.map((filterType) => fetchAvailableFilterEnumValues( studyUuid, - currentNode.id, + currentNode?.id, computingType.LOAD_FLOW, filterType ) @@ -251,7 +249,7 @@ export const useFetchFiltersEnums = (): { .finally(() => { setLoading(false); }); - }, [loadFlowStatus, studyUuid, currentNode.id]); + }, [loadFlowStatus, studyUuid, currentNode?.id]); return { loading, result, error }; }; diff --git a/src/components/results/loadflow/load-flow-result.tsx b/src/components/results/loadflow/load-flow-result.tsx index e1a275454f..3509c777a9 100644 --- a/src/components/results/loadflow/load-flow-result.tsx +++ b/src/components/results/loadflow/load-flow-result.tsx @@ -11,7 +11,7 @@ import { useSelector } from 'react-redux'; import { useTheme } from '@mui/material'; import { GridReadyEvent, RowClassParams } from 'ag-grid-community'; import { ComputingType } from '../../computing-status/computing-type'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { LoadflowResultProps } from './load-flow-result.type'; import { @@ -37,7 +37,7 @@ export const LoadFlowResult: FunctionComponent = ({ const intl = useIntl(); const loadFlowStatus = useSelector( - (state: ReduxState) => state.computingStatus[ComputingType.LOAD_FLOW] + (state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW] ); const gridRef = useRef(); diff --git a/src/components/results/securityanalysis/security-analysis-result-tab.tsx b/src/components/results/securityanalysis/security-analysis-result-tab.tsx index 8f29d8b03b..5d6711985f 100644 --- a/src/components/results/securityanalysis/security-analysis-result-tab.tsx +++ b/src/components/results/securityanalysis/security-analysis-result-tab.tsx @@ -15,7 +15,7 @@ import React, { } from 'react'; import { useSelector } from 'react-redux'; import { FormattedMessage } from 'react-intl'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { Box } from '@mui/system'; import { Tabs, Tab, Select, MenuItem, LinearProgress } from '@mui/material'; import { fetchSecurityAnalysisResult } from '../../../services/study/security-analysis'; @@ -124,7 +124,7 @@ export const SecurityAnalysisResultTab: FunctionComponent< } }, [enableDeveloperMode, tabIndex, previousEnableDeveloperMode]); const securityAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SECURITY_ANALYSIS] ); @@ -151,6 +151,7 @@ export const SecurityAnalysisResultTab: FunctionComponent< { filterType: SECURITY_ANALYSIS_RESULT_STORE_FIELD, filterTab: getStoreFields(tabIndex), + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setSecurityAnalysisResultFilter, }, memoizedSetPageCallback diff --git a/src/components/results/securityanalysis/security-analysis-result-utils.ts b/src/components/results/securityanalysis/security-analysis-result-utils.ts index f42dcad4c4..8f7ddfc52a 100644 --- a/src/components/results/securityanalysis/security-analysis-result-utils.ts +++ b/src/components/results/securityanalysis/security-analysis-result-utils.ts @@ -51,7 +51,7 @@ import computingType, { ComputingType, } from '../../computing-status/computing-type'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import RunningStatus from 'components/utils/running-status'; import { SecurityAnalysisFilterEnumsType } from './use-security-analysis-column-defs'; @@ -622,12 +622,10 @@ export const useFetchFiltersEnums = () => { side: null, }, }); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const securityAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SECURITY_ANALYSIS] ); @@ -647,7 +645,7 @@ export const useFetchFiltersEnums = () => { const promises = filterTypes.map((filterType) => fetchAvailableFilterEnumValues( studyUuid, - currentNode.id, + currentNode?.id, computingType.SECURITY_ANALYSIS, filterType ) @@ -682,7 +680,7 @@ export const useFetchFiltersEnums = () => { .finally(() => { setLoading(false); }); - }, [securityAnalysisStatus, studyUuid, currentNode.id]); + }, [securityAnalysisStatus, studyUuid, currentNode?.id]); return { loading, result, error }; }; diff --git a/src/components/results/securityanalysis/security-analysis-table.tsx b/src/components/results/securityanalysis/security-analysis-table.tsx index ee367a96ea..91fc4d0171 100644 --- a/src/components/results/securityanalysis/security-analysis-table.tsx +++ b/src/components/results/securityanalysis/security-analysis-table.tsx @@ -16,7 +16,7 @@ import { GridReadyEvent } from 'ag-grid-community'; import { IntlShape, useIntl } from 'react-intl'; import { DefaultCellRenderer } from '../../spreadsheet/utils/cell-renderers'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { ComputingType } from '../../computing-status/computing-type'; import { CustomAGGrid } from '@gridsuite/commons-ui'; @@ -26,7 +26,7 @@ export const SecurityAnalysisTable: FunctionComponent< const intl: IntlShape = useIntl(); const resultStatusMessages = useIntlResultStatusMessages(intl); const securityAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SECURITY_ANALYSIS] ); const rowsToShow = getRows(rows, securityAnalysisStatus); 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 7888642bc8..edd92af33b 100644 --- a/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx +++ b/src/components/results/securityanalysis/use-security-analysis-column-defs.tsx @@ -22,7 +22,7 @@ import { import { SortPropsType } from 'hooks/use-aggrid-sort'; import { FilterEnumsType, FilterPropsType } from 'hooks/use-aggrid-row-filter'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; const styles = { button: { @@ -53,12 +53,12 @@ export const useSecurityAnalysisColumnsDefs: UseSecurityAnalysisColumnsDefsProps ) => { const intl = useIntl(); const { snackError } = useSnackMessage(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode + (state: AppState) => state.currentTreeNode ); - const nodeUuid = currentNode.id; + const nodeUuid = currentNode?.id; // for nmk views, click handler on subjectId cell const onClickNmKConstraint = useCallback( 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 4a5114a0ec..9590946ddd 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 @@ -18,7 +18,7 @@ import { RunningStatus } from '../../../utils/running-status'; import { ComputationReportViewer } from '../../common/computation-report-viewer'; import { REPORT_TYPES } from '../../../utils/report-type'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../../redux/reducer.type'; +import { AppState } from '../../../../redux/reducer'; import { ComputingType } from '../../../computing-status/computing-type'; import { RESULTS_LOADING_DELAY } from '../../../network/constants'; @@ -53,7 +53,7 @@ export const NonEvacuatedEnergyResultTab: FunctionComponent< const LOGS_TAB_INDEX = 1; const nonEvacuatedEnergyStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.NON_EVACUATED_ENERGY_ANALYSIS] ); 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 e35d859147..4bb62380ed 100644 --- a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx +++ b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx @@ -62,6 +62,7 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => { const { updateFilter, filterSelector } = useAggridRowFilter({ filterType: SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD, filterTab: mappingTabs(sensiKind, nOrNkIndex), + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setSensitivityAnalysisResultFilter, }); diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-all-buses-result.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-all-buses-result.tsx index 7b462b1219..cad767edfa 100644 --- a/src/components/results/shortcircuit/shortcircuit-analysis-all-buses-result.tsx +++ b/src/components/results/shortcircuit/shortcircuit-analysis-all-buses-result.tsx @@ -12,7 +12,7 @@ import { } from 'components/results/shortcircuit/shortcircuit-analysis-result.type'; import { ShortCircuitAnalysisResult } from 'components/results/shortcircuit/shortcircuit-analysis-result'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { FunctionComponent, useCallback, useState } from 'react'; import { ComputingType } from 'components/computing-status/computing-type'; import { GridReadyEvent } from 'ag-grid-community'; @@ -26,8 +26,7 @@ export const ShortCircuitAnalysisAllBusesResult: FunctionComponent< ShortCircuitAnalysisAllBusResultProps > = ({ onGridColumnsChanged, onRowDataUpdated }) => { const allBusesShortCircuitAnalysisStatus = useSelector( - (state: ReduxState) => - state.computingStatus[ComputingType.SHORT_CIRCUIT] + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT] ); const [result, setResult] = useState([]); diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-one-bus-result.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-one-bus-result.tsx index c8643eb5a6..5dae6926c5 100644 --- a/src/components/results/shortcircuit/shortcircuit-analysis-one-bus-result.tsx +++ b/src/components/results/shortcircuit/shortcircuit-analysis-one-bus-result.tsx @@ -13,7 +13,7 @@ import { } from 'components/results/shortcircuit/shortcircuit-analysis-result.type'; import { ShortCircuitAnalysisResult } from 'components/results/shortcircuit/shortcircuit-analysis-result'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { FunctionComponent, useCallback, useEffect, useState } from 'react'; import { fetchShortCircuitAnalysisResult } from 'services/study/short-circuit-analysis'; import { useSnackMessage } from '@gridsuite/commons-ui'; @@ -32,14 +32,12 @@ export const ShortCircuitAnalysisOneBusResult: FunctionComponent< const { snackError } = useSnackMessage(); const oneBusShortCircuitAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT_ONE_BUS] ); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const [faultResult, setFaultResult] = useState(); const [feederResults, setFeederResults] = useState(); diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx index 6b420ac353..3757e58dc4 100644 --- a/src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx +++ b/src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx @@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl'; import { ComputationReportViewer } from '../common/computation-report-viewer'; import { useSelector } from 'react-redux'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { ComputingType } from '../../computing-status/computing-type'; import { RunningStatus } from '../../utils/running-status'; import { ShortCircuitAnalysisOneBusResult } from './shortcircuit-analysis-one-bus-result'; @@ -50,7 +50,7 @@ export const ShortCircuitAnalysisResultTab: FunctionComponent< ShortCircuitAnalysisResultTabProps > = ({ studyUuid, nodeUuid, view }) => { const lastCompletedComputation = useSelector( - (state: ReduxState) => state.lastCompletedComputation + (state: AppState) => state.lastCompletedComputation ); const [csvHeaders, setCsvHeaders] = useState([]); @@ -58,6 +58,7 @@ export const ShortCircuitAnalysisResultTab: FunctionComponent< const resultTabIndexRedirection = useMemo( () => + // @ts-expect-error TODO: manage null case computingTypeToShortcircuitTabRedirection(lastCompletedComputation), [lastCompletedComputation] ); @@ -67,11 +68,10 @@ export const ShortCircuitAnalysisResultTab: FunctionComponent< const [resultOrLogIndex, setResultOrLogIndex] = useState(0); const AllBusesShortCircuitStatus = useSelector( - (state: ReduxState) => - state.computingStatus[ComputingType.SHORT_CIRCUIT] + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT] ); const OneBusShortCircuitStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT_ONE_BUS] ); diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-result-table.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-result-table.tsx index 83b4e22fd7..d92797db18 100644 --- a/src/components/results/shortcircuit/shortcircuit-analysis-result-table.tsx +++ b/src/components/results/shortcircuit/shortcircuit-analysis-result-table.tsx @@ -25,7 +25,7 @@ import { } from '../../utils/aggrid-rows-handler'; import { useSelector } from 'react-redux'; import { ComputingType } from '../../computing-status/computing-type'; -import { ReduxState } from '../../../redux/reducer.type'; +import { AppState } from '../../../redux/reducer'; import { DefaultCellRenderer } from '../../spreadsheet/utils/cell-renderers'; import { FilterEnumsType, @@ -231,7 +231,7 @@ const ShortCircuitAnalysisResultTable: FunctionComponent< }, [intl, analysisType, sortProps, filterProps, filterEnums]); const shortCircuitAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ analysisType === ShortCircuitAnalysisType.ALL_BUSES ? ComputingType.SHORT_CIRCUIT diff --git a/src/components/results/shortcircuit/shortcircuit-analysis-result.tsx b/src/components/results/shortcircuit/shortcircuit-analysis-result.tsx index b56c325d99..cd3d3fe31a 100644 --- a/src/components/results/shortcircuit/shortcircuit-analysis-result.tsx +++ b/src/components/results/shortcircuit/shortcircuit-analysis-result.tsx @@ -13,7 +13,7 @@ import { SCAPagedResults, ShortCircuitAnalysisType, } from './shortcircuit-analysis-result.type'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { RunningStatus } from 'components/utils/running-status'; import React, { FunctionComponent, @@ -80,10 +80,8 @@ export const ShortCircuitAnalysisResult: FunctionComponent< const [isFetching, setIsFetching] = useState(false); const [filterEnums, setFilterEnums] = useState({}); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const isOneBusShortCircuitAnalysisType = analysisType === ShortCircuitAnalysisType.ONE_BUS; @@ -110,6 +108,7 @@ export const ShortCircuitAnalysisResult: FunctionComponent< { filterType: SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD, filterTab: mappingTabs(analysisType), + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setShortcircuitAnalysisResultFilter, }, memoizedSetPageCallback @@ -233,7 +232,7 @@ export const ShortCircuitAnalysisResult: FunctionComponent< headerId: 'ShortCircuitAnalysisResultsError', }) ); - }, [analysisStatus, intl, snackError, studyUuid, currentNode.id]); + }, [analysisStatus, intl, snackError, studyUuid, currentNode?.id]); const openLoader = useOpenLoaderShortWait({ isLoading: analysisStatus === RunningStatus.RUNNING || isFetching, diff --git a/src/components/results/use-results-tab.ts b/src/components/results/use-results-tab.ts index 22fecc4f01..cc691ce27f 100644 --- a/src/components/results/use-results-tab.ts +++ b/src/components/results/use-results-tab.ts @@ -10,7 +10,7 @@ import { IService } from 'components/result-view-tab'; import { StudyView } from 'components/study-pane'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { ShortCircuitAnalysisResultTabs } from './shortcircuit/shortcircuit-analysis-result.type'; export enum ResultsTabsRootLevel { @@ -40,7 +40,7 @@ export const useResultsTab = ( resultTabIndexRedirection: ResultTabIndexRedirection, setTabIndex: React.Dispatch>, view: string -): Dispatch> => { +): Dispatch> => { const [redirectionLock, setRedirectionLock] = useResultsTabRedirectionLock(); @@ -54,13 +54,13 @@ export const useResultsTab = ( }; const useResultsTabRedirectionLock = (): [ - Boolean, - Dispatch> + boolean, + Dispatch> ] => { - const lastCompletedComputation: string = useSelector( - (state: ReduxState) => state.lastCompletedComputation + const lastCompletedComputation = useSelector( + (state: AppState) => state.lastCompletedComputation ); - const [redirectionLock, setRedirectionLock] = useState(false); + const [redirectionLock, setRedirectionLock] = useState(false); useEffect(() => { //we ought to release the redirection lock if the user launches a new computation diff --git a/src/components/spreadsheet/table-wrapper.jsx b/src/components/spreadsheet/table-wrapper.jsx index bda31d86c8..cbdf73b559 100644 --- a/src/components/spreadsheet/table-wrapper.jsx +++ b/src/components/spreadsheet/table-wrapper.jsx @@ -236,6 +236,7 @@ const TableWrapper = (props) => { const { updateFilter, filterSelector } = useAggridLocalRowFilter(gridRef, { filterType: SPREADSHEET_STORE_FIELD, filterTab: TABLES_DEFINITION_INDEXES.get(tabIndex).type, + // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setSpreadsheetFilter, }); diff --git a/src/components/study-container.jsx b/src/components/study-container.jsx index 18716b75c8..583fe443d8 100644 --- a/src/components/study-container.jsx +++ b/src/components/study-container.jsx @@ -52,7 +52,7 @@ import { invalidateLoadFlowStatus } from 'services/study/loadflow'; import { HttpStatusCode } from 'utils/http-status-code'; import { usePrevious } from './utils/utils'; -import { StudyIndexationStatus } from 'redux/reducer.type'; +import { StudyIndexationStatus } from 'redux/reducer'; import { fetchDirectoryElementPath } from '@gridsuite/commons-ui'; function isWorthUpdate( 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 415c8af803..502f70eb6d 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 @@ -30,7 +30,8 @@ import { } from '../utils/equipment-types'; import { centerOnSubstation, openDiagram } from '../../redux/actions'; import { fetchNetworkElementInfos } from '../../services/study/network'; -import { ReduxState } from '../../redux/reducer.type'; +import { AppState } from '../../redux/reducer'; +import { AppDispatch } from '../../redux/store'; interface CustomSuffixRendererProps extends TagRendererProps { onClose?: () => void; @@ -39,16 +40,14 @@ interface CustomSuffixRendererProps extends TagRendererProps { export const CustomSuffixRenderer: FunctionComponent< CustomSuffixRendererProps > = ({ element, onClose, ...tagRendererProps }) => { - const dispatch = useDispatch(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const dispatch = useDispatch(); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const networkAreaDiagramNbVoltageLevels = useSelector( - (state: ReduxState) => state.networkAreaDiagramNbVoltageLevels + (state: AppState) => state.networkAreaDiagramNbVoltageLevels ); const networkAreaDiagramDepth = useSelector( - (state: ReduxState) => state.networkAreaDiagramDepth + (state: AppState) => state.networkAreaDiagramDepth ); const centerOnSubstationCB = useCallback( @@ -58,6 +57,7 @@ export const CustomSuffixRenderer: FunctionComponent< return; } let substationIdPromise; + // @ts-expect-error: conflicts between commons-ui's EquipmentType and gridstudy's EQUIPMENT_TYPE if (element.type === EQUIPMENT_TYPES.SUBSTATION) { substationIdPromise = Promise.resolve(element.id); } else { @@ -89,7 +89,9 @@ export const CustomSuffixRenderer: FunctionComponent< ); if ( + // @ts-expect-error: conflicts between commons-ui's EquipmentType and gridstudy's EQUIPMENT_TYPE element.type === EQUIPMENT_TYPES.SUBSTATION || + // @ts-expect-error: conflicts between commons-ui's EquipmentType and gridstudy's EQUIPMENT_TYPE element.type === EQUIPMENT_TYPES.VOLTAGE_LEVEL ) { return ( 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 91b08f8669..3f3b279ccc 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 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; import { ElementSearchDialog, Equipment, @@ -46,16 +46,16 @@ export const TopBarEquipmentSearchDialog: FunctionComponent< } = props; const intl = useIntl(); - const studyUuid = useSelector((state: ReduxState) => state.studyUuid); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode - ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); const [equipmentTypeFilter, setEquipmentTypeFilter] = useState(null); const { searchTerm, updateSearchTerm, equipmentsFound, isLoading } = useTopBarSearchMatchingEquipment({ + // @ts-expect-error TODO: manage null case studyUuid: studyUuid, + // @ts-expect-error TODO: manage null case nodeUuid: currentNode?.id, equipmentType: equipmentTypeFilter ?? undefined, }); @@ -75,6 +75,7 @@ export const TopBarEquipmentSearchDialog: FunctionComponent< (equipment: EquipmentInfos) => { closeDialog(); updateSearchTerm(''); + // @ts-expect-error TODO: manage null case addToLocalStorageSearchEquipmentHistory(studyUuid, equipment); fetchNetworkElementInfos( studyUuid, @@ -89,6 +90,7 @@ export const TopBarEquipmentSearchDialog: FunctionComponent< }) .catch(() => { excludeElementFromCurrentSearchHistory( + // @ts-expect-error TODO: manage null case studyUuid, equipment ); diff --git a/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx b/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx index 3f90045163..47227cb5c3 100644 --- a/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx +++ b/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx @@ -8,22 +8,20 @@ import { isNodeBuilt } from 'components/graph/util/model-functions'; import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; import { - ReduxState, + AppState, StudyDisplayMode, StudyIndexationStatus, -} from 'redux/reducer.type'; +} from 'redux/reducer'; export const useDisabledSearchReason = () => { const intl = useIntl(); const studyDisplayMode = useSelector( - (state: ReduxState) => state.studyDisplayMode + (state: AppState) => state.studyDisplayMode ); const studyIndexationStatus = useSelector( - (state: ReduxState) => state.studyIndexationStatus - ); - const currentNode = useSelector( - (state: ReduxState) => state.currentTreeNode + (state: AppState) => state.studyIndexationStatus ); + const currentNode = useSelector((state: AppState) => state.currentTreeNode); if (studyDisplayMode === StudyDisplayMode.TREE) { return intl.formatMessage({ diff --git a/src/components/top-bar-equipment-seach-dialog/use-search-event.tsx b/src/components/top-bar-equipment-seach-dialog/use-search-event.tsx index 917f857699..f2ba307bb1 100644 --- a/src/components/top-bar-equipment-seach-dialog/use-search-event.tsx +++ b/src/components/top-bar-equipment-seach-dialog/use-search-event.tsx @@ -6,10 +6,10 @@ */ import { useEffect } from 'react'; import { useSelector } from 'react-redux'; -import { ReduxState } from 'redux/reducer.type'; +import { AppState } from 'redux/reducer'; export const useSearchEvent = (enableSearchCallback: () => void) => { - const user = useSelector((state: ReduxState) => state.user); + const user = useSelector((state: AppState) => state.user); useEffect(() => { if (user) { diff --git a/src/hooks/use-aggrid-row-filter.ts b/src/hooks/use-aggrid-row-filter.ts index a79466e4bd..75fc01374b 100644 --- a/src/hooks/use-aggrid-row-filter.ts +++ b/src/hooks/use-aggrid-row-filter.ts @@ -12,6 +12,8 @@ import { } from 'components/custom-aggrid/custom-aggrid-header.type'; import { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { AppDispatch } from '../redux/store'; +import { AppState } from '../redux/reducer'; export type FilterEnumsType = Record; @@ -55,10 +57,11 @@ export const useAggridRowFilter = ( filterStoreParam: FilterStorePropsType, updateFilterCallback?: () => void ): UseAggridRowFilterOutputType => { - const dispatch = useDispatch(); + const dispatch = useDispatch(); const { filterType, filterTab, filterStoreAction } = filterStoreParam; const filterStore = useSelector( - (state: any) => state[filterType][filterTab] + // @ts-expect-error TODO: found a better way to go into state + (state: AppState) => state[filterType][filterTab] ); const updateFilter = useCallback( @@ -87,6 +90,7 @@ export const useAggridRowFilter = ( updateFilterCallback && updateFilterCallback(); filterStoreAction && filterTab && + // @ts-expect-error TODO: maybe resolve this with discriminate union parameter in FilterStorePropsType? dispatch(filterStoreAction(filterTab, updatedFilters)); }, [ diff --git a/src/hooks/use-computation-results-count.ts b/src/hooks/use-computation-results-count.ts index e492cd9e20..61e35533c6 100644 --- a/src/hooks/use-computation-results-count.ts +++ b/src/hooks/use-computation-results-count.ts @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { useSelector } from 'react-redux'; -import { ReduxState } from '../redux/reducer.type'; +import { AppState } from '../redux/reducer'; import ComputingType from 'components/computing-status/computing-type'; import RunningStatus from 'components/utils/running-status'; @@ -16,41 +16,40 @@ import RunningStatus from 'components/utils/running-status'; */ export const useComputationResultsCount = () => { const loadFlowStatus = useSelector( - (state: ReduxState) => state.computingStatus[ComputingType.LOAD_FLOW] + (state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW] ); const securityAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SECURITY_ANALYSIS] ); const sensitivityAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SENSITIVITY_ANALYSIS] ); const nonEvacuateEnergyAnalysisStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.NON_EVACUATED_ENERGY_ANALYSIS] ); const oneBusallBusesShortCircuitStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT_ONE_BUS] ); const allBusesShortCircuitStatus = useSelector( - (state: ReduxState) => - state.computingStatus[ComputingType.SHORT_CIRCUIT] + (state: AppState) => state.computingStatus[ComputingType.SHORT_CIRCUIT] ); const dynamicSimulationStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.DYNAMIC_SIMULATION] ); const voltageInitStatus = useSelector( - (state: ReduxState) => + (state: AppState) => state.computingStatus[ComputingType.VOLTAGE_INITIALIZATION] ); diff --git a/src/hooks/use-get-study-impacts.ts b/src/hooks/use-get-study-impacts.ts index ce73b082fd..5a8d169cc4 100644 --- a/src/hooks/use-get-study-impacts.ts +++ b/src/hooks/use-get-study-impacts.ts @@ -9,9 +9,9 @@ import { useSelector } from 'react-redux'; import { DeletedEquipment, NetworkImpactsInfos, - ReduxState, - UpdateTypes, -} from '../redux/reducer.type'; + AppState, + NotificationType, +} from '../redux/reducer'; import { UUID } from 'crypto'; interface StudyImpactsWithReset extends NetworkImpactsInfos { @@ -25,7 +25,7 @@ interface StudyImpactsWithReset extends NetworkImpactsInfos { */ export const useGetStudyImpacts = (): StudyImpactsWithReset => { const studyUpdatedForce = useSelector( - (state: ReduxState) => state.studyUpdated + (state: AppState) => state.studyUpdated ); const [impactedSubstationsIds, setImpactedSubstationsIds] = useState< @@ -51,7 +51,7 @@ export const useGetStudyImpacts = (): StudyImpactsWithReset => { }, []); useEffect(() => { - if (studyUpdatedForce.type === UpdateTypes.STUDY) { + if (studyUpdatedForce.type === NotificationType.STUDY) { const { impactedSubstationsIds: substationsIds, deletedEquipments, diff --git a/src/hooks/use-optional-service-status.ts b/src/hooks/use-optional-service-status.ts index df22991da1..087b7ea189 100644 --- a/src/hooks/use-optional-service-status.ts +++ b/src/hooks/use-optional-service-status.ts @@ -6,7 +6,7 @@ */ import { useSelector } from 'react-redux'; -import { ReduxState } from '../redux/reducer.type'; +import { AppState } from '../redux/reducer'; import { OptionalServicesNames, OptionalServicesStatus, @@ -16,7 +16,7 @@ export const useOptionalServiceStatus = ( serviceName: OptionalServicesNames ): OptionalServicesStatus | undefined => { const optionalServices = useSelector( - (state: ReduxState) => state.optionalServices + (state: AppState) => state.optionalServices ); const optionalService = optionalServices?.find( (service) => service.name === serviceName diff --git a/src/redux/actions.js b/src/redux/actions.js deleted file mode 100644 index 1b37d318c3..0000000000 --- a/src/redux/actions.js +++ /dev/null @@ -1,755 +0,0 @@ -/** - * Copyright (c) 2022, 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 { - PARAM_CENTER_LABEL, - PARAM_DIAGONAL_LABEL, - PARAM_LANGUAGE, - PARAM_LIMIT_REDUCTION, - PARAM_LINE_FLOW_ALERT_THRESHOLD, - PARAM_LINE_FLOW_COLOR_MODE, - PARAM_LINE_FLOW_MODE, - PARAM_LINE_FULL_PATH, - PARAM_LINE_PARALLEL_PATH, - PARAM_SUBSTATION_LAYOUT, - PARAM_COMPONENT_LIBRARY, - PARAM_THEME, - PARAM_USE_NAME, - PARAM_FAVORITE_CONTINGENCY_LISTS, - PARAM_FLUX_CONVENTION, - PARAM_MAP_MANUAL_REFRESH, - PARAM_MAP_BASEMAP, - PARAM_DEVELOPER_MODE, - PARAMS_LOADED, -} from '../utils/config-params'; - -export const LOAD_EQUIPMENTS = 'LOAD_EQUIPMENTS'; - -export function loadEquipments(equipmentType, equipments) { - return { - type: LOAD_EQUIPMENTS, - equipmentType: equipmentType, - equipments: equipments, - }; -} - -export const UPDATE_EQUIPMENTS = 'UPDATE_EQUIPMENTS'; - -export function updateEquipments(equipments) { - return { - type: UPDATE_EQUIPMENTS, - equipments: equipments, - }; -} - -export const DELETE_EQUIPMENTS = 'DELETE_EQUIPMENTS'; - -export function deleteEquipments(equipments) { - return { - type: DELETE_EQUIPMENTS, - equipments, - }; -} - -export const RESET_EQUIPMENTS = 'RESET_EQUIPMENTS'; - -export function resetEquipments() { - return { - type: RESET_EQUIPMENTS, - }; -} - -export const RESET_EQUIPMENTS_BY_TYPES = 'RESET_EQUIPMENTS_BY_TYPES'; - -export function resetEquipmentsByTypes(equipmentTypes) { - return { - type: RESET_EQUIPMENTS_BY_TYPES, - equipmentTypes: equipmentTypes, - }; -} - -export const RESET_EQUIPMENTS_POST_LOADFLOW = 'RESET_EQUIPMENTS_POST_LOADFLOW'; - -export function resetEquipmentsPostLoadflow() { - return { - type: RESET_EQUIPMENTS_POST_LOADFLOW, - }; -} - -export const MAP_EQUIPMENTS_CREATED = 'MAP_EQUIPMENTS_CREATED'; - -export function mapEquipmentsCreated( - mapEquipments, - newLines, - newTieLines, - newSubstations, - newHvdcLines -) { - return { - type: MAP_EQUIPMENTS_CREATED, - mapEquipments: mapEquipments, - newLines: newLines, - newTieLines: newTieLines, - newSubstations: newSubstations, - newHvdcLines: newHvdcLines, - }; -} - -export const LOAD_NETWORK_MODIFICATION_TREE_SUCCESS = - 'LOAD_NETWORK_MODIFICATION_TREE_SUCCESS'; - -export function loadNetworkModificationTreeSuccess( - networkModificationTreeModel -) { - return { - type: LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, - networkModificationTreeModel: networkModificationTreeModel, - }; -} - -export const NETWORK_MODIFICATION_TREE_NODE_ADDED = - 'NETWORK_MODIFICATION_TREE_NODE_ADDED'; - -export function networkModificationTreeNodeAdded( - networkModificationTreeNode, - parentNodeId, - insertMode, - referenceNodeId -) { - return { - type: NETWORK_MODIFICATION_TREE_NODE_ADDED, - networkModificationTreeNode: networkModificationTreeNode, - parentNodeId: parentNodeId, - insertMode: insertMode, - referenceNodeId: referenceNodeId, - }; -} - -export const NETWORK_MODIFICATION_TREE_NODE_MOVED = - 'NETWORK_MODIFICATION_TREE_NODE_MOVED'; - -export function networkModificationTreeNodeMoved( - networkModificationTreeNode, - parentNodeId, - insertMode, - referenceNodeId -) { - return { - type: NETWORK_MODIFICATION_TREE_NODE_MOVED, - networkModificationTreeNode, - parentNodeId, - insertMode, - referenceNodeId, - }; -} - -export const NETWORK_MODIFICATION_HANDLE_SUBTREE = - 'NETWORK_MODIFICATION_HANDLE_SUBTREE'; - -export function networkModificationHandleSubtree( - networkModificationTreeNodes, - parentNodeId -) { - return { - type: NETWORK_MODIFICATION_HANDLE_SUBTREE, - networkModificationTreeNodes: networkModificationTreeNodes, - parentNodeId: parentNodeId, - }; -} - -export const NETWORK_MODIFICATION_TREE_NODES_REMOVED = - 'NETWORK_MODIFICATION_TREE_NODES_REMOVED'; - -export function networkModificationTreeNodesRemoved( - networkModificationTreeNodes -) { - return { - type: NETWORK_MODIFICATION_TREE_NODES_REMOVED, - networkModificationTreeNodes: networkModificationTreeNodes, - }; -} - -export const NETWORK_MODIFICATION_TREE_NODES_UPDATED = - 'NETWORK_MODIFICATION_TREE_NODES_UPDATED'; - -export function networkModificationTreeNodesUpdated( - networkModificationTreeNodes -) { - return { - type: NETWORK_MODIFICATION_TREE_NODES_UPDATED, - networkModificationTreeNodes: networkModificationTreeNodes, - }; -} - -export const SELECT_THEME = 'SELECT_THEME'; - -export function selectTheme(theme) { - return { type: SELECT_THEME, [PARAM_THEME]: theme }; -} - -export const SELECT_LANGUAGE = 'SELECT_LANGUAGE'; - -export function selectLanguage(language) { - return { type: SELECT_LANGUAGE, [PARAM_LANGUAGE]: language }; -} - -export const SELECT_COMPUTED_LANGUAGE = 'SELECT_COMPUTED_LANGUAGE'; - -export function selectComputedLanguage(computedLanguage) { - return { - type: SELECT_COMPUTED_LANGUAGE, - computedLanguage: computedLanguage, - }; -} - -export const SET_PARAMS_LOADED = 'SET_PARAMS_LOADED'; - -export function setParamsLoaded() { - return { - type: SET_PARAMS_LOADED, - [PARAMS_LOADED]: true, - }; -} - -export const OPEN_STUDY = 'OPEN_STUDY'; - -export function openStudy(studyUuid) { - return { type: OPEN_STUDY, studyRef: [studyUuid] }; -} - -export const CLOSE_STUDY = 'CLOSE_STUDY'; - -export function closeStudy() { - return { type: CLOSE_STUDY }; -} - -export const REMOVE_SELECTED_CASE = 'REMOVE_SELECTED_CASE'; - -export function removeSelectedCase() { - return { type: REMOVE_SELECTED_CASE }; -} - -export const USE_NAME = 'USE_NAME'; - -export function selectUseName(useName) { - return { type: USE_NAME, [PARAM_USE_NAME]: useName }; -} - -export const CENTER_LABEL = 'CENTER_LABEL'; - -export function selectCenterLabelState(centerLabel) { - return { type: CENTER_LABEL, [PARAM_CENTER_LABEL]: centerLabel }; -} - -export const DIAGONAL_LABEL = 'DIAGONAL_LABEL'; - -export function selectDiagonalLabelState(diagonalLabel) { - return { type: DIAGONAL_LABEL, [PARAM_DIAGONAL_LABEL]: diagonalLabel }; -} - -export const LINE_FULL_PATH = 'LINE_FULL_PATH'; - -export function selectLineFullPathState(lineFullPath) { - return { type: LINE_FULL_PATH, [PARAM_LINE_FULL_PATH]: lineFullPath }; -} - -export const LINE_PARALLEL_PATH = 'LINE_PARALLEL_PATH'; - -export function selectLineParallelPathState(lineParallelPath) { - return { - type: LINE_PARALLEL_PATH, - [PARAM_LINE_PARALLEL_PATH]: lineParallelPath, - }; -} - -export const LINE_FLOW_MODE = 'LINE_FLOW_MODE'; - -export function selectLineFlowMode(lineFlowMode) { - return { type: LINE_FLOW_MODE, [PARAM_LINE_FLOW_MODE]: lineFlowMode }; -} - -export const FLUX_CONVENTION = 'FLUX_CONVENTION'; - -export function selectFluxConvention(fluxConvention) { - return { type: FLUX_CONVENTION, [PARAM_FLUX_CONVENTION]: fluxConvention }; -} - -export const ENABLE_DEVELOPER_MODE = 'ENABLE_DEVELOPER_MODE'; - -export function selectEnableDeveloperMode(enableDeveloperMode) { - return { - type: ENABLE_DEVELOPER_MODE, - [PARAM_DEVELOPER_MODE]: enableDeveloperMode, - }; -} - -export const LINE_FLOW_COLOR_MODE = 'LINE_FLOW_COLOR_MODE'; - -export function selectLineFlowColorMode(lineFlowColorMode) { - return { - type: LINE_FLOW_COLOR_MODE, - [PARAM_LINE_FLOW_COLOR_MODE]: lineFlowColorMode, - }; -} - -export const LINE_FLOW_ALERT_THRESHOLD = 'LINE_FLOW_ALERT_THRESHOLD'; - -export function selectLineFlowAlertThreshold(lineFlowAlertThreshold) { - return { - type: LINE_FLOW_ALERT_THRESHOLD, - [PARAM_LINE_FLOW_ALERT_THRESHOLD]: lineFlowAlertThreshold, - }; -} - -export const LIMIT_REDUCTION = 'LIMIT_REDUCTION'; - -export function selectLimitReduction(limitReduction) { - return { - type: LIMIT_REDUCTION, - [PARAM_LIMIT_REDUCTION]: limitReduction, - }; -} - -export const LIMIT_REDUCTION_MODIFIED = 'LIMIT_REDUCTION_MODIFIED'; - -export function limitReductionModified(limitReductionModified) { - return { - type: LIMIT_REDUCTION_MODIFIED, - limitReductionModified: limitReductionModified, - }; -} - -export const STUDY_UPDATED = 'STUDY_UPDATED'; - -export function studyUpdated(eventData) { - return { type: STUDY_UPDATED, eventData }; -} - -export const MAP_DATA_LOADING = 'MAP_DATA_LOADING'; - -export function setMapDataLoading(mapDataLoading) { - return { - type: MAP_DATA_LOADING, - mapDataLoading, - }; -} - -export const MAP_MANUAL_REFRESH = 'MAP_MANUAL_REFRESH'; - -export function selectMapManualRefresh(mapManualRefresh) { - return { - type: MAP_MANUAL_REFRESH, - [PARAM_MAP_MANUAL_REFRESH]: mapManualRefresh, - }; -} - -export const MAP_BASEMAP = 'MAP_BASEMAP'; - -export function selectMapBaseMap(mapBaseMap) { - return { - type: MAP_BASEMAP, - [PARAM_MAP_BASEMAP]: mapBaseMap, - }; -} - -export const RESET_MAP_RELOADED = 'RESET_MAP_RELOADED'; - -export function resetMapReloaded() { - return { - type: RESET_MAP_RELOADED, - }; -} - -export const MAP_EQUIPMENTS_INITIALIZED = 'MAP_EQUIPMENTS_INITIALIZED'; - -export function setMapEquipementsInitialized(newValue) { - return { - type: MAP_EQUIPMENTS_INITIALIZED, - newValue, - }; -} - -export const SUBSTATION_LAYOUT = 'SUBSTATION_LAYOUT'; - -export function selectSubstationLayout(substationLayout) { - return { - type: SUBSTATION_LAYOUT, - [PARAM_SUBSTATION_LAYOUT]: substationLayout, - }; -} - -export const COMPONENT_LIBRARY = 'COMPONENT_LIBRARY'; - -export function selectComponentLibrary(componentLibrary) { - return { - type: COMPONENT_LIBRARY, - [PARAM_COMPONENT_LIBRARY]: componentLibrary, - }; -} - -export const SET_FULLSCREEN_DIAGRAM = 'SET_FULLSCREEN_DIAGRAM'; - -export function setFullScreenDiagram(diagramIdParam, svgTypeParam = undefined) { - return { - type: SET_FULLSCREEN_DIAGRAM, - diagramId: diagramIdParam, - svgType: svgTypeParam, - }; -} - -export const CHANGE_DISPLAYED_COLUMNS_NAMES = 'CHANGE_DISPLAYED_COLUMNS_NAMES'; - -export function changeDisplayedColumns(displayedColumnsParams) { - return { - type: CHANGE_DISPLAYED_COLUMNS_NAMES, - displayedColumnsNamesParams: displayedColumnsParams, - }; -} - -export const CHANGE_LOCKED_COLUMNS_NAMES = 'CHANGE_LOCKED_COLUMNS_NAMES'; - -export function changeLockedColumns(lockedColumnsParams) { - return { - type: CHANGE_LOCKED_COLUMNS_NAMES, - lockedColumnsNamesParams: lockedColumnsParams, - }; -} - -export const CHANGE_REORDERED_COLUMNS = 'CHANGE_REORDERED_COLUMNS'; - -export function changeReorderedColumns(reorderedColumnsParams) { - return { - type: CHANGE_REORDERED_COLUMNS, - reorderedColumnsParams: reorderedColumnsParams, - }; -} - -export const FAVORITE_CONTINGENCY_LISTS = 'FAVORITE_CONTINGENCY_LISTS'; - -export function selectFavoriteContingencyLists(favoriteContingencyLists) { - return { - type: FAVORITE_CONTINGENCY_LISTS, - [PARAM_FAVORITE_CONTINGENCY_LISTS]: favoriteContingencyLists, - }; -} - -export const CURRENT_TREE_NODE = 'CURRENT_NODE'; - -export function setCurrentTreeNode(currentTreeNode) { - return { - type: CURRENT_TREE_NODE, - currentTreeNode: currentTreeNode, - }; -} - -export const SELECTION_FOR_COPY = 'SELECTION_FOR_COPY'; - -export function setSelectionForCopy(selectionForCopy) { - return { - type: SELECTION_FOR_COPY, - selectionForCopy: selectionForCopy, - }; -} - -export const SET_MODIFICATIONS_DRAWER_OPEN = 'SET_MODIFICATIONS_DRAWER_OPEN'; - -export function setModificationsDrawerOpen(isModificationsDrawerOpen) { - return { - type: SET_MODIFICATIONS_DRAWER_OPEN, - isModificationsDrawerOpen: isModificationsDrawerOpen, - }; -} - -export const SET_EVENT_SCENARIO_DRAWER_OPEN = 'SET_EVENT_SCENARIO_DRAWER_OPEN'; - -export function setEventScenarioDrawerOpen(isEventScenarioDrawerOpen) { - return { - type: SET_EVENT_SCENARIO_DRAWER_OPEN, - isEventScenarioDrawerOpen: isEventScenarioDrawerOpen, - }; -} - -export const CENTER_ON_SUBSTATION = 'CENTER_ON_SUBSTATION'; - -export function centerOnSubstation(substationId) { - return { - type: CENTER_ON_SUBSTATION, - centerOnSubstation: { to: substationId }, - }; -} - -export const ADD_NOTIFICATION = 'ADD_NOTIFICATION'; - -export function addNotification(notificationIds) { - return { - type: ADD_NOTIFICATION, - notificationIds: notificationIds, - }; -} - -export const REMOVE_NOTIFICATION_BY_NODE = 'REMOVE_NOTIFICATION_BY_NODE'; - -export function removeNotificationByNode(notificationIds) { - return { - type: REMOVE_NOTIFICATION_BY_NODE, - notificationIds: notificationIds, - }; -} - -export const SET_MODIFICATIONS_IN_PROGRESS = 'SET_MODIFICATIONS_IN_PROGRESS'; - -export function setModificationsInProgress(isModificationsInProgress) { - return { - type: SET_MODIFICATIONS_IN_PROGRESS, - isModificationsInProgress: isModificationsInProgress, - }; -} - -export const SET_STUDY_DISPLAY_MODE = 'SET_STUDY_DISPLAY_MODE'; - -export function setStudyDisplayMode(studyDisplayMode) { - return { - type: SET_STUDY_DISPLAY_MODE, - studyDisplayMode: studyDisplayMode, - }; -} - -export const OPEN_DIAGRAM = 'OPEN_DIAGRAM'; - -export function openDiagram(id, svgType) { - return { - type: OPEN_DIAGRAM, - id: id, - svgType: svgType, - }; -} - -export const MINIMIZE_DIAGRAM = 'MINIMIZE_DIAGRAM'; - -export function minimizeDiagram(id, svgType) { - return { - type: MINIMIZE_DIAGRAM, - id: id, - svgType: svgType, - }; -} - -export const TOGGLE_PIN_DIAGRAM = 'TOGGLE_PIN_DIAGRAM'; - -export function togglePinDiagram(id, svgType) { - return { - type: TOGGLE_PIN_DIAGRAM, - id: id, - svgType: svgType, - }; -} - -export const CLOSE_DIAGRAM = 'CLOSE_DIAGRAM'; - -export function closeDiagram(id, svgType) { - return { - type: CLOSE_DIAGRAM, - id: id, - svgType: svgType, - }; -} - -export const CLOSE_DIAGRAMS = 'CLOSE_DIAGRAMS'; - -export function closeDiagrams(ids) { - return { - type: CLOSE_DIAGRAMS, - ids: ids, - }; -} - -export const STOP_DIAGRAM_BLINK = 'STOP_DIAGRAM_BLINK'; - -export function stopDiagramBlink() { - return { - type: STOP_DIAGRAM_BLINK, - }; -} - -export const RESET_NETWORK_AREA_DIAGRAM_DEPTH = - 'RESET_NETWORK_AREA_DIAGRAM_DEPTH'; - -export function resetNetworkAreaDiagramDepth() { - return { - type: RESET_NETWORK_AREA_DIAGRAM_DEPTH, - }; -} - -export const INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH = - 'INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH'; - -export function incrementNetworkAreaDiagramDepth() { - return { - type: INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, - }; -} - -export const DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH = - 'DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH'; - -export function decrementNetworkAreaDiagramDepth() { - return { - type: DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, - }; -} - -export const NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS = - 'NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS'; - -export function setNetworkAreaDiagramNbVoltageLevels(nbVoltageLevels) { - return { - type: NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, - nbVoltageLevels: nbVoltageLevels, - }; -} - -export const SET_COMPUTING_STATUS = 'SET_COMPUTING_STATUS'; - -export function setComputingStatus(computingType, runningStatus) { - return { - type: SET_COMPUTING_STATUS, - computingType: computingType, - runningStatus: runningStatus, - }; -} - -export const SET_COMPUTATION_STARTING = 'SET_COMPUTATION_STARTING'; - -export function setComputationStarting(computationStarting) { - return { - type: SET_COMPUTATION_STARTING, - computationStarting: computationStarting, - }; -} - -export const SET_STUDY_INDEXATION_STATUS = 'SET_STUDY_INDEXATION_STATUS'; - -export function setStudyIndexationStatus(studyIndexationStatus) { - return { - type: SET_STUDY_INDEXATION_STATUS, - studyIndexationStatus: studyIndexationStatus, - }; -} - -export const SET_OPTIONAL_SERVICES = 'SET_SERVICES'; - -export const setOptionalServices = (optionalServices) => { - return { - type: SET_OPTIONAL_SERVICES, - optionalServices: optionalServices, - }; -}; - -export const SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM = - 'SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM'; - -export function setOneBusShortcircuitAnalysisDiagram(diagramId, nodeId) { - return { - type: SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, - diagramId: diagramId, - nodeId: nodeId, - }; -} - -export const ADD_TO_RECENT_GLOBAL_FILTERS = 'ADD_TO_RECENT_GLOBAL_FILTERS'; - -export function addToRecentGlobalFilters(globalFilters) { - return { - type: ADD_TO_RECENT_GLOBAL_FILTERS, - globalFilters: globalFilters, - }; -} - -export const SET_LAST_COMPLETED_COMPUTATION = 'SET_LAST_COMPLETED_COMPUTATION'; - -export function setLastCompletedComputation(lastCompletedComputation) { - return { - type: SET_LAST_COMPLETED_COMPUTATION, - lastCompletedComputation: lastCompletedComputation, - }; -} - -export const LOADFLOW_RESULT_FILTER = 'LOADFLOW_RESULT_FILTER'; - -export function setLoadflowResultFilter(filterTab, loadflowResultFilter) { - return { - type: LOADFLOW_RESULT_FILTER, - filterTab: filterTab, - loadflowResultFilter: loadflowResultFilter, - }; -} - -export const SECURITY_ANALYSIS_RESULT_FILTER = - 'SECURITY_ANALYSIS_RESULT_FILTER'; - -export function setSecurityAnalysisResultFilter( - filterTab, - securityAnalysisResultFilter -) { - return { - type: SECURITY_ANALYSIS_RESULT_FILTER, - filterTab: filterTab, - securityAnalysisResultFilter: securityAnalysisResultFilter, - }; -} - -export const SENSITIVITY_ANALYSIS_RESULT_FILTER = - 'SENSITIVITY_ANALYSIS_RESULT_FILTER'; - -export function setSensitivityAnalysisResultFilter( - filterTab, - sensitivityAnalysisResultFilter -) { - return { - type: SENSITIVITY_ANALYSIS_RESULT_FILTER, - filterTab: filterTab, - sensitivityAnalysisResultFilter: sensitivityAnalysisResultFilter, - }; -} - -export const SHORTCIRCUIT_ANALYSIS_RESULT_FILTER = - 'SHORTCIRCUIT_ANALYSIS_RESULT_FILTER'; - -export function setShortcircuitAnalysisResultFilter( - filterTab, - shortcircuitAnalysisResultFilter -) { - return { - type: SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, - filterTab: filterTab, - shortcircuitAnalysisResultFilter: shortcircuitAnalysisResultFilter, - }; -} - -export const DYNAMIC_SIMULATION_RESULT_FILTER = - 'DYNAMIC_SIMULATION_RESULT_FILTER'; - -export function setDynamicSimulationResultFilter( - filterTab, - dynamicSimulationResultFilter -) { - return { - type: DYNAMIC_SIMULATION_RESULT_FILTER, - filterTab: filterTab, - dynamicSimulationResultFilter: dynamicSimulationResultFilter, - }; -} - -export const SPREADSHEET_FILTER = 'SPREADSHEET_FILTER'; - -export function setSpreadsheetFilter(filterTab, spreadsheetFilter) { - return { - type: SPREADSHEET_FILTER, - filterTab: filterTab, - spreadsheetFilter: spreadsheetFilter, - }; -} diff --git a/src/redux/actions.ts b/src/redux/actions.ts new file mode 100644 index 0000000000..b9e7eadb0a --- /dev/null +++ b/src/redux/actions.ts @@ -0,0 +1,1307 @@ +/** + * Copyright (c) 2022, 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 { + MAP_BASEMAP_CARTO, + MAP_BASEMAP_CARTO_NOLABEL, + MAP_BASEMAP_MAPBOX, + PARAM_CENTER_LABEL, + PARAM_COMPONENT_LIBRARY, + PARAM_DEVELOPER_MODE, + PARAM_DIAGONAL_LABEL, + PARAM_FAVORITE_CONTINGENCY_LISTS, + PARAM_FLUX_CONVENTION, + PARAM_LANGUAGE, + PARAM_LIMIT_REDUCTION, + PARAM_LINE_FLOW_ALERT_THRESHOLD, + PARAM_LINE_FLOW_COLOR_MODE, + PARAM_LINE_FLOW_MODE, + PARAM_LINE_FULL_PATH, + PARAM_LINE_PARALLEL_PATH, + PARAM_MAP_BASEMAP, + PARAM_MAP_MANUAL_REFRESH, + PARAM_SUBSTATION_LAYOUT, + PARAM_THEME, + PARAM_USE_NAME, + PARAMS_LOADED, +} from '../utils/config-params'; +import { Action } from 'redux'; +import { GsLang, GsLangUser, GsTheme } from '@gridsuite/commons-ui'; +import { UUID } from 'crypto'; +import { UnknownArray } from 'type-fest'; +import { IEquipment } from '../services/study/contingency-list'; +import NetworkModificationTreeModel from '../components/graph/network-modification-tree-model'; +import { NodeInsertModes } from '../components/graph/nodes/node-insert-modes'; +import { LineFlowColorMode, MapEquipments } from '@powsybl/diagram-viewer'; +import { + AppState, + CurrentTreeNode, + EquipmentUpdateType, + OneBusShortCircuitAnalysisDiagram, + SelectionForCopy, + SpreadsheetEquipmentType, + StudyDisplayMode, + StudyIndexationStatus, + StudyUpdatedEventData, +} from './reducer'; +import { ComputingType } from '../components/computing-status/computing-type'; +import { RunningStatus } from '../components/utils/running-status'; +import { IOptionalService } from '../components/utils/optional-services'; +import { FluxConventions } from '../components/dialogs/parameters/network-parameters'; +import { LineFlowMode } from '@powsybl/diagram-viewer'; +import { + DiagramType, + SubstationLayout, +} from '../components/diagrams/diagram-common'; +import { Filter } from '../components/results/common/results-global-filter'; +import { + DYNAMIC_SIMULATION_RESULT_STORE_FIELD, + LOADFLOW_RESULT_STORE_FIELD, + SECURITY_ANALYSIS_RESULT_STORE_FIELD, + SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD, + SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD, + SPREADSHEET_STORE_FIELD, +} from '../utils/store-filter-fields'; + +type MutableUnknownArray = unknown[]; + +type ColumnName = { + index: number; + value: TValue; +}; + +export type AppActions = + | LoadEquipmentsAction + | UpdateEquipmentsAction + | DeleteEquipmentsAction + | ResetEquipmentsAction + | ResetEquipmentsByTypesAction + | ResetEquipmentsPostLoadflowAction + | MapEquipmentsCreatedAction + | LoadNetworkModificationTreeSuccessAction + | NetworkModificationTreeNodeAddedAction + | NetworkModificationTreeNodeMovedAction + | NetworkModificationHandleSubtreeAction + | NetworkModificationTreeNodesRemovedAction + | NetworkModificationTreeNodesUpdatedAction + | SelectThemeAction + | SelectLanguageAction + | SelectComputedLanguageAction + | SetParamsLoadedAction + | OpenStudyAction + | CloseStudyAction + | RemoveSelectedCaseAction + | UseNameAction + | CenterLabelAction + | DiagonalLabelAction + | LineFullPathAction + | LineParallelPathAction + | LineFlowModeAction + | FluxConventionAction + | EnableDeveloperModeAction + | LineFlowColorModeAction + | LineFlowAlertThresholdAction + | LimitReductionAction + | LimitReductionModifiedAction + | StudyUpdatedAction + | MapDataLoadingAction + | MapManualRefreshAction + | MapBasemapAction + | ResetMapReloadedAction + | MapEquipmentsInitializedAction + | SubstationLayoutAction + | ComponentLibraryAction + | SetFullscreenDiagramAction + | ChangeDisplayedColumnsNamesAction + | ChangeLockedColumnsNamesAction + | ChangeReorderedColumnsAction + | FavoriteContingencyListsAction + | CurrentTreeNodeAction + | SelectionForCopyAction + | SetModificationsDrawerOpenAction + | SetEventScenarioDrawerOpenAction + | CenterOnSubstationAction + | AddNotificationAction + | RemoveNotificationByNodeAction + | SetModificationsInProgressAction + | SetStudyDisplayModeAction + | OpenDiagramAction + | MinimizeDiagramAction + | TogglePinDiagramAction + | CloseDiagramAction + | CloseDiagramsAction + | StopDiagramBlinkAction + | ResetNetworkAreaDiagramDepthAction + | IncrementNetworkAreaDiagramDepthAction + | DecrementNetworkAreaDiagramDepthAction + | NetworkAreaDiagramNbVoltageLevelsAction + | SetComputingStatusAction + | SetComputationStartingAction + | SetStudyIndexationStatusAction + | SetOptionalServicesAction + | SetOneBusShortcircuitAnalysisDiagramAction + | AddToRecentGlobalFiltersAction + | SetLastCompletedComputationAction + | LoadflowResultFilterAction + | SecurityAnalysisResultFilterAction + | SensitivityAnalysisResultFilterAction + | ShortcircuitAnalysisResultFilterAction + | DynamicSimulationResultFilterAction + | SpreadsheetFilterAction; + +export const LOAD_EQUIPMENTS = 'LOAD_EQUIPMENTS'; +export type LoadEquipmentsAction = Readonly> & { + equipmentType: SpreadsheetEquipmentType; + equipments: IEquipment[]; +}; + +export function loadEquipments( + equipmentType: SpreadsheetEquipmentType, + equipments: IEquipment[] +): LoadEquipmentsAction { + return { + type: LOAD_EQUIPMENTS, + equipmentType: equipmentType, + equipments: equipments, + }; +} + +export const UPDATE_EQUIPMENTS = 'UPDATE_EQUIPMENTS'; +export type UpdateEquipmentsAction = Readonly< + Action +> & { + equipments: Record; +}; +export function updateEquipments( + equipments: Record +): UpdateEquipmentsAction { + return { + type: UPDATE_EQUIPMENTS, + equipments: equipments, + }; +} + +type EquipmentToDelete = { + equipmentType: SpreadsheetEquipmentType; + equipmentId: string; +}; +export const DELETE_EQUIPMENTS = 'DELETE_EQUIPMENTS'; +export type DeleteEquipmentsAction = Readonly< + Action +> & { + equipments: EquipmentToDelete[]; +}; +export function deleteEquipments( + equipments: EquipmentToDelete[] +): DeleteEquipmentsAction { + return { + type: DELETE_EQUIPMENTS, + equipments, + }; +} + +export const RESET_EQUIPMENTS = 'RESET_EQUIPMENTS'; +export type ResetEquipmentsAction = Readonly>; +export function resetEquipments(): ResetEquipmentsAction { + return { + type: RESET_EQUIPMENTS, + }; +} + +export const RESET_EQUIPMENTS_BY_TYPES = 'RESET_EQUIPMENTS_BY_TYPES'; +export type ResetEquipmentsByTypesAction = Readonly< + Action +> & { + equipmentTypes: SpreadsheetEquipmentType[]; +}; +export function resetEquipmentsByTypes( + equipmentTypes: SpreadsheetEquipmentType[] +): ResetEquipmentsByTypesAction { + return { + type: RESET_EQUIPMENTS_BY_TYPES, + equipmentTypes: equipmentTypes, + }; +} + +export const RESET_EQUIPMENTS_POST_LOADFLOW = 'RESET_EQUIPMENTS_POST_LOADFLOW'; +export type ResetEquipmentsPostLoadflowAction = Readonly< + Action +>; +export function resetEquipmentsPostLoadflow(): ResetEquipmentsPostLoadflowAction { + return { + type: RESET_EQUIPMENTS_POST_LOADFLOW, + }; +} + +export const MAP_EQUIPMENTS_CREATED = 'MAP_EQUIPMENTS_CREATED'; +export type MapEquipmentsCreatedAction = Readonly< + Action +> & { + mapEquipments: MapEquipments; + newLines?: MutableUnknownArray; + newTieLines?: MutableUnknownArray; + newSubstations?: MutableUnknownArray; + newHvdcLines?: MutableUnknownArray; +}; +export function mapEquipmentsCreated( + mapEquipments: MapEquipments, + newLines?: MutableUnknownArray, + newTieLines?: MutableUnknownArray, + newSubstations?: MutableUnknownArray, + newHvdcLines?: MutableUnknownArray +): MapEquipmentsCreatedAction { + return { + type: MAP_EQUIPMENTS_CREATED, + mapEquipments: mapEquipments, + newLines: newLines, + newTieLines: newTieLines, + newSubstations: newSubstations, + newHvdcLines: newHvdcLines, + }; +} + +export const LOAD_NETWORK_MODIFICATION_TREE_SUCCESS = + 'LOAD_NETWORK_MODIFICATION_TREE_SUCCESS'; +export type LoadNetworkModificationTreeSuccessAction = Readonly< + Action +> & { + networkModificationTreeModel: NetworkModificationTreeModel; +}; +export function loadNetworkModificationTreeSuccess( + networkModificationTreeModel: NetworkModificationTreeModel +): LoadNetworkModificationTreeSuccessAction { + return { + type: LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, + networkModificationTreeModel: networkModificationTreeModel, + }; +} + +export const NETWORK_MODIFICATION_TREE_NODE_ADDED = + 'NETWORK_MODIFICATION_TREE_NODE_ADDED'; +export type NetworkModificationTreeNodeAddedAction = Readonly< + Action +> & { + networkModificationTreeNode: CurrentTreeNode; + parentNodeId: string; + insertMode: NodeInsertModes; + referenceNodeId: string; +}; +export function networkModificationTreeNodeAdded( + networkModificationTreeNode: CurrentTreeNode, + parentNodeId: string, + insertMode: NodeInsertModes, + referenceNodeId: string +): NetworkModificationTreeNodeAddedAction { + return { + type: NETWORK_MODIFICATION_TREE_NODE_ADDED, + networkModificationTreeNode: networkModificationTreeNode, + parentNodeId: parentNodeId, + insertMode: insertMode, + referenceNodeId: referenceNodeId, + }; +} + +export const NETWORK_MODIFICATION_TREE_NODE_MOVED = + 'NETWORK_MODIFICATION_TREE_NODE_MOVED'; +export type NetworkModificationTreeNodeMovedAction = Readonly< + Action +> & { + networkModificationTreeNode: CurrentTreeNode; + parentNodeId: string; + insertMode: NodeInsertModes; + referenceNodeId: string; +}; +export function networkModificationTreeNodeMoved( + networkModificationTreeNode: CurrentTreeNode, + parentNodeId: string, + insertMode: NodeInsertModes, + referenceNodeId: string +): NetworkModificationTreeNodeMovedAction { + return { + type: NETWORK_MODIFICATION_TREE_NODE_MOVED, + networkModificationTreeNode, + parentNodeId, + insertMode, + referenceNodeId, + }; +} + +export const NETWORK_MODIFICATION_HANDLE_SUBTREE = + 'NETWORK_MODIFICATION_HANDLE_SUBTREE'; +export type NetworkModificationHandleSubtreeAction = Readonly< + Action +> & { + networkModificationTreeNodes: CurrentTreeNode[]; + parentNodeId: string; +}; +export function networkModificationHandleSubtree( + networkModificationTreeNodes: CurrentTreeNode[], + parentNodeId: string +): NetworkModificationHandleSubtreeAction { + return { + type: NETWORK_MODIFICATION_HANDLE_SUBTREE, + networkModificationTreeNodes: networkModificationTreeNodes, + parentNodeId: parentNodeId, + }; +} + +export const NETWORK_MODIFICATION_TREE_NODES_REMOVED = + 'NETWORK_MODIFICATION_TREE_NODES_REMOVED'; +export type NetworkModificationTreeNodesRemovedAction = Readonly< + Action +> & { + networkModificationTreeNodes: CurrentTreeNode[]; +}; +export function networkModificationTreeNodesRemoved( + networkModificationTreeNodes: CurrentTreeNode[] +): NetworkModificationTreeNodesRemovedAction { + return { + type: NETWORK_MODIFICATION_TREE_NODES_REMOVED, + networkModificationTreeNodes: networkModificationTreeNodes, + }; +} + +export const NETWORK_MODIFICATION_TREE_NODES_UPDATED = + 'NETWORK_MODIFICATION_TREE_NODES_UPDATED'; +export type NetworkModificationTreeNodesUpdatedAction = Readonly< + Action +> & { + networkModificationTreeNodes: CurrentTreeNode[]; +}; +export function networkModificationTreeNodesUpdated( + networkModificationTreeNodes: CurrentTreeNode[] +): NetworkModificationTreeNodesUpdatedAction { + return { + type: NETWORK_MODIFICATION_TREE_NODES_UPDATED, + networkModificationTreeNodes: networkModificationTreeNodes, + }; +} + +export const SELECT_THEME = 'SELECT_THEME'; +export type SelectThemeAction = Readonly> & { + [PARAM_THEME]: GsTheme; +}; +export function selectTheme(theme: GsTheme): SelectThemeAction { + return { type: SELECT_THEME, [PARAM_THEME]: theme }; +} + +export const SELECT_LANGUAGE = 'SELECT_LANGUAGE'; +export type SelectLanguageAction = Readonly> & { + [PARAM_LANGUAGE]: GsLang; +}; +export function selectLanguage(language: GsLang): SelectLanguageAction { + return { type: SELECT_LANGUAGE, [PARAM_LANGUAGE]: language }; +} + +export const SELECT_COMPUTED_LANGUAGE = 'SELECT_COMPUTED_LANGUAGE'; +export type SelectComputedLanguageAction = Readonly< + Action +> & { + computedLanguage: GsLangUser; +}; +export function selectComputedLanguage( + computedLanguage: GsLangUser +): SelectComputedLanguageAction { + return { + type: SELECT_COMPUTED_LANGUAGE, + computedLanguage: computedLanguage, + }; +} + +export const SET_PARAMS_LOADED = 'SET_PARAMS_LOADED'; +export type SetParamsLoadedAction = Readonly< + Action +> & { + [PARAMS_LOADED]: true; +}; +export function setParamsLoaded(): SetParamsLoadedAction { + return { + type: SET_PARAMS_LOADED, + [PARAMS_LOADED]: true, + }; +} + +export const OPEN_STUDY = 'OPEN_STUDY'; +export type OpenStudyAction = Readonly> & { + studyRef: [UUID]; +}; +export function openStudy(studyUuid: UUID): OpenStudyAction { + return { type: OPEN_STUDY, studyRef: [studyUuid] }; +} + +export const CLOSE_STUDY = 'CLOSE_STUDY'; +export type CloseStudyAction = Readonly>; +export function closeStudy(): CloseStudyAction { + return { type: CLOSE_STUDY }; +} + +export const REMOVE_SELECTED_CASE = 'REMOVE_SELECTED_CASE'; +export type RemoveSelectedCaseAction = Readonly< + Action +>; +export function removeSelectedCase(): RemoveSelectedCaseAction { + return { type: REMOVE_SELECTED_CASE }; +} + +export const USE_NAME = 'USE_NAME'; +export type UseNameAction = Readonly> & { + [PARAM_USE_NAME]: boolean; +}; +export function selectUseName(useName: boolean): UseNameAction { + return { type: USE_NAME, [PARAM_USE_NAME]: useName }; +} + +export const CENTER_LABEL = 'CENTER_LABEL'; +export type CenterLabelAction = Readonly> & { + [PARAM_CENTER_LABEL]: boolean; +}; +export function selectCenterLabelState( + centerLabel: boolean +): CenterLabelAction { + return { type: CENTER_LABEL, [PARAM_CENTER_LABEL]: centerLabel }; +} + +export const DIAGONAL_LABEL = 'DIAGONAL_LABEL'; +export type DiagonalLabelAction = Readonly> & { + [PARAM_DIAGONAL_LABEL]: boolean; +}; +export function selectDiagonalLabelState( + diagonalLabel: boolean +): DiagonalLabelAction { + return { type: DIAGONAL_LABEL, [PARAM_DIAGONAL_LABEL]: diagonalLabel }; +} + +export const LINE_FULL_PATH = 'LINE_FULL_PATH'; +export type LineFullPathAction = Readonly> & { + [PARAM_LINE_FULL_PATH]: boolean; +}; +export function selectLineFullPathState( + lineFullPath: boolean +): LineFullPathAction { + return { type: LINE_FULL_PATH, [PARAM_LINE_FULL_PATH]: lineFullPath }; +} + +export const LINE_PARALLEL_PATH = 'LINE_PARALLEL_PATH'; +export type LineParallelPathAction = Readonly< + Action +> & { + [PARAM_LINE_PARALLEL_PATH]: boolean; +}; +export function selectLineParallelPathState( + lineParallelPath: boolean +): LineParallelPathAction { + return { + type: LINE_PARALLEL_PATH, + [PARAM_LINE_PARALLEL_PATH]: lineParallelPath, + }; +} + +export const LINE_FLOW_MODE = 'LINE_FLOW_MODE'; +export type LineFlowModeAction = Readonly> & { + [PARAM_LINE_FLOW_MODE]: LineFlowMode; +}; +export function selectLineFlowMode( + lineFlowMode: LineFlowMode +): LineFlowModeAction { + return { type: LINE_FLOW_MODE, [PARAM_LINE_FLOW_MODE]: lineFlowMode }; +} + +export const FLUX_CONVENTION = 'FLUX_CONVENTION'; +export type FluxConventionAction = Readonly> & { + [PARAM_FLUX_CONVENTION]: FluxConventions; +}; +export function selectFluxConvention( + fluxConvention: FluxConventions +): FluxConventionAction { + return { type: FLUX_CONVENTION, [PARAM_FLUX_CONVENTION]: fluxConvention }; +} + +export const ENABLE_DEVELOPER_MODE = 'ENABLE_DEVELOPER_MODE'; +export type EnableDeveloperModeAction = Readonly< + Action +> & { + [PARAM_DEVELOPER_MODE]: boolean; +}; +export function selectEnableDeveloperMode( + enableDeveloperMode: boolean +): EnableDeveloperModeAction { + return { + type: ENABLE_DEVELOPER_MODE, + [PARAM_DEVELOPER_MODE]: enableDeveloperMode, + }; +} + +export const LINE_FLOW_COLOR_MODE = 'LINE_FLOW_COLOR_MODE'; +export type LineFlowColorModeAction = Readonly< + Action +> & { + [PARAM_LINE_FLOW_COLOR_MODE]: LineFlowColorMode; +}; +export function selectLineFlowColorMode( + lineFlowColorMode: LineFlowColorMode +): LineFlowColorModeAction { + return { + type: LINE_FLOW_COLOR_MODE, + [PARAM_LINE_FLOW_COLOR_MODE]: lineFlowColorMode, + }; +} + +export const LINE_FLOW_ALERT_THRESHOLD = 'LINE_FLOW_ALERT_THRESHOLD'; +export type LineFlowAlertThresholdAction = Readonly< + Action +> & { + [PARAM_LINE_FLOW_ALERT_THRESHOLD]: number; +}; +export function selectLineFlowAlertThreshold( + lineFlowAlertThreshold: number +): LineFlowAlertThresholdAction { + return { + type: LINE_FLOW_ALERT_THRESHOLD, + [PARAM_LINE_FLOW_ALERT_THRESHOLD]: lineFlowAlertThreshold, + }; +} + +export const LIMIT_REDUCTION = 'LIMIT_REDUCTION'; +export type LimitReductionAction = Readonly> & { + [PARAM_LIMIT_REDUCTION]: number; +}; +export function selectLimitReduction( + limitReduction: number +): LimitReductionAction { + return { + type: LIMIT_REDUCTION, + [PARAM_LIMIT_REDUCTION]: limitReduction, + }; +} + +export const LIMIT_REDUCTION_MODIFIED = 'LIMIT_REDUCTION_MODIFIED'; +export type LimitReductionModifiedAction = Readonly< + Action +> & { + limitReductionModified: boolean; +}; +export function limitReductionModified( + limitReductionModified: boolean +): LimitReductionModifiedAction { + return { + type: LIMIT_REDUCTION_MODIFIED, + limitReductionModified: limitReductionModified, + }; +} + +export const STUDY_UPDATED = 'STUDY_UPDATED'; +export type StudyUpdatedAction = Readonly> & { + eventData: StudyUpdatedEventData; +}; +/* +export type StudyUpdated = { + force: IntRange<0, 1>; +} & (StudyUpdatedUndefined | StudyUpdatedStudy); + */ +export function studyUpdated( + eventData: StudyUpdatedEventData +): StudyUpdatedAction { + return { type: STUDY_UPDATED, eventData }; +} + +export const MAP_DATA_LOADING = 'MAP_DATA_LOADING'; +export type MapDataLoadingAction = Readonly> & { + mapDataLoading: boolean; +}; +export function setMapDataLoading( + mapDataLoading: boolean +): MapDataLoadingAction { + return { + type: MAP_DATA_LOADING, + mapDataLoading, + }; +} + +export const MAP_MANUAL_REFRESH = 'MAP_MANUAL_REFRESH'; +export type MapManualRefreshAction = Readonly< + Action +> & { + [PARAM_MAP_MANUAL_REFRESH]: boolean; +}; +export function selectMapManualRefresh( + mapManualRefresh: boolean +): MapManualRefreshAction { + return { + type: MAP_MANUAL_REFRESH, + [PARAM_MAP_MANUAL_REFRESH]: mapManualRefresh, + }; +} + +export const MAP_BASEMAP = 'MAP_BASEMAP'; +export type MapBasemapAction = Readonly> & { + [PARAM_MAP_BASEMAP]: + | typeof MAP_BASEMAP_MAPBOX + | typeof MAP_BASEMAP_CARTO + | typeof MAP_BASEMAP_CARTO_NOLABEL; +}; +export function selectMapBaseMap( + mapBaseMap: + | typeof MAP_BASEMAP_MAPBOX + | typeof MAP_BASEMAP_CARTO + | typeof MAP_BASEMAP_CARTO_NOLABEL +): MapBasemapAction { + return { + type: MAP_BASEMAP, + [PARAM_MAP_BASEMAP]: mapBaseMap, + }; +} + +export const RESET_MAP_RELOADED = 'RESET_MAP_RELOADED'; +export type ResetMapReloadedAction = Readonly< + Action +>; +export function resetMapReloaded(): ResetMapReloadedAction { + return { + type: RESET_MAP_RELOADED, + }; +} + +export const MAP_EQUIPMENTS_INITIALIZED = 'MAP_EQUIPMENTS_INITIALIZED'; +export type MapEquipmentsInitializedAction = Readonly< + Action +> & { + newValue: boolean; +}; +export function setMapEquipementsInitialized( + newValue: boolean +): MapEquipmentsInitializedAction { + return { + type: MAP_EQUIPMENTS_INITIALIZED, + newValue, + }; +} + +export const SUBSTATION_LAYOUT = 'SUBSTATION_LAYOUT'; +export type SubstationLayoutAction = Readonly< + Action +> & { + [PARAM_SUBSTATION_LAYOUT]: SubstationLayout; +}; +export function selectSubstationLayout( + substationLayout: SubstationLayout +): SubstationLayoutAction { + return { + type: SUBSTATION_LAYOUT, + [PARAM_SUBSTATION_LAYOUT]: substationLayout, + }; +} + +export const COMPONENT_LIBRARY = 'COMPONENT_LIBRARY'; +export type ComponentLibraryAction = Readonly< + Action +> & { + [PARAM_COMPONENT_LIBRARY]: unknown; +}; +export function selectComponentLibrary( + componentLibrary: unknown +): ComponentLibraryAction { + return { + type: COMPONENT_LIBRARY, + [PARAM_COMPONENT_LIBRARY]: componentLibrary, + }; +} + +export const SET_FULLSCREEN_DIAGRAM = 'SET_FULLSCREEN_DIAGRAM'; +export type SetFullscreenDiagramAction = Readonly< + Action +> & + ( + | { diagramId: null } + | { + diagramId: string; + svgType: DiagramType; + } + ); +export function setFullScreenDiagram( + diagramIdParam: null +): SetFullscreenDiagramAction; +export function setFullScreenDiagram( + diagramIdParam: string, + svgTypeParam: DiagramType +): SetFullscreenDiagramAction; +export function setFullScreenDiagram( + diagramIdParam: string | null, + svgTypeParam?: DiagramType +): SetFullscreenDiagramAction { + return { + type: SET_FULLSCREEN_DIAGRAM, + diagramId: diagramIdParam, + // @ts-expect-error: function overload protect call + svgType: svgTypeParam, + }; +} + +export const CHANGE_DISPLAYED_COLUMNS_NAMES = 'CHANGE_DISPLAYED_COLUMNS_NAMES'; +export type ChangeDisplayedColumnsNamesAction = Readonly< + Action +> & { + displayedColumnsNamesParams: ColumnName[]; +}; +export function changeDisplayedColumns( + displayedColumnsParams: ColumnName[] +): ChangeDisplayedColumnsNamesAction { + return { + type: CHANGE_DISPLAYED_COLUMNS_NAMES, + displayedColumnsNamesParams: displayedColumnsParams, + }; +} + +export const CHANGE_LOCKED_COLUMNS_NAMES = 'CHANGE_LOCKED_COLUMNS_NAMES'; +export type ChangeLockedColumnsNamesAction = Readonly< + Action +> & { + lockedColumnsNamesParams: ColumnName[]; +}; +export function changeLockedColumns( + lockedColumnsParams: ColumnName[] +): ChangeLockedColumnsNamesAction { + return { + type: CHANGE_LOCKED_COLUMNS_NAMES, + lockedColumnsNamesParams: lockedColumnsParams, + }; +} + +export const CHANGE_REORDERED_COLUMNS = 'CHANGE_REORDERED_COLUMNS'; +export type ChangeReorderedColumnsAction = Readonly< + Action +> & { + reorderedColumnsParams: ColumnName[]; +}; +export function changeReorderedColumns( + reorderedColumnsParams: ColumnName[] +): ChangeReorderedColumnsAction { + return { + type: CHANGE_REORDERED_COLUMNS, + reorderedColumnsParams: reorderedColumnsParams, + }; +} + +export const FAVORITE_CONTINGENCY_LISTS = 'FAVORITE_CONTINGENCY_LISTS'; +export type FavoriteContingencyListsAction = Readonly< + Action +> & { + [PARAM_FAVORITE_CONTINGENCY_LISTS]: MutableUnknownArray; +}; +export function selectFavoriteContingencyLists( + favoriteContingencyLists: MutableUnknownArray +): FavoriteContingencyListsAction { + return { + type: FAVORITE_CONTINGENCY_LISTS, + [PARAM_FAVORITE_CONTINGENCY_LISTS]: favoriteContingencyLists, + }; +} + +export const CURRENT_TREE_NODE = 'CURRENT_TREE_NODE'; +export type CurrentTreeNodeAction = Readonly< + Action +> & { + currentTreeNode: CurrentTreeNode; +}; +export function setCurrentTreeNode( + currentTreeNode: CurrentTreeNode +): CurrentTreeNodeAction { + return { + type: CURRENT_TREE_NODE, + currentTreeNode: currentTreeNode, + }; +} + +export const SELECTION_FOR_COPY = 'SELECTION_FOR_COPY'; +export type SelectionForCopyAction = Readonly< + Action +> & { + selectionForCopy: NonNullable; +}; +export function setSelectionForCopy( + selectionForCopy: NonNullable +): SelectionForCopyAction { + return { + type: SELECTION_FOR_COPY, + selectionForCopy: selectionForCopy, + }; +} + +export const SET_MODIFICATIONS_DRAWER_OPEN = 'SET_MODIFICATIONS_DRAWER_OPEN'; +export type SetModificationsDrawerOpenAction = Readonly< + Action +> & { + isModificationsDrawerOpen: boolean; +}; +export function setModificationsDrawerOpen( + isModificationsDrawerOpen: boolean +): SetModificationsDrawerOpenAction { + return { + type: SET_MODIFICATIONS_DRAWER_OPEN, + isModificationsDrawerOpen: isModificationsDrawerOpen, + }; +} + +export const SET_EVENT_SCENARIO_DRAWER_OPEN = 'SET_EVENT_SCENARIO_DRAWER_OPEN'; +export type SetEventScenarioDrawerOpenAction = Readonly< + Action +> & { + isEventScenarioDrawerOpen: boolean; +}; +export function setEventScenarioDrawerOpen( + isEventScenarioDrawerOpen: boolean +): SetEventScenarioDrawerOpenAction { + return { + type: SET_EVENT_SCENARIO_DRAWER_OPEN, + isEventScenarioDrawerOpen: isEventScenarioDrawerOpen, + }; +} + +export const CENTER_ON_SUBSTATION = 'CENTER_ON_SUBSTATION'; +export type CenterOnSubstationAction = Readonly< + Action +> & { + centerOnSubstation: { to: unknown }; +}; +export function centerOnSubstation( + substationId: unknown +): CenterOnSubstationAction { + return { + type: CENTER_ON_SUBSTATION, + centerOnSubstation: { to: substationId }, + }; +} + +export const ADD_NOTIFICATION = 'ADD_NOTIFICATION'; +export type AddNotificationAction = Readonly< + Action +> & { + notificationIds: UUID[]; +}; +export function addNotification( + notificationIds: UUID[] +): AddNotificationAction { + return { + type: ADD_NOTIFICATION, + notificationIds: notificationIds, + }; +} + +export const REMOVE_NOTIFICATION_BY_NODE = 'REMOVE_NOTIFICATION_BY_NODE'; +export type RemoveNotificationByNodeAction = Readonly< + Action +> & { + notificationIds: UnknownArray; +}; +export function removeNotificationByNode( + notificationIds: UnknownArray +): RemoveNotificationByNodeAction { + return { + type: REMOVE_NOTIFICATION_BY_NODE, + notificationIds: notificationIds, + }; +} + +export const SET_MODIFICATIONS_IN_PROGRESS = 'SET_MODIFICATIONS_IN_PROGRESS'; +export type SetModificationsInProgressAction = Readonly< + Action +> & { + isModificationsInProgress: boolean; +}; +export function setModificationsInProgress( + isModificationsInProgress: boolean +): SetModificationsInProgressAction { + return { + type: SET_MODIFICATIONS_IN_PROGRESS, + isModificationsInProgress: isModificationsInProgress, + }; +} + +export const SET_STUDY_DISPLAY_MODE = 'SET_STUDY_DISPLAY_MODE'; +export type SetStudyDisplayModeAction = Readonly< + Action +> & { + studyDisplayMode: StudyDisplayMode; +}; +export function setStudyDisplayMode( + studyDisplayMode: StudyDisplayMode +): SetStudyDisplayModeAction { + return { + type: SET_STUDY_DISPLAY_MODE, + studyDisplayMode: studyDisplayMode, + }; +} + +export const OPEN_DIAGRAM = 'OPEN_DIAGRAM'; +export type OpenDiagramAction = Readonly> & { + id: string; + svgType: DiagramType; +}; +export function openDiagram( + id: string, + svgType: DiagramType +): OpenDiagramAction { + return { + type: OPEN_DIAGRAM, + id: id, + svgType: svgType, + }; +} + +export const MINIMIZE_DIAGRAM = 'MINIMIZE_DIAGRAM'; +export type MinimizeDiagramAction = Readonly< + Action +> & { + id: string; + svgType: DiagramType; +}; +export function minimizeDiagram( + id: string, + svgType: DiagramType +): MinimizeDiagramAction { + return { + type: MINIMIZE_DIAGRAM, + id: id, + svgType: svgType, + }; +} + +export const TOGGLE_PIN_DIAGRAM = 'TOGGLE_PIN_DIAGRAM'; +export type TogglePinDiagramAction = Readonly< + Action +> & { + id: string; + svgType: DiagramType; +}; +export function togglePinDiagram( + id: string, + svgType: DiagramType +): TogglePinDiagramAction { + return { + type: TOGGLE_PIN_DIAGRAM, + id: id, + svgType: svgType, + }; +} + +export const CLOSE_DIAGRAM = 'CLOSE_DIAGRAM'; +export type CloseDiagramAction = Readonly> & { + id: string; + svgType: DiagramType; +}; +export function closeDiagram( + id: string, + svgType: DiagramType +): CloseDiagramAction { + return { + type: CLOSE_DIAGRAM, + id: id, + svgType: svgType, + }; +} + +export const CLOSE_DIAGRAMS = 'CLOSE_DIAGRAMS'; +export type CloseDiagramsAction = Readonly> & { + ids: string[]; +}; +export function closeDiagrams(ids: string[]): CloseDiagramsAction { + return { + type: CLOSE_DIAGRAMS, + ids: ids, + }; +} + +export const STOP_DIAGRAM_BLINK = 'STOP_DIAGRAM_BLINK'; +export type StopDiagramBlinkAction = Readonly< + Action +>; +export function stopDiagramBlink(): StopDiagramBlinkAction { + return { + type: STOP_DIAGRAM_BLINK, + }; +} + +export const RESET_NETWORK_AREA_DIAGRAM_DEPTH = + 'RESET_NETWORK_AREA_DIAGRAM_DEPTH'; +export type ResetNetworkAreaDiagramDepthAction = Readonly< + Action +>; +export function resetNetworkAreaDiagramDepth(): ResetNetworkAreaDiagramDepthAction { + return { + type: RESET_NETWORK_AREA_DIAGRAM_DEPTH, + }; +} + +export const INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH = + 'INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH'; +export type IncrementNetworkAreaDiagramDepthAction = Readonly< + Action +>; +export function incrementNetworkAreaDiagramDepth(): IncrementNetworkAreaDiagramDepthAction { + return { + type: INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + }; +} + +export const DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH = + 'DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH'; +export type DecrementNetworkAreaDiagramDepthAction = Readonly< + Action +>; +export function decrementNetworkAreaDiagramDepth(): DecrementNetworkAreaDiagramDepthAction { + return { + type: DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + }; +} + +export const NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS = + 'NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS'; +export type NetworkAreaDiagramNbVoltageLevelsAction = Readonly< + Action +> & { + nbVoltageLevels: number; +}; +export function setNetworkAreaDiagramNbVoltageLevels( + nbVoltageLevels: number +): NetworkAreaDiagramNbVoltageLevelsAction { + return { + type: NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, + nbVoltageLevels: nbVoltageLevels, + }; +} + +export const SET_COMPUTING_STATUS = 'SET_COMPUTING_STATUS'; +export type SetComputingStatusAction = Readonly< + Action +> & { + computingType: ComputingType; + runningStatus: RunningStatus; +}; +export function setComputingStatus( + computingType: ComputingType, + runningStatus: RunningStatus +): SetComputingStatusAction { + return { + type: SET_COMPUTING_STATUS, + computingType: computingType, + runningStatus: runningStatus, + }; +} + +export const SET_COMPUTATION_STARTING = 'SET_COMPUTATION_STARTING'; +export type SetComputationStartingAction = Readonly< + Action +> & { + computationStarting: boolean; +}; +export function setComputationStarting( + computationStarting: boolean +): SetComputationStartingAction { + return { + type: SET_COMPUTATION_STARTING, + computationStarting: computationStarting, + }; +} + +export const SET_STUDY_INDEXATION_STATUS = 'SET_STUDY_INDEXATION_STATUS'; +export type SetStudyIndexationStatusAction = Readonly< + Action +> & { + studyIndexationStatus: StudyIndexationStatus; +}; +export function setStudyIndexationStatus( + studyIndexationStatus: StudyIndexationStatus +): SetStudyIndexationStatusAction { + return { + type: SET_STUDY_INDEXATION_STATUS, + studyIndexationStatus: studyIndexationStatus, + }; +} + +export const SET_OPTIONAL_SERVICES = 'SET_OPTIONAL_SERVICES'; +export type SetOptionalServicesAction = Readonly< + Action +> & { + optionalServices: IOptionalService[]; +}; +export function setOptionalServices( + optionalServices: IOptionalService[] +): SetOptionalServicesAction { + return { + type: SET_OPTIONAL_SERVICES, + optionalServices: optionalServices, + }; +} + +export const SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM = + 'SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM'; +export type SetOneBusShortcircuitAnalysisDiagramAction = Readonly< + Action +> & + (OneBusShortCircuitAnalysisDiagram | { diagramId: null }); + +export function setOneBusShortcircuitAnalysisDiagram( + diagramId: null +): SetOneBusShortcircuitAnalysisDiagramAction; +export function setOneBusShortcircuitAnalysisDiagram( + diagramId: OneBusShortCircuitAnalysisDiagram['diagramId'], + nodeId: OneBusShortCircuitAnalysisDiagram['nodeId'] +): SetOneBusShortcircuitAnalysisDiagramAction; +export function setOneBusShortcircuitAnalysisDiagram( + diagramId: OneBusShortCircuitAnalysisDiagram['diagramId'] | null, + nodeId?: OneBusShortCircuitAnalysisDiagram['nodeId'] +): SetOneBusShortcircuitAnalysisDiagramAction { + return { + type: SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, + diagramId: diagramId, + // @ts-expect-error: function overload protect call + nodeId: nodeId, + }; +} + +export const ADD_TO_RECENT_GLOBAL_FILTERS = 'ADD_TO_RECENT_GLOBAL_FILTERS'; +export type AddToRecentGlobalFiltersAction = Readonly< + Action +> & { + globalFilters: Filter[]; +}; +export function addToRecentGlobalFilters( + globalFilters: Filter[] +): AddToRecentGlobalFiltersAction { + return { + type: ADD_TO_RECENT_GLOBAL_FILTERS, + globalFilters: globalFilters, + }; +} + +export const SET_LAST_COMPLETED_COMPUTATION = 'SET_LAST_COMPLETED_COMPUTATION'; +export type SetLastCompletedComputationAction = Readonly< + Action +> & { + lastCompletedComputation: ComputingType | null; +}; +export function setLastCompletedComputation( + lastCompletedComputation?: ComputingType +): SetLastCompletedComputationAction { + return { + type: SET_LAST_COMPLETED_COMPUTATION, + lastCompletedComputation: lastCompletedComputation ?? null, + }; +} + +export const LOADFLOW_RESULT_FILTER = 'LOADFLOW_RESULT_FILTER'; +export type LoadflowResultFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof LOADFLOW_RESULT_STORE_FIELD]; + [LOADFLOW_RESULT_STORE_FIELD]: MutableUnknownArray; +}; +export function setLoadflowResultFilter( + filterTab: keyof AppState[typeof LOADFLOW_RESULT_STORE_FIELD], + loadflowResultFilter: MutableUnknownArray +): LoadflowResultFilterAction { + return { + type: LOADFLOW_RESULT_FILTER, + filterTab: filterTab, + [LOADFLOW_RESULT_STORE_FIELD]: loadflowResultFilter, + }; +} + +export const SECURITY_ANALYSIS_RESULT_FILTER = + 'SECURITY_ANALYSIS_RESULT_FILTER'; +export type SecurityAnalysisResultFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof SECURITY_ANALYSIS_RESULT_STORE_FIELD]; + [SECURITY_ANALYSIS_RESULT_STORE_FIELD]: MutableUnknownArray; +}; +export function setSecurityAnalysisResultFilter( + filterTab: keyof AppState[typeof SECURITY_ANALYSIS_RESULT_STORE_FIELD], + securityAnalysisResultFilter: MutableUnknownArray +): SecurityAnalysisResultFilterAction { + return { + type: SECURITY_ANALYSIS_RESULT_FILTER, + filterTab: filterTab, + [SECURITY_ANALYSIS_RESULT_STORE_FIELD]: securityAnalysisResultFilter, + }; +} + +export const SENSITIVITY_ANALYSIS_RESULT_FILTER = + 'SENSITIVITY_ANALYSIS_RESULT_FILTER'; +export type SensitivityAnalysisResultFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]; + [SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]: MutableUnknownArray; +}; +export function setSensitivityAnalysisResultFilter( + filterTab: keyof AppState[typeof SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD], + sensitivityAnalysisResultFilter: MutableUnknownArray +): SensitivityAnalysisResultFilterAction { + return { + type: SENSITIVITY_ANALYSIS_RESULT_FILTER, + filterTab: filterTab, + [SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]: + sensitivityAnalysisResultFilter, + }; +} + +export const SHORTCIRCUIT_ANALYSIS_RESULT_FILTER = + 'SHORTCIRCUIT_ANALYSIS_RESULT_FILTER'; +export type ShortcircuitAnalysisResultFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]; + [SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]: MutableUnknownArray; +}; +export function setShortcircuitAnalysisResultFilter( + filterTab: keyof AppState[typeof SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD], + shortcircuitAnalysisResultFilter: MutableUnknownArray +): ShortcircuitAnalysisResultFilterAction { + return { + type: SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, + filterTab: filterTab, + [SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]: + shortcircuitAnalysisResultFilter, + }; +} + +export const DYNAMIC_SIMULATION_RESULT_FILTER = + 'DYNAMIC_SIMULATION_RESULT_FILTER'; +export type DynamicSimulationResultFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof DYNAMIC_SIMULATION_RESULT_STORE_FIELD]; + [DYNAMIC_SIMULATION_RESULT_STORE_FIELD]: MutableUnknownArray; +}; +export function setDynamicSimulationResultFilter( + filterTab: keyof AppState[typeof DYNAMIC_SIMULATION_RESULT_STORE_FIELD], + dynamicSimulationResultFilter: MutableUnknownArray +): DynamicSimulationResultFilterAction { + return { + type: DYNAMIC_SIMULATION_RESULT_FILTER, + filterTab: filterTab, + [DYNAMIC_SIMULATION_RESULT_STORE_FIELD]: dynamicSimulationResultFilter, + }; +} + +export const SPREADSHEET_FILTER = 'SPREADSHEET_FILTER'; +export type SpreadsheetFilterAction = Readonly< + Action +> & { + filterTab: keyof AppState[typeof SPREADSHEET_STORE_FIELD]; + [SPREADSHEET_STORE_FIELD]: MutableUnknownArray; +}; +export function setSpreadsheetFilter( + filterTab: keyof AppState[typeof SPREADSHEET_STORE_FIELD], + spreadsheetFilter: MutableUnknownArray +): SpreadsheetFilterAction { + return { + type: SPREADSHEET_FILTER, + filterTab: filterTab, + [SPREADSHEET_STORE_FIELD]: spreadsheetFilter, + }; +} diff --git a/src/redux/reducer.js b/src/redux/reducer.js deleted file mode 100644 index e128cc1b25..0000000000 --- a/src/redux/reducer.js +++ /dev/null @@ -1,1339 +0,0 @@ -/** - * Copyright (c) 2022, 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 { createReducer } from '@reduxjs/toolkit'; - -import { - LOGOUT_ERROR, - RESET_AUTHENTICATION_ROUTER_ERROR, - SHOW_AUTH_INFO_LOGIN, - UNAUTHORIZED_USER_INFO, - USER, - USER_VALIDATION_ERROR, -} from '@gridsuite/commons-ui'; -import { EQUIPMENT_TYPES } from 'components/utils/equipment-types'; -import { - ADD_TO_RECENT_GLOBAL_FILTERS, - ADD_NOTIFICATION, - CENTER_LABEL, - CENTER_ON_SUBSTATION, - CHANGE_DISPLAYED_COLUMNS_NAMES, - CHANGE_LOCKED_COLUMNS_NAMES, - CHANGE_REORDERED_COLUMNS, - CLOSE_DIAGRAM, - CLOSE_DIAGRAMS, - CLOSE_STUDY, - COMPONENT_LIBRARY, - CURRENT_TREE_NODE, - DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, - DIAGONAL_LABEL, - ENABLE_DEVELOPER_MODE, - FAVORITE_CONTINGENCY_LISTS, - FLUX_CONVENTION, - INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, - LIMIT_REDUCTION, - LIMIT_REDUCTION_MODIFIED, - LINE_FLOW_ALERT_THRESHOLD, - LINE_FLOW_COLOR_MODE, - LINE_FLOW_MODE, - LINE_FULL_PATH, - LINE_PARALLEL_PATH, - LOAD_EQUIPMENTS, - LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, - MAP_BASEMAP, - MAP_DATA_LOADING, - MAP_EQUIPMENTS_CREATED, - MAP_EQUIPMENTS_INITIALIZED, - MAP_MANUAL_REFRESH, - MINIMIZE_DIAGRAM, - NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, - NETWORK_MODIFICATION_HANDLE_SUBTREE, - NETWORK_MODIFICATION_TREE_NODE_ADDED, - NETWORK_MODIFICATION_TREE_NODE_MOVED, - NETWORK_MODIFICATION_TREE_NODES_REMOVED, - NETWORK_MODIFICATION_TREE_NODES_UPDATED, - OPEN_DIAGRAM, - OPEN_STUDY, - REMOVE_NOTIFICATION_BY_NODE, - RESET_EQUIPMENTS, - RESET_EQUIPMENTS_POST_LOADFLOW, - RESET_MAP_RELOADED, - RESET_NETWORK_AREA_DIAGRAM_DEPTH, - SELECT_COMPUTED_LANGUAGE, - SELECT_LANGUAGE, - SELECT_THEME, - SELECTION_FOR_COPY, - SET_COMPUTATION_STARTING, - SET_COMPUTING_STATUS, - SET_EVENT_SCENARIO_DRAWER_OPEN, - SET_FULLSCREEN_DIAGRAM, - SET_LAST_COMPLETED_COMPUTATION, - SET_MODIFICATIONS_DRAWER_OPEN, - SET_MODIFICATIONS_IN_PROGRESS, - SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, - SET_OPTIONAL_SERVICES, - SET_PARAMS_LOADED, - SET_STUDY_DISPLAY_MODE, - SET_STUDY_INDEXATION_STATUS, - STOP_DIAGRAM_BLINK, - LOADFLOW_RESULT_FILTER, - SECURITY_ANALYSIS_RESULT_FILTER, - SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, - SENSITIVITY_ANALYSIS_RESULT_FILTER, - SPREADSHEET_FILTER, - DYNAMIC_SIMULATION_RESULT_FILTER, - STUDY_UPDATED, - USE_NAME, - SUBSTATION_LAYOUT, - TOGGLE_PIN_DIAGRAM, - UPDATE_EQUIPMENTS, - RESET_EQUIPMENTS_BY_TYPES, - DELETE_EQUIPMENTS, -} from './actions'; -import { - getLocalStorageComputedLanguage, - getLocalStorageLanguage, - getLocalStorageTheme, - saveLocalStorageLanguage, - saveLocalStorageTheme, -} from './local-storage/local-storage'; -import { TABLES_COLUMNS_NAMES_JSON } from '../components/spreadsheet/utils/config-tables'; -import { - MAP_BASEMAP_MAPBOX, - PARAM_CENTER_LABEL, - PARAM_COMPONENT_LIBRARY, - PARAM_DEVELOPER_MODE, - PARAM_DIAGONAL_LABEL, - PARAM_FAVORITE_CONTINGENCY_LISTS, - PARAM_FLUX_CONVENTION, - PARAM_LANGUAGE, - PARAM_LIMIT_REDUCTION, - PARAM_LINE_FLOW_ALERT_THRESHOLD, - PARAM_LINE_FLOW_COLOR_MODE, - PARAM_LINE_FLOW_MODE, - PARAM_LINE_FULL_PATH, - PARAM_LINE_PARALLEL_PATH, - PARAM_MAP_BASEMAP, - PARAM_MAP_MANUAL_REFRESH, - PARAM_SUBSTATION_LAYOUT, - PARAM_THEME, - PARAM_USE_NAME, - PARAMS_LOADED, -} from '../utils/config-params'; -import NetworkModificationTreeModel from '../components/graph/network-modification-tree-model'; -import { FluxConventions } from '../components/dialogs/parameters/network-parameters'; -import { loadDiagramStateFromSessionStorage } from './session-storage'; -import { DiagramType, ViewState } from '../components/diagrams/diagram-common'; -import { getAllChildren } from 'components/graph/util/model-functions'; -import { CopyType } from 'components/network-modification-tree-pane'; -import { ComputingType } from 'components/computing-status/computing-type'; -import { RunningStatus } from 'components/utils/running-status'; -import { NodeInsertModes } from '../components/utils/node-insert-modes'; -import { - OptionalServicesNames, - OptionalServicesStatus, -} from '../components/utils/optional-services'; -import { formatFetchedEquipments } from 'components/spreadsheet/utils/equipment-table-utils'; -import { - LOADFLOW_CURRENT_LIMIT_VIOLATION, - LOADFLOW_RESULT, - LOADFLOW_VOLTAGE_LIMIT_VIOLATION, - SECURITY_ANALYSIS_RESULT_N, - SECURITY_ANALYSIS_RESULT_N_K, - SENSITIVITY_AT_NODE_N, - SENSITIVITY_AT_NODE_N_K, - SENSITIVITY_IN_DELTA_A_N, - SENSITIVITY_IN_DELTA_A_N_K, - SENSITIVITY_IN_DELTA_MW_N, - SENSITIVITY_IN_DELTA_MW_N_K, - ALL_BUSES, - LOADFLOW_RESULT_STORE_FIELD, - SECURITY_ANALYSIS_RESULT_STORE_FIELD, - SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD, - SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD, - DYNAMIC_SIMULATION_RESULT_STORE_FIELD, - TIMELINE, - SPREADSHEET_STORE_FIELD, - ONE_BUS, -} from 'utils/store-filter-fields'; -import { StudyIndexationStatus, StudyDisplayMode } from './reducer.type'; - -const paramsInitialState = { - [PARAM_THEME]: getLocalStorageTheme(), - [PARAM_LANGUAGE]: getLocalStorageLanguage(), - [PARAM_USE_NAME]: true, - [PARAM_LINE_FULL_PATH]: true, - [PARAM_LINE_PARALLEL_PATH]: true, - [PARAM_LIMIT_REDUCTION]: 100, - [PARAM_LINE_FLOW_ALERT_THRESHOLD]: 100, - [PARAM_MAP_MANUAL_REFRESH]: false, - [PARAM_MAP_BASEMAP]: MAP_BASEMAP_MAPBOX, - [PARAM_LINE_FLOW_MODE]: 'feeders', - [PARAM_LINE_FLOW_COLOR_MODE]: 'nominalVoltage', - [PARAM_CENTER_LABEL]: false, - [PARAM_DIAGONAL_LABEL]: false, - [PARAM_SUBSTATION_LAYOUT]: 'horizontal', - [PARAM_COMPONENT_LIBRARY]: null, - [PARAM_FAVORITE_CONTINGENCY_LISTS]: [], - [PARAM_FLUX_CONVENTION]: FluxConventions.IIDM, - [PARAM_DEVELOPER_MODE]: false, - [PARAMS_LOADED]: false, -}; - -const initialComputingStatus = { - [ComputingType.LOAD_FLOW]: RunningStatus.IDLE, - [ComputingType.SECURITY_ANALYSIS]: RunningStatus.IDLE, - [ComputingType.SENSITIVITY_ANALYSIS]: RunningStatus.IDLE, - [ComputingType.NON_EVACUATED_ENERGY_ANALYSIS]: RunningStatus.IDLE, - [ComputingType.SHORT_CIRCUIT]: RunningStatus.IDLE, - [ComputingType.SHORT_CIRCUIT_ONE_BUS]: RunningStatus.IDLE, - [ComputingType.DYNAMIC_SIMULATION]: RunningStatus.IDLE, - [ComputingType.VOLTAGE_INITIALIZATION]: RunningStatus.IDLE, - [ComputingType.STATE_ESTIMATION]: RunningStatus.IDLE, -}; - -const initialSpreadsheetNetworkState = { - [EQUIPMENT_TYPES.SUBSTATION]: null, - [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: null, - [EQUIPMENT_TYPES.LINE]: null, - [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER]: null, - [EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER]: null, - [EQUIPMENT_TYPES.GENERATOR]: null, - [EQUIPMENT_TYPES.LOAD]: null, - [EQUIPMENT_TYPES.BATTERY]: null, - [EQUIPMENT_TYPES.DANGLING_LINE]: null, - [EQUIPMENT_TYPES.TIE_LINE]: null, - [EQUIPMENT_TYPES.HVDC_LINE]: null, - [EQUIPMENT_TYPES.LCC_CONVERTER_STATION]: null, - [EQUIPMENT_TYPES.VSC_CONVERTER_STATION]: null, - [EQUIPMENT_TYPES.SHUNT_COMPENSATOR]: null, - [EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR]: null, - [EQUIPMENT_TYPES.BUS]: null, -}; - -const initialSpreadsheetFilter = { - [EQUIPMENT_TYPES.SUBSTATION]: [], - [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: [], - [EQUIPMENT_TYPES.LINE]: [], - [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER]: [], - [EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER]: [], - [EQUIPMENT_TYPES.GENERATOR]: [], - [EQUIPMENT_TYPES.LOAD]: [], - [EQUIPMENT_TYPES.SHUNT_COMPENSATOR]: [], - [EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR]: [], - [EQUIPMENT_TYPES.BATTERY]: [], - [EQUIPMENT_TYPES.HVDC_LINE]: [], - [EQUIPMENT_TYPES.LCC_CONVERTER_STATION]: [], - [EQUIPMENT_TYPES.VSC_CONVERTER_STATION]: [], - [EQUIPMENT_TYPES.DANGLING_LINE]: [], - [EQUIPMENT_TYPES.BUS]: [], - [EQUIPMENT_TYPES.TIE_LINE]: [], -}; - -export const defaultOptionalServicesState = Object.keys( - OptionalServicesNames -).map((key) => ({ - name: key, - status: OptionalServicesStatus.Pending, -})); - -const initialState = { - studyUuid: null, - currentTreeNode: null, - selectionForCopy: { - sourceStudyUuid: null, - nodeId: null, - copyType: null, - allChildrenIds: null, - }, - mapEquipments: null, - geoData: null, - networkModificationTreeModel: new NetworkModificationTreeModel(), - computedLanguage: getLocalStorageComputedLanguage(), - user: null, - signInCallbackError: null, - authenticationRouterError: null, - showAuthenticationRouterLogin: false, - studyUpdated: { force: 0, eventData: {} }, - mapDataLoading: false, - fullScreenDiagram: null, - allDisplayedColumnsNames: TABLES_COLUMNS_NAMES_JSON, - allLockedColumnsNames: [], - allReorderedTableDefinitionIndexes: [], - isExplorerDrawerOpen: true, - isModificationsDrawerOpen: false, - isEventScenarioDrawerOpen: false, - centerOnSubstation: null, - notificationIdList: [], - isModificationsInProgress: false, - studyDisplayMode: StudyDisplayMode.HYBRID, - diagramStates: [], - reloadMap: true, - isMapEquipmentsInitialized: false, - networkAreaDiagramDepth: 0, - networkAreaDiagramNbVoltageLevels: 0, - spreadsheetNetwork: { ...initialSpreadsheetNetworkState }, - computingStatus: { ...initialComputingStatus }, - computationStarting: false, - optionalServices: defaultOptionalServicesState, - oneBusShortCircuitAnalysisDiagram: null, - studyIndexationStatus: StudyIndexationStatus.NOT_INDEXED, - ...paramsInitialState, - limitReductionModified: false, - recentGlobalFilters: [], - lastCompletedComputation: null, - // Results filters - [LOADFLOW_RESULT_STORE_FIELD]: { - [LOADFLOW_CURRENT_LIMIT_VIOLATION]: [], - [LOADFLOW_VOLTAGE_LIMIT_VIOLATION]: [], - [LOADFLOW_RESULT]: [], - }, - [SECURITY_ANALYSIS_RESULT_STORE_FIELD]: { - [SECURITY_ANALYSIS_RESULT_N]: [], - [SECURITY_ANALYSIS_RESULT_N_K]: [], - }, - [SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]: { - [SENSITIVITY_IN_DELTA_MW_N]: [], - [SENSITIVITY_IN_DELTA_MW_N_K]: [], - [SENSITIVITY_IN_DELTA_A_N]: [], - [SENSITIVITY_IN_DELTA_A_N_K]: [], - [SENSITIVITY_AT_NODE_N]: [], - [SENSITIVITY_AT_NODE_N_K]: [], - }, - [SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]: { - [ONE_BUS]: [], - [ALL_BUSES]: [], - }, - [DYNAMIC_SIMULATION_RESULT_STORE_FIELD]: { - [TIMELINE]: [], - }, - - // Spreadsheet filters - [SPREADSHEET_STORE_FIELD]: { ...initialSpreadsheetFilter }, - - // Hack to avoid reload Geo Data when switching display mode to TREE then back to MAP or HYBRID - // defaulted to true to init load geo data with HYBRID defaulted display Mode - // TODO REMOVE LATER -}; - -export const reducer = createReducer(initialState, (builder) => { - builder.addCase(OPEN_STUDY, (state, action) => { - state.studyUuid = action.studyRef[0]; - - if (action.studyRef[0] != null) { - state.diagramStates = loadDiagramStateFromSessionStorage( - action.studyRef[0] - ); - } - }); - - builder.addCase(CLOSE_STUDY, (state) => { - state.studyUuid = null; - state.geoData = null; - state.networkModificationTreeModel = null; - }); - - builder.addCase(MAP_EQUIPMENTS_CREATED, (state, action) => { - let newMapEquipments; - //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(); - } - if (action.newLines) { - newMapEquipments.lines = action.newLines; - newMapEquipments.completeLinesInfos(); - } - if (action.newTieLines) { - newMapEquipments.tieLines = action.newTieLines; - newMapEquipments.completeTieLinesInfos(); - } - if (action.newSubstations) { - newMapEquipments.substations = action.newSubstations; - newMapEquipments.completeSubstationsInfos(); - } - if (action.newHvdcLines) { - newMapEquipments.hvdcLines = action.newHvdcLines; - newMapEquipments.completeHvdcLinesInfos(); - } - state.mapEquipments = newMapEquipments; - }); - - builder.addCase(LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, (state, action) => { - state.networkModificationTreeModel = - action.networkModificationTreeModel; - state.networkModificationTreeModel.setBuildingStatus(); - }); - - builder.addCase(NETWORK_MODIFICATION_TREE_NODE_ADDED, (state, action) => { - if (state.networkModificationTreeModel) { - let newModel = - state.networkModificationTreeModel.newSharedForUpdate(); - newModel.addChild( - action.networkModificationTreeNode, - action.parentNodeId, - action.insertMode, - action.referenceNodeId - ); - newModel.updateLayout(); - state.networkModificationTreeModel = newModel; - // check if added node is the new parent of the current Node - if ( - action.networkModificationTreeNode?.childrenIds.includes( - state.currentTreeNode?.id - ) - ) { - // Then must overwrite currentTreeNode to set new parentNodeUuid - synchCurrentTreeNode(state, state.currentTreeNode?.id); - } - } - }); - - builder.addCase(NETWORK_MODIFICATION_TREE_NODE_MOVED, (state, action) => { - if (state.networkModificationTreeModel) { - let newModel = - state.networkModificationTreeModel.newSharedForUpdate(); - newModel.removeNodes([action.networkModificationTreeNode.id]); - newModel.addChild( - action.networkModificationTreeNode, - action.parentNodeId, - action.insertMode, - action.referenceNodeId - ); - newModel.updateLayout(); - state.networkModificationTreeModel = newModel; - // check if added node is the new parent of the current Node - if ( - action.networkModificationTreeNode?.childrenIds.includes( - state.currentTreeNode?.id - ) - ) { - // Then must overwrite currentTreeNode to set new parentNodeUuid - synchCurrentTreeNode(state, state.currentTreeNode?.id); - } - } - }); - - builder.addCase(NETWORK_MODIFICATION_HANDLE_SUBTREE, (state, action) => { - if (state.networkModificationTreeModel) { - let newModel = - state.networkModificationTreeModel.newSharedForUpdate(); - unravelSubTree( - newModel, - action.parentNodeId, - action.networkModificationTreeNodes - ); - - newModel.updateLayout(); - state.networkModificationTreeModel = newModel; - } - }); - - builder.addCase( - NETWORK_MODIFICATION_TREE_NODES_REMOVED, - (state, action) => { - if (state.networkModificationTreeModel) { - let newModel = - state.networkModificationTreeModel.newSharedForUpdate(); - - //we assume all the deleted nodes are contiguous, so the new parent selected will be the nearest upstream node. - //in the future, if the deleted nodes are no longer contiguous we will need another implementation - const nextCurrentNodeUuid = newModel.treeNodes - .filter((node) => - action.networkModificationTreeNodes.includes(node.id) - ) - .map((node) => node.data.parentNodeUuid) - .find( - (parentNodeUuid) => - !action.networkModificationTreeNodes.includes( - parentNodeUuid - ) - ); - - newModel.removeNodes(action.networkModificationTreeNodes); - newModel.updateLayout(); - state.networkModificationTreeModel = newModel; - - // check if current node is in the nodes deleted list - if ( - action.networkModificationTreeNodes.includes( - state.currentTreeNode?.id - ) - ) { - synchCurrentTreeNode(state, nextCurrentNodeUuid); - } // check if parent node of the current node is in the nodes deleted list - else if ( - action.networkModificationTreeNodes.includes( - state.currentTreeNode?.data?.parentNodeUuid - ) - ) { - // Then must overwrite currentTreeNode to get new parentNodeUuid - synchCurrentTreeNode(state, state.currentTreeNode?.id); - } - } - } - ); - - builder.addCase( - NETWORK_MODIFICATION_TREE_NODES_UPDATED, - (state, action) => { - if (state.networkModificationTreeModel) { - let newModel = - state.networkModificationTreeModel.newSharedForUpdate(); - newModel.updateNodes(action.networkModificationTreeNodes); - state.networkModificationTreeModel = newModel; - state.networkModificationTreeModel.setBuildingStatus(); - // check if current node is in the nodes updated list - if ( - action.networkModificationTreeNodes.find( - (node) => node.id === state.currentTreeNode?.id - ) - ) { - synchCurrentTreeNode(state, state.currentTreeNode?.id); - // current node has changed, then will need to reload Geo Data - state.reloadMap = true; - } - } - } - ); - - builder.addCase(STUDY_UPDATED, (state, action) => { - state.studyUpdated = { - force: 1 - state.studyUpdated.force, - type: action.eventData.headers.updateType, - eventData: action.eventData, - }; - }); - - builder.addCase(MAP_DATA_LOADING, (state, action) => { - state.mapDataLoading = action.mapDataLoading; - }); - - builder.addCase(SELECT_THEME, (state, action) => { - state[PARAM_THEME] = action[PARAM_THEME]; - saveLocalStorageTheme(state[PARAM_THEME]); - }); - - builder.addCase(SELECT_LANGUAGE, (state, action) => { - state[PARAM_LANGUAGE] = action[PARAM_LANGUAGE]; - saveLocalStorageLanguage(state[PARAM_LANGUAGE]); - }); - - builder.addCase(SELECT_COMPUTED_LANGUAGE, (state, action) => { - state.computedLanguage = action.computedLanguage; - }); - - builder.addCase(SET_PARAMS_LOADED, (state, action) => { - state[PARAMS_LOADED] = action[PARAMS_LOADED]; - }); - - builder.addCase(USE_NAME, (state, action) => { - state[PARAM_USE_NAME] = action[PARAM_USE_NAME]; - }); - - builder.addCase(USER, (state, action) => { - state.user = action.user; - }); - - builder.addCase(CENTER_LABEL, (state, action) => { - state[PARAM_CENTER_LABEL] = action[PARAM_CENTER_LABEL]; - }); - - builder.addCase(DIAGONAL_LABEL, (state, action) => { - state[PARAM_DIAGONAL_LABEL] = action[PARAM_DIAGONAL_LABEL]; - }); - - builder.addCase(LINE_FULL_PATH, (state, action) => { - state[PARAM_LINE_FULL_PATH] = action[PARAM_LINE_FULL_PATH]; - }); - - builder.addCase(LINE_PARALLEL_PATH, (state, action) => { - state[PARAM_LINE_PARALLEL_PATH] = action[PARAM_LINE_PARALLEL_PATH]; - }); - - builder.addCase(LINE_FLOW_MODE, (state, action) => { - state[PARAM_LINE_FLOW_MODE] = action[PARAM_LINE_FLOW_MODE]; - }); - - builder.addCase(FLUX_CONVENTION, (state, action) => { - state[PARAM_FLUX_CONVENTION] = action[PARAM_FLUX_CONVENTION]; - }); - - builder.addCase(ENABLE_DEVELOPER_MODE, (state, action) => { - state[PARAM_DEVELOPER_MODE] = action[PARAM_DEVELOPER_MODE]; - }); - - builder.addCase(LINE_FLOW_COLOR_MODE, (state, action) => { - state[PARAM_LINE_FLOW_COLOR_MODE] = action[PARAM_LINE_FLOW_COLOR_MODE]; - }); - - builder.addCase(LIMIT_REDUCTION, (state, action) => { - state[PARAM_LIMIT_REDUCTION] = action[PARAM_LIMIT_REDUCTION]; - }); - - builder.addCase(LIMIT_REDUCTION_MODIFIED, (state, action) => { - state.limitReductionModified = action.limitReductionModified; - }); - - builder.addCase(LINE_FLOW_ALERT_THRESHOLD, (state, action) => { - state[PARAM_LINE_FLOW_ALERT_THRESHOLD] = - action[PARAM_LINE_FLOW_ALERT_THRESHOLD]; - }); - - builder.addCase(UNAUTHORIZED_USER_INFO, (state, action) => { - state.authenticationRouterError = action.authenticationRouterError; - }); - - builder.addCase(LOGOUT_ERROR, (state, action) => { - state.authenticationRouterError = action.authenticationRouterError; - }); - - builder.addCase(USER_VALIDATION_ERROR, (state, action) => { - state.authenticationRouterError = action.authenticationRouterError; - }); - - builder.addCase(RESET_AUTHENTICATION_ROUTER_ERROR, (state, action) => { - state.authenticationRouterError = null; - }); - - builder.addCase(SHOW_AUTH_INFO_LOGIN, (state, action) => { - state.showAuthenticationRouterLogin = - action.showAuthenticationRouterLogin; - }); - - builder.addCase(MAP_MANUAL_REFRESH, (state, action) => { - state[PARAM_MAP_MANUAL_REFRESH] = action[PARAM_MAP_MANUAL_REFRESH]; - }); - - builder.addCase(MAP_BASEMAP, (state, action) => { - state[PARAM_MAP_BASEMAP] = action[PARAM_MAP_BASEMAP]; - }); - - builder.addCase(RESET_MAP_RELOADED, (state) => { - state.reloadMap = false; - }); - - builder.addCase(MAP_EQUIPMENTS_INITIALIZED, (state, action) => { - state.isMapEquipmentsInitialized = action.newValue; - }); - - builder.addCase(SUBSTATION_LAYOUT, (state, action) => { - state[PARAM_SUBSTATION_LAYOUT] = action[PARAM_SUBSTATION_LAYOUT]; - }); - - builder.addCase(COMPONENT_LIBRARY, (state, action) => { - state[PARAM_COMPONENT_LIBRARY] = action[PARAM_COMPONENT_LIBRARY]; - }); - - builder.addCase(SET_FULLSCREEN_DIAGRAM, (state, action) => { - state.fullScreenDiagram = { - id: action.diagramId, - svgType: action.svgType, - }; - }); - - builder.addCase(CHANGE_DISPLAYED_COLUMNS_NAMES, (state, action) => { - const newDisplayedColumnsNames = [...state.allDisplayedColumnsNames]; - action.displayedColumnsNamesParams.forEach((param) => { - if (param) { - newDisplayedColumnsNames[param.index] = param.value; - } - }); - state.allDisplayedColumnsNames = newDisplayedColumnsNames; - }); - - builder.addCase(CHANGE_LOCKED_COLUMNS_NAMES, (state, action) => { - let newLockedColumnsNames = [...state.allLockedColumnsNames]; - action.lockedColumnsNamesParams.forEach((param) => { - if (param) { - newLockedColumnsNames[param.index] = param.value; - } - }); - state.allLockedColumnsNames = newLockedColumnsNames; - }); - - builder.addCase(CHANGE_REORDERED_COLUMNS, (state, action) => { - let newReorderedColumns = [...state.allReorderedTableDefinitionIndexes]; - action.reorderedColumnsParams.forEach((param) => { - if (param) { - newReorderedColumns[param.index] = param.value; - } - }); - state.allReorderedTableDefinitionIndexes = newReorderedColumns; - }); - - builder.addCase(FAVORITE_CONTINGENCY_LISTS, (state, action) => { - state[PARAM_FAVORITE_CONTINGENCY_LISTS] = - action[PARAM_FAVORITE_CONTINGENCY_LISTS]; - }); - - builder.addCase(CURRENT_TREE_NODE, (state, action) => { - state.currentTreeNode = action.currentTreeNode; - state.reloadMap = true; - }); - - builder.addCase(SELECTION_FOR_COPY, (state, action) => { - const selectionForCopy = action.selectionForCopy; - if ( - selectionForCopy.sourceStudyUuid === state.studyUuid && - selectionForCopy.nodeId && - (selectionForCopy.copyType === CopyType.SUBTREE_COPY || - selectionForCopy.copyType === CopyType.SUBTREE_CUT) - ) { - selectionForCopy.allChildrenIds = getAllChildren( - state.networkModificationTreeModel, - selectionForCopy.nodeId - ).map((child) => child.id); - } - state.selectionForCopy = selectionForCopy; - }); - - builder.addCase(SET_MODIFICATIONS_DRAWER_OPEN, (state, action) => { - state.isModificationsDrawerOpen = action.isModificationsDrawerOpen; - - // exclusively open between two components - if ( - action.isModificationsDrawerOpen && - state.isEventScenarioDrawerOpen - ) { - state.isEventScenarioDrawerOpen = !state.isEventScenarioDrawerOpen; - } - }); - - builder.addCase(SET_EVENT_SCENARIO_DRAWER_OPEN, (state, action) => { - state.isEventScenarioDrawerOpen = action.isEventScenarioDrawerOpen; - - // exclusively open between two components - if ( - action.isEventScenarioDrawerOpen && - state.isModificationsDrawerOpen - ) { - state.isModificationsDrawerOpen = !state.isModificationsDrawerOpen; - } - }); - - builder.addCase(CENTER_ON_SUBSTATION, (state, action) => { - state.centerOnSubstation = action.centerOnSubstation; - }); - - builder.addCase(ADD_NOTIFICATION, (state, action) => { - state.notificationIdList = [ - ...state.notificationIdList, - ...action.notificationIds, - ]; - }); - - builder.addCase(REMOVE_NOTIFICATION_BY_NODE, (state, action) => { - state.notificationIdList = [ - ...state.notificationIdList.filter( - (nodeId) => !action.notificationIds.includes(nodeId) - ), - ]; - }); - - builder.addCase(SET_MODIFICATIONS_IN_PROGRESS, (state, action) => { - state.isModificationsInProgress = action.isModificationsInProgress; - }); - - builder.addCase(SET_STUDY_DISPLAY_MODE, (state, action) => { - if (Object.values(StudyDisplayMode).includes(action.studyDisplayMode)) { - // Hack to avoid reload Geo Data when switching display mode to TREE then back to MAP or HYBRID - // Some actions in the TREE display mode could change this value after that - // ex: change current Node, current Node updated ... - if (action.studyDisplayMode === StudyDisplayMode.TREE) { - state.reloadMap = false; - } - - state.studyDisplayMode = action.studyDisplayMode; - } - }); - - /* - * The following functions' goal are to update state.diagramStates with nodes of the following type : - * { id: 'diagramID', svgType: 'SvgType of the diagram', state: 'ViewState of the diagram' } - * - * Depending on the diagram's svgType, the state.diagramStates is different. - * For Network Area Diagrams (SvgType.NETWORK_AREA_DIAGRAM), all the states should be the same. - * As an example, if one is PINNED, then all of them should be. - * For Single Line Diagrams (SvgType.VOLTAGE_LEVEL or SvgType.SUBSTATION), each diagram has its own state. - */ - builder.addCase(OPEN_DIAGRAM, (state, action) => { - const diagramStates = state.diagramStates; - const diagramToOpenIndex = diagramStates.findIndex( - (diagram) => - diagram.id === action.id && diagram.svgType === action.svgType - ); - - if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - // First, we check if there is already a Network Area Diagram in the diagramStates. - const firstNadIndex = diagramStates.findIndex( - (diagram) => - diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM - ); - if (firstNadIndex < 0) { - // If there is no NAD, then we add the new one. - diagramStates.push({ - id: action.id, - svgType: DiagramType.NETWORK_AREA_DIAGRAM, - state: ViewState.OPENED, - }); - - // If there is already a diagram in fullscreen mode, the new opened NAD will take its place. - if (state.fullScreenDiagram?.id) { - state.fullScreenDiagram = { - id: action.id, - svgType: DiagramType.NETWORK_AREA_DIAGRAM, - }; - } - } else { - // If there is already at least one NAD, and if it is minimized, then we change all of them to opened. - if ( - diagramStates[firstNadIndex].state === ViewState.MINIMIZED - ) { - diagramStates.forEach((diagram) => { - if ( - diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM - ) { - diagram.state = ViewState.OPENED; - } - }); - } - // If the NAD to open is not already in the diagramStates, we add it. - if (diagramToOpenIndex < 0) { - diagramStates.push({ - id: action.id, - svgType: DiagramType.NETWORK_AREA_DIAGRAM, - state: diagramStates[firstNadIndex].state, - }); - } - - // If there is a SLD in fullscreen, we have to display in fullscreen the new NAD. - // Because it is the first NAD displayed that counts for the fullscreen status, we put the fist nad's id there. - if ( - state.fullScreenDiagram?.svgType && - state.fullScreenDiagram?.svgType !== - DiagramType.NETWORK_AREA_DIAGRAM - ) { - state.fullScreenDiagram = { - id: diagramStates[firstNadIndex].id, - svgType: DiagramType.NETWORK_AREA_DIAGRAM, - }; - } - } - } else { - // We check if the SLD to open is already in the diagramStates. - if (diagramToOpenIndex >= 0) { - // If the SLD to open is already in the diagramStates and it is minimized, then we change it to opened. - if ( - diagramStates[diagramToOpenIndex].state === - ViewState.MINIMIZED - ) { - // We minimize all the other OPENED SLD. - diagramStates.forEach((diagram) => { - if ( - diagram.svgType !== - DiagramType.NETWORK_AREA_DIAGRAM && - diagram.state === ViewState.OPENED - ) { - diagram.state = ViewState.MINIMIZED; - } - }); - const diagramToOpen = diagramStates[diagramToOpenIndex]; - - // We open and push the SLD to the last position in the array, so it is displayed at the right of the others - diagramToOpen.state = ViewState.OPENED; - diagramStates.splice(diagramToOpenIndex, 1); - diagramStates.push(diagramToOpen); - } else { - console.info( - 'Diagram already opened : ' + - diagramStates[diagramToOpenIndex].id + - ' (' + - diagramStates[diagramToOpenIndex].svgType + - ')' - ); - diagramStates[diagramToOpenIndex].needsToBlink = true; - } - } else { - // We minimize all the other OPENED SLD. - diagramStates.forEach((diagram) => { - if ( - diagram.svgType !== DiagramType.NETWORK_AREA_DIAGRAM && - diagram.state === ViewState.OPENED - ) { - diagram.state = ViewState.MINIMIZED; - } - }); - // And we add the new one. - diagramStates.push({ - id: action.id, - svgType: action.svgType, - state: ViewState.OPENED, - }); - } - - // If there is already a diagram in fullscreen mode, the new opened SLD will take its place. - if (state.fullScreenDiagram?.id) { - state.fullScreenDiagram = { - id: action.id, - svgType: action.svgType, - }; - } - } - state.diagramStates = diagramStates; - }); - - builder.addCase(MINIMIZE_DIAGRAM, (state, action) => { - const diagramStates = state.diagramStates; - - if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - // For network area diagrams, the ID is irrelevant, we will minimize all the NAD in the state.diagramStates. - diagramStates.forEach((diagram) => { - if (diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - diagram.state = ViewState.MINIMIZED; - } - }); - } else { - // For single line diagram, we will update the corresponding diagram. - const diagramToMinimizeIndex = diagramStates.findIndex( - (diagram) => - diagram.id === action.id && - diagram.svgType === action.svgType - ); - if (diagramToMinimizeIndex >= 0) { - diagramStates[diagramToMinimizeIndex].state = - ViewState.MINIMIZED; - } - } - state.diagramStates = diagramStates; - }); - - builder.addCase(TOGGLE_PIN_DIAGRAM, (state, action) => { - const diagramStates = state.diagramStates; - - // search targeted diagram among the diagramStates - const diagramToPinToggleIndex = diagramStates.findIndex( - (diagram) => - diagram.id === action.id && diagram.svgType === action.svgType - ); - if (diagramToPinToggleIndex >= 0) { - if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - // If the current NAD is PINNED, we set all NAD to OPENED. Otherwise, we set them to PINNED. - const newStateForNads = - diagramStates[diagramToPinToggleIndex].state === - ViewState.PINNED - ? ViewState.OPENED - : ViewState.PINNED; - diagramStates.forEach((diagram) => { - if (diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - diagram.state = newStateForNads; - } - }); - } else { - if ( - diagramStates[diagramToPinToggleIndex].state !== - ViewState.PINNED - ) { - // If the current SLD is minimized or opened, we pin it. - diagramStates[diagramToPinToggleIndex].state = - ViewState.PINNED; - } else { - // If the current SLD is pinned, we check if there is already another SLD opened (there can only be one - // SLD opened -not pinned- at a time). If there is, then we minimize the current SLD. If none, we open it. - const currentlyOpenedDiagramIndex = diagramStates.findIndex( - (diagram) => - diagram.state === ViewState.OPENED && - (diagram.svgType === DiagramType.SUBSTATION || - diagram.svgType === DiagramType.VOLTAGE_LEVEL) - ); - if (currentlyOpenedDiagramIndex >= 0) { - diagramStates[diagramToPinToggleIndex].state = - ViewState.MINIMIZED; - } else { - diagramStates[diagramToPinToggleIndex].state = - ViewState.OPENED; - } - } - } - } - - state.diagramStates = diagramStates; - }); - - builder.addCase(CLOSE_DIAGRAM, (state, action) => { - let diagramStates = state.diagramStates; - - if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { - // If we close a NAD, we close all of them. - diagramStates = diagramStates.filter( - (diagram) => - diagram.svgType !== DiagramType.NETWORK_AREA_DIAGRAM - ); - } else { - // If we close a SLD, we only remove one. - const diagramToCloseIndex = diagramStates.findIndex( - (diagram) => - diagram.id === action.id && - diagram.svgType === action.svgType - ); - if (diagramToCloseIndex >= 0) { - diagramStates.splice(diagramToCloseIndex, 1); - } - } - - state.diagramStates = diagramStates; - }); - - builder.addCase(CLOSE_DIAGRAMS, (state, action) => { - const idsToClose = new Set(action.ids); - state.diagramStates = state.diagramStates.filter( - (diagram) => !idsToClose.has(diagram.id) - ); - }); - - builder.addCase(STOP_DIAGRAM_BLINK, (state) => { - state.diagramStates.forEach((diagram) => { - if (diagram.needsToBlink) { - diagram.needsToBlink = undefined; - } - }); - }); - - builder.addCase(RESET_NETWORK_AREA_DIAGRAM_DEPTH, (state) => { - state.networkAreaDiagramDepth = 0; - }); - - builder.addCase(INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, (state) => { - state.networkAreaDiagramDepth = state.networkAreaDiagramDepth + 1; - }); - - builder.addCase(DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, (state) => { - if (state.networkAreaDiagramDepth > 0) { - state.networkAreaDiagramDepth = state.networkAreaDiagramDepth - 1; - } - }); - - builder.addCase(NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, (state, action) => { - state.networkAreaDiagramNbVoltageLevels = action.nbVoltageLevels; - }); - - builder.addCase(LOAD_EQUIPMENTS, (state, action) => { - state.spreadsheetNetwork[action.equipmentType] = action.equipments; - }); - - builder.addCase(UPDATE_EQUIPMENTS, (state, action) => { - // for now, this action receives an object containing all equipments from a substation - // it will be modified when the notifications received after a network modification will be more precise - const updatedEquipments = action.equipments; - - // equipmentType : type of equipment updated - // equipments : list of updated equipments of type - for (const [updateType, equipments] of Object.entries( - updatedEquipments - )) { - const equipmentType = getEquipmentTypeFromUpdateType(updateType); - const currentEquipment = state.spreadsheetNetwork[equipmentType]; - - // Format the updated equipments to match the table format - const formattedEquipments = formatFetchedEquipments( - equipmentType, - equipments - ); - - // if the equipments are not loaded into the store yet, we don't have to update them - if (currentEquipment != null) { - //since substations data contains voltage level ones, they have to be treated separatly - if (equipmentType === EQUIPMENT_TYPES.SUBSTATION) { - const [updatedSubtations, updatedVoltageLevels] = - updateSubstationsAndVoltageLevels( - state.spreadsheetNetwork[ - EQUIPMENT_TYPES.SUBSTATION - ], - state.spreadsheetNetwork[ - EQUIPMENT_TYPES.VOLTAGE_LEVEL - ], - formattedEquipments - ); - - state.spreadsheetNetwork[EQUIPMENT_TYPES.SUBSTATION] = - updatedSubtations; - state.spreadsheetNetwork[EQUIPMENT_TYPES.VOLTAGE_LEVEL] = - updatedVoltageLevels; - } else { - state.spreadsheetNetwork[equipmentType] = updateEquipments( - currentEquipment, - formattedEquipments - ); - } - } - } - }); - - builder.addCase(DELETE_EQUIPMENTS, (state, action) => { - action.equipments.forEach( - ({ - equipmentType: equipmentToDeleteType, - equipmentId: equipmentToDeleteId, - }) => { - const currentEquipments = - state.spreadsheetNetwork[equipmentToDeleteType]; - if (currentEquipments != null) { - // in case of voltage level deletion, we need to update the linked substation which contains a list of its voltage levels - if ( - equipmentToDeleteType === EQUIPMENT_TYPES.VOLTAGE_LEVEL - ) { - const currentSubstations = - state.spreadsheetNetwork[ - EQUIPMENT_TYPES.SUBSTATION - ]; - if (currentSubstations != null) { - state.spreadsheetNetwork[ - EQUIPMENT_TYPES.SUBSTATION - ] = updateSubstationAfterVLDeletion( - currentSubstations, - equipmentToDeleteId - ); - } - } - - state.spreadsheetNetwork[equipmentToDeleteType] = - deleteEquipment(currentEquipments, equipmentToDeleteId); - } - } - ); - }); - - builder.addCase(RESET_EQUIPMENTS, (state) => { - state.spreadsheetNetwork = { ...initialSpreadsheetNetworkState }; - }); - builder.addCase(RESET_EQUIPMENTS_BY_TYPES, (state, action) => { - action.equipmentTypes.forEach((equipmentType) => { - state.spreadsheetNetwork[equipmentType] = null; - }); - }); - - builder.addCase(RESET_EQUIPMENTS_POST_LOADFLOW, (state) => { - state.spreadsheetNetwork = { - ...initialSpreadsheetNetworkState, - [EQUIPMENT_TYPES.SUBSTATION]: - state.spreadsheetNetwork[EQUIPMENT_TYPES.SUBSTATION], - [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: - state.spreadsheetNetwork[EQUIPMENT_TYPES.VOLTAGE_LEVEL], - [EQUIPMENT_TYPES.HVDC_LINE]: - state.spreadsheetNetwork[EQUIPMENT_TYPES.HVDC_LINE], - }; - }); - - builder.addCase(SET_COMPUTING_STATUS, (state, action) => { - state.computingStatus[action.computingType] = action.runningStatus; - }); - - builder.addCase(SET_COMPUTATION_STARTING, (state, action) => { - state.computationStarting = action.computationStarting; - }); - - builder.addCase(SET_OPTIONAL_SERVICES, (state, action) => { - state.optionalServices = action.optionalServices; - }); - - builder.addCase( - SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, - (state, action) => { - state.oneBusShortCircuitAnalysisDiagram = { - diagramId: action.diagramId, - nodeId: action.nodeId, - }; - } - ); - - builder.addCase(SET_STUDY_INDEXATION_STATUS, (state, action) => { - state.studyIndexationStatus = action.studyIndexationStatus; - }); - - builder.addCase(ADD_TO_RECENT_GLOBAL_FILTERS, (state, action) => { - let newRecentGlobalFilters = [...state.recentGlobalFilters]; - action.globalFilters.forEach((filter) => { - if ( - !newRecentGlobalFilters.some( - (obj) => - obj.label === filter.label && - obj.filterType === filter.filterType - ) - ) { - newRecentGlobalFilters.push(filter); - } - }); - state.recentGlobalFilters = newRecentGlobalFilters; - }); - - builder.addCase(SET_LAST_COMPLETED_COMPUTATION, (state, action) => { - state.lastCompletedComputation = action.lastCompletedComputation; - }); - - builder.addCase(LOADFLOW_RESULT_FILTER, (state, action) => { - state[LOADFLOW_RESULT_STORE_FIELD][action.filterTab] = - action[LOADFLOW_RESULT_STORE_FIELD]; - }); - - builder.addCase(SECURITY_ANALYSIS_RESULT_FILTER, (state, action) => { - state[SECURITY_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = - action[SECURITY_ANALYSIS_RESULT_STORE_FIELD]; - }); - - builder.addCase(SENSITIVITY_ANALYSIS_RESULT_FILTER, (state, action) => { - state[SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = - action[SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]; - }); - - builder.addCase(SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, (state, action) => { - state[SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = - action[SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]; - }); - - builder.addCase(DYNAMIC_SIMULATION_RESULT_FILTER, (state, action) => { - state[DYNAMIC_SIMULATION_RESULT_STORE_FIELD][action.filterTab] = - action[DYNAMIC_SIMULATION_RESULT_STORE_FIELD]; - }); - - builder.addCase(SPREADSHEET_FILTER, (state, action) => { - state[SPREADSHEET_STORE_FIELD][action.filterTab] = - action[SPREADSHEET_STORE_FIELD]; - }); -}); - -function updateSubstationAfterVLDeletion(currentSubstations, VLToDeleteId) { - const substationToUpdateIndex = currentSubstations.findIndex((sub) => - sub.voltageLevels.some((vl) => vl.id === VLToDeleteId) - ); - if (substationToUpdateIndex >= 0) { - currentSubstations[substationToUpdateIndex].voltageLevels = - currentSubstations[substationToUpdateIndex].voltageLevels.filter( - (vl) => vl.id !== VLToDeleteId - ); - } - - return currentSubstations; -} - -function getEquipmentTypeFromUpdateType(updateType) { - switch (updateType) { - case 'lines': - return EQUIPMENT_TYPES.LINE; - case 'tieLines': - return EQUIPMENT_TYPES.TIE_LINE; - case 'twoWindingsTransformers': - return EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER; - case 'threeWindingsTransformers': - return EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER; - case 'generators': - return EQUIPMENT_TYPES.GENERATOR; - case 'loads': - return EQUIPMENT_TYPES.LOAD; - case 'batteries': - return EQUIPMENT_TYPES.BATTERY; - case 'danglingLines': - return EQUIPMENT_TYPES.DANGLING_LINE; - case 'hvdcLines': - return EQUIPMENT_TYPES.HVDC_LINE; - case 'lccConverterStations': - return EQUIPMENT_TYPES.LCC_CONVERTER_STATION; - case 'vscConverterStations': - return EQUIPMENT_TYPES.VSC_CONVERTER_STATION; - case 'shuntCompensators': - return EQUIPMENT_TYPES.SHUNT_COMPENSATOR; - case 'staticVarCompensators': - return EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR; - case 'voltageLevels': - return EQUIPMENT_TYPES.VOLTAGE_LEVEL; - case 'substations': - return EQUIPMENT_TYPES.SUBSTATION; - case 'buses': - return EQUIPMENT_TYPES.BUS; - default: - return; - } -} - -function deleteEquipment(currentEquipments, equipmentToDeleteId) { - const equipmentToDeleteIndex = currentEquipments.findIndex( - (eq) => eq.id === equipmentToDeleteId - ); - if (equipmentToDeleteIndex >= 0) { - currentEquipments.splice(equipmentToDeleteIndex, 1); - } - return currentEquipments; -} - -function updateSubstationsAndVoltageLevels( - currentSubstations, - currentVoltageLevels, - newOrUpdatedSubstations -) { - const updatedSubstations = updateEquipments( - currentSubstations, - newOrUpdatedSubstations - ); - - let updatedVoltageLevels = null; - - // if voltage levels are not loaded yet, we don't need to update them - if (currentVoltageLevels != null) { - const newOrUpdatedVoltageLevels = newOrUpdatedSubstations.reduce( - (acc, currentSub) => { - return acc.concat([...currentSub.voltageLevels]); - }, - [] - ); - - updatedVoltageLevels = updateEquipments( - currentVoltageLevels, - newOrUpdatedVoltageLevels - ); - } - - return [updatedSubstations, updatedVoltageLevels]; -} - -function updateEquipments(currentEquipments, newOrUpdatedEquipments) { - newOrUpdatedEquipments.forEach((equipment) => { - const existingEquipmentIndex = currentEquipments.findIndex( - (equip) => equip.id === equipment.id - ); - - if (existingEquipmentIndex >= 0) { - currentEquipments[existingEquipmentIndex] = equipment; - } else { - currentEquipments.push(equipment); - } - }); - - return currentEquipments; -} - -function synchCurrentTreeNode(state, nextCurrentNodeUuid) { - const nextCurrentNode = state.networkModificationTreeModel?.treeNodes.find( - (node) => node?.id === nextCurrentNodeUuid - ); - // we need to overwrite state.currentTreeNode to consider label change for example. - state.currentTreeNode = { ...nextCurrentNode }; -} - -function unravelSubTree(treeModel, subtreeParentId, node) { - if (node) { - if (treeModel.treeNodes.find((el) => el.id === node.id)) { - treeModel.removeNodes([node.id]); - } - treeModel.addChild(node, subtreeParentId, NodeInsertModes.After); - - if (node.children.length > 0) { - node.children.forEach((child) => { - unravelSubTree(treeModel, node.id, child); - }); - } - } -} diff --git a/src/redux/reducer.test.js b/src/redux/reducer.test.ts similarity index 80% rename from src/redux/reducer.test.js rename to src/redux/reducer.test.ts index 0bbf5422ce..c4a9224221 100644 --- a/src/redux/reducer.test.js +++ b/src/redux/reducer.test.ts @@ -7,9 +7,7 @@ // Because of a circular import issue, we have to import the store to run the // unit tests, even if your IDE is showing that the import is unused. -// eslint-disable-next-line -import { store } from './store'; -import { reducer } from './reducer'; +import { Actions, AppState, reducer as appReducer } from './reducer'; import { resetNetworkAreaDiagramDepth, incrementNetworkAreaDiagramDepth, @@ -23,6 +21,9 @@ import { stopDiagramBlink, } from './actions'; import { DiagramType, ViewState } from '../components/diagrams/diagram-common'; +import { Reducer } from 'redux'; + +const reducer = appReducer as Reducer, Actions>; test('reducer.RESET_NETWORK_AREA_DIAGRAM_DEPTH', () => { const initialState = { networkAreaDiagramDepth: 12 }; @@ -64,32 +65,38 @@ test('reducer.SET_FULLSCREEN_DIAGRAM', () => { // From initial values const initialState = { fullScreenDiagram: null }; const expectedState = { - fullScreenDiagram: { id: 3, svgType: DiagramType.VOLTAGE_LEVEL }, + fullScreenDiagram: { id: '3', svgType: DiagramType.VOLTAGE_LEVEL }, }; expect( reducer( initialState, - setFullScreenDiagram(3, DiagramType.VOLTAGE_LEVEL) + setFullScreenDiagram('3', DiagramType.VOLTAGE_LEVEL) ) ).toEqual(expectedState); // Changing the fullscreen diagram const initialState2 = { - fullScreenDiagram: { id: 6, svgType: DiagramType.NETWORK_AREA_DIAGRAM }, + fullScreenDiagram: { + id: '6', + svgType: DiagramType.NETWORK_AREA_DIAGRAM, + }, }; const expectedState2 = { - fullScreenDiagram: { id: 12, svgType: DiagramType.SUBSTATION }, + fullScreenDiagram: { id: '12', svgType: DiagramType.SUBSTATION }, }; expect( - reducer(initialState2, setFullScreenDiagram(12, DiagramType.SUBSTATION)) + reducer( + initialState2, + setFullScreenDiagram('12', DiagramType.SUBSTATION) + ) ).toEqual(expectedState2); // Removing the fullscreen const initialState3 = { fullScreenDiagram: { - id: 18, + id: '18', svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; @@ -106,7 +113,7 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState = { diagramStates: [ { - id: 65, + id: '65', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -114,14 +121,14 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState, openDiagram(65, DiagramType.SUBSTATION)) + reducer(initialState, openDiagram('65', DiagramType.SUBSTATION)) ).toEqual(expectedState); // Open a SLD that is already opened const initialState2 = { diagramStates: [ { - id: 174, + id: '174', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, @@ -130,7 +137,7 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState2 = { diagramStates: [ { - id: 174, + id: '174', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, needsToBlink: true, @@ -139,19 +146,19 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState2, openDiagram(174, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState2, openDiagram('174', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState2); // Open a SLD that is already minimized const initialState3 = { diagramStates: [ { - id: 34, + id: '34', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 35, + id: '35', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, @@ -160,12 +167,12 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState3 = { diagramStates: [ { - id: 35, + id: '35', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 34, + id: '34', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -173,14 +180,14 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState3, openDiagram(34, DiagramType.SUBSTATION)) + reducer(initialState3, openDiagram('34', DiagramType.SUBSTATION)) ).toEqual(expectedState3); // Open a SLD that is already pinned const initialState4 = { diagramStates: [ { - id: 99, + id: '99', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -189,7 +196,7 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState4 = { diagramStates: [ { - id: 99, + id: '99', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, needsToBlink: true, @@ -198,14 +205,14 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState4, openDiagram(99, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState4, openDiagram('99', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState4); // Open a SLD when a NAD with the same ID is already opened const initialState5 = { diagramStates: [ { - id: 50, + id: '50', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -214,12 +221,12 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState5 = { diagramStates: [ { - id: 50, + id: '50', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 50, + id: '50', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -227,39 +234,39 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState5, openDiagram(50, DiagramType.SUBSTATION)) + reducer(initialState5, openDiagram('50', DiagramType.SUBSTATION)) ).toEqual(expectedState5); // Open a SLD when there are other opened and pinned SLD const initialState6 = { diagramStates: [ { - id: 101, + id: '101', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 102, + id: '102', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 103, + id: '103', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 104, + id: '104', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, // Should be minimized { - id: 105, + id: '105', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 106, + id: '106', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -268,37 +275,37 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { const expectedState6 = { diagramStates: [ { - id: 101, + id: '101', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 102, + id: '102', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 103, + id: '103', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 104, + id: '104', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 105, + id: '105', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 106, + id: '106', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 107, + id: '107', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, // The new SLD is the only opened SLD @@ -306,48 +313,48 @@ test('reducer.OPEN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState6, openDiagram(107, DiagramType.SUBSTATION)) + reducer(initialState6, openDiagram('107', DiagramType.SUBSTATION)) ).toEqual(expectedState6); // Open a SLD in fullscreen instead of another diagram const initialState7 = { diagramStates: [ { - id: 82, + id: '82', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 83, + id: '83', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, ], - fullScreenDiagram: { id: 82, svgType: DiagramType.SUBSTATION }, + fullScreenDiagram: { id: '82', svgType: DiagramType.SUBSTATION }, }; const expectedState7 = { diagramStates: [ { - id: 82, + id: '82', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 83, + id: '83', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 503, + id: '503', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, ], - fullScreenDiagram: { id: 503, svgType: DiagramType.VOLTAGE_LEVEL }, + fullScreenDiagram: { id: '503', svgType: DiagramType.VOLTAGE_LEVEL }, }; expect( - reducer(initialState7, openDiagram(503, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState7, openDiagram('503', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState7); }); @@ -357,7 +364,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const expectedState = { diagramStates: [ { - id: 37, + id: '37', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -365,14 +372,17 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { }; expect( - reducer(initialState, openDiagram(37, DiagramType.NETWORK_AREA_DIAGRAM)) + reducer( + initialState, + openDiagram('37', DiagramType.NETWORK_AREA_DIAGRAM) + ) ).toEqual(expectedState); // Open a NAD that is already opened const initialState2 = { diagramStates: [ { - id: 18, + id: '18', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -381,7 +391,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const expectedState2 = { diagramStates: [ { - id: 18, + id: '18', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -391,7 +401,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState2, - openDiagram(18, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('18', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState2); @@ -399,7 +409,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState3 = { diagramStates: [ { - id: 51, + id: '51', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, @@ -408,7 +418,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const expectedState3 = { diagramStates: [ { - id: 51, + id: '51', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -418,7 +428,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState3, - openDiagram(51, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('51', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState3); @@ -426,7 +436,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState4 = { diagramStates: [ { - id: 74, + id: '74', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -435,12 +445,12 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const expectedState4 = { diagramStates: [ { - id: 74, + id: '74', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 22, + id: '22', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -450,7 +460,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState4, - openDiagram(22, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('22', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState4); @@ -458,7 +468,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState5 = { diagramStates: [ { - id: 33, + id: '33', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, @@ -467,12 +477,12 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const expectedState5 = { diagramStates: [ { - id: 33, + id: '33', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 44, + id: '44', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -482,7 +492,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState5, - openDiagram(44, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('44', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState5); @@ -490,28 +500,28 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState6 = { diagramStates: [ { - id: 38, + id: '38', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, ], - fullScreenDiagram: { id: 38, svgType: DiagramType.VOLTAGE_LEVEL }, + fullScreenDiagram: { id: '38', svgType: DiagramType.VOLTAGE_LEVEL }, }; const expectedState6 = { diagramStates: [ { - id: 38, + id: '38', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 28, + id: '28', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, ], fullScreenDiagram: { - id: 28, + id: '28', svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; @@ -519,7 +529,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState6, - openDiagram(28, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('28', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState6); @@ -527,38 +537,38 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState7 = { diagramStates: [ { - id: 14, + id: '14', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 14, + id: '14', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, ], - fullScreenDiagram: { id: 14, svgType: DiagramType.VOLTAGE_LEVEL }, + fullScreenDiagram: { id: '14', svgType: DiagramType.VOLTAGE_LEVEL }, }; const expectedState7 = { diagramStates: [ { - id: 14, + id: '14', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 14, + id: '14', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 39, + id: '39', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, ], fullScreenDiagram: { - id: 14, + id: '14', svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; @@ -566,7 +576,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState7, - openDiagram(39, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('39', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState7); @@ -574,31 +584,31 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { const initialState8 = { diagramStates: [ { - id: 85, + id: '85', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, ], fullScreenDiagram: { - id: 85, + id: '85', svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; const expectedState8 = { diagramStates: [ { - id: 85, + id: '85', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, { - id: 79, + id: '79', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, ], fullScreenDiagram: { - id: 85, + id: '85', svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; @@ -606,7 +616,7 @@ test('reducer.OPEN_DIAGRAM.nad_specific', () => { expect( reducer( initialState8, - openDiagram(79, DiagramType.NETWORK_AREA_DIAGRAM) + openDiagram('79', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState8); }); @@ -617,14 +627,14 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { const expectedState = { diagramStates: [] }; expect( - reducer(initialState, minimizeDiagram(1, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState, minimizeDiagram('1', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState); // Try to minimize a nonexistant SLD (bis) const initialState2 = { diagramStates: [ { - id: 12, + id: '12', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, @@ -633,7 +643,7 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { const expectedState2 = { diagramStates: [ { - id: 12, + id: '12', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, @@ -641,14 +651,14 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState2, minimizeDiagram(33, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState2, minimizeDiagram('33', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState2); // Minimize an open SLD const initialState3 = { diagramStates: [ { - id: 7, + id: '7', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -657,7 +667,7 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { const expectedState3 = { diagramStates: [ { - id: 7, + id: '7', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, @@ -665,24 +675,24 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState3, minimizeDiagram(7, DiagramType.SUBSTATION)) + reducer(initialState3, minimizeDiagram('7', DiagramType.SUBSTATION)) ).toEqual(expectedState3); // Minimize a pinned SLD const initialState4 = { diagramStates: [ { - id: 63, + id: '63', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 47, + id: '47', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 25, + id: '25', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -691,17 +701,17 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { const expectedState4 = { diagramStates: [ { - id: 63, + id: '63', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 47, + id: '47', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 25, + id: '25', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -709,24 +719,24 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState4, minimizeDiagram(47, DiagramType.SUBSTATION)) + reducer(initialState4, minimizeDiagram('47', DiagramType.SUBSTATION)) ).toEqual(expectedState4); // Minimize an already minimized SLD const initialState5 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 22, + id: '22', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -735,17 +745,17 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { const expectedState5 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 22, + id: '22', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -753,7 +763,7 @@ test('reducer.MINIMIZE_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState5, minimizeDiagram(1, DiagramType.VOLTAGE_LEVEL)) + reducer(initialState5, minimizeDiagram('1', DiagramType.VOLTAGE_LEVEL)) ).toEqual(expectedState5); }); @@ -762,32 +772,32 @@ test('reducer.MINIMIZE_DIAGRAM.nad_specific', () => { const initialState = { diagramStates: [ { - id: 10, + id: '10', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 200, + id: '200', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 10, + id: '10', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 200, + id: '200', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 3, + id: '3', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 4, + id: '4', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -796,32 +806,32 @@ test('reducer.MINIMIZE_DIAGRAM.nad_specific', () => { const expectedState = { diagramStates: [ { - id: 10, + id: '10', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 200, + id: '200', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 10, + id: '10', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, { - id: 200, + id: '200', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, { - id: 3, + id: '3', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 4, + id: '4', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.MINIMIZED, }, @@ -831,7 +841,7 @@ test('reducer.MINIMIZE_DIAGRAM.nad_specific', () => { expect( reducer( initialState, - minimizeDiagram(200, DiagramType.NETWORK_AREA_DIAGRAM) + minimizeDiagram('200', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState); }); @@ -841,12 +851,12 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { const initialState = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -855,12 +865,12 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { const expectedState = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -868,19 +878,19 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState, togglePinDiagram(1, DiagramType.SUBSTATION)) + reducer(initialState, togglePinDiagram('1', DiagramType.SUBSTATION)) ).toEqual(expectedState); // Pin a SLD const initialState2 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 2, + id: '2', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -889,12 +899,12 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { const expectedState2 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 2, + id: '2', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, @@ -902,24 +912,24 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState2, togglePinDiagram(2, DiagramType.SUBSTATION)) + reducer(initialState2, togglePinDiagram('2', DiagramType.SUBSTATION)) ).toEqual(expectedState2); // Unpin a SLD when no other SLD is already open const initialState3 = { diagramStates: [ { - id: 31, + id: '31', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 32, + id: '32', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 33, + id: '33', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -928,17 +938,17 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { const expectedState3 = { diagramStates: [ { - id: 31, + id: '31', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 32, + id: '32', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 33, + id: '33', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -946,34 +956,34 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState3, togglePinDiagram(32, DiagramType.SUBSTATION)) + reducer(initialState3, togglePinDiagram('32', DiagramType.SUBSTATION)) ).toEqual(expectedState3); // Unpin a SLD when there is already another opened SLD const initialState4 = { diagramStates: [ { - id: 10, + id: '10', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 20, + id: '20', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 30, + id: '30', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 40, + id: '40', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 50, + id: '50', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -982,27 +992,27 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { const expectedState4 = { diagramStates: [ { - id: 10, + id: '10', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 20, + id: '20', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 30, + id: '30', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 40, + id: '40', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 50, + id: '50', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -1010,7 +1020,10 @@ test('reducer.TOGGLE_PIN_DIAGRAM.sld_specific', () => { }; expect( - reducer(initialState4, togglePinDiagram(40, DiagramType.VOLTAGE_LEVEL)) + reducer( + initialState4, + togglePinDiagram('40', DiagramType.VOLTAGE_LEVEL) + ) ).toEqual(expectedState4); }); @@ -1019,12 +1032,12 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const initialState = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -1033,12 +1046,12 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const expectedState = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -1048,7 +1061,7 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { expect( reducer( initialState, - togglePinDiagram(1, DiagramType.NETWORK_AREA_DIAGRAM) + togglePinDiagram('1', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState); @@ -1056,17 +1069,17 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const initialState2 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, { - id: 3, + id: '3', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -1075,17 +1088,17 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const expectedState2 = { diagramStates: [ { - id: 1, + id: '1', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 2, + id: '2', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 3, + id: '3', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -1095,7 +1108,7 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { expect( reducer( initialState2, - togglePinDiagram(3, DiagramType.NETWORK_AREA_DIAGRAM) + togglePinDiagram('3', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState2); @@ -1103,17 +1116,17 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const initialState3 = { diagramStates: [ { - id: 3, + id: '3', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 4, + id: '4', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 5, + id: '5', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -1122,17 +1135,17 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { const expectedState3 = { diagramStates: [ { - id: 3, + id: '3', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, { - id: 4, + id: '4', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.MINIMIZED, }, { - id: 5, + id: '5', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -1142,7 +1155,7 @@ test('reducer.TOGGLE_PIN_DIAGRAM.nad_specific', () => { expect( reducer( initialState3, - togglePinDiagram(3, DiagramType.NETWORK_AREA_DIAGRAM) + togglePinDiagram('3', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState3); }); @@ -1152,7 +1165,7 @@ test('reducer.CLOSE_DIAGRAM', () => { const initialState = { diagramStates: [ { - id: 6, + id: '6', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -1161,7 +1174,7 @@ test('reducer.CLOSE_DIAGRAM', () => { const expectedState = { diagramStates: [ { - id: 6, + id: '6', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -1169,19 +1182,19 @@ test('reducer.CLOSE_DIAGRAM', () => { }; expect( - reducer(initialState, closeDiagram(6, DiagramType.SUBSTATION)) + reducer(initialState, closeDiagram('6', DiagramType.SUBSTATION)) ).toEqual(expectedState); // Close a SLD const initialState2 = { diagramStates: [ { - id: 3, + id: '3', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 54, + id: '54', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -1190,7 +1203,7 @@ test('reducer.CLOSE_DIAGRAM', () => { const expectedState2 = { diagramStates: [ { - id: 3, + id: '3', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, @@ -1198,29 +1211,29 @@ test('reducer.CLOSE_DIAGRAM', () => { }; expect( - reducer(initialState2, closeDiagram(54, DiagramType.SUBSTATION)) + reducer(initialState2, closeDiagram('54', DiagramType.SUBSTATION)) ).toEqual(expectedState2); // Close a NAD const initialState3 = { diagramStates: [ { - id: 32, + id: '32', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, { - id: 64, + id: '64', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, { - id: 64, + id: '64', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 82, + id: '82', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.PINNED, }, @@ -1229,7 +1242,7 @@ test('reducer.CLOSE_DIAGRAM', () => { const expectedState3 = { diagramStates: [ { - id: 64, + id: '64', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, @@ -1239,7 +1252,7 @@ test('reducer.CLOSE_DIAGRAM', () => { expect( reducer( initialState3, - closeDiagram(64, DiagramType.NETWORK_AREA_DIAGRAM) + closeDiagram('64', DiagramType.NETWORK_AREA_DIAGRAM) ) ).toEqual(expectedState3); }); @@ -1249,32 +1262,32 @@ test('reducer.CLOSE_DIAGRAMS', () => { const initialState = { diagramStates: [ { - id: 10, + id: '10', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 20, + id: '20', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 30, + id: '30', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, { - id: 5, + id: '5', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, { - id: 10, + id: '10', svgType: DiagramType.VOLTAGE_LEVEL, state: ViewState.PINNED, }, { - id: 10, + id: '10', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, @@ -1283,39 +1296,39 @@ test('reducer.CLOSE_DIAGRAMS', () => { const expectedState = { diagramStates: [ { - id: 20, + id: '20', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 5, + id: '5', svgType: DiagramType.NETWORK_AREA_DIAGRAM, state: ViewState.OPENED, }, ], }; - expect(reducer(initialState, closeDiagrams([6, 10, 30, 455]))).toEqual( - expectedState - ); + expect( + reducer(initialState, closeDiagrams(['6', '10', '30', '455'])) + ).toEqual(expectedState); }); test('reducer.STOP_DIAGRAM_BLINK', () => { const initialState = { diagramStates: [ { - id: 102, + id: '102', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 202, + id: '202', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, needsToBlink: true, }, { - id: 302, + id: '302', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, needsToBlink: true, @@ -1325,17 +1338,17 @@ test('reducer.STOP_DIAGRAM_BLINK', () => { const expectedState = { diagramStates: [ { - id: 102, + id: '102', svgType: DiagramType.SUBSTATION, state: ViewState.MINIMIZED, }, { - id: 202, + id: '202', svgType: DiagramType.SUBSTATION, state: ViewState.PINNED, }, { - id: 302, + id: '302', svgType: DiagramType.SUBSTATION, state: ViewState.OPENED, }, diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts new file mode 100644 index 0000000000..04b21962e0 --- /dev/null +++ b/src/redux/reducer.ts @@ -0,0 +1,1929 @@ +/** + * Copyright (c) 2022, 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 { createReducer } from '@reduxjs/toolkit'; +import { + AuthenticationActions, + AuthenticationRouterErrorAction, + AuthenticationRouterErrorState, + CommonStoreState, + GsLang, + GsLangUser, + GsTheme, + LOGOUT_ERROR, + LogoutErrorAction, + RESET_AUTHENTICATION_ROUTER_ERROR, + SHOW_AUTH_INFO_LOGIN, + ShowAuthenticationRouterLoginAction, + UNAUTHORIZED_USER_INFO, + UnauthorizedUserAction, + USER, + USER_VALIDATION_ERROR, + UserAction, + UserValidationErrorAction, +} from '@gridsuite/commons-ui'; +import { EQUIPMENT_TYPES } from 'components/utils/equipment-types'; +import { + ADD_NOTIFICATION, + ADD_TO_RECENT_GLOBAL_FILTERS, + AddNotificationAction, + AddToRecentGlobalFiltersAction, + AppActions, + CENTER_LABEL, + CENTER_ON_SUBSTATION, + CenterLabelAction, + CenterOnSubstationAction, + CHANGE_DISPLAYED_COLUMNS_NAMES, + CHANGE_LOCKED_COLUMNS_NAMES, + CHANGE_REORDERED_COLUMNS, + ChangeDisplayedColumnsNamesAction, + ChangeLockedColumnsNamesAction, + ChangeReorderedColumnsAction, + CLOSE_DIAGRAM, + CLOSE_DIAGRAMS, + CLOSE_STUDY, + CloseDiagramAction, + CloseDiagramsAction, + CloseStudyAction, + COMPONENT_LIBRARY, + ComponentLibraryAction, + CURRENT_TREE_NODE, + CurrentTreeNodeAction, + DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + DecrementNetworkAreaDiagramDepthAction, + DELETE_EQUIPMENTS, + DeleteEquipmentsAction, + DIAGONAL_LABEL, + DiagonalLabelAction, + DYNAMIC_SIMULATION_RESULT_FILTER, + DynamicSimulationResultFilterAction, + ENABLE_DEVELOPER_MODE, + EnableDeveloperModeAction, + FAVORITE_CONTINGENCY_LISTS, + FavoriteContingencyListsAction, + FLUX_CONVENTION, + FluxConventionAction, + INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + IncrementNetworkAreaDiagramDepthAction, + LIMIT_REDUCTION, + LIMIT_REDUCTION_MODIFIED, + LimitReductionAction, + LimitReductionModifiedAction, + LINE_FLOW_ALERT_THRESHOLD, + LINE_FLOW_COLOR_MODE, + LINE_FLOW_MODE, + LINE_FULL_PATH, + LINE_PARALLEL_PATH, + LineFlowAlertThresholdAction, + LineFlowColorModeAction, + LineFlowModeAction, + LineFullPathAction, + LineParallelPathAction, + LOAD_EQUIPMENTS, + LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, + LoadEquipmentsAction, + LOADFLOW_RESULT_FILTER, + LoadflowResultFilterAction, + LoadNetworkModificationTreeSuccessAction, + MAP_BASEMAP, + MAP_DATA_LOADING, + MAP_EQUIPMENTS_CREATED, + MAP_EQUIPMENTS_INITIALIZED, + MAP_MANUAL_REFRESH, + MapBasemapAction, + MapDataLoadingAction, + MapEquipmentsCreatedAction, + MapEquipmentsInitializedAction, + MapManualRefreshAction, + MINIMIZE_DIAGRAM, + MinimizeDiagramAction, + NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, + NETWORK_MODIFICATION_HANDLE_SUBTREE, + NETWORK_MODIFICATION_TREE_NODE_ADDED, + NETWORK_MODIFICATION_TREE_NODE_MOVED, + NETWORK_MODIFICATION_TREE_NODES_REMOVED, + NETWORK_MODIFICATION_TREE_NODES_UPDATED, + NetworkAreaDiagramNbVoltageLevelsAction, + NetworkModificationHandleSubtreeAction, + NetworkModificationTreeNodeAddedAction, + NetworkModificationTreeNodeMovedAction, + NetworkModificationTreeNodesRemovedAction, + NetworkModificationTreeNodesUpdatedAction, + OPEN_DIAGRAM, + OPEN_STUDY, + OpenDiagramAction, + OpenStudyAction, + REMOVE_NOTIFICATION_BY_NODE, + RemoveNotificationByNodeAction, + RESET_EQUIPMENTS, + RESET_EQUIPMENTS_BY_TYPES, + RESET_EQUIPMENTS_POST_LOADFLOW, + RESET_MAP_RELOADED, + RESET_NETWORK_AREA_DIAGRAM_DEPTH, + ResetEquipmentsAction, + ResetEquipmentsByTypesAction, + ResetEquipmentsPostLoadflowAction, + ResetMapReloadedAction, + ResetNetworkAreaDiagramDepthAction, + SECURITY_ANALYSIS_RESULT_FILTER, + SecurityAnalysisResultFilterAction, + SELECT_COMPUTED_LANGUAGE, + SELECT_LANGUAGE, + SELECT_THEME, + SelectComputedLanguageAction, + SELECTION_FOR_COPY, + SelectionForCopyAction, + SelectLanguageAction, + SelectThemeAction, + SENSITIVITY_ANALYSIS_RESULT_FILTER, + SensitivityAnalysisResultFilterAction, + SET_COMPUTATION_STARTING, + SET_COMPUTING_STATUS, + SET_EVENT_SCENARIO_DRAWER_OPEN, + SET_FULLSCREEN_DIAGRAM, + SET_LAST_COMPLETED_COMPUTATION, + SET_MODIFICATIONS_DRAWER_OPEN, + SET_MODIFICATIONS_IN_PROGRESS, + SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, + SET_OPTIONAL_SERVICES, + SET_PARAMS_LOADED, + SET_STUDY_DISPLAY_MODE, + SET_STUDY_INDEXATION_STATUS, + SetComputationStartingAction, + SetComputingStatusAction, + SetEventScenarioDrawerOpenAction, + SetFullscreenDiagramAction, + SetLastCompletedComputationAction, + SetModificationsDrawerOpenAction, + SetModificationsInProgressAction, + SetOneBusShortcircuitAnalysisDiagramAction, + SetOptionalServicesAction, + SetParamsLoadedAction, + SetStudyDisplayModeAction, + SetStudyIndexationStatusAction, + SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, + ShortcircuitAnalysisResultFilterAction, + SPREADSHEET_FILTER, + SpreadsheetFilterAction, + STOP_DIAGRAM_BLINK, + StopDiagramBlinkAction, + STUDY_UPDATED, + StudyUpdatedAction, + SUBSTATION_LAYOUT, + SubstationLayoutAction, + TOGGLE_PIN_DIAGRAM, + TogglePinDiagramAction, + UPDATE_EQUIPMENTS, + UpdateEquipmentsAction, + USE_NAME, + UseNameAction, +} from './actions'; +import { + getLocalStorageComputedLanguage, + getLocalStorageLanguage, + getLocalStorageTheme, + saveLocalStorageLanguage, + saveLocalStorageTheme, +} from './session-storage/local-storage'; +import { TABLES_COLUMNS_NAMES_JSON } from '../components/spreadsheet/utils/config-tables'; +import { + MAP_BASEMAP_CARTO, + MAP_BASEMAP_CARTO_NOLABEL, + MAP_BASEMAP_MAPBOX, + PARAM_CENTER_LABEL, + PARAM_COMPONENT_LIBRARY, + PARAM_COMPUTED_LANGUAGE, + PARAM_DEVELOPER_MODE, + PARAM_DIAGONAL_LABEL, + PARAM_FAVORITE_CONTINGENCY_LISTS, + PARAM_FLUX_CONVENTION, + PARAM_LANGUAGE, + PARAM_LIMIT_REDUCTION, + PARAM_LINE_FLOW_ALERT_THRESHOLD, + PARAM_LINE_FLOW_COLOR_MODE, + PARAM_LINE_FLOW_MODE, + PARAM_LINE_FULL_PATH, + PARAM_LINE_PARALLEL_PATH, + PARAM_MAP_BASEMAP, + PARAM_MAP_MANUAL_REFRESH, + PARAM_SUBSTATION_LAYOUT, + PARAM_THEME, + PARAM_USE_NAME, + PARAMS_LOADED, +} from '../utils/config-params'; +import NetworkModificationTreeModel from '../components/graph/network-modification-tree-model'; +import { FluxConventions } from '../components/dialogs/parameters/network-parameters'; +import { loadDiagramStateFromSessionStorage } from './session-storage/diagram-state'; +import { + DiagramType, + SubstationLayout, + ViewState, +} from '../components/diagrams/diagram-common'; +import { getAllChildren } from 'components/graph/util/model-functions'; +import { CopyType } from 'components/network-modification-tree-pane'; +import { ComputingType } from 'components/computing-status/computing-type'; +import { RunningStatus } from 'components/utils/running-status'; +import { NodeInsertModes } from '../components/graph/nodes/node-insert-modes'; +import { + IOptionalService, + OptionalServicesNames, + OptionalServicesStatus, +} from '../components/utils/optional-services'; +import { formatFetchedEquipments } from 'components/spreadsheet/utils/equipment-table-utils'; +import { + ALL_BUSES, + DYNAMIC_SIMULATION_RESULT_STORE_FIELD, + LOADFLOW_CURRENT_LIMIT_VIOLATION, + LOADFLOW_RESULT, + LOADFLOW_RESULT_STORE_FIELD, + LOADFLOW_VOLTAGE_LIMIT_VIOLATION, + ONE_BUS, + SECURITY_ANALYSIS_RESULT_N, + SECURITY_ANALYSIS_RESULT_N_K, + SECURITY_ANALYSIS_RESULT_STORE_FIELD, + SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD, + SENSITIVITY_AT_NODE_N, + SENSITIVITY_AT_NODE_N_K, + SENSITIVITY_IN_DELTA_A_N, + SENSITIVITY_IN_DELTA_A_N_K, + SENSITIVITY_IN_DELTA_MW_N, + SENSITIVITY_IN_DELTA_MW_N_K, + SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD, + SPREADSHEET_STORE_FIELD, + TIMELINE, +} from 'utils/store-filter-fields'; +import { UUID } from 'crypto'; +import { Filter } from '../components/results/common/results-global-filter'; +import { + LineFlowColorMode, + LineFlowMode, + MapEquipments, +} from '@powsybl/diagram-viewer'; +import { UnknownArray, ValueOf } from 'type-fest'; +import { IEquipment } from '../services/study/contingency-list'; +import { Node } from 'react-flow-renderer'; +import { BUILD_STATUS } from '../components/network/constants'; + +export enum NotificationType { + STUDY = 'study', +} + +export enum StudyIndexationStatus { + NOT_INDEXED = 'NOT_INDEXED', + INDEXING_ONGOING = 'INDEXING_ONGOING', + INDEXED = 'INDEXED', +} + +export enum StudyDisplayMode { + MAP = 'Map', + TREE = 'Tree', + HYBRID = 'Hybrid', + DRAW = 'Draw', +} + +export interface OneBusShortCircuitAnalysisDiagram { + diagramId: string; + nodeId: UUID; +} + +// Headers +export interface StudyUpdatedEventDataHeader { + studyUuid: UUID; + parentNode: UUID; + timestamp: number; + updateType?: string; + node?: UUID; + nodes?: UUID[]; + error?: string; + userId?: string; +} + +// Payloads +export interface DeletedEquipment { + equipmentId: string; + equipmentType: string; +} + +export interface NetworkImpactsInfos { + impactedSubstationsIds: UUID[]; + deletedEquipments: DeletedEquipment[]; + impactedElementTypes: string[]; +} + +// EventData +export interface StudyUpdatedEventData { + headers: StudyUpdatedEventDataHeader; + payload: NetworkImpactsInfos; +} + +interface StudyUpdatedEventDataUnknown { + headers: StudyUpdatedEventDataHeader; + payload: string; +} + +// Notification types +type StudyUpdatedStudy = { + type: NotificationType.STUDY; + eventData: StudyUpdatedEventData; +}; + +type StudyUpdatedUndefined = { + type: undefined; + eventData: StudyUpdatedEventDataUnknown; +}; + +// Redux state +export type StudyUpdated = { + force: number; //IntRange<0, 1>; +} & (StudyUpdatedUndefined | StudyUpdatedStudy); + +export interface TreeNodeData { + parentNodeUuid: UUID; + label: string; + description: string; + buildStatus: BUILD_STATUS; + readonly: boolean; +} +export type CurrentTreeNode = Node & { id: UUID }; + +export interface ComputingStatus { + [ComputingType.LOAD_FLOW]: RunningStatus; + [ComputingType.SECURITY_ANALYSIS]: RunningStatus; + [ComputingType.SENSITIVITY_ANALYSIS]: RunningStatus; + [ComputingType.NON_EVACUATED_ENERGY_ANALYSIS]: RunningStatus; + [ComputingType.SHORT_CIRCUIT]: RunningStatus; + [ComputingType.SHORT_CIRCUIT_ONE_BUS]: RunningStatus; + [ComputingType.DYNAMIC_SIMULATION]: RunningStatus; + [ComputingType.VOLTAGE_INITIALIZATION]: RunningStatus; + [ComputingType.STATE_ESTIMATION]: RunningStatus; +} + +export type SpreadsheetEquipmentType = Exclude< + EQUIPMENT_TYPES, + 'BUSBAR_SECTION' | 'HVDC_CONVERTER_STATION' | 'SWITCH' +>; +export type SpreadsheetFilterState = Record< + SpreadsheetEquipmentType, + UnknownArray +>; + +export type DiagramState = { + id: string; + svgType: DiagramType; + state: ViewState; + needsToBlink?: boolean; +}; + +export type SelectionForCopy = { + sourceStudyUuid: UUID | null; + nodeId: string | null; + copyType: ValueOf | null; + allChildrenIds: string[] | null; +}; + +export type Actions = AppActions | AuthenticationActions; + +export interface AppState extends CommonStoreState { + signInCallbackError: Error | null; + authenticationRouterError: AuthenticationRouterErrorState | null; + showAuthenticationRouterLogin: boolean; + + studyUpdated: StudyUpdated; + studyUuid: UUID | null; + currentTreeNode: CurrentTreeNode | null; + computingStatus: ComputingStatus; + lastCompletedComputation: ComputingType | null; + computationStarting: boolean; + optionalServices: IOptionalService[]; + oneBusShortCircuitAnalysisDiagram: OneBusShortCircuitAnalysisDiagram | null; + notificationIdList: UUID[]; + nonEvacuatedEnergyNotif: boolean; + recentGlobalFilters: Filter[]; + mapEquipments: MapEquipments | null; + networkAreaDiagramNbVoltageLevels: number; + networkAreaDiagramDepth: number; + studyDisplayMode: StudyDisplayMode; + studyIndexationStatus: StudyIndexationStatus; + + limitReductionModified: boolean; + selectionForCopy: SelectionForCopy; + geoData: null; + networkModificationTreeModel: NetworkModificationTreeModel | null; + mapDataLoading: boolean; + diagramStates: DiagramState[]; + fullScreenDiagram: null | { + id: string; + svgType?: DiagramType; + }; + allDisplayedColumnsNames: UnknownArray; + allLockedColumnsNames: UnknownArray; + allReorderedTableDefinitionIndexes: UnknownArray; + isExplorerDrawerOpen: boolean; + isModificationsDrawerOpen: boolean; + isEventScenarioDrawerOpen: boolean; + centerOnSubstation: null | { + to: unknown; + }; + isModificationsInProgress: boolean; + reloadMap: boolean; + isMapEquipmentsInitialized: boolean; + spreadsheetNetwork: SpreadsheetNetworkState; + + [PARAM_THEME]: GsTheme; + [PARAM_LANGUAGE]: GsLang; + [PARAM_COMPUTED_LANGUAGE]: GsLangUser; + [PARAM_LIMIT_REDUCTION]: number; + [PARAM_USE_NAME]: boolean; + [PARAM_LINE_FULL_PATH]: boolean; + [PARAM_LINE_PARALLEL_PATH]: boolean; + [PARAM_LINE_FLOW_ALERT_THRESHOLD]: number; + [PARAM_MAP_MANUAL_REFRESH]: boolean; + [PARAM_MAP_BASEMAP]: + | typeof MAP_BASEMAP_MAPBOX + | typeof MAP_BASEMAP_CARTO + | typeof MAP_BASEMAP_CARTO_NOLABEL; //TODO enum + [PARAM_LINE_FLOW_MODE]: LineFlowMode; + [PARAM_LINE_FLOW_COLOR_MODE]: LineFlowColorMode; + [PARAM_CENTER_LABEL]: boolean; + [PARAM_DIAGONAL_LABEL]: boolean; + [PARAM_SUBSTATION_LAYOUT]: SubstationLayout; + [PARAM_COMPONENT_LIBRARY]: unknown | null; + [PARAM_FAVORITE_CONTINGENCY_LISTS]: UnknownArray; + [PARAM_FLUX_CONVENTION]: FluxConventions; + [PARAM_DEVELOPER_MODE]: boolean; + [PARAMS_LOADED]: boolean; + + [LOADFLOW_RESULT_STORE_FIELD]: { + [LOADFLOW_CURRENT_LIMIT_VIOLATION]: UnknownArray; + [LOADFLOW_VOLTAGE_LIMIT_VIOLATION]: UnknownArray; + [LOADFLOW_RESULT]: UnknownArray; + }; + [SECURITY_ANALYSIS_RESULT_STORE_FIELD]: { + [SECURITY_ANALYSIS_RESULT_N]: UnknownArray; + [SECURITY_ANALYSIS_RESULT_N_K]: UnknownArray; + }; + [SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]: { + [SENSITIVITY_IN_DELTA_MW_N]: UnknownArray; + [SENSITIVITY_IN_DELTA_MW_N_K]: UnknownArray; + [SENSITIVITY_IN_DELTA_A_N]: UnknownArray; + [SENSITIVITY_IN_DELTA_A_N_K]: UnknownArray; + [SENSITIVITY_AT_NODE_N]: UnknownArray; + [SENSITIVITY_AT_NODE_N_K]: UnknownArray; + }; + [SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]: { + [ONE_BUS]: UnknownArray; + [ALL_BUSES]: UnknownArray; + }; + [DYNAMIC_SIMULATION_RESULT_STORE_FIELD]: { + [TIMELINE]: UnknownArray; + }; + + [SPREADSHEET_STORE_FIELD]: SpreadsheetFilterState; +} + +export type SpreadsheetNetworkState = Record< + SpreadsheetEquipmentType, + IEquipment[] | null +>; +const initialSpreadsheetNetworkState: SpreadsheetNetworkState = { + [EQUIPMENT_TYPES.SUBSTATION]: null, + [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: null, + [EQUIPMENT_TYPES.LINE]: null, + [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER]: null, + [EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER]: null, + [EQUIPMENT_TYPES.GENERATOR]: null, + [EQUIPMENT_TYPES.LOAD]: null, + [EQUIPMENT_TYPES.BATTERY]: null, + [EQUIPMENT_TYPES.DANGLING_LINE]: null, + [EQUIPMENT_TYPES.TIE_LINE]: null, + [EQUIPMENT_TYPES.HVDC_LINE]: null, + [EQUIPMENT_TYPES.LCC_CONVERTER_STATION]: null, + [EQUIPMENT_TYPES.VSC_CONVERTER_STATION]: null, + [EQUIPMENT_TYPES.SHUNT_COMPENSATOR]: null, + [EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR]: null, + [EQUIPMENT_TYPES.BUS]: null, +}; + +const initialState: AppState = { + studyUuid: null, + currentTreeNode: null, + selectionForCopy: { + sourceStudyUuid: null, + nodeId: null, + copyType: null, + allChildrenIds: null, + }, + mapEquipments: null, + geoData: null, + networkModificationTreeModel: new NetworkModificationTreeModel(), + computedLanguage: getLocalStorageComputedLanguage(), + user: null, + signInCallbackError: null, + authenticationRouterError: null, + showAuthenticationRouterLogin: false, + // @ts-expect-error TODO can't have empty eventData here + studyUpdated: { force: 0, eventData: {} }, + mapDataLoading: false, + fullScreenDiagram: null, + allDisplayedColumnsNames: TABLES_COLUMNS_NAMES_JSON, + allLockedColumnsNames: [], + allReorderedTableDefinitionIndexes: [], + isExplorerDrawerOpen: true, + isModificationsDrawerOpen: false, + isEventScenarioDrawerOpen: false, + centerOnSubstation: null, + notificationIdList: [], + isModificationsInProgress: false, + studyDisplayMode: StudyDisplayMode.HYBRID, + diagramStates: [], + reloadMap: true, + isMapEquipmentsInitialized: false, + networkAreaDiagramDepth: 0, + networkAreaDiagramNbVoltageLevels: 0, + spreadsheetNetwork: { ...initialSpreadsheetNetworkState }, + computingStatus: { + [ComputingType.LOAD_FLOW]: RunningStatus.IDLE, + [ComputingType.SECURITY_ANALYSIS]: RunningStatus.IDLE, + [ComputingType.SENSITIVITY_ANALYSIS]: RunningStatus.IDLE, + [ComputingType.NON_EVACUATED_ENERGY_ANALYSIS]: RunningStatus.IDLE, + [ComputingType.SHORT_CIRCUIT]: RunningStatus.IDLE, + [ComputingType.SHORT_CIRCUIT_ONE_BUS]: RunningStatus.IDLE, + [ComputingType.DYNAMIC_SIMULATION]: RunningStatus.IDLE, + [ComputingType.VOLTAGE_INITIALIZATION]: RunningStatus.IDLE, + [ComputingType.STATE_ESTIMATION]: RunningStatus.IDLE, + }, + computationStarting: false, + optionalServices: ( + Object.keys(OptionalServicesNames) as OptionalServicesNames[] + ).map((key) => ({ + name: key, + status: OptionalServicesStatus.Pending, + })), + oneBusShortCircuitAnalysisDiagram: null, + studyIndexationStatus: StudyIndexationStatus.NOT_INDEXED, + limitReductionModified: false, + + // params + [PARAM_THEME]: getLocalStorageTheme(), + [PARAM_LANGUAGE]: getLocalStorageLanguage(), + [PARAM_USE_NAME]: true, + [PARAM_LINE_FULL_PATH]: true, + [PARAM_LINE_PARALLEL_PATH]: true, + [PARAM_LIMIT_REDUCTION]: 100, + [PARAM_LINE_FLOW_ALERT_THRESHOLD]: 100, + [PARAM_MAP_MANUAL_REFRESH]: false, + [PARAM_MAP_BASEMAP]: MAP_BASEMAP_MAPBOX, + [PARAM_LINE_FLOW_MODE]: LineFlowMode.FEEDERS, + [PARAM_LINE_FLOW_COLOR_MODE]: LineFlowColorMode.NOMINAL_VOLTAGE, + [PARAM_CENTER_LABEL]: false, + [PARAM_DIAGONAL_LABEL]: false, + [PARAM_SUBSTATION_LAYOUT]: SubstationLayout.HORIZONTAL, + [PARAM_COMPONENT_LIBRARY]: null, + [PARAM_FAVORITE_CONTINGENCY_LISTS]: [], + [PARAM_FLUX_CONVENTION]: FluxConventions.IIDM, + [PARAM_DEVELOPER_MODE]: false, + [PARAMS_LOADED]: false, + + recentGlobalFilters: [], + lastCompletedComputation: null, + + // Results filters + [LOADFLOW_RESULT_STORE_FIELD]: { + [LOADFLOW_CURRENT_LIMIT_VIOLATION]: [], + [LOADFLOW_VOLTAGE_LIMIT_VIOLATION]: [], + [LOADFLOW_RESULT]: [], + }, + [SECURITY_ANALYSIS_RESULT_STORE_FIELD]: { + [SECURITY_ANALYSIS_RESULT_N]: [], + [SECURITY_ANALYSIS_RESULT_N_K]: [], + }, + [SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]: { + [SENSITIVITY_IN_DELTA_MW_N]: [], + [SENSITIVITY_IN_DELTA_MW_N_K]: [], + [SENSITIVITY_IN_DELTA_A_N]: [], + [SENSITIVITY_IN_DELTA_A_N_K]: [], + [SENSITIVITY_AT_NODE_N]: [], + [SENSITIVITY_AT_NODE_N_K]: [], + }, + [SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]: { + [ONE_BUS]: [], + [ALL_BUSES]: [], + }, + [DYNAMIC_SIMULATION_RESULT_STORE_FIELD]: { + [TIMELINE]: [], + }, + + // Spreadsheet filters + [SPREADSHEET_STORE_FIELD]: { + [EQUIPMENT_TYPES.SUBSTATION]: [], + [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: [], + [EQUIPMENT_TYPES.LINE]: [], + [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER]: [], + [EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER]: [], + [EQUIPMENT_TYPES.GENERATOR]: [], + [EQUIPMENT_TYPES.LOAD]: [], + [EQUIPMENT_TYPES.SHUNT_COMPENSATOR]: [], + [EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR]: [], + [EQUIPMENT_TYPES.BATTERY]: [], + [EQUIPMENT_TYPES.HVDC_LINE]: [], + [EQUIPMENT_TYPES.LCC_CONVERTER_STATION]: [], + [EQUIPMENT_TYPES.VSC_CONVERTER_STATION]: [], + [EQUIPMENT_TYPES.DANGLING_LINE]: [], + [EQUIPMENT_TYPES.BUS]: [], + [EQUIPMENT_TYPES.TIE_LINE]: [], + }, + + // Hack to avoid reload Geo Data when switching display mode to TREE then back to MAP or HYBRID + // defaulted to true to init load geo data with HYBRID defaulted display Mode + // TODO REMOVE LATER +}; + +export const reducer = createReducer(initialState, (builder) => { + builder.addCase(OPEN_STUDY, (state, action: OpenStudyAction) => { + state.studyUuid = action.studyRef[0]; + + if (action.studyRef[0] != null) { + state.diagramStates = loadDiagramStateFromSessionStorage( + action.studyRef[0] + ); + } + }); + + builder.addCase(CLOSE_STUDY, (state, action: CloseStudyAction) => { + state.studyUuid = null; + state.geoData = null; + state.networkModificationTreeModel = null; + }); + + builder.addCase( + MAP_EQUIPMENTS_CREATED, + (state, action: MapEquipmentsCreatedAction) => { + let newMapEquipments; + //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(); + } + if (action.newLines) { + newMapEquipments.lines = action.newLines; + // @ts-expect-error TODO: set parameter(s) optional in diagram-viewer + newMapEquipments.completeLinesInfos(); + } + if (action.newTieLines) { + newMapEquipments.tieLines = action.newTieLines; + // @ts-expect-error TODO: set parameter(s) optional in diagram-viewer + newMapEquipments.completeTieLinesInfos(); + } + if (action.newSubstations) { + newMapEquipments.substations = action.newSubstations; + // @ts-expect-error TODO: set parameter(s) optional in diagram-viewer + newMapEquipments.completeSubstationsInfos(); + } + if (action.newHvdcLines) { + newMapEquipments.hvdcLines = action.newHvdcLines; + // @ts-expect-error TODO: set parameter(s) optional in diagram-viewer + newMapEquipments.completeHvdcLinesInfos(); + } + state.mapEquipments = newMapEquipments; + } + ); + + builder.addCase( + LOAD_NETWORK_MODIFICATION_TREE_SUCCESS, + (state, action: LoadNetworkModificationTreeSuccessAction) => { + state.networkModificationTreeModel = + action.networkModificationTreeModel; + state.networkModificationTreeModel.setBuildingStatus(); + } + ); + + builder.addCase( + NETWORK_MODIFICATION_TREE_NODE_ADDED, + (state, action: NetworkModificationTreeNodeAddedAction) => { + if (state.networkModificationTreeModel) { + let newModel = + state.networkModificationTreeModel.newSharedForUpdate(); + newModel.addChild( + action.networkModificationTreeNode, + action.parentNodeId, + action.insertMode, + action.referenceNodeId + ); + newModel.updateLayout(); + state.networkModificationTreeModel = newModel; + // check if added node is the new parent of the current Node + if ( + // @ts-expect-error TODO: childrenIds not exist in ReactFlow node + action.networkModificationTreeNode?.childrenIds.includes( + state.currentTreeNode?.id + ) + ) { + // Then must overwrite currentTreeNode to set new parentNodeUuid + // @ts-expect-error TODO: what to do if current node null? + synchCurrentTreeNode(state, state.currentTreeNode?.id); + } + } + } + ); + + builder.addCase( + NETWORK_MODIFICATION_TREE_NODE_MOVED, + (state, action: NetworkModificationTreeNodeMovedAction) => { + if (state.networkModificationTreeModel) { + let newModel = + state.networkModificationTreeModel.newSharedForUpdate(); + newModel.removeNodes([action.networkModificationTreeNode.id]); + newModel.addChild( + action.networkModificationTreeNode, + action.parentNodeId, + action.insertMode, + action.referenceNodeId + ); + newModel.updateLayout(); + state.networkModificationTreeModel = newModel; + // check if added node is the new parent of the current Node + if ( + // @ts-expect-error TODO: childrenIds not exist in ReactFlow node + action.networkModificationTreeNode?.childrenIds.includes( + state.currentTreeNode?.id + ) + ) { + // Then must overwrite currentTreeNode to set new parentNodeUuid + // @ts-expect-error TODO: what to do if current node null? + synchCurrentTreeNode(state, state.currentTreeNode?.id); + } + } + } + ); + + builder.addCase( + NETWORK_MODIFICATION_HANDLE_SUBTREE, + (state, action: NetworkModificationHandleSubtreeAction) => { + if (state.networkModificationTreeModel) { + let newModel = + state.networkModificationTreeModel.newSharedForUpdate(); + unravelSubTree( + newModel, + action.parentNodeId, + // @ts-expect-error TODO problem: we receive an array of node but func await 1 node + action.networkModificationTreeNodes + ); + + newModel.updateLayout(); + state.networkModificationTreeModel = newModel; + } + } + ); + + builder.addCase( + NETWORK_MODIFICATION_TREE_NODES_REMOVED, + (state, action: NetworkModificationTreeNodesRemovedAction) => { + if (state.networkModificationTreeModel) { + let newModel = + state.networkModificationTreeModel.newSharedForUpdate() as NetworkModificationTreeModel; + + //we assume all the deleted nodes are contiguous, so the new parent selected will be the nearest upstream node. + //in the future, if the deleted nodes are no longer contiguous we will need another implementation + const nextCurrentNodeUuid = newModel.treeNodes + .filter((node) => + action.networkModificationTreeNodes.includes(node.id) + ) + .map((node) => node.data.parentNodeUuid) + .find( + (parentNodeUuid) => + !action.networkModificationTreeNodes.includes( + parentNodeUuid + ) + ); + + newModel.removeNodes(action.networkModificationTreeNodes); + newModel.updateLayout(); + state.networkModificationTreeModel = newModel; + + // check if current node is in the nodes deleted list + if ( + action.networkModificationTreeNodes.includes( + // @ts-expect-error TODO: what to do if current node null? + state.currentTreeNode?.id + ) + ) { + synchCurrentTreeNode(state, nextCurrentNodeUuid); + } // check if parent node of the current node is in the nodes deleted list + else if ( + action.networkModificationTreeNodes.includes( + // @ts-expect-error TODO: what to do if current node null? + state.currentTreeNode?.data?.parentNodeUuid + ) + ) { + // Then must overwrite currentTreeNode to get new parentNodeUuid + // @ts-expect-error TODO: what to do if current node null? + synchCurrentTreeNode(state, state.currentTreeNode?.id); + } + } + } + ); + + builder.addCase( + NETWORK_MODIFICATION_TREE_NODES_UPDATED, + (state, action: NetworkModificationTreeNodesUpdatedAction) => { + if (state.networkModificationTreeModel) { + let newModel = + state.networkModificationTreeModel.newSharedForUpdate(); + newModel.updateNodes(action.networkModificationTreeNodes); + state.networkModificationTreeModel = newModel; + state.networkModificationTreeModel?.setBuildingStatus(); + // check if current node is in the nodes updated list + if ( + action.networkModificationTreeNodes.find( + (node) => node.id === state.currentTreeNode?.id + ) + ) { + // @ts-expect-error TODO: what to do if current node null? + synchCurrentTreeNode(state, state.currentTreeNode?.id); + // current node has changed, then will need to reload Geo Data + state.reloadMap = true; + } + } + } + ); + + builder.addCase(STUDY_UPDATED, (state, action: StudyUpdatedAction) => { + state.studyUpdated = { + force: 1 - state.studyUpdated.force, + // @ts-expect-error TODO types incompatible here + type: action.eventData.headers.updateType, + eventData: action.eventData, + }; + }); + + builder.addCase(MAP_DATA_LOADING, (state, action: MapDataLoadingAction) => { + state.mapDataLoading = action.mapDataLoading; + }); + + builder.addCase(SELECT_THEME, (state, action: SelectThemeAction) => { + state[PARAM_THEME] = action[PARAM_THEME]; + saveLocalStorageTheme(state[PARAM_THEME]); + }); + + builder.addCase(SELECT_LANGUAGE, (state, action: SelectLanguageAction) => { + state[PARAM_LANGUAGE] = action[PARAM_LANGUAGE]; + saveLocalStorageLanguage(state[PARAM_LANGUAGE]); + }); + + builder.addCase( + SELECT_COMPUTED_LANGUAGE, + (state, action: SelectComputedLanguageAction) => { + state.computedLanguage = action.computedLanguage; + } + ); + + builder.addCase( + SET_PARAMS_LOADED, + (state, action: SetParamsLoadedAction) => { + state[PARAMS_LOADED] = action[PARAMS_LOADED]; + } + ); + + builder.addCase(USE_NAME, (state, action: UseNameAction) => { + state[PARAM_USE_NAME] = action[PARAM_USE_NAME]; + }); + + builder.addCase(USER, (state, action: UserAction) => { + state.user = action.user; + }); + + builder.addCase(CENTER_LABEL, (state, action: CenterLabelAction) => { + state[PARAM_CENTER_LABEL] = action[PARAM_CENTER_LABEL]; + }); + + builder.addCase(DIAGONAL_LABEL, (state, action: DiagonalLabelAction) => { + state[PARAM_DIAGONAL_LABEL] = action[PARAM_DIAGONAL_LABEL]; + }); + + builder.addCase(LINE_FULL_PATH, (state, action: LineFullPathAction) => { + state[PARAM_LINE_FULL_PATH] = action[PARAM_LINE_FULL_PATH]; + }); + + builder.addCase( + LINE_PARALLEL_PATH, + (state, action: LineParallelPathAction) => { + state[PARAM_LINE_PARALLEL_PATH] = action[PARAM_LINE_PARALLEL_PATH]; + } + ); + + builder.addCase(LINE_FLOW_MODE, (state, action: LineFlowModeAction) => { + state[PARAM_LINE_FLOW_MODE] = action[PARAM_LINE_FLOW_MODE]; + }); + + builder.addCase(FLUX_CONVENTION, (state, action: FluxConventionAction) => { + state[PARAM_FLUX_CONVENTION] = action[PARAM_FLUX_CONVENTION]; + }); + + builder.addCase( + ENABLE_DEVELOPER_MODE, + (state, action: EnableDeveloperModeAction) => { + state[PARAM_DEVELOPER_MODE] = action[PARAM_DEVELOPER_MODE]; + } + ); + + builder.addCase( + LINE_FLOW_COLOR_MODE, + (state, action: LineFlowColorModeAction) => { + state[PARAM_LINE_FLOW_COLOR_MODE] = + action[PARAM_LINE_FLOW_COLOR_MODE]; + } + ); + + builder.addCase(LIMIT_REDUCTION, (state, action: LimitReductionAction) => { + state[PARAM_LIMIT_REDUCTION] = action[PARAM_LIMIT_REDUCTION]; + }); + + builder.addCase( + LIMIT_REDUCTION_MODIFIED, + (state, action: LimitReductionModifiedAction) => { + state.limitReductionModified = action.limitReductionModified; + } + ); + + builder.addCase( + LINE_FLOW_ALERT_THRESHOLD, + (state, action: LineFlowAlertThresholdAction) => { + state[PARAM_LINE_FLOW_ALERT_THRESHOLD] = + action[PARAM_LINE_FLOW_ALERT_THRESHOLD]; + } + ); + + builder.addCase( + UNAUTHORIZED_USER_INFO, + (state, action: UnauthorizedUserAction) => { + state.authenticationRouterError = action.authenticationRouterError; + } + ); + + builder.addCase(LOGOUT_ERROR, (state, action: LogoutErrorAction) => { + state.authenticationRouterError = action.authenticationRouterError; + }); + + builder.addCase( + USER_VALIDATION_ERROR, + (state, action: UserValidationErrorAction) => { + state.authenticationRouterError = action.authenticationRouterError; + } + ); + + builder.addCase( + RESET_AUTHENTICATION_ROUTER_ERROR, + (state, action: AuthenticationRouterErrorAction) => { + state.authenticationRouterError = null; + } + ); + + builder.addCase( + SHOW_AUTH_INFO_LOGIN, + (state, action: ShowAuthenticationRouterLoginAction) => { + state.showAuthenticationRouterLogin = + action.showAuthenticationRouterLogin; + } + ); + + builder.addCase( + MAP_MANUAL_REFRESH, + (state, action: MapManualRefreshAction) => { + state[PARAM_MAP_MANUAL_REFRESH] = action[PARAM_MAP_MANUAL_REFRESH]; + } + ); + + builder.addCase(MAP_BASEMAP, (state, action: MapBasemapAction) => { + state[PARAM_MAP_BASEMAP] = action[PARAM_MAP_BASEMAP]; + }); + + builder.addCase( + RESET_MAP_RELOADED, + (state, action: ResetMapReloadedAction) => { + state.reloadMap = false; + } + ); + + builder.addCase( + MAP_EQUIPMENTS_INITIALIZED, + (state, action: MapEquipmentsInitializedAction) => { + state.isMapEquipmentsInitialized = action.newValue; + } + ); + + builder.addCase( + SUBSTATION_LAYOUT, + (state, action: SubstationLayoutAction) => { + state[PARAM_SUBSTATION_LAYOUT] = action[PARAM_SUBSTATION_LAYOUT]; + } + ); + + builder.addCase( + COMPONENT_LIBRARY, + (state, action: ComponentLibraryAction) => { + state[PARAM_COMPONENT_LIBRARY] = action[PARAM_COMPONENT_LIBRARY]; + } + ); + + builder.addCase( + SET_FULLSCREEN_DIAGRAM, + (state, action: SetFullscreenDiagramAction) => { + state.fullScreenDiagram = action.diagramId + ? { + id: action.diagramId, + svgType: action.svgType, + } + : null; + } + ); + + builder.addCase( + CHANGE_DISPLAYED_COLUMNS_NAMES, + (state, action: ChangeDisplayedColumnsNamesAction) => { + const newDisplayedColumnsNames = [ + ...state.allDisplayedColumnsNames, + ]; + action.displayedColumnsNamesParams.forEach((param) => { + if (param) { + newDisplayedColumnsNames[param.index] = param.value; + } + }); + state.allDisplayedColumnsNames = newDisplayedColumnsNames; + } + ); + + builder.addCase( + CHANGE_LOCKED_COLUMNS_NAMES, + (state, action: ChangeLockedColumnsNamesAction) => { + let newLockedColumnsNames = [...state.allLockedColumnsNames]; + action.lockedColumnsNamesParams.forEach((param) => { + if (param) { + newLockedColumnsNames[param.index] = param.value; + } + }); + state.allLockedColumnsNames = newLockedColumnsNames; + } + ); + + builder.addCase( + CHANGE_REORDERED_COLUMNS, + (state, action: ChangeReorderedColumnsAction) => { + let newReorderedColumns = [ + ...state.allReorderedTableDefinitionIndexes, + ]; + action.reorderedColumnsParams.forEach((param) => { + if (param) { + newReorderedColumns[param.index] = param.value; + } + }); + state.allReorderedTableDefinitionIndexes = newReorderedColumns; + } + ); + + builder.addCase( + FAVORITE_CONTINGENCY_LISTS, + (state, action: FavoriteContingencyListsAction) => { + state[PARAM_FAVORITE_CONTINGENCY_LISTS] = + action[PARAM_FAVORITE_CONTINGENCY_LISTS]; + } + ); + + builder.addCase( + CURRENT_TREE_NODE, + (state, action: CurrentTreeNodeAction) => { + state.currentTreeNode = action.currentTreeNode; + state.reloadMap = true; + } + ); + + builder.addCase( + SELECTION_FOR_COPY, + (state, action: SelectionForCopyAction) => { + const selectionForCopy = action.selectionForCopy; + if ( + selectionForCopy.sourceStudyUuid === state.studyUuid && + selectionForCopy.nodeId && + (selectionForCopy.copyType === CopyType.SUBTREE_COPY || + selectionForCopy.copyType === CopyType.SUBTREE_CUT) + ) { + selectionForCopy.allChildrenIds = getAllChildren( + state.networkModificationTreeModel, + selectionForCopy.nodeId + ).map((child) => child.id); + } + state.selectionForCopy = selectionForCopy; + } + ); + + builder.addCase( + SET_MODIFICATIONS_DRAWER_OPEN, + (state, action: SetModificationsDrawerOpenAction) => { + state.isModificationsDrawerOpen = action.isModificationsDrawerOpen; + + // exclusively open between two components + if ( + action.isModificationsDrawerOpen && + state.isEventScenarioDrawerOpen + ) { + state.isEventScenarioDrawerOpen = + !state.isEventScenarioDrawerOpen; + } + } + ); + + builder.addCase( + SET_EVENT_SCENARIO_DRAWER_OPEN, + (state, action: SetEventScenarioDrawerOpenAction) => { + state.isEventScenarioDrawerOpen = action.isEventScenarioDrawerOpen; + + // exclusively open between two components + if ( + action.isEventScenarioDrawerOpen && + state.isModificationsDrawerOpen + ) { + state.isModificationsDrawerOpen = + !state.isModificationsDrawerOpen; + } + } + ); + + builder.addCase( + CENTER_ON_SUBSTATION, + (state, action: CenterOnSubstationAction) => { + state.centerOnSubstation = action.centerOnSubstation; + } + ); + + builder.addCase( + ADD_NOTIFICATION, + (state, action: AddNotificationAction) => { + state.notificationIdList = [ + ...state.notificationIdList, + ...action.notificationIds, + ]; + } + ); + + builder.addCase( + REMOVE_NOTIFICATION_BY_NODE, + (state, action: RemoveNotificationByNodeAction) => { + state.notificationIdList = [ + ...state.notificationIdList.filter( + (nodeId) => !action.notificationIds.includes(nodeId) + ), + ]; + } + ); + + builder.addCase( + SET_MODIFICATIONS_IN_PROGRESS, + (state, action: SetModificationsInProgressAction) => { + state.isModificationsInProgress = action.isModificationsInProgress; + } + ); + + builder.addCase( + SET_STUDY_DISPLAY_MODE, + (state, action: SetStudyDisplayModeAction) => { + if ( + Object.values(StudyDisplayMode).includes( + action.studyDisplayMode + ) + ) { + // Hack to avoid reload Geo Data when switching display mode to TREE then back to MAP or HYBRID + // Some actions in the TREE display mode could change this value after that + // ex: change current Node, current Node updated ... + if (action.studyDisplayMode === StudyDisplayMode.TREE) { + state.reloadMap = false; + } + + state.studyDisplayMode = action.studyDisplayMode; + } + } + ); + + /* + * The following functions' goal are to update state.diagramStates with nodes of the following type : + * { id: 'diagramID', svgType: 'SvgType of the diagram', state: 'ViewState of the diagram' } + * + * Depending on the diagram's svgType, the state.diagramStates is different. + * For Network Area Diagrams (SvgType.NETWORK_AREA_DIAGRAM), all the states should be the same. + * As an example, if one is PINNED, then all of them should be. + * For Single Line Diagrams (SvgType.VOLTAGE_LEVEL or SvgType.SUBSTATION), each diagram has its own state. + */ + builder.addCase(OPEN_DIAGRAM, (state, action: OpenDiagramAction) => { + const diagramStates = state.diagramStates; + const diagramToOpenIndex = diagramStates.findIndex( + (diagram) => + diagram.id === action.id && diagram.svgType === action.svgType + ); + + if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { + // First, we check if there is already a Network Area Diagram in the diagramStates. + const firstNadIndex = diagramStates.findIndex( + (diagram) => + diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM + ); + if (firstNadIndex < 0) { + // If there is no NAD, then we add the new one. + diagramStates.push({ + id: action.id, + svgType: DiagramType.NETWORK_AREA_DIAGRAM, + state: ViewState.OPENED, + }); + + // If there is already a diagram in fullscreen mode, the new opened NAD will take its place. + if (state.fullScreenDiagram?.id) { + state.fullScreenDiagram = { + id: action.id, + svgType: DiagramType.NETWORK_AREA_DIAGRAM, + }; + } + } else { + // If there is already at least one NAD, and if it is minimized, then we change all of them to opened. + if ( + diagramStates[firstNadIndex].state === ViewState.MINIMIZED + ) { + diagramStates.forEach((diagram) => { + if ( + diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM + ) { + diagram.state = ViewState.OPENED; + } + }); + } + // If the NAD to open is not already in the diagramStates, we add it. + if (diagramToOpenIndex < 0) { + diagramStates.push({ + id: action.id, + svgType: DiagramType.NETWORK_AREA_DIAGRAM, + state: diagramStates[firstNadIndex].state, + }); + } + + // If there is a SLD in fullscreen, we have to display in fullscreen the new NAD. + // Because it is the first NAD displayed that counts for the fullscreen status, we put the fist nad's id there. + if ( + state.fullScreenDiagram?.svgType && + state.fullScreenDiagram?.svgType !== + DiagramType.NETWORK_AREA_DIAGRAM + ) { + state.fullScreenDiagram = { + id: diagramStates[firstNadIndex].id, + svgType: DiagramType.NETWORK_AREA_DIAGRAM, + }; + } + } + } else { + // We check if the SLD to open is already in the diagramStates. + if (diagramToOpenIndex >= 0) { + // If the SLD to open is already in the diagramStates and it is minimized, then we change it to opened. + if ( + diagramStates[diagramToOpenIndex].state === + ViewState.MINIMIZED + ) { + // We minimize all the other OPENED SLD. + diagramStates.forEach((diagram) => { + if ( + diagram.svgType !== + DiagramType.NETWORK_AREA_DIAGRAM && + diagram.state === ViewState.OPENED + ) { + diagram.state = ViewState.MINIMIZED; + } + }); + const diagramToOpen = diagramStates[diagramToOpenIndex]; + + // We open and push the SLD to the last position in the array, so it is displayed at the right of the others + diagramToOpen.state = ViewState.OPENED; + diagramStates.splice(diagramToOpenIndex, 1); + diagramStates.push(diagramToOpen); + } else { + console.info( + 'Diagram already opened : ' + + diagramStates[diagramToOpenIndex].id + + ' (' + + diagramStates[diagramToOpenIndex].svgType + + ')' + ); + diagramStates[diagramToOpenIndex].needsToBlink = true; + } + } else { + // We minimize all the other OPENED SLD. + diagramStates.forEach((diagram) => { + if ( + diagram.svgType !== DiagramType.NETWORK_AREA_DIAGRAM && + diagram.state === ViewState.OPENED + ) { + diagram.state = ViewState.MINIMIZED; + } + }); + // And we add the new one. + diagramStates.push({ + id: action.id, + svgType: action.svgType, + state: ViewState.OPENED, + }); + } + + // If there is already a diagram in fullscreen mode, the new opened SLD will take its place. + if (state.fullScreenDiagram?.id) { + state.fullScreenDiagram = { + id: action.id, + svgType: action.svgType, + }; + } + } + state.diagramStates = diagramStates; + }); + + builder.addCase( + MINIMIZE_DIAGRAM, + (state, action: MinimizeDiagramAction) => { + const diagramStates = state.diagramStates; + + if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { + // For network area diagrams, the ID is irrelevant, we will minimize all the NAD in the state.diagramStates. + diagramStates.forEach((diagram) => { + if (diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { + diagram.state = ViewState.MINIMIZED; + } + }); + } else { + // For single line diagram, we will update the corresponding diagram. + const diagramToMinimizeIndex = diagramStates.findIndex( + (diagram) => + diagram.id === action.id && + diagram.svgType === action.svgType + ); + if (diagramToMinimizeIndex >= 0) { + diagramStates[diagramToMinimizeIndex].state = + ViewState.MINIMIZED; + } + } + state.diagramStates = diagramStates; + } + ); + + builder.addCase( + TOGGLE_PIN_DIAGRAM, + (state, action: TogglePinDiagramAction) => { + const diagramStates = state.diagramStates; + + // search targeted diagram among the diagramStates + const diagramToPinToggleIndex = diagramStates.findIndex( + (diagram) => + diagram.id === action.id && + diagram.svgType === action.svgType + ); + if (diagramToPinToggleIndex >= 0) { + if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { + // If the current NAD is PINNED, we set all NAD to OPENED. Otherwise, we set them to PINNED. + const newStateForNads = + diagramStates[diagramToPinToggleIndex].state === + ViewState.PINNED + ? ViewState.OPENED + : ViewState.PINNED; + diagramStates.forEach((diagram) => { + if ( + diagram.svgType === DiagramType.NETWORK_AREA_DIAGRAM + ) { + diagram.state = newStateForNads; + } + }); + } else { + if ( + diagramStates[diagramToPinToggleIndex].state !== + ViewState.PINNED + ) { + // If the current SLD is minimized or opened, we pin it. + diagramStates[diagramToPinToggleIndex].state = + ViewState.PINNED; + } else { + // If the current SLD is pinned, we check if there is already another SLD opened (there can only be one + // SLD opened -not pinned- at a time). If there is, then we minimize the current SLD. If none, we open it. + const currentlyOpenedDiagramIndex = + diagramStates.findIndex( + (diagram) => + diagram.state === ViewState.OPENED && + (diagram.svgType === + DiagramType.SUBSTATION || + diagram.svgType === + DiagramType.VOLTAGE_LEVEL) + ); + if (currentlyOpenedDiagramIndex >= 0) { + diagramStates[diagramToPinToggleIndex].state = + ViewState.MINIMIZED; + } else { + diagramStates[diagramToPinToggleIndex].state = + ViewState.OPENED; + } + } + } + } + + state.diagramStates = diagramStates; + } + ); + + builder.addCase(CLOSE_DIAGRAM, (state, action: CloseDiagramAction) => { + let diagramStates = state.diagramStates; + + if (action.svgType === DiagramType.NETWORK_AREA_DIAGRAM) { + // If we close a NAD, we close all of them. + diagramStates = diagramStates.filter( + (diagram) => + diagram.svgType !== DiagramType.NETWORK_AREA_DIAGRAM + ); + } else { + // If we close a SLD, we only remove one. + const diagramToCloseIndex = diagramStates.findIndex( + (diagram) => + diagram.id === action.id && + diagram.svgType === action.svgType + ); + if (diagramToCloseIndex >= 0) { + diagramStates.splice(diagramToCloseIndex, 1); + } + } + + state.diagramStates = diagramStates; + }); + + builder.addCase(CLOSE_DIAGRAMS, (state, action: CloseDiagramsAction) => { + const idsToClose = new Set(action.ids); + state.diagramStates = state.diagramStates.filter( + (diagram) => !idsToClose.has(diagram.id) + ); + }); + + builder.addCase( + STOP_DIAGRAM_BLINK, + (state, action: StopDiagramBlinkAction) => { + state.diagramStates.forEach((diagram) => { + if (diagram.needsToBlink) { + diagram.needsToBlink = undefined; + } + }); + } + ); + + builder.addCase( + RESET_NETWORK_AREA_DIAGRAM_DEPTH, + (state, action: ResetNetworkAreaDiagramDepthAction) => { + state.networkAreaDiagramDepth = 0; + } + ); + + builder.addCase( + INCREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + (state, action: IncrementNetworkAreaDiagramDepthAction) => { + state.networkAreaDiagramDepth = state.networkAreaDiagramDepth + 1; + } + ); + + builder.addCase( + DECREMENT_NETWORK_AREA_DIAGRAM_DEPTH, + (state, action: DecrementNetworkAreaDiagramDepthAction) => { + if (state.networkAreaDiagramDepth > 0) { + state.networkAreaDiagramDepth = + state.networkAreaDiagramDepth - 1; + } + } + ); + + builder.addCase( + NETWORK_AREA_DIAGRAM_NB_VOLTAGE_LEVELS, + (state, action: NetworkAreaDiagramNbVoltageLevelsAction) => { + state.networkAreaDiagramNbVoltageLevels = action.nbVoltageLevels; + } + ); + + builder.addCase(LOAD_EQUIPMENTS, (state, action: LoadEquipmentsAction) => { + state.spreadsheetNetwork[action.equipmentType] = action.equipments; + }); + + builder.addCase( + UPDATE_EQUIPMENTS, + (state, action: UpdateEquipmentsAction) => { + // for now, this action receives an object containing all equipments from a substation + // it will be modified when the notifications received after a network modification will be more precise + const updatedEquipments = action.equipments; + + // equipmentType : type of equipment updated + // equipments : list of updated equipments of type + for (const [updateType, equipments] of Object.entries( + updatedEquipments + ) as [EquipmentUpdateType, IEquipment[]][]) { + const equipmentType = + getEquipmentTypeFromUpdateType(updateType); + const currentEquipment: IEquipment[] | null = + // @ts-expect-error TODO manage undefined value case + state.spreadsheetNetwork[equipmentType]; + + // Format the updated equipments to match the table format + const formattedEquipments = formatFetchedEquipments( + // @ts-expect-error TODO manage undefined value case + equipmentType, + equipments + ); + + // if the equipments are not loaded into the store yet, we don't have to update them + if (currentEquipment != null) { + //since substations data contains voltage level ones, they have to be treated separatly + if (equipmentType === EQUIPMENT_TYPES.SUBSTATION) { + const [updatedSubstations, updatedVoltageLevels] = + updateSubstationsAndVoltageLevels( + state.spreadsheetNetwork[ + EQUIPMENT_TYPES.SUBSTATION + ] as Substation[], + // @ts-expect-error TODO manage null value case + state.spreadsheetNetwork[ + EQUIPMENT_TYPES.VOLTAGE_LEVEL + ], + formattedEquipments + ); + + state.spreadsheetNetwork[EQUIPMENT_TYPES.SUBSTATION] = + updatedSubstations; + state.spreadsheetNetwork[ + EQUIPMENT_TYPES.VOLTAGE_LEVEL + ] = updatedVoltageLevels; + } else { + // @ts-expect-error TODO manage undefined value case + state.spreadsheetNetwork[equipmentType] = + updateEquipments( + currentEquipment, + formattedEquipments + ); + } + } + } + } + ); + + builder.addCase( + DELETE_EQUIPMENTS, + (state, action: DeleteEquipmentsAction) => { + action.equipments.forEach( + ({ + equipmentType: equipmentToDeleteType, + equipmentId: equipmentToDeleteId, + }) => { + const currentEquipments = + state.spreadsheetNetwork[equipmentToDeleteType]; + if (currentEquipments != null) { + // in case of voltage level deletion, we need to update the linked substation which contains a list of its voltage levels + if ( + equipmentToDeleteType === + EQUIPMENT_TYPES.VOLTAGE_LEVEL + ) { + const currentSubstations = state.spreadsheetNetwork[ + EQUIPMENT_TYPES.SUBSTATION + ] as Substation[] | null; + if (currentSubstations != null) { + state.spreadsheetNetwork[ + EQUIPMENT_TYPES.SUBSTATION + ] = updateSubstationAfterVLDeletion( + currentSubstations, + equipmentToDeleteId + ); + } + } + + state.spreadsheetNetwork[equipmentToDeleteType] = + deleteEquipment( + currentEquipments, + equipmentToDeleteId + ); + } + } + ); + } + ); + + builder.addCase( + RESET_EQUIPMENTS, + (state, action: ResetEquipmentsAction) => { + state.spreadsheetNetwork = { + ...initialSpreadsheetNetworkState, + }; + } + ); + builder.addCase( + RESET_EQUIPMENTS_BY_TYPES, + (state, action: ResetEquipmentsByTypesAction) => { + action.equipmentTypes.forEach((equipmentType) => { + state.spreadsheetNetwork[equipmentType] = null; + }); + } + ); + + builder.addCase( + RESET_EQUIPMENTS_POST_LOADFLOW, + (state, action: ResetEquipmentsPostLoadflowAction) => { + state.spreadsheetNetwork = { + ...initialSpreadsheetNetworkState, + [EQUIPMENT_TYPES.SUBSTATION]: + state.spreadsheetNetwork[EQUIPMENT_TYPES.SUBSTATION], + [EQUIPMENT_TYPES.VOLTAGE_LEVEL]: + state.spreadsheetNetwork[EQUIPMENT_TYPES.VOLTAGE_LEVEL], + [EQUIPMENT_TYPES.HVDC_LINE]: + state.spreadsheetNetwork[EQUIPMENT_TYPES.HVDC_LINE], + }; + } + ); + + builder.addCase( + SET_COMPUTING_STATUS, + (state, action: SetComputingStatusAction) => { + state.computingStatus[action.computingType] = action.runningStatus; + } + ); + + builder.addCase( + SET_COMPUTATION_STARTING, + (state, action: SetComputationStartingAction) => { + state.computationStarting = action.computationStarting; + } + ); + + builder.addCase( + SET_OPTIONAL_SERVICES, + (state, action: SetOptionalServicesAction) => { + state.optionalServices = action.optionalServices; + } + ); + + builder.addCase( + SET_ONE_BUS_SHORTCIRCUIT_ANALYSIS_DIAGRAM, + (state, action: SetOneBusShortcircuitAnalysisDiagramAction) => { + state.oneBusShortCircuitAnalysisDiagram = action.diagramId + ? { + diagramId: action.diagramId, + nodeId: action.nodeId, + } + : null; + } + ); + + builder.addCase( + SET_STUDY_INDEXATION_STATUS, + (state, action: SetStudyIndexationStatusAction) => { + state.studyIndexationStatus = action.studyIndexationStatus; + } + ); + + builder.addCase( + ADD_TO_RECENT_GLOBAL_FILTERS, + (state, action: AddToRecentGlobalFiltersAction) => { + let newRecentGlobalFilters = [...state.recentGlobalFilters]; + action.globalFilters.forEach((filter) => { + if ( + !newRecentGlobalFilters.some( + (obj) => + obj.label === filter.label && + obj.filterType === filter.filterType + ) + ) { + newRecentGlobalFilters.push(filter); + } + }); + state.recentGlobalFilters = newRecentGlobalFilters; + } + ); + + builder.addCase( + SET_LAST_COMPLETED_COMPUTATION, + (state, action: SetLastCompletedComputationAction) => { + state.lastCompletedComputation = action.lastCompletedComputation; + } + ); + + builder.addCase( + LOADFLOW_RESULT_FILTER, + (state, action: LoadflowResultFilterAction) => { + state[LOADFLOW_RESULT_STORE_FIELD][action.filterTab] = + action[LOADFLOW_RESULT_STORE_FIELD]; + } + ); + + builder.addCase( + SECURITY_ANALYSIS_RESULT_FILTER, + (state, action: SecurityAnalysisResultFilterAction) => { + state[SECURITY_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = + action[SECURITY_ANALYSIS_RESULT_STORE_FIELD]; + } + ); + + builder.addCase( + SENSITIVITY_ANALYSIS_RESULT_FILTER, + (state, action: SensitivityAnalysisResultFilterAction) => { + state[SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = + action[SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD]; + } + ); + + builder.addCase( + SHORTCIRCUIT_ANALYSIS_RESULT_FILTER, + (state, action: ShortcircuitAnalysisResultFilterAction) => { + state[SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD][action.filterTab] = + action[SHORTCIRCUIT_ANALYSIS_RESULT_STORE_FIELD]; + } + ); + + builder.addCase( + DYNAMIC_SIMULATION_RESULT_FILTER, + (state, action: DynamicSimulationResultFilterAction) => { + state[DYNAMIC_SIMULATION_RESULT_STORE_FIELD][action.filterTab] = + action[DYNAMIC_SIMULATION_RESULT_STORE_FIELD]; + } + ); + + builder.addCase( + SPREADSHEET_FILTER, + (state, action: SpreadsheetFilterAction) => { + state[SPREADSHEET_STORE_FIELD][action.filterTab] = + action[SPREADSHEET_STORE_FIELD]; + } + ); +}); + +function updateSubstationAfterVLDeletion( + currentSubstations: Substation[], + VLToDeleteId: string +): Substation[] { + const substationToUpdateIndex = currentSubstations.findIndex((sub) => + sub.voltageLevels.some((vl) => vl.id === VLToDeleteId) + ); + if (substationToUpdateIndex >= 0) { + currentSubstations[substationToUpdateIndex].voltageLevels = + currentSubstations[substationToUpdateIndex].voltageLevels.filter( + (vl) => vl.id !== VLToDeleteId + ); + } + + return currentSubstations; +} + +export enum EquipmentUpdateType { + LINES = 'lines', + TIE_LINES = 'tieLines', + TWO_WINDINGS_TRANSFORMERS = 'twoWindingsTransformers', + THREE_WINDINGS_TRANSFORMERS = 'threeWindingsTransformers', + GENERATORS = 'generators', + LOADS = 'loads', + BATTERIES = 'batteries', + DANGLING_LINES = 'danglingLines', + HVDC_LINES = 'hvdcLines', + LCC_CONVERTER_STATIONS = 'lccConverterStations', + VSC_CONVERTER_STATIONS = 'vscConverterStations', + SHUNT_COMPENSATORS = 'shuntCompensators', + STATIC_VAR_COMPENSATORS = 'staticVarCompensators', + VOLTAGE_LEVELS = 'voltageLevels', + SUBSTATIONS = 'substations', + BUSES = 'buses', +} + +function getEquipmentTypeFromUpdateType( + updateType: EquipmentUpdateType +): EQUIPMENT_TYPES | undefined { + switch (updateType) { + case 'lines': + return EQUIPMENT_TYPES.LINE; + case 'tieLines': + return EQUIPMENT_TYPES.TIE_LINE; + case 'twoWindingsTransformers': + return EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER; + case 'threeWindingsTransformers': + return EQUIPMENT_TYPES.THREE_WINDINGS_TRANSFORMER; + case 'generators': + return EQUIPMENT_TYPES.GENERATOR; + case 'loads': + return EQUIPMENT_TYPES.LOAD; + case 'batteries': + return EQUIPMENT_TYPES.BATTERY; + case 'danglingLines': + return EQUIPMENT_TYPES.DANGLING_LINE; + case 'hvdcLines': + return EQUIPMENT_TYPES.HVDC_LINE; + case 'lccConverterStations': + return EQUIPMENT_TYPES.LCC_CONVERTER_STATION; + case 'vscConverterStations': + return EQUIPMENT_TYPES.VSC_CONVERTER_STATION; + case 'shuntCompensators': + return EQUIPMENT_TYPES.SHUNT_COMPENSATOR; + case 'staticVarCompensators': + return EQUIPMENT_TYPES.STATIC_VAR_COMPENSATOR; + case 'voltageLevels': + return EQUIPMENT_TYPES.VOLTAGE_LEVEL; + case 'substations': + return EQUIPMENT_TYPES.SUBSTATION; + case 'buses': + return EQUIPMENT_TYPES.BUS; + default: + return; + } +} + +function deleteEquipment( + currentEquipments: IEquipment[], + equipmentToDeleteId: string +) { + const equipmentToDeleteIndex = currentEquipments.findIndex( + (eq) => eq.id === equipmentToDeleteId + ); + if (equipmentToDeleteIndex >= 0) { + currentEquipments.splice(equipmentToDeleteIndex, 1); + } + return currentEquipments; +} + +export type Substation = IEquipment & { + voltageLevels: IEquipment[]; +}; + +function updateSubstationsAndVoltageLevels( + currentSubstations: Substation[], + currentVoltageLevels: IEquipment[], + newOrUpdatedSubstations: Substation[] +) { + const updatedSubstations = updateEquipments( + currentSubstations, + newOrUpdatedSubstations + ); + + let updatedVoltageLevels = null; + + // if voltage levels are not loaded yet, we don't need to update them + if (currentVoltageLevels != null) { + const newOrUpdatedVoltageLevels = newOrUpdatedSubstations.reduce( + (acc, currentSub) => { + return acc.concat([...currentSub.voltageLevels]); + }, + [] as IEquipment[] + ); + + updatedVoltageLevels = updateEquipments( + currentVoltageLevels, + newOrUpdatedVoltageLevels + ); + } + + return [updatedSubstations, updatedVoltageLevels]; +} + +function updateEquipments( + currentEquipments: IEquipment[], + newOrUpdatedEquipments: IEquipment[] +) { + newOrUpdatedEquipments.forEach((equipment) => { + const existingEquipmentIndex = currentEquipments.findIndex( + (equip) => equip.id === equipment.id + ); + + if (existingEquipmentIndex >= 0) { + currentEquipments[existingEquipmentIndex] = equipment; + } else { + currentEquipments.push(equipment); + } + }); + + return currentEquipments; +} + +function synchCurrentTreeNode(state: AppState, nextCurrentNodeUuid: string) { + const nextCurrentNode = state.networkModificationTreeModel?.treeNodes.find( + (node) => node?.id === nextCurrentNodeUuid + ); + // we need to overwrite state.currentTreeNode to consider label change for example. + state.currentTreeNode = { ...nextCurrentNode }; +} + +function unravelSubTree( + treeModel: NetworkModificationTreeModel, + subtreeParentId: string, + node: Node +) { + if (node) { + if (treeModel.treeNodes.find((el) => el.id === node.id)) { + treeModel.removeNodes([node.id]); + } + treeModel.addChild(node, subtreeParentId, NodeInsertModes.After); + + // @ts-expect-error TODO problem: ReactFlow node don't have "children" variable + if (node.children.length > 0) { + // @ts-expect-error TODO problem: ReactFlow node don't have "children" variable + node.children.forEach((child) => { + unravelSubTree(treeModel, node.id, child); + }); + } + } +} diff --git a/src/redux/reducer.type.ts b/src/redux/reducer.type.ts deleted file mode 100644 index 2039edae87..0000000000 --- a/src/redux/reducer.type.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright (c) 2023, 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 { ComputingType } from 'components/computing-status/computing-type'; -import { RunningStatus } from 'components/utils/running-status'; -import { UUID } from 'crypto'; -import { IOptionalService } from '../components/utils/optional-services'; -import { Filter } from '../components/results/common/results-global-filter'; -import { MapEquipments } from '@powsybl/diagram-viewer'; - -export enum UpdateTypes { - STUDY = 'study', -} - -export enum StudyIndexationStatus { - NOT_INDEXED = 'NOT_INDEXED', - INDEXING_ONGOING = 'INDEXING_ONGOING', - INDEXED = 'INDEXED', -} - -export enum StudyDisplayMode { - MAP = 'Map', - TREE = 'Tree', - HYBRID = 'Hybrid', - DRAW = 'Draw', -} - -export interface ReduxState { - studyUpdated: StudyUpdated; - studyUuid: UUID; - currentTreeNode: CurrentTreeNode; - computingStatus: ComputingStatus; - lastCompletedComputation: ComputingType; - computationStarting: boolean; - optionalServices: IOptionalService[]; - limitReduction: string; - user: User; - oneBusShortCircuitAnalysisDiagram: oneBusShortCircuitAnalysisDiagram; - notificationIdList: UUID[]; - theme: string; - nonEvacuatedEnergyNotif: boolean; - recentGlobalFilters: Filter[]; - mapEquipments: MapEquipments | null; - networkAreaDiagramNbVoltageLevels: number; - networkAreaDiagramDepth: number; - studyDisplayMode: StudyDisplayMode; - studyIndexationStatus: StudyIndexationStatus; -} - -export interface oneBusShortCircuitAnalysisDiagram { - diagramId: string; - nodeId: UUID; -} - -// Headers -export interface StudyUpdatedEventDataHeader { - studyUuid: UUID; - parentNode: UUID; - timestamp: number; - updateType?: string; - node?: UUID; - nodes?: UUID[]; - error?: string; - userId?: string; -} - -// Payloads -export interface DeletedEquipment { - equipmentId: string; - equipmentType: string; -} - -export interface NetworkImpactsInfos { - impactedSubstationsIds: UUID[]; - deletedEquipments: DeletedEquipment[]; - impactedElementTypes: string[]; -} - -// EventData -interface StudyUpdatedEventData { - headers: StudyUpdatedEventDataHeader; - payload: NetworkImpactsInfos; -} - -interface StudyUpdatedEventDataUnknown { - headers: StudyUpdatedEventDataHeader; - payload: string; -} - -// Notification types -type StudyUpdatedStudy = { - type: UpdateTypes.STUDY; - eventData: StudyUpdatedEventData; -}; - -type StudyUpdatedUndefined = { - type: undefined; - eventData: StudyUpdatedEventDataUnknown; -}; - -// Redux state -export type StudyUpdated = { - force: 0 | 1; -} & (StudyUpdatedUndefined | StudyUpdatedStudy); - -export interface CurrentTreeNodeData { - parentNodeUuid: UUID; - label: string; - description: string; - buildStatus: string; - readonly: boolean; -} - -export interface CurrentTreeNode { - id: UUID; - type: string; - data: CurrentTreeNodeData; - targetPosition: string; - sourcePosition: string; -} - -export interface ComputingStatus { - [ComputingType.LOAD_FLOW]: RunningStatus; - [ComputingType.SECURITY_ANALYSIS]: RunningStatus; - [ComputingType.SENSITIVITY_ANALYSIS]: RunningStatus; - [ComputingType.NON_EVACUATED_ENERGY_ANALYSIS]: RunningStatus; - [ComputingType.SHORT_CIRCUIT]: RunningStatus; - [ComputingType.SHORT_CIRCUIT_ONE_BUS]: RunningStatus; - [ComputingType.DYNAMIC_SIMULATION]: RunningStatus; - [ComputingType.VOLTAGE_INITIALIZATION]: RunningStatus; - [ComputingType.STATE_ESTIMATION]: RunningStatus; -} - -export interface User { - id_token: string; - access_token: string; - token_type: string; - scope: string; - profile: Profile; - expires_at: number; -} - -interface Profile { - sub: string; - name: string; - email: string; - s_hash: string; -} diff --git a/src/redux/store.js b/src/redux/store.ts similarity index 77% rename from src/redux/store.js rename to src/redux/store.ts index 8aabc6431a..23fe288508 100644 --- a/src/redux/store.js +++ b/src/redux/store.ts @@ -5,12 +5,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { legacy_createStore as createStore } from 'redux'; -import { reducer } from './reducer'; +import { legacy_createStore as createStore, Store } from 'redux'; +import { Actions, AppState, reducer } from './reducer'; import { setCommonStore } from '@gridsuite/commons-ui'; export const store = createStore(reducer); setCommonStore(store); +export type AppDispatch = Store['dispatch']; // to avoid to reset the state with HMR // https://redux.js.org/usage/configuring-your-store#hot-reloading diff --git a/src/utils/config-params.js b/src/utils/config-params.js index 7bfa999852..57bef550b4 100644 --- a/src/utils/config-params.js +++ b/src/utils/config-params.js @@ -24,6 +24,7 @@ export const PARAM_SUBSTATION_LAYOUT = 'substationLayout'; export const PARAM_COMPONENT_LIBRARY = 'componentLibrary'; export const PARAM_FLUX_CONVENTION = 'fluxConvention'; export const PARAM_LANGUAGE = 'language'; +export const PARAM_COMPUTED_LANGUAGE = 'computedLanguage'; export const PARAM_DEVELOPER_MODE = 'enableDeveloperMode'; export const PARAMS_LOADED = 'paramsLoaded'; From 8599a487e359b80cf445fb8fa0c759f965d05b76 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Wed, 24 Jul 2024 13:36:26 +0200 Subject: [PATCH 5/9] fix cyclic dependency in files --- .../custom-aggrid/custom-aggrid-header.jsx | 2 +- src/components/diagrams/diagram-pane.jsx | 7 ++- .../substation-modification-form.jsx | 3 +- .../curve/dialog/equipment-filter.jsx | 7 ++- .../parameters/load-flow-parameters.jsx | 2 +- .../results/common/results-global-filter.tsx | 3 +- .../spreadsheet/country-cell-render.tsx | 9 ++- src/components/spreadsheet/table-wrapper.jsx | 3 +- .../spreadsheet/utils/config-tables.js | 21 ++++--- .../utils/equipment-table-editors.jsx | 2 +- .../utils/localized-countries-hook.js | 58 ------------------- .../rhf-inputs/country-selection-input.jsx | 6 +- src/redux/reducer.test.ts | 16 ++++- src/redux/reducer.ts | 3 +- src/redux/store.ts | 2 + src/redux/user-store.ts | 45 ++++++++++++++ src/services/directory-notification.js | 5 +- src/services/utils.js | 13 ++--- 18 files changed, 106 insertions(+), 101 deletions(-) delete mode 100644 src/components/utils/localized-countries-hook.js create mode 100644 src/redux/user-store.ts diff --git a/src/components/custom-aggrid/custom-aggrid-header.jsx b/src/components/custom-aggrid/custom-aggrid-header.jsx index 20354662a0..a2bc0b4bf6 100644 --- a/src/components/custom-aggrid/custom-aggrid-header.jsx +++ b/src/components/custom-aggrid/custom-aggrid-header.jsx @@ -20,13 +20,13 @@ import { } from '@mui/material'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; +import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { SortWay } from '../../hooks/use-aggrid-sort'; import { FILTER_TEXT_COMPARATORS, FILTER_DATA_TYPES, } from './custom-aggrid-header.type'; import { mergeSx } from '../utils/functions'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import CustomAggridBooleanFilter from './custom-aggrid-filters/custom-aggrid-boolean-filter'; import CustomAggridDurationFilter from './custom-aggrid-filters/custom-aggrid-duration-filter'; diff --git a/src/components/diagrams/diagram-pane.jsx b/src/components/diagrams/diagram-pane.jsx index d81dedd433..407fe1ddcc 100644 --- a/src/components/diagrams/diagram-pane.jsx +++ b/src/components/diagrams/diagram-pane.jsx @@ -49,7 +49,11 @@ import { useNameOrId } from '../utils/equipmentInfosHandler'; import { syncDiagramStateWithSessionStorage } from '../../redux/session-storage/diagram-state'; import SingleLineDiagramContent from './singleLineDiagram/single-line-diagram-content'; import NetworkAreaDiagramContent from './networkAreaDiagram/network-area-diagram-content'; -import { useDebounce, useSnackMessage } from '@gridsuite/commons-ui'; +import { + useDebounce, + useLocalizedCountries, + useSnackMessage, +} from '@gridsuite/commons-ui'; import { setNetworkAreaDiagramNbVoltageLevels } from '../../redux/actions'; import { useIntl } from 'react-intl'; import { @@ -59,7 +63,6 @@ import { import { fetchSvg, getNetworkAreaDiagramUrl } from '../../services/study'; import { mergeSx } from '../utils/functions'; import { Box } from '@mui/system'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; // Returns a callback that returns a promise const useDisplayView = (studyUuid, currentNode) => { diff --git a/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx b/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx index 7f82624162..8f1cd1da73 100644 --- a/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx +++ b/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx @@ -8,10 +8,9 @@ import Grid from '@mui/material/Grid'; import { filledTextField, gridItem } from '../../../dialogUtils'; import React from 'react'; -import { TextInput } from '@gridsuite/commons-ui'; +import { TextInput, useLocalizedCountries } from '@gridsuite/commons-ui'; import { COUNTRY, EQUIPMENT_NAME } from 'components/utils/field-constants'; import CountrySelectionInput from 'components/utils/rhf-inputs/country-selection-input'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { TextField } from '@mui/material'; import PropertiesForm from '../../common/properties/properties-form'; diff --git a/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx b/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx index 3ee9a6392e..4c3a854356 100644 --- a/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx +++ b/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx @@ -17,13 +17,16 @@ import { useState, } from 'react'; import { useSelector } from 'react-redux'; -import { CustomAGGrid, useSnackMessage } from '@gridsuite/commons-ui'; +import { + CustomAGGrid, + useLocalizedCountries, + useSnackMessage, +} from '@gridsuite/commons-ui'; import { Box } from '@mui/system'; import { fetchAllCountries } from '../../../../../../services/study/network-map'; import { evaluateJsonFilter } from '../../../../../../services/study/filter'; import { fetchVoltageLevelsMapInfos } from '../../../../../../services/study/network'; import CheckboxAutocomplete from '../../../../../utils/checkbox-autocomplete'; -import { useLocalizedCountries } from '../../../../../utils/localized-countries-hook'; import { buildExpertFilter, CURVE_EQUIPMENT_TYPES, diff --git a/src/components/dialogs/parameters/load-flow-parameters.jsx b/src/components/dialogs/parameters/load-flow-parameters.jsx index 1a5ca7940f..7c7ec43542 100644 --- a/src/components/dialogs/parameters/load-flow-parameters.jsx +++ b/src/components/dialogs/parameters/load-flow-parameters.jsx @@ -9,6 +9,7 @@ import { DirectoryItemSelector, ElementType, FlatParameters, + useLocalizedCountries, useSnackMessage, } from '@gridsuite/commons-ui'; import { Autocomplete, Box, Chip, Grid, TextField } from '@mui/material'; @@ -20,7 +21,6 @@ import { PARAM_LIMIT_REDUCTION, } from '../../../utils/config-params'; import { mergeSx } from '../../utils/functions'; -import { useLocalizedCountries } from '../../utils/localized-countries-hook'; import { replaceAllDefaultValues } from '../../utils/utils'; import { LineSeparator } from '../dialogUtils'; import CreateParameterDialog from './common/parameters-creation-dialog'; diff --git a/src/components/results/common/results-global-filter.tsx b/src/components/results/common/results-global-filter.tsx index 9557ea7534..ad5789334c 100644 --- a/src/components/results/common/results-global-filter.tsx +++ b/src/components/results/common/results-global-filter.tsx @@ -10,8 +10,8 @@ import { Box, FilterOptionsState } from '@mui/material'; import { Autocomplete, Chip, InputAdornment, TextField } from '@mui/material'; import { FilterAlt } from '@mui/icons-material'; import { FormattedMessage, useIntl } from 'react-intl'; +import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { mergeSx } from '../../utils/functions'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { useDispatch, useSelector } from 'react-redux'; import { addToRecentGlobalFilters } from '../../../redux/actions'; import { Theme } from '@mui/material'; @@ -121,6 +121,7 @@ const ResultsGlobalFilter: FunctionComponent = ({ filters = emptyArray, }) => { const intl = useIntl(); + // @ts-expect-error: will be fixed in the next version of commons-ui const { translate } = useLocalizedCountries(); const dispatch = useDispatch(); const recentGlobalFilters = useSelector( diff --git a/src/components/spreadsheet/country-cell-render.tsx b/src/components/spreadsheet/country-cell-render.tsx index 3811bb4230..6a2ef09784 100644 --- a/src/components/spreadsheet/country-cell-render.tsx +++ b/src/components/spreadsheet/country-cell-render.tsx @@ -4,14 +4,17 @@ * 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 { useLocalizedCountries } from 'components/utils/localized-countries-hook'; -import React from 'react'; +import { FunctionComponent } from 'react'; +import { useLocalizedCountries } from '@gridsuite/commons-ui'; interface CountryCellRendererProps { value: string; } -const CountryCellRenderer: React.FC = ({ value }) => { +const CountryCellRenderer: FunctionComponent = ({ + value, +}) => { + // @ts-expect-error: will be fixed in the next version of commons-ui const { translate } = useLocalizedCountries(); const countryName = translate(value); return {countryName}; diff --git a/src/components/spreadsheet/table-wrapper.jsx b/src/components/spreadsheet/table-wrapper.jsx index cbdf73b559..903e68456a 100644 --- a/src/components/spreadsheet/table-wrapper.jsx +++ b/src/components/spreadsheet/table-wrapper.jsx @@ -25,7 +25,7 @@ import { TABLES_DEFINITION_TYPES, } from './utils/config-tables'; import { EquipmentTable } from './equipment-table'; -import { useSnackMessage } from '@gridsuite/commons-ui'; +import { useLocalizedCountries, useSnackMessage } from '@gridsuite/commons-ui'; import { PARAM_FLUX_CONVENTION } from '../../utils/config-params'; import { RunningStatus } from '../utils/running-status'; import { @@ -89,7 +89,6 @@ import { makeAgGridCustomHeaderColumn } from 'components/custom-aggrid/custom-ag import { useAggridLocalRowFilter } from 'hooks/use-aggrid-local-row-filter'; import { useAgGridLocalSort } from 'hooks/use-aggrid-local-sort'; import { setSpreadsheetFilter } from 'redux/actions'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { SPREADSHEET_STORE_FIELD } from 'utils/store-filter-fields'; const useEditBuffer = () => { diff --git a/src/components/spreadsheet/utils/config-tables.js b/src/components/spreadsheet/utils/config-tables.js index 9059193da6..cf702b7844 100644 --- a/src/components/spreadsheet/utils/config-tables.js +++ b/src/components/spreadsheet/utils/config-tables.js @@ -47,7 +47,7 @@ import { NOMINAL_V } from '../../utils/field-constants'; import CountryCellRenderer from '../country-cell-render'; import EnumCellRenderer from '../enum-cell-renderer'; import { BooleanFilterValue } from 'components/custom-aggrid/custom-aggrid-header-utils'; -import { store } from '../../../redux/store'; +import { useSelector } from 'react-redux'; const generateTapPositions = (params) => { return params @@ -81,13 +81,12 @@ const applyFluxConvention = (convention, val) => { return val; }; -const getFluxConvention = () => { - const state = store.getState(); - return state.fluxConvention; -}; +function useFluxConvention() { + return useSelector((state) => state.fluxConvention); +} //this function enables us to exclude some columns from the computation of the spreadsheet global filter -// The columns we want to include in the global filter at the date of this comment : ID (all), Name, Country, Type and Nominal Voltage (all). +// The columns we want to include in the global filter at the date of this comment: ID (all), Name, Country, Type and Nominal Voltage (all). // All the others should be excluded. const excludeFromGlobalFilter = () => ''; @@ -2083,7 +2082,7 @@ export const TABLES_DEFINITIONS = { numeric: true, ...defaultNumericFilterConfig( applyFluxConvention, - getFluxConvention + useFluxConvention ), fractionDigits: 1, normed: applyFluxConvention, @@ -2096,7 +2095,7 @@ export const TABLES_DEFINITIONS = { numeric: true, ...defaultNumericFilterConfig( applyFluxConvention, - getFluxConvention + useFluxConvention ), fractionDigits: 1, normed: applyFluxConvention, @@ -2823,7 +2822,7 @@ export const TABLES_DEFINITIONS = { numeric: true, ...defaultNumericFilterConfig( applyFluxConvention, - getFluxConvention + useFluxConvention ), fractionDigits: 1, normed: applyFluxConvention, @@ -3129,7 +3128,7 @@ export const TABLES_DEFINITIONS = { numeric: true, ...defaultNumericFilterConfig( applyFluxConvention, - getFluxConvention + useFluxConvention ), fractionDigits: 1, normed: applyFluxConvention, @@ -3142,7 +3141,7 @@ export const TABLES_DEFINITIONS = { numeric: true, ...defaultNumericFilterConfig( applyFluxConvention, - getFluxConvention + useFluxConvention ), fractionDigits: 1, normed: applyFluxConvention, diff --git a/src/components/spreadsheet/utils/equipment-table-editors.jsx b/src/components/spreadsheet/utils/equipment-table-editors.jsx index 226ec6e011..f89cc1abc3 100644 --- a/src/components/spreadsheet/utils/equipment-table-editors.jsx +++ b/src/components/spreadsheet/utils/equipment-table-editors.jsx @@ -17,11 +17,11 @@ import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { Autocomplete, TextField, Tooltip } from '@mui/material'; import { FormattedMessage, useIntl } from 'react-intl'; +import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { checkValidationsAndRefreshCells, deepUpdateValue, } from './equipment-table-utils'; -import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import RegulatingTerminalModificationDialog from 'components/dialogs/network-modifications/generator/modification/regulating-terminal-modification-dialog'; import { getTapChangerRegulationTerminalValue } from 'components/utils/utils'; diff --git a/src/components/utils/localized-countries-hook.js b/src/components/utils/localized-countries-hook.js deleted file mode 100644 index c5c5c553aa..0000000000 --- a/src/components/utils/localized-countries-hook.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2023, 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 { useParameterState } from '../dialogs/parameters/parameters'; -import { PARAM_LANGUAGE } from '../../utils/config-params'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { getComputedLanguage } from '../../utils/language'; -import localizedCountries from 'localized-countries'; -import countriesFr from 'localized-countries/data/fr'; -import countriesEn from 'localized-countries/data/en'; - -export const useLocalizedCountries = () => { - const [languageLocal] = useParameterState(PARAM_LANGUAGE); - const [localizedCountriesModule, setLocalizedCountriesModule] = useState(); - - //TODO FM this is disgusting, can we make it better ? - useEffect(() => { - const lang = getComputedLanguage(languageLocal).substr(0, 2); - let localizedCountriesResult; - // vite does not support ESM dynamic imports on node_modules, so we have to imports the languages before and do this - // https://github.com/vitejs/vite/issues/14102 - if (lang === 'fr') { - localizedCountriesResult = localizedCountries(countriesFr); - } else if (lang === 'en') { - localizedCountriesResult = localizedCountries(countriesEn); - } else { - console.warn( - 'Unsupported language "' + - lang + - '" for countries translation, we use english as default' - ); - localizedCountriesResult = localizedCountries(countriesEn); - } - setLocalizedCountriesModule(localizedCountriesResult); - }, [languageLocal]); - - const countryCodes = useMemo( - () => - localizedCountriesModule - ? Object.keys(localizedCountriesModule.object()) - : [], - [localizedCountriesModule] - ); - - const translate = useCallback( - (countryCode) => - localizedCountriesModule - ? localizedCountriesModule.get(countryCode) - : '', - [localizedCountriesModule] - ); - - return { translate, countryCodes }; -}; diff --git a/src/components/utils/rhf-inputs/country-selection-input.jsx b/src/components/utils/rhf-inputs/country-selection-input.jsx index 38ac091559..b41ee22b44 100644 --- a/src/components/utils/rhf-inputs/country-selection-input.jsx +++ b/src/components/utils/rhf-inputs/country-selection-input.jsx @@ -5,8 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { AutocompleteInput } from '@gridsuite/commons-ui'; -import { useLocalizedCountries } from '../localized-countries-hook'; +import { + AutocompleteInput, + useLocalizedCountries, +} from '@gridsuite/commons-ui'; const CountrySelectionInput = ({ name, label, formProps, ...props }) => { const { translate, countryCodes } = useLocalizedCountries(); diff --git a/src/redux/reducer.test.ts b/src/redux/reducer.test.ts index c4a9224221..9f6be38df8 100644 --- a/src/redux/reducer.test.ts +++ b/src/redux/reducer.test.ts @@ -7,7 +7,12 @@ // Because of a circular import issue, we have to import the store to run the // unit tests, even if your IDE is showing that the import is unused. -import { Actions, AppState, reducer as appReducer } from './reducer'; +import { + Actions, + AppState, + reducer as appReducer, + initialState, +} from './reducer'; import { resetNetworkAreaDiagramDepth, incrementNetworkAreaDiagramDepth, @@ -21,9 +26,14 @@ import { stopDiagramBlink, } from './actions'; import { DiagramType, ViewState } from '../components/diagrams/diagram-common'; -import { Reducer } from 'redux'; +import { UnknownAction } from 'redux'; -const reducer = appReducer as Reducer, Actions>; +function reducer(statePatch: Partial, action: Actions) { + return appReducer( + { ...initialState, ...statePatch }, + action as UnknownAction + ); +} test('reducer.RESET_NETWORK_AREA_DIAGRAM_DEPTH', () => { const initialState = { networkAreaDiagramDepth: 12 }; diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index 04b21962e0..2219fb26fc 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -508,7 +508,8 @@ const initialSpreadsheetNetworkState: SpreadsheetNetworkState = { [EQUIPMENT_TYPES.BUS]: null, }; -const initialState: AppState = { +// exported only for reducer's tests +export const initialState: AppState = { studyUuid: null, currentTreeNode: null, selectionForCopy: { diff --git a/src/redux/store.ts b/src/redux/store.ts index 23fe288508..9a819239cc 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -8,9 +8,11 @@ import { legacy_createStore as createStore, Store } from 'redux'; import { Actions, AppState, reducer } from './reducer'; import { setCommonStore } from '@gridsuite/commons-ui'; +import { setUserStore } from './user-store'; export const store = createStore(reducer); setCommonStore(store); +setUserStore(store); export type AppDispatch = Store['dispatch']; // to avoid to reset the state with HMR diff --git a/src/redux/user-store.ts b/src/redux/user-store.ts new file mode 100644 index 0000000000..ca5131ed45 --- /dev/null +++ b/src/redux/user-store.ts @@ -0,0 +1,45 @@ +/* + * 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/. + */ + +/* + * This file is only to break the cyclic dependency in reducer.test + reducers + store + * TODO: remove when upgrading to next commons-ui version + */ +/* + at src/redux/store.ts:12:33 + at src/services/utils.js:7:1 + at src/services/study/index.js:8:1 + at src/components/utils/inputs/input-hooks.jsx:41:1 + at src/components/dialogs/commons/modification-dialog-content.jsx:19:1 + at src/components/dialogs/commons/modificationDialog.jsx:12:1 + at src/components/dialogs/network-modifications/generator/modification/regulating-terminal-modification-dialog.jsx:23:1 + at src/components/spreadsheet/utils/equipment-table-editors.jsx:25:1 + at src/components/spreadsheet/utils/config-tables.js:11:1 + at src/redux/reducer.ts:192:1 + at src/redux/reducer.test.ts:10:1 + */ + +import { User } from 'oidc-client'; + +type UserStoreState = { + user: User | null; +}; + +interface UserStore { + getState(): UserStoreState; +} + +let userStore: UserStore | undefined; + +export function setUserStore(store: UserStore): void { + userStore = store; +} + +//TODO use the one from commons-ui instead when exported in next version +export function getUserToken() { + return userStore?.getState().user?.id_token ?? undefined; +} diff --git a/src/services/directory-notification.js b/src/services/directory-notification.js index e6f8e39c48..ce590803d3 100644 --- a/src/services/directory-notification.js +++ b/src/services/directory-notification.js @@ -6,7 +6,8 @@ */ import ReconnectingWebSocket from 'reconnecting-websocket'; -import { getToken, getUrlWithToken, getWsBase } from './utils'; +import { getUrlWithToken, getWsBase } from './utils'; +import { getUserToken } from '../redux/user-store'; const PREFIX_DIRECTORY_NOTIFICATION_WS = import.meta.env.VITE_WS_GATEWAY + '/directory-notification'; @@ -38,7 +39,7 @@ export function connectNotificationsWsUpdateDirectories() { const webSocketUrl = `${webSocketBaseUrl}${PREFIX_DIRECTORY_NOTIFICATION_WS}/notify?updateType=directories`; const reconnectingWebSocket = new ReconnectingWebSocket( - () => `${webSocketUrl}&access_token=${getToken()}` + () => `${webSocketUrl}&access_token=${getUserToken()}` ); reconnectingWebSocket.onopen = function () { console.info( diff --git a/src/services/utils.js b/src/services/utils.js index bbf59cd1e5..f5f8506f0c 100644 --- a/src/services/utils.js +++ b/src/services/utils.js @@ -4,8 +4,8 @@ * 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 { store } from '../redux/store'; import { fetchAppsMetadata } from '@gridsuite/commons-ui'; +import { getUserToken } from '../redux/user-store'; export const FetchStatus = { SUCCEED: 'SUCCEED', @@ -68,11 +68,6 @@ const handleError = (response) => { }); }; -export const getToken = () => { - const state = store.getState(); - return state.user.id_token; -}; - const prepareRequest = (init, token) => { if (!(typeof init == 'undefined' || typeof init == 'object')) { throw new TypeError( @@ -81,7 +76,7 @@ const prepareRequest = (init, token) => { } const initCopy = Object.assign({}, init); initCopy.headers = new Headers(initCopy.headers || {}); - const tokenCopy = token ? token : getToken(); + const tokenCopy = token ? token : getUserToken(); initCopy.headers.append('Authorization', 'Bearer ' + tokenCopy); return initCopy; }; @@ -180,9 +175,9 @@ export const getQueryParamsList = (params, paramName) => { export function getUrlWithToken(baseUrl) { if (baseUrl.includes('?')) { - return baseUrl + '&access_token=' + getToken(); + return baseUrl + '&access_token=' + getUserToken(); } else { - return baseUrl + '?access_token=' + getToken(); + return baseUrl + '?access_token=' + getUserToken(); } } From 651fe8d82d8842630211da8855cf7e9347f227e8 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Wed, 24 Jul 2024 14:44:09 +0200 Subject: [PATCH 6/9] jest doesn't support ts enum --- src/redux/reducer.test.ts | 27 +++++++++++---------------- src/redux/reducer.ts | 8 ++++---- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/redux/reducer.test.ts b/src/redux/reducer.test.ts index 9f6be38df8..caa734dc39 100644 --- a/src/redux/reducer.test.ts +++ b/src/redux/reducer.test.ts @@ -10,30 +10,25 @@ import { Actions, AppState, - reducer as appReducer, initialState, + reducer as appReducer, } from './reducer'; import { - resetNetworkAreaDiagramDepth, - incrementNetworkAreaDiagramDepth, - decrementNetworkAreaDiagramDepth, - setFullScreenDiagram, - openDiagram, - minimizeDiagram, - togglePinDiagram, closeDiagram, closeDiagrams, + decrementNetworkAreaDiagramDepth, + incrementNetworkAreaDiagramDepth, + minimizeDiagram, + openDiagram, + resetNetworkAreaDiagramDepth, + setFullScreenDiagram, stopDiagramBlink, + togglePinDiagram, } from './actions'; import { DiagramType, ViewState } from '../components/diagrams/diagram-common'; -import { UnknownAction } from 'redux'; +import { Reducer } from 'redux'; -function reducer(statePatch: Partial, action: Actions) { - return appReducer( - { ...initialState, ...statePatch }, - action as UnknownAction - ); -} +const reducer = appReducer as Reducer, Actions>; test('reducer.RESET_NETWORK_AREA_DIAGRAM_DEPTH', () => { const initialState = { networkAreaDiagramDepth: 12 }; @@ -110,7 +105,7 @@ test('reducer.SET_FULLSCREEN_DIAGRAM', () => { svgType: DiagramType.NETWORK_AREA_DIAGRAM, }, }; - const expectedState3 = { fullScreenDiagram: { id: null } }; + const expectedState3 = { fullScreenDiagram: null }; expect(reducer(initialState3, setFullScreenDiagram(null))).toEqual( expectedState3 diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index 2219fb26fc..d971106d74 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -508,8 +508,7 @@ const initialSpreadsheetNetworkState: SpreadsheetNetworkState = { [EQUIPMENT_TYPES.BUS]: null, }; -// exported only for reducer's tests -export const initialState: AppState = { +const initialState: AppState = { studyUuid: null, currentTreeNode: null, selectionForCopy: { @@ -578,8 +577,9 @@ export const initialState: AppState = { [PARAM_LINE_FLOW_ALERT_THRESHOLD]: 100, [PARAM_MAP_MANUAL_REFRESH]: false, [PARAM_MAP_BASEMAP]: MAP_BASEMAP_MAPBOX, - [PARAM_LINE_FLOW_MODE]: LineFlowMode.FEEDERS, - [PARAM_LINE_FLOW_COLOR_MODE]: LineFlowColorMode.NOMINAL_VOLTAGE, + [PARAM_LINE_FLOW_MODE]: 'feeders' as LineFlowMode.FEEDERS, // because jest not support enum + [PARAM_LINE_FLOW_COLOR_MODE]: + 'nominalVoltage' as LineFlowColorMode.NOMINAL_VOLTAGE, // because jest not support enum [PARAM_CENTER_LABEL]: false, [PARAM_DIAGONAL_LABEL]: false, [PARAM_SUBSTATION_LAYOUT]: SubstationLayout.HORIZONTAL, From d53efc323fc07a150a03936cf5cdcd5d2bf755e3 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Wed, 31 Jul 2024 16:52:06 +0200 Subject: [PATCH 7/9] review --- .../by-formula/formula/formula-form.tsx | 4 +-- .../by-formula/formula/formula-utils.tsx | 26 ++++++++++++++++--- .../event-modification-scenario-editor.tsx | 3 ++- .../graph/network-modification-tree-model.js | 4 ++- .../sensitivity-analysis-result-tab.jsx | 1 - src/components/spreadsheet/table-wrapper.jsx | 1 - .../utils/equipment-table-utils.ts | 2 +- src/redux/actions.ts | 18 ++++++++----- 8 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx b/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx index f140ca68a7..d43833fadc 100644 --- a/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx +++ b/src/components/dialogs/network-modifications/by-formula/formula/formula-form.tsx @@ -26,7 +26,7 @@ import { useIntl } from 'react-intl'; import Grid from '@mui/material/Grid'; interface FormulaProps { - name: String; + name: string; index: number; } @@ -45,7 +45,7 @@ const FormulaForm: FunctionComponent = ({ name, index }) => { const intl = useIntl(); const equipmentFields: { id: string; label: string }[] = - // @ts-expect-error TODO: conflicts types + // @ts-expect-error TODO: missing type in context EQUIPMENTS_FIELDS?.[equipmentTypeWatch] ?? []; const filtersField = ( diff --git a/src/components/dialogs/network-modifications/by-formula/formula/formula-utils.tsx b/src/components/dialogs/network-modifications/by-formula/formula/formula-utils.tsx index f215745659..9f01b16d43 100644 --- a/src/components/dialogs/network-modifications/by-formula/formula/formula-utils.tsx +++ b/src/components/dialogs/network-modifications/by-formula/formula/formula-utils.tsx @@ -21,7 +21,22 @@ import { import yup from 'components/utils/yup-config'; import { AnyObject, TestContext, TestFunction } from 'yup'; -export const EQUIPMENTS_FIELDS = { +export type EquipmentField = { + id: string; + label: string; +}; +type EquipmentFieldsKeys = + | EQUIPMENT_TYPES.GENERATOR + | EQUIPMENT_TYPES.BATTERY + | EQUIPMENT_TYPES.SHUNT_COMPENSATOR + | EQUIPMENT_TYPES.VOLTAGE_LEVEL + | EQUIPMENT_TYPES.LOAD + | EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER; +type EquipmentFields = { + [key in EquipmentFieldsKeys]: EquipmentField[]; +}; + +export const EQUIPMENTS_FIELDS: EquipmentFields = { [EQUIPMENT_TYPES.GENERATOR]: [ { id: 'RATED_NOMINAL_POWER', label: 'RatedNominalPowerText' }, { id: 'MINIMUM_ACTIVE_POWER', label: 'MinimumActivePowerText' }, @@ -93,13 +108,16 @@ export const EQUIPMENTS_FIELDS = { ], }; -function isValueInEquipmentFields(context: TestContext, value: any) { +function isValueInEquipmentFields( + context: TestContext, + value: string +) { // this will return the highest level parent, so we can get the equipment type const parent = context.from?.[context.from.length - 1]; const equipmentType = parent?.value?.[EQUIPMENT_TYPE_FIELD]; return parent - ? // @ts-expect-error TODO: conflicts types - EQUIPMENTS_FIELDS[equipmentType]?.some( + ? // @ts-expect-error TODO: missing type in context + EQUIPMENTS_FIELDS[equipmentType!]?.some( (field: { id: string; label: string }) => field.id === value ) : false; 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 2214d88b50..56d30c55b0 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 @@ -30,6 +30,7 @@ import { EVENT_CRUD_FINISHED, EventCrudType, } from 'components/network/constants.type'; +import { UUID } from 'crypto'; import { AppState, StudyUpdated } from '../../../../redux/reducer'; import { Event, @@ -64,7 +65,7 @@ const EventModificationScenarioEditor = () => { const [events, setEvents] = useState([]); const currentNode = useSelector((state: AppState) => state.currentTreeNode); - const currentNodeIdRef = useRef(); // initial empty to get first update + const currentNodeIdRef = useRef(); // initial empty to get first update const [pendingState, setPendingState] = useState(false); const [selectedItems, setSelectedItems] = useState([]); diff --git a/src/components/graph/network-modification-tree-model.js b/src/components/graph/network-modification-tree-model.js index d9d7d4a63b..1169a43cfc 100644 --- a/src/components/graph/network-modification-tree-model.js +++ b/src/components/graph/network-modification-tree-model.js @@ -8,6 +8,7 @@ import { getLayoutedNodes } from './layout'; import { convertNodetoReactFlowModelNode } from './util/model-functions'; import { NodeInsertModes } from '../../components/graph/nodes/node-insert-modes'; +import { BUILD_STATUS } from '../network/constants'; // Function to count children nodes for a given parentId recursively in an array of nodes. // TODO refactoring when changing NetworkModificationTreeModel as it becomes an object containing nodes @@ -232,7 +233,8 @@ export default class NetworkModificationTreeModel { setBuildingStatus() { this.isAnyNodeBuilding = this.treeNodes.find( - (node) => node?.data?.globalBuildStatus === 'BUILDING' + (node) => + node?.data?.globalBuildStatus === BUILD_STATUS.BUILDING ) !== undefined; } 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 0bfc5dc012..71bc2f4290 100644 --- a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx +++ b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.jsx @@ -65,7 +65,6 @@ const SensitivityAnalysisResultTab = ({ studyUuid, nodeUuid }) => { const { updateFilter, filterSelector } = useAggridRowFilter({ filterType: SENSITIVITY_ANALYSIS_RESULT_STORE_FIELD, filterTab: mappingTabs(sensiKind, nOrNkIndex), - // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setSensitivityAnalysisResultFilter, }); diff --git a/src/components/spreadsheet/table-wrapper.jsx b/src/components/spreadsheet/table-wrapper.jsx index ae9de51ca1..a1b33e1240 100644 --- a/src/components/spreadsheet/table-wrapper.jsx +++ b/src/components/spreadsheet/table-wrapper.jsx @@ -221,7 +221,6 @@ const TableWrapper = (props) => { const { updateFilter, filterSelector } = useAggridLocalRowFilter(gridRef, { filterType: SPREADSHEET_STORE_FIELD, filterTab: TABLES_DEFINITION_INDEXES.get(tabIndex).type, - // @ts-expect-error TODO: found how to have Action type in props type filterStoreAction: setSpreadsheetFilter, }); diff --git a/src/components/spreadsheet/utils/equipment-table-utils.ts b/src/components/spreadsheet/utils/equipment-table-utils.ts index f18e26dba6..b7154d1ac7 100644 --- a/src/components/spreadsheet/utils/equipment-table-utils.ts +++ b/src/components/spreadsheet/utils/equipment-table-utils.ts @@ -216,7 +216,7 @@ export const formatFetchedEquipments = ( equipments: IEquipment[] ) => { if (equipments && equipments?.length > 0) { - return equipments.map((equipment: any) => { + return equipments.map((equipment) => { return formatFetchedEquipment(equipmentType, equipment); }); } diff --git a/src/redux/actions.ts b/src/redux/actions.ts index b193ff896d..b391ca1229 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -737,12 +737,18 @@ export function setFullScreenDiagram( diagramIdParam: string | null, svgTypeParam?: DiagramType ): SetFullscreenDiagramAction { - return { - type: SET_FULLSCREEN_DIAGRAM, - diagramId: diagramIdParam, - // @ts-expect-error: function overload protect call - svgType: svgTypeParam, - }; + if (diagramIdParam === null) { + return { + type: SET_FULLSCREEN_DIAGRAM, + diagramId: diagramIdParam, + }; + } else { + return { + type: SET_FULLSCREEN_DIAGRAM, + diagramId: diagramIdParam, + svgType: svgTypeParam!, + }; + } } export const CHANGE_DISPLAYED_COLUMNS_NAMES = 'CHANGE_DISPLAYED_COLUMNS_NAMES'; From 66432b1cc78b93cfe41276b2848a5b8e371bc503 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Wed, 31 Jul 2024 16:49:46 +0200 Subject: [PATCH 8/9] restore `useLocalizedCountries` --- .../custom-aggrid/custom-aggrid-header.jsx | 2 +- src/components/diagrams/diagram-pane.jsx | 7 +-- .../substation-modification-form.jsx | 3 +- .../curve/dialog/equipment-filter.jsx | 7 +-- .../parameters/load-flow-parameters.jsx | 2 +- .../results/common/results-global-filter.tsx | 3 +- .../spreadsheet/country-cell-render.tsx | 9 +-- src/components/spreadsheet/table-wrapper.jsx | 3 +- .../utils/equipment-table-editors.jsx | 2 +- .../utils/localized-countries-hook.js | 58 +++++++++++++++++++ .../rhf-inputs/country-selection-input.jsx | 6 +- 11 files changed, 75 insertions(+), 27 deletions(-) create mode 100644 src/components/utils/localized-countries-hook.js diff --git a/src/components/custom-aggrid/custom-aggrid-header.jsx b/src/components/custom-aggrid/custom-aggrid-header.jsx index a2bc0b4bf6..20354662a0 100644 --- a/src/components/custom-aggrid/custom-aggrid-header.jsx +++ b/src/components/custom-aggrid/custom-aggrid-header.jsx @@ -20,13 +20,13 @@ import { } from '@mui/material'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { SortWay } from '../../hooks/use-aggrid-sort'; import { FILTER_TEXT_COMPARATORS, FILTER_DATA_TYPES, } from './custom-aggrid-header.type'; import { mergeSx } from '../utils/functions'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import CustomAggridBooleanFilter from './custom-aggrid-filters/custom-aggrid-boolean-filter'; import CustomAggridDurationFilter from './custom-aggrid-filters/custom-aggrid-duration-filter'; diff --git a/src/components/diagrams/diagram-pane.jsx b/src/components/diagrams/diagram-pane.jsx index b821509afe..c4e6274787 100644 --- a/src/components/diagrams/diagram-pane.jsx +++ b/src/components/diagrams/diagram-pane.jsx @@ -49,11 +49,7 @@ import { useNameOrId } from '../utils/equipmentInfosHandler'; import { syncDiagramStateWithSessionStorage } from '../../redux/session-storage/diagram-state'; import SingleLineDiagramContent from './singleLineDiagram/single-line-diagram-content'; import NetworkAreaDiagramContent from './networkAreaDiagram/network-area-diagram-content'; -import { - useDebounce, - useLocalizedCountries, - useSnackMessage, -} from '@gridsuite/commons-ui'; +import { useDebounce, useSnackMessage } from '@gridsuite/commons-ui'; import { setNetworkAreaDiagramNbVoltageLevels } from '../../redux/actions'; import { useIntl } from 'react-intl'; import { @@ -63,6 +59,7 @@ import { import { fetchSvg, getNetworkAreaDiagramUrl } from '../../services/study'; import { mergeSx } from '../utils/functions'; import { Box } from '@mui/system'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; // Returns a callback that returns a promise const useDisplayView = (studyUuid, currentNode) => { diff --git a/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx b/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx index 8f1cd1da73..7f82624162 100644 --- a/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx +++ b/src/components/dialogs/network-modifications/substation/modification/substation-modification-form.jsx @@ -8,9 +8,10 @@ import Grid from '@mui/material/Grid'; import { filledTextField, gridItem } from '../../../dialogUtils'; import React from 'react'; -import { TextInput, useLocalizedCountries } from '@gridsuite/commons-ui'; +import { TextInput } from '@gridsuite/commons-ui'; import { COUNTRY, EQUIPMENT_NAME } from 'components/utils/field-constants'; import CountrySelectionInput from 'components/utils/rhf-inputs/country-selection-input'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { TextField } from '@mui/material'; import PropertiesForm from '../../common/properties/properties-form'; diff --git a/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx b/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx index 4c3a854356..3ee9a6392e 100644 --- a/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx +++ b/src/components/dialogs/parameters/dynamicsimulation/curve/dialog/equipment-filter.jsx @@ -17,16 +17,13 @@ import { useState, } from 'react'; import { useSelector } from 'react-redux'; -import { - CustomAGGrid, - useLocalizedCountries, - useSnackMessage, -} from '@gridsuite/commons-ui'; +import { CustomAGGrid, useSnackMessage } from '@gridsuite/commons-ui'; import { Box } from '@mui/system'; import { fetchAllCountries } from '../../../../../../services/study/network-map'; import { evaluateJsonFilter } from '../../../../../../services/study/filter'; import { fetchVoltageLevelsMapInfos } from '../../../../../../services/study/network'; import CheckboxAutocomplete from '../../../../../utils/checkbox-autocomplete'; +import { useLocalizedCountries } from '../../../../../utils/localized-countries-hook'; import { buildExpertFilter, CURVE_EQUIPMENT_TYPES, diff --git a/src/components/dialogs/parameters/load-flow-parameters.jsx b/src/components/dialogs/parameters/load-flow-parameters.jsx index 7c7ec43542..1a5ca7940f 100644 --- a/src/components/dialogs/parameters/load-flow-parameters.jsx +++ b/src/components/dialogs/parameters/load-flow-parameters.jsx @@ -9,7 +9,6 @@ import { DirectoryItemSelector, ElementType, FlatParameters, - useLocalizedCountries, useSnackMessage, } from '@gridsuite/commons-ui'; import { Autocomplete, Box, Chip, Grid, TextField } from '@mui/material'; @@ -21,6 +20,7 @@ import { PARAM_LIMIT_REDUCTION, } from '../../../utils/config-params'; import { mergeSx } from '../../utils/functions'; +import { useLocalizedCountries } from '../../utils/localized-countries-hook'; import { replaceAllDefaultValues } from '../../utils/utils'; import { LineSeparator } from '../dialogUtils'; import CreateParameterDialog from './common/parameters-creation-dialog'; diff --git a/src/components/results/common/results-global-filter.tsx b/src/components/results/common/results-global-filter.tsx index ad5789334c..9557ea7534 100644 --- a/src/components/results/common/results-global-filter.tsx +++ b/src/components/results/common/results-global-filter.tsx @@ -10,8 +10,8 @@ import { Box, FilterOptionsState } from '@mui/material'; import { Autocomplete, Chip, InputAdornment, TextField } from '@mui/material'; import { FilterAlt } from '@mui/icons-material'; import { FormattedMessage, useIntl } from 'react-intl'; -import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { mergeSx } from '../../utils/functions'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { useDispatch, useSelector } from 'react-redux'; import { addToRecentGlobalFilters } from '../../../redux/actions'; import { Theme } from '@mui/material'; @@ -121,7 +121,6 @@ const ResultsGlobalFilter: FunctionComponent = ({ filters = emptyArray, }) => { const intl = useIntl(); - // @ts-expect-error: will be fixed in the next version of commons-ui const { translate } = useLocalizedCountries(); const dispatch = useDispatch(); const recentGlobalFilters = useSelector( diff --git a/src/components/spreadsheet/country-cell-render.tsx b/src/components/spreadsheet/country-cell-render.tsx index 6a2ef09784..3811bb4230 100644 --- a/src/components/spreadsheet/country-cell-render.tsx +++ b/src/components/spreadsheet/country-cell-render.tsx @@ -4,17 +4,14 @@ * 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 { FunctionComponent } from 'react'; -import { useLocalizedCountries } from '@gridsuite/commons-ui'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; +import React from 'react'; interface CountryCellRendererProps { value: string; } -const CountryCellRenderer: FunctionComponent = ({ - value, -}) => { - // @ts-expect-error: will be fixed in the next version of commons-ui +const CountryCellRenderer: React.FC = ({ value }) => { const { translate } = useLocalizedCountries(); const countryName = translate(value); return {countryName}; diff --git a/src/components/spreadsheet/table-wrapper.jsx b/src/components/spreadsheet/table-wrapper.jsx index a1b33e1240..708196a46b 100644 --- a/src/components/spreadsheet/table-wrapper.jsx +++ b/src/components/spreadsheet/table-wrapper.jsx @@ -20,7 +20,7 @@ import { TABLES_NAMES, } from './utils/config-tables'; import { EquipmentTable } from './equipment-table'; -import { useLocalizedCountries, useSnackMessage } from '@gridsuite/commons-ui'; +import { useSnackMessage } from '@gridsuite/commons-ui'; import { PARAM_FLUX_CONVENTION } from '../../utils/config-params'; import { RunningStatus } from '../utils/running-status'; import { @@ -82,6 +82,7 @@ import { makeAgGridCustomHeaderColumn } from 'components/custom-aggrid/custom-ag import { useAggridLocalRowFilter } from 'hooks/use-aggrid-local-row-filter'; import { useAgGridSort } from 'hooks/use-aggrid-sort'; import { setSpreadsheetFilter } from 'redux/actions'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import { SPREADSHEET_SORT_STORE, SPREADSHEET_STORE_FIELD, diff --git a/src/components/spreadsheet/utils/equipment-table-editors.jsx b/src/components/spreadsheet/utils/equipment-table-editors.jsx index ff9f03e583..3b4445b0a8 100644 --- a/src/components/spreadsheet/utils/equipment-table-editors.jsx +++ b/src/components/spreadsheet/utils/equipment-table-editors.jsx @@ -17,11 +17,11 @@ import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { Autocomplete, TextField, Tooltip } from '@mui/material'; import { FormattedMessage, useIntl } from 'react-intl'; -import { useLocalizedCountries } from '@gridsuite/commons-ui'; import { checkValidationsAndRefreshCells, deepUpdateValue, } from './equipment-table-utils'; +import { useLocalizedCountries } from 'components/utils/localized-countries-hook'; import RegulatingTerminalModificationDialog from 'components/dialogs/network-modifications/generator/modification/regulating-terminal-modification-dialog'; import { getTapChangerRegulationTerminalValue } from 'components/utils/utils'; diff --git a/src/components/utils/localized-countries-hook.js b/src/components/utils/localized-countries-hook.js new file mode 100644 index 0000000000..c5c5c553aa --- /dev/null +++ b/src/components/utils/localized-countries-hook.js @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2023, 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 { useParameterState } from '../dialogs/parameters/parameters'; +import { PARAM_LANGUAGE } from '../../utils/config-params'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { getComputedLanguage } from '../../utils/language'; +import localizedCountries from 'localized-countries'; +import countriesFr from 'localized-countries/data/fr'; +import countriesEn from 'localized-countries/data/en'; + +export const useLocalizedCountries = () => { + const [languageLocal] = useParameterState(PARAM_LANGUAGE); + const [localizedCountriesModule, setLocalizedCountriesModule] = useState(); + + //TODO FM this is disgusting, can we make it better ? + useEffect(() => { + const lang = getComputedLanguage(languageLocal).substr(0, 2); + let localizedCountriesResult; + // vite does not support ESM dynamic imports on node_modules, so we have to imports the languages before and do this + // https://github.com/vitejs/vite/issues/14102 + if (lang === 'fr') { + localizedCountriesResult = localizedCountries(countriesFr); + } else if (lang === 'en') { + localizedCountriesResult = localizedCountries(countriesEn); + } else { + console.warn( + 'Unsupported language "' + + lang + + '" for countries translation, we use english as default' + ); + localizedCountriesResult = localizedCountries(countriesEn); + } + setLocalizedCountriesModule(localizedCountriesResult); + }, [languageLocal]); + + const countryCodes = useMemo( + () => + localizedCountriesModule + ? Object.keys(localizedCountriesModule.object()) + : [], + [localizedCountriesModule] + ); + + const translate = useCallback( + (countryCode) => + localizedCountriesModule + ? localizedCountriesModule.get(countryCode) + : '', + [localizedCountriesModule] + ); + + return { translate, countryCodes }; +}; diff --git a/src/components/utils/rhf-inputs/country-selection-input.jsx b/src/components/utils/rhf-inputs/country-selection-input.jsx index b41ee22b44..38ac091559 100644 --- a/src/components/utils/rhf-inputs/country-selection-input.jsx +++ b/src/components/utils/rhf-inputs/country-selection-input.jsx @@ -5,10 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { - AutocompleteInput, - useLocalizedCountries, -} from '@gridsuite/commons-ui'; +import { AutocompleteInput } from '@gridsuite/commons-ui'; +import { useLocalizedCountries } from '../localized-countries-hook'; const CountrySelectionInput = ({ name, label, formProps, ...props }) => { const { translate, countryCodes } = useLocalizedCountries(); From bb829964afe9eb9d9e1fd387f11093d225e037bd Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 1 Aug 2024 14:42:31 +0200 Subject: [PATCH 9/9] fix cyclic dependency --- src/components/horizontal-toolbar.jsx | 2 +- src/components/map-viewer.jsx | 3 ++- src/components/network-modification-tree-pane.jsx | 2 +- src/components/network-modification-tree.jsx | 2 +- src/components/network-modification.type.ts | 14 ++++++++++++++ .../use-disabled-search-reason.tsx | 7 ++----- src/redux/actions.ts | 2 +- src/redux/reducer.ts | 8 +------- 8 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 src/components/network-modification.type.ts diff --git a/src/components/horizontal-toolbar.jsx b/src/components/horizontal-toolbar.jsx index 8e3048d956..822f1500e6 100644 --- a/src/components/horizontal-toolbar.jsx +++ b/src/components/horizontal-toolbar.jsx @@ -23,7 +23,7 @@ import { TOOLTIP_DELAY } from '../utils/UIconstants'; import OfflineBoltOutlinedIcon from '@mui/icons-material/OfflineBoltOutlined'; import { useParameterState } from './dialogs/parameters/parameters'; import { PARAM_DEVELOPER_MODE } from '../utils/config-params'; -import { StudyDisplayMode } from 'redux/reducer'; +import { StudyDisplayMode } from './network-modification.type'; const styles = { selected: (theme) => ({ diff --git a/src/components/map-viewer.jsx b/src/components/map-viewer.jsx index e49a5dc9cd..558132e4e6 100644 --- a/src/components/map-viewer.jsx +++ b/src/components/map-viewer.jsx @@ -28,11 +28,12 @@ import { darken } from '@mui/material/styles'; import ComputingType from './computing-status/computing-type'; import { useIntl } from 'react-intl'; import { useSnackMessage } from '@gridsuite/commons-ui'; -import { StudyDisplayMode } from 'redux/reducer'; import { Global, css } from '@emotion/react'; import { EQUIPMENT_TYPES } from './utils/equipment-types'; import SelectionCreationPanel from './network/selection-creation-panel'; +import { StudyDisplayMode } from './network-modification.type'; + const styles = { map: { display: 'flex', diff --git a/src/components/network-modification-tree-pane.jsx b/src/components/network-modification-tree-pane.jsx index 59cad25185..2b752f9338 100644 --- a/src/components/network-modification-tree-pane.jsx +++ b/src/components/network-modification-tree-pane.jsx @@ -41,7 +41,7 @@ import { import { buildNode, getUniqueNodeName, unbuildNode } from '../services/study'; import RestoreNodesDialog from './dialogs/restore-node-dialog'; import ScenarioEditor from './graph/menus/dynamic-simulation/scenario-editor'; -import { StudyDisplayMode } from '../redux/reducer'; +import { StudyDisplayMode } from './network-modification.type'; const styles = { container: { diff --git a/src/components/network-modification-tree.jsx b/src/components/network-modification-tree.jsx index 2c4d41df29..8a07cbc3ba 100644 --- a/src/components/network-modification-tree.jsx +++ b/src/components/network-modification-tree.jsx @@ -28,7 +28,7 @@ import { useIntl } from 'react-intl'; import CropFreeIcon from '@mui/icons-material/CropFree'; import { nodeTypes } from './graph/util/model-constants'; import { BUILD_STATUS } from './network/constants'; -import { StudyDisplayMode } from '../redux/reducer'; +import { StudyDisplayMode } from './network-modification.type'; // snapGrid value set to [15, 15] which is the default value for ReactFlow // it has to be explicitly set as prop of the ReactFlow component, even if snapToGrid option is set to false diff --git a/src/components/network-modification.type.ts b/src/components/network-modification.type.ts new file mode 100644 index 0000000000..a9d3ad66d8 --- /dev/null +++ b/src/components/network-modification.type.ts @@ -0,0 +1,14 @@ +/* + * 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/. + */ + +// move here because of cyclic dependency between reducer and network-modification-tree-pane & network-modification-tree +export enum StudyDisplayMode { + MAP = 'Map', + TREE = 'Tree', + HYBRID = 'Hybrid', + DRAW = 'Draw', +} diff --git a/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx b/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx index 47227cb5c3..d4ad6c0a09 100644 --- a/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx +++ b/src/components/top-bar-equipment-seach-dialog/use-disabled-search-reason.tsx @@ -7,11 +7,8 @@ import { isNodeBuilt } from 'components/graph/util/model-functions'; import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; -import { - AppState, - StudyDisplayMode, - StudyIndexationStatus, -} from 'redux/reducer'; +import { AppState, StudyIndexationStatus } from 'redux/reducer'; +import { StudyDisplayMode } from '../network-modification.type'; export const useDisabledSearchReason = () => { const intl = useIntl(); diff --git a/src/redux/actions.ts b/src/redux/actions.ts index b391ca1229..1680c55375 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -48,7 +48,6 @@ import { OneBusShortCircuitAnalysisDiagram, SelectionForCopy, SpreadsheetEquipmentType, - StudyDisplayMode, StudyIndexationStatus, StudyUpdatedEventData, TableSortKeysType, @@ -71,6 +70,7 @@ import { SPREADSHEET_STORE_FIELD, } from '../utils/store-sort-filter-fields'; import { SortConfigType } from '../hooks/use-aggrid-sort'; +import { StudyDisplayMode } from '../components/network-modification.type'; type MutableUnknownArray = unknown[]; diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index f7ecd4c4f8..c3050efcdf 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -280,6 +280,7 @@ import { IEquipment } from '../services/study/contingency-list'; import { Node } from 'react-flow-renderer'; import { BUILD_STATUS } from '../components/network/constants'; import { SortConfigType, SortWay } from '../hooks/use-aggrid-sort'; +import { StudyDisplayMode } from '../components/network-modification.type'; export enum NotificationType { STUDY = 'study', @@ -291,13 +292,6 @@ export enum StudyIndexationStatus { INDEXED = 'INDEXED', } -export enum StudyDisplayMode { - MAP = 'Map', - TREE = 'Tree', - HYBRID = 'Hybrid', - DRAW = 'Draw', -} - export interface OneBusShortCircuitAnalysisDiagram { diagramId: string; nodeId: UUID;