From 28a204ad70461d5ef310c74602b6a98daf0ef09c Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 15 Jan 2026 16:19:15 +0100 Subject: [PATCH 1/4] Adapt diagrams to new error handling setup --- package.json | 2 +- src/components/workspace/diagrams/nad/use-nad-diagram.ts | 8 ++++---- src/components/workspace/diagrams/sld/use-sld-diagram.ts | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 06cfe73d3e..db2b1eae9d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@gridsuite/commons-ui": "0.153.0", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.154.0.tgz", "@hello-pangea/dnd": "^18.0.1", "@hookform/resolvers": "^4.1.3", "@mui/icons-material": "^5.18.0", diff --git a/src/components/workspace/diagrams/nad/use-nad-diagram.ts b/src/components/workspace/diagrams/nad/use-nad-diagram.ts index 0280374c02..6a70225ccd 100644 --- a/src/components/workspace/diagrams/nad/use-nad-diagram.ts +++ b/src/components/workspace/diagrams/nad/use-nad-diagram.ts @@ -8,7 +8,7 @@ import type { UUID } from 'node:crypto'; import { useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useSnackMessage } from '@gridsuite/commons-ui'; +import { snackWithFallback, useSnackMessage } from '@gridsuite/commons-ui'; import { AppState } from '../../../../redux/reducer'; import { DiagramType, NetworkAreaDiagram } from '../../../grid-layout/cards/diagrams/diagram.type'; import { fetchSvg, getNetworkAreaDiagramUrl } from '../../../../services/study'; @@ -131,15 +131,15 @@ export const useNadDiagram = ({ panelId, studyUuid, currentNodeId, currentRootNe let errorMessage: string; if (error?.status === 400) { errorMessage = 'nadConfiguredPositionsModeFailed'; - snackError({ headerId: errorMessage }); + snackWithFallback(snackError, error, { headerId: errorMessage }); } else if (error?.status === 404) { errorMessage = 'VoltageLevelNotFound'; } else if (error?.status === 403) { errorMessage = error.message || 'svgLoadingFail'; - snackError({ headerId: errorMessage }); + snackWithFallback(snackError, error, { headerId: errorMessage }); } else { errorMessage = 'svgLoadingFail'; - snackError({ headerId: errorMessage }); + snackWithFallback(snackError, error, { headerId: errorMessage }); } setGlobalError(errorMessage); }, diff --git a/src/components/workspace/diagrams/sld/use-sld-diagram.ts b/src/components/workspace/diagrams/sld/use-sld-diagram.ts index e426b84268..e9526c204e 100644 --- a/src/components/workspace/diagrams/sld/use-sld-diagram.ts +++ b/src/components/workspace/diagrams/sld/use-sld-diagram.ts @@ -8,7 +8,7 @@ import type { UUID } from 'node:crypto'; import { useCallback, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { useSnackMessage, PARAM_LANGUAGE } from '@gridsuite/commons-ui'; +import { useSnackMessage, PARAM_LANGUAGE, snackWithFallback } from '@gridsuite/commons-ui'; import { AppState } from '../../../../redux/reducer'; import { Diagram, DiagramType } from '../../../grid-layout/cards/diagrams/diagram.type'; import { fetchSvg } from '../../../../services/study'; @@ -65,6 +65,7 @@ export const useSldDiagram = ({ const handleFetchError = useCallback( (error: any) => { + console.log(error); console.error('Error fetching SLD diagram:', error); let errorMessage: string; if (error?.status === 404) { @@ -76,11 +77,11 @@ export const useSldDiagram = ({ }); } else if (error?.status === 403) { errorMessage = error.message || 'svgLoadingFail'; - snackError({ headerId: errorMessage }); + snackWithFallback(snackError, error, { headerId: errorMessage }); setGlobalError(errorMessage); } else { errorMessage = 'svgLoadingFail'; - snackError({ headerId: errorMessage }); + snackWithFallback(snackError, error, { headerId: errorMessage }); setGlobalError(errorMessage); } }, From 54a784ce9e4cb8aa95cfaf06ca3d5715077f222c Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 15 Jan 2026 17:10:52 +0100 Subject: [PATCH 2/4] Remove debug message --- src/components/workspace/diagrams/sld/use-sld-diagram.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/workspace/diagrams/sld/use-sld-diagram.ts b/src/components/workspace/diagrams/sld/use-sld-diagram.ts index e9526c204e..d55d2bf8ab 100644 --- a/src/components/workspace/diagrams/sld/use-sld-diagram.ts +++ b/src/components/workspace/diagrams/sld/use-sld-diagram.ts @@ -65,7 +65,6 @@ export const useSldDiagram = ({ const handleFetchError = useCallback( (error: any) => { - console.log(error); console.error('Error fetching SLD diagram:', error); let errorMessage: string; if (error?.status === 404) { From 607233bf76ddbccb17d5514d3ff2abf402c92678 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 28 Jan 2026 11:19:36 +0100 Subject: [PATCH 3/4] Temp update commons ui --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b68481175f..9ad1fb1f0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@gridsuite/commons-ui": "0.161.0", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.161.0.tgz", "@hello-pangea/dnd": "^18.0.1", "@hookform/resolvers": "^4.1.3", "@mui/icons-material": "^5.18.0", @@ -3290,8 +3290,8 @@ }, "node_modules/@gridsuite/commons-ui": { "version": "0.161.0", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.161.0.tgz", - "integrity": "sha512-oFCLfSOxAOzXQuK4ovqG9mQk5hHu0IlnARkZA97K9N2MKC7bbQTQlorvBkZbAJ+ZNwptmAZRvIXA9z2fHrgD1g==", + "resolved": "file:../commons-ui/gridsuite-commons-ui-0.161.0.tgz", + "integrity": "sha512-XWQH4UyNL8IO067ITSyVpv0cBiRDl4RmkUscH8WE6JjG5BRDo2bsbM+GDM4dOgLFNo6lj1SaC7sdnCb/M1nEDw==", "license": "MPL-2.0", "dependencies": { "@ag-grid-community/locale": "^33.3.2", diff --git a/package.json b/package.json index c12188fec4..42752c8d4f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@gridsuite/commons-ui": "0.161.0", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.161.0.tgz", "@hello-pangea/dnd": "^18.0.1", "@hookform/resolvers": "^4.1.3", "@mui/icons-material": "^5.18.0", From 63b8bcedc1af752796928c2472b5f552a7a975e0 Mon Sep 17 00:00:00 2001 From: Slimane AMAR Date: Wed, 11 Feb 2026 19:18:11 +0100 Subject: [PATCH 4/4] Review --- src/components/report-viewer-tab.jsx | 2 +- src/components/result-view-tab.tsx | 2 +- .../utils/alert-custom-message-node.tsx | 6 ++-- .../workspace/diagrams/diagram-wrapper.tsx | 3 +- .../workspace/diagrams/nad/use-nad-diagram.ts | 34 +++++-------------- .../workspace/diagrams/sld/use-sld-diagram.ts | 33 ++++-------------- src/translations/en.json | 4 --- src/translations/fr.json | 4 --- 8 files changed, 21 insertions(+), 67 deletions(-) diff --git a/src/components/report-viewer-tab.jsx b/src/components/report-viewer-tab.jsx index 8ab9d38c6d..3edd34b91f 100644 --- a/src/components/report-viewer-tab.jsx +++ b/src/components/report-viewer-tab.jsx @@ -131,7 +131,7 @@ export const ReportViewerTab = ({ visible, currentNode, disabled }) => { return ( <> - {disabled && } + {disabled && } {!disabled && !!report && ( diff --git a/src/components/result-view-tab.tsx b/src/components/result-view-tab.tsx index 639aecefcb..ff016307c5 100644 --- a/src/components/result-view-tab.tsx +++ b/src/components/result-view-tab.tsx @@ -319,7 +319,7 @@ export const ResultViewTab: FunctionComponent = ({ {services.map((service) => renderTab(service))} - {disabled && } + {disabled && } {services.map((service, index) => renderTabPanelLazy(service, index))} diff --git a/src/components/utils/alert-custom-message-node.tsx b/src/components/utils/alert-custom-message-node.tsx index ab7a3ef652..8d5eb914db 100644 --- a/src/components/utils/alert-custom-message-node.tsx +++ b/src/components/utils/alert-custom-message-node.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { mergeSx, type MuiStyles, type SxStyle } from '@gridsuite/commons-ui'; +import { ErrorMessageDescriptor, mergeSx, type MuiStyles, type SxStyle } from '@gridsuite/commons-ui'; import Alert from '@mui/material/Alert'; import { FormattedMessage } from 'react-intl'; @@ -18,7 +18,7 @@ const styles = { } as const satisfies MuiStyles; interface AlertCustomMessageNodeProps { - message: string; + message: ErrorMessageDescriptor; noMargin?: boolean; style?: SxStyle; } @@ -28,7 +28,7 @@ const AlertCustomMessageNode = (props: AlertCustomMessageNodeProps) => { return ( - + ); }; diff --git a/src/components/workspace/diagrams/diagram-wrapper.tsx b/src/components/workspace/diagrams/diagram-wrapper.tsx index 1ee978b1f2..7487b6571d 100644 --- a/src/components/workspace/diagrams/diagram-wrapper.tsx +++ b/src/components/workspace/diagrams/diagram-wrapper.tsx @@ -9,11 +9,12 @@ import { Box, CircularProgress } from '@mui/material'; import { ReactNode } from 'react'; import AlertCustomMessageNode from '../../utils/alert-custom-message-node'; import { cardStyles } from '../../grid-layout/cards/card-styles'; +import { ErrorMessageDescriptor } from '@gridsuite/commons-ui'; interface DiagramWrapperProps { loading: boolean; hasSvg: boolean; - globalError?: string; + globalError?: ErrorMessageDescriptor; children: ReactNode; } diff --git a/src/components/workspace/diagrams/nad/use-nad-diagram.ts b/src/components/workspace/diagrams/nad/use-nad-diagram.ts index 83be11cb68..a8719b88b5 100644 --- a/src/components/workspace/diagrams/nad/use-nad-diagram.ts +++ b/src/components/workspace/diagrams/nad/use-nad-diagram.ts @@ -8,16 +8,16 @@ import type { UUID } from 'node:crypto'; import { useCallback, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { snackWithFallback, useSnackMessage } from '@gridsuite/commons-ui'; +import { ErrorMessageDescriptor, extractErrorMessageDescriptor } from '@gridsuite/commons-ui'; import { AppState } from '../../../../redux/reducer'; import { DiagramType, NetworkAreaDiagram } from '../../../grid-layout/cards/diagrams/diagram.type'; import { fetchSvg, getNetworkAreaDiagramUrl } from '../../../../services/study'; -import { saveNadConfig, deleteNadConfig } from '../../../../services/study/workspace'; +import { deleteNadConfig, saveNadConfig } from '../../../../services/study/workspace'; import { mergePositions } from '../../../grid-layout/cards/diagrams/diagram-utils'; import type { DiagramMetadata } from '@powsybl/network-viewer'; import { useDiagramNotifications } from '../common/use-diagram-notifications'; import { isNodeBuilt } from '../../../graph/util/model-functions'; -import { selectNadDiagramFields, selectActiveWorkspaceId } from '../../../../redux/slices/workspace-selectors'; +import { selectActiveWorkspaceId, selectNadDiagramFields } from '../../../../redux/slices/workspace-selectors'; import type { RootState } from '../../../../redux/store'; import { useWorkspacePanelActions } from '../../hooks/use-workspace-panel-actions'; import { PERSISTENT_NAD_FIELDS } from '../../types/workspace.types'; @@ -66,7 +66,6 @@ export const useNadDiagram = ({ panelId, studyUuid, currentNodeId, currentRootNe const workspaceId = useSelector((state: RootState) => selectActiveWorkspaceId(state)); const currentNode = useSelector((state: AppState) => state.currentTreeNode); const networkVisuParams = useSelector((state: AppState) => state.networkVisualizationsParameters); - const { snackError } = useSnackMessage(); const [diagram, setDiagram] = useState(() => ({ type: DiagramType.NETWORK_AREA_DIAGRAM, @@ -83,7 +82,7 @@ export const useNadDiagram = ({ panelId, studyUuid, currentNodeId, currentRootNe positions: [], })); const [loading, setLoading] = useState(false); - const [globalError, setGlobalError] = useState(); + const [globalError, setGlobalError] = useState(); const setDiagramAndSync = useCallback( (updater: React.SetStateAction, syncToBackend = true) => { @@ -127,30 +126,13 @@ export const useNadDiagram = ({ panelId, studyUuid, currentNodeId, currentRootNe [setDiagramAndSync] ); - const handleFetchError = useCallback( - (error: any) => { - console.error('Error fetching NAD diagram:', error); - let errorMessage: string; - if (error?.status === 400) { - errorMessage = 'nadConfiguredPositionsModeFailed'; - snackWithFallback(snackError, error, { headerId: errorMessage }); - } else if (error?.status === 404) { - errorMessage = 'VoltageLevelNotFound'; - } else if (error?.status === 403) { - errorMessage = error.message || 'svgLoadingFail'; - snackWithFallback(snackError, error, { headerId: errorMessage }); - } else { - errorMessage = 'svgLoadingFail'; - snackWithFallback(snackError, error, { headerId: errorMessage }); - } - setGlobalError(errorMessage); - }, - [snackError] - ); + const handleFetchError = useCallback((error: any) => { + setGlobalError(extractErrorMessageDescriptor(error, '')); + }, []); const fetchDiagram = useCallback(() => { if (!currentNode || !isNodeBuilt(currentNode)) { - setGlobalError('InvalidNode'); + setGlobalError({ descriptor: { id: 'InvalidNode' } }); return Promise.resolve(); } diff --git a/src/components/workspace/diagrams/sld/use-sld-diagram.ts b/src/components/workspace/diagrams/sld/use-sld-diagram.ts index f1320fe3ff..1b517dfbcc 100644 --- a/src/components/workspace/diagrams/sld/use-sld-diagram.ts +++ b/src/components/workspace/diagrams/sld/use-sld-diagram.ts @@ -8,7 +8,7 @@ import type { UUID } from 'node:crypto'; import { useCallback, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { useSnackMessage, PARAM_LANGUAGE, snackWithFallback } from '@gridsuite/commons-ui'; +import { ErrorMessageDescriptor, extractErrorMessageDescriptor, PARAM_LANGUAGE } from '@gridsuite/commons-ui'; import { AppState } from '../../../../redux/reducer'; import { Diagram, DiagramType } from '../../../grid-layout/cards/diagrams/diagram.type'; import { fetchSvg } from '../../../../services/study'; @@ -41,7 +41,6 @@ export const useSldDiagram = ({ const networkVisuParams = useSelector((state: AppState) => state.networkVisualizationsParameters); const paramUseName = useSelector((state: AppState) => state[PARAM_USE_NAME]); const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]); - const { snackError } = useSnackMessage(); const [diagram, setDiagram] = useState( () => @@ -52,7 +51,7 @@ export const useSldDiagram = ({ }) as Diagram ); const [loading, setLoading] = useState(false); - const [globalError, setGlobalError] = useState(); + const [globalError, setGlobalError] = useState(); // Helper to process SVG data - extracted to reduce nesting const processSvgData = useCallback((svgData: any) => { @@ -61,29 +60,9 @@ export const useSldDiagram = ({ } }, []); - const handleFetchError = useCallback( - (error: any) => { - console.error('Error fetching SLD diagram:', error); - let errorMessage: string; - if (error?.status === 404) { - setDiagram((current) => { - errorMessage = - current.type === DiagramType.SUBSTATION ? 'SubstationNotFound' : 'VoltageLevelNotFound'; - setGlobalError(errorMessage); - return current; - }); - } else if (error?.status === 403) { - errorMessage = error.message || 'svgLoadingFail'; - snackWithFallback(snackError, error, { headerId: errorMessage }); - setGlobalError(errorMessage); - } else { - errorMessage = 'svgLoadingFail'; - snackWithFallback(snackError, error, { headerId: errorMessage }); - setGlobalError(errorMessage); - } - }, - [snackError] - ); + const handleFetchError = useCallback((error: any) => { + setGlobalError(extractErrorMessageDescriptor(error, '')); + }, []); const handleFetchComplete = useCallback(() => { setLoading(false); @@ -175,7 +154,7 @@ export const useSldDiagram = ({ if (!currentNode?.id) return; if (currentNode.type !== NodeType.ROOT && !isStatusBuilt(currentNode?.data?.globalBuildStatus)) { - setGlobalError('InvalidNode'); + setGlobalError({ descriptor: { id: 'InvalidNode' } }); return; } diff --git a/src/translations/en.json b/src/translations/en.json index f3f56a6b09..3297c3c3e7 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -67,8 +67,6 @@ "studyNotFound": "Study with id \"{studyUuid}\" has not been found", "noWritePermissionOnStudy": "The user has no access right on study with id \"{studyUuid}\"", "svgNotFound": "Diagram has not been found: {error}; {svgUrl}", - "svgLoadingFail": "The diagram couldn't be loaded", - "nadConfiguredPositionsModeFailed": "The configured positions have not been initialized. You need to change the initialization parameter of the network area diagrams.", "networkLoadingFail": "Network of study with id \"{studyUuid}\" couldn't be loaded", "geoDataLoadingFail": "An error occurred while loading geographical data.", @@ -1187,8 +1185,6 @@ "YupNotTypeNumber": "This field only accepts numeric values", "YupNotTypeDefault": "Field value format is incorrect", - "SubstationNotFound": "This substation does not exist in this network", - "VoltageLevelNotFound": "This voltage level does not exist in this network", "NetworkEquipmentNotFound": "The equipment \"{equipmentId}\" does not exist in this network", "SLDOpenedInTheGrid": "The {diagramType} \"{equipmentId}\" was opened in the image grid", "NADOpenedInTheGrid": "The network area diagram \"{elementId}\" was opened in the image grid", diff --git a/src/translations/fr.json b/src/translations/fr.json index 2281b05c00..e5b230f8da 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -67,8 +67,6 @@ "studyNotFound": "L'étude avec l'identifiant \"{studyUuid}\" n'a pas été trouvée", "noWritePermissionOnStudy": "L'utilisateur n'a pas le droit d'accès sur l'étude avec l'identifiant \"{studyUuid}\"", "svgNotFound": "L'image poste n'a pas été trouvée : {error}; {svgUrl}", - "svgLoadingFail": "L'image n'a pas pu être chargée", - "nadConfiguredPositionsModeFailed": "Les positions configurées n'ont pas été initialisées. Vous devez modifier le paramétrage d'initialisation des images nodales de la zone.", "networkLoadingFail": "Le réseau de l'étude avec l'identifiant \"{studyUuid}\" n'a pas pu être chargé", "geoDataLoadingFail": "Erreur lors du chargement des données géographiques.", @@ -1183,8 +1181,6 @@ "YupNotTypeNumber": "Ce champ n'accepte que des valeurs numériques", "YupNotTypeDefault": "La valeur du champ n'est pas au bon format", - "SubstationNotFound": "Ce site n'existe pas dans ce réseau", - "VoltageLevelNotFound": "Ce poste n'existe pas dans ce réseau", "NetworkEquipmentNotFound": "L'ouvrage \"{equipmentId}\" n'existe pas dans ce réseau", "SLDOpenedInTheGrid": "Le {diagramType} \"{equipmentId}\" a été ouvert dans la grille des images",