diff --git a/src/components/results/common/global-filter/hooks/use-global-filter-options.ts b/src/components/results/common/global-filter/hooks/use-global-filter-options.ts index 8d1418c584..58ee704dae 100644 --- a/src/components/results/common/global-filter/hooks/use-global-filter-options.ts +++ b/src/components/results/common/global-filter/hooks/use-global-filter-options.ts @@ -18,8 +18,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { AppState } from '../../../../../redux/reducer.type'; import { useBaseVoltages } from '../../../../../hooks/use-base-voltages'; import { addToGlobalFilterOptions } from '../../../../../redux/actions'; -import { fetchNetworkExistence } from 'services/study/network'; -import { HttpStatusCode } from 'utils/http-status-code'; +import { fetchNetworkExistence, RootNetworkStatusInfos } from 'services/study/network'; /** * Custom hook that manages global filter options for tables. @@ -58,9 +57,9 @@ export const useGlobalFilterOptions = () => { if (!studyUuid || !currentNode?.id || !currentRootNetworkUuid) return; try { - const response = await fetchNetworkExistence(studyUuid, currentRootNetworkUuid); + const response: RootNetworkStatusInfos = await fetchNetworkExistence(studyUuid, currentRootNetworkUuid); - if (response.status === HttpStatusCode.OK) { + if (response?.exists) { const countryCodes = await fetchAllCountries(studyUuid, currentNode.id, currentRootNetworkUuid); const newCountriesFilter = countryCodes diff --git a/src/components/study-container.jsx b/src/components/study-container.jsx index c88fb04b06..746c37ce1f 100644 --- a/src/components/study-container.jsx +++ b/src/components/study-container.jsx @@ -46,7 +46,11 @@ import { useAllComputingStatus } from './computing-status/use-all-computing-stat import { fetchNetworkModificationTree } from '../services/study/tree-subtree'; import { useTreeModelSync } from '../hooks/use-tree-model-sync'; import { useNodeActivitySync } from 'components/node-activity/hooks/use-node-activity-sync'; -import { fetchNetworkExistence, fetchRootNetworkIndexationStatus } from '../services/study/network'; +import { + fetchNetworkExistence, + fetchRootNetworkIndexationStatus, + RootNetworkLoadStatus, +} from '../services/study/network'; import { fetchStudy, recreateStudyNetwork, reindexAllRootNetwork } from 'services/study/study'; import { HttpStatusCode } from 'utils/http-status-code'; @@ -163,7 +167,7 @@ export function StudyContainer() { useAllComputingStatus(studyUuid, currentNode?.id, currentRootNetworkUuid); - const { snackError, snackWarning, snackInfo } = useSnackMessage(); + const { snackError, snackWarning, snackInfo, snackSuccess } = useSnackMessage(); useExportNotification(); useTreeModelSync(studyUuid); @@ -400,51 +404,57 @@ export function StudyContainer() { }, [studyUuid, currentRootNetworkUuid, dispatch, snackError]); const checkNetworkExistenceAndRecreateIfNotFound = useCallback( - (successCallback) => { - fetchNetworkExistence(studyUuid, currentRootNetworkUuid) - .then((response) => { - if (response.status === HttpStatusCode.OK) { - successCallback && successCallback(); - checkRootNetworkIndexation().then(loadTree); - } else { - // response.state === NO_CONTENT - // if network is not found, we try to recreate study network from existing case - recreateStudyNetwork(studyUuid, currentRootNetworkUuid) - .then(() => { - snackWarning({ - headerId: 'recreatingNetworkStudy', - persist: true, - }); - }) - .catch((error) => { - if (error.status === HttpStatusCode.FAILED_DEPENDENCY) { - // when trying to recreate study network, if case can't be found (424 error), we display an error - setErrorMessage( - intlRef.current.formatMessage({ - id: 'invalidStudyError', - }) - ); - } else { - // unknown error when trying to recreate network from study case - setErrorMessage( - intlRef.current.formatMessage({ - id: 'networkRecreationError', - }) - ); - } + async (successCallback) => { + try { + const existence = await fetchNetworkExistence(studyUuid, currentRootNetworkUuid); + if (existence?.exists) { + successCallback?.(); + const status = await checkRootNetworkIndexation(); + loadTree(status); + } else { + // response.state === NO_CONTENT + // if network is not found, we try to recreate study network from existing case + try { + await recreateStudyNetwork(studyUuid, currentRootNetworkUuid); + if (existence?.rootNetworkLoadStatus === RootNetworkLoadStatus.UNLOADED) { + snackInfo({ + headerId: 'rootNetworkStudyUnloaded', + persist: true, + }); + } else { + snackWarning({ + headerId: 'recreatingNetworkStudy', + persist: true, }); + } + } catch (error) { + if (error.status === HttpStatusCode.FAILED_DEPENDENCY) { + // when trying to recreate study network, if case can't be found (424 error), we display an error + setErrorMessage( + intlRef.current.formatMessage({ + id: 'invalidStudyError', + }) + ); + } else { + // unknown error when trying to recreate network from study case + setErrorMessage( + intlRef.current.formatMessage({ + id: 'networkRecreationError', + }) + ); + } } - }) - .catch(() => { - // unknown error when checking network existence - setErrorMessage( - intlRef.current.formatMessage({ - id: 'checkNetworkExistenceError', - }) - ); - }); + } + } catch { + // unknown error when checking network existence + setErrorMessage( + intlRef.current.formatMessage({ + id: 'checkNetworkExistenceError', + }) + ); + } }, - [studyUuid, currentRootNetworkUuid, checkRootNetworkIndexation, loadTree, snackWarning, intlRef] + [studyUuid, currentRootNetworkUuid, checkRootNetworkIndexation, loadTree, snackInfo, snackWarning, intlRef] ); useEffect(() => { @@ -467,11 +477,6 @@ export function StudyContainer() { return; } dispatch(setRootNetworkIndexationStatus(eventData.headers.indexation_status)); - if (eventData.headers.indexation_status === RootNetworkIndexationStatus.INDEXED) { - snackInfo({ - headerId: 'rootNetworkIndexationDone', - }); - } // notification that the study is not indexed anymore then ask to refresh if (eventData.headers.indexation_status === RootNetworkIndexationStatus.NOT_INDEXED) { snackWarning({ @@ -481,7 +486,7 @@ export function StudyContainer() { } if (isStudyNetworkRecreationNotification(eventData)) { const successCallback = () => - snackInfo({ + snackSuccess({ headerId: 'studyNetworkRecovered', }); @@ -494,7 +499,7 @@ export function StudyContainer() { } } }, - [checkNetworkExistenceAndRecreateIfNotFound, snackInfo, snackWarning, dispatch] + [dispatch, snackWarning, checkNetworkExistenceAndRecreateIfNotFound, snackSuccess] ); useNotificationsListener(NotificationsUrlKeys.STUDY, { diff --git a/src/services/study/network.ts b/src/services/study/network.ts index 331df3d96a..be5376ced7 100644 --- a/src/services/study/network.ts +++ b/src/services/study/network.ts @@ -385,10 +385,22 @@ export function fetchVoltageLevelsMapInfos( ); } -export const fetchNetworkExistence = (studyUuid: UUID, rootNetworkUuid: UUID) => { +export enum RootNetworkLoadStatus { + LOADED = 'LOADED', + UNLOADED = 'UNLOADED', + UNLOADING = 'UNLOADING', + LOADING = 'LOADING', +} + +export interface RootNetworkStatusInfos { + exists: boolean; + rootNetworkLoadStatus: RootNetworkLoadStatus; +} + +export const fetchNetworkExistence = (studyUuid: UUID, rootNetworkUuid: UUID): Promise => { const fetchNetworkExistenceUrl = `${PREFIX_STUDY_QUERIES}/v1/studies/${studyUuid}/root-networks/${rootNetworkUuid}/network`; - return backendFetch(fetchNetworkExistenceUrl, { method: 'HEAD' }); + return backendFetchJson(fetchNetworkExistenceUrl, { method: 'GET' }); }; export const fetchRootNetworkIndexationStatus = (studyUuid: UUID, rootNetworkUuid: UUID) => { diff --git a/src/translations/messages-en.ts b/src/translations/messages-en.ts index 0d6971bf1f..b3a5491482 100644 --- a/src/translations/messages-en.ts +++ b/src/translations/messages-en.ts @@ -937,6 +937,7 @@ const messages_en = { GeneratorAvailability: 'Generator availability', chooseElement: 'Choose element', studyNetworkRecovered: 'Study network has been recreated successfully', + rootNetworkStudyUnloaded: 'Due to a period of inactivity, this study has been unloaded', recreatingNetworkStudy: 'Impossible to get the study network. Reconstruction of the network from the initial situation...', invalidStudyError: 'Invalid study : Root situation can not be found', @@ -987,7 +988,6 @@ const messages_en = { ShortcircuitInProgress: 'Shortcircuit computation in progress...', tableChangingError: 'An error occurred when modifying the data', - rootNetworkIndexationDone: 'Root Network indexation done. Search functionality is now available', rootNetworkIndexationNotIndexed: "Serverside warning: Something went wrong, Study equipments aren't indexed anymore. Please refresh the page (F5)", rootNetworkIndexationError: 'Root Network indexation process has failed.', diff --git a/src/translations/messages-fr.ts b/src/translations/messages-fr.ts index 1334b8975e..9d4b0e53dd 100644 --- a/src/translations/messages-fr.ts +++ b/src/translations/messages-fr.ts @@ -950,6 +950,7 @@ const messages_fr = { GeneratorAvailability: 'Indisponibilité groupes', chooseElement: 'Choisir un element', studyNetworkRecovered: "Le réseau de l'étude a été réimporté avec succès", + rootNetworkStudyUnloaded: "En raison d'une période d'inactivité, cette étude a été déchargée", recreatingNetworkStudy: "Impossible de récupérer le réseau de l'étude. Reconstruction du réseau à partir de la situation initiale...", invalidStudyError: 'Étude invalide : la situation racine est introuvable', @@ -1000,8 +1001,6 @@ const messages_fr = { ShortcircuitInProgress: 'Calcul de court-circuit en cours...', tableChangingError: 'Une erreur est survenue lors de la modification des données', - rootNetworkIndexationDone: - "L'indexation de réseau racine est terminée. La fonctionnalité de recherche est disponible", rootNetworkIndexationNotIndexed: "Alerte côté serveur :Un incident s'est produit, les équipements de l'étude ne sont plus indexés. Merci de rafraîchir la page (F5)", rootNetworkIndexationError: "L'indexation de réseau racine a échoué.",