diff --git a/src/components/app-top-bar.jsx b/src/components/app-top-bar.jsx index fcf1e59edc..791e32247e 100644 --- a/src/components/app-top-bar.jsx +++ b/src/components/app-top-bar.jsx @@ -51,7 +51,7 @@ const styles = { }, }; -const AppTopBar = ({ user, userManager }) => { +const AppTopBar = ({ userProfile, userManager }) => { const dispatch = useDispatch(); const theme = useSelector((state) => state[PARAM_THEME]); const studyUuid = useSelector((state) => state.studyUuid); @@ -66,12 +66,12 @@ const AppTopBar = ({ user, userManager }) => { const [isDeveloperMode, handleChangeDeveloperMode] = useParameterState(PARAM_DEVELOPER_MODE); useEffect(() => { - if (user !== null) { + if (userProfile !== null) { fetchAppsMetadata().then((res) => { setAppsAndUrls(res); }); } - }, [user]); + }, [userProfile]); return ( { appColor="#0CA789" appLogo={theme === LIGHT_THEME ? : } onLogoutClick={() => logout(dispatch, userManager.instance)} - user={user} + userProfile={userProfile} appsAndUrls={appsAndUrls} onThemeClick={handleChangeTheme} appVersion={AppPackage.version} @@ -95,7 +95,7 @@ const AppTopBar = ({ user, userManager }) => { language={languageLocal} dense > - {user && studyUuid && currentRootNetworkUuid && ( + {userProfile && studyUuid && currentRootNetworkUuid && ( @@ -121,7 +121,7 @@ const AppTopBar = ({ user, userManager }) => { }; AppTopBar.propTypes = { - user: PropTypes.object, + userProfile: PropTypes.object, userManager: PropTypes.object.isRequired, }; diff --git a/src/components/app.jsx b/src/components/app.jsx index 0aa451bd70..26d8b3d9dc 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -6,7 +6,7 @@ */ import { useCallback, useEffect, useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { retrieveOptionalServices } from './utils/optional-services'; import { Navigate, Route, Routes, useLocation, useMatch, useNavigate } from 'react-router'; import { @@ -89,7 +89,7 @@ const App = () => { .catch(() => cleanupStaleStudyData()); }, []); - const user = useSelector((state) => state.user); + const userProfile = useSelector((state) => state.user?.profile ?? null, shallowEqual); const studyUuid = useSelector((state) => state.studyUuid); const signInCallbackError = useSelector((state) => state.signInCallbackError); const authenticationRouterError = useSelector((state) => state.authenticationRouterError); @@ -343,7 +343,7 @@ const App = () => { }, [initialMatchSilentRenewCallbackUrl, dispatch, initialMatchSigninCallbackUrl]); useEffect(() => { - if (user !== null && studyUuid !== null) { + if (userProfile !== null && studyUuid !== null) { const fetchNetworkVisualizationParametersPromise = getNetworkVisualizationParameters(studyUuid).then( (params) => updateNetworkVisualizationsParams(params) ); @@ -386,8 +386,15 @@ const App = () => { }) .catch((error) => snackWithFallback(snackError, error, { headerId: 'paramsRetrievingError' })); } - }, [user, studyUuid, dispatch, updateParams, snackError, updateNetworkVisualizationsParams, resetTableDefinitions]); - + }, [ + userProfile, + studyUuid, + dispatch, + updateParams, + snackError, + updateNetworkVisualizationsParams, + resetTableDefinitions, + ]); return (
{ flexDirection: 'column', }} > - - + +
{ overflow: isStudyPane ? 'hidden' : 'auto', }} > - {user !== null ? ( + {userProfile !== null ? ( } /> > => { // The websocket API doesn't allow relative urls const wsBase = getWsBase(); - const tokenId = useSelector((state: AppState) => state.user?.id_token); const studyUuid = useSelector((state: AppState) => state.studyUuid); - // return a mapColumns with NOTIFICATIONS_URL_KEYS and undefined value if URL is not yet buildable (tokenId) + // return a mapColumns with NOTIFICATIONS_URL_KEYS and undefined value if URL is not yet buildable (studyUuid) // it will be used to register listeners as soon as possible. return useMemo( () => ({ - [NotificationsUrlKeys.CONFIG]: tokenId - ? getUrlWithToken( - `${wsBase}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?${new URLSearchParams({ - appName: APP_NAME, - })}` - ) + [NotificationsUrlKeys.CONFIG]: `${wsBase}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?${new URLSearchParams({ appName: APP_NAME })}`, + [NotificationsUrlKeys.GLOBAL_CONFIG]: `${wsBase}${PREFIX_CONFIG_NOTIFICATION_WS}/global`, + [NotificationsUrlKeys.STUDY]: studyUuid + ? `${wsBase}${PREFIX_STUDY_NOTIFICATION_WS}/notify?studyUuid=${encodeURIComponent(studyUuid)}` : undefined, - [NotificationsUrlKeys.GLOBAL_CONFIG]: tokenId - ? getUrlWithToken(`${wsBase}${PREFIX_CONFIG_NOTIFICATION_WS}/global`) - : undefined, - [NotificationsUrlKeys.STUDY]: - tokenId && studyUuid - ? getUrlWithToken( - `${wsBase}${PREFIX_STUDY_NOTIFICATION_WS}/notify?studyUuid=${encodeURIComponent(studyUuid)}` - ) - : undefined, - [NotificationsUrlKeys.DIRECTORY_DELETE_STUDY]: - tokenId && studyUuid - ? getUrlWithToken( - `${wsBase}${PREFIX_DIRECTORY_NOTIFICATION_WS}/notify?updateType=deleteElement&elementUuid=${encodeURIComponent( - studyUuid - )}` - ) - : undefined, - [NotificationsUrlKeys.DIRECTORY]: tokenId - ? getUrlWithToken(`${wsBase}${PREFIX_DIRECTORY_NOTIFICATION_WS}/notify?updateType=directories`) + [NotificationsUrlKeys.DIRECTORY_DELETE_STUDY]: studyUuid + ? `${wsBase}${PREFIX_DIRECTORY_NOTIFICATION_WS}/notify?updateType=deleteElement&elementUuid=${encodeURIComponent( + studyUuid + )}` : undefined, + [NotificationsUrlKeys.DIRECTORY]: `${wsBase}${PREFIX_DIRECTORY_NOTIFICATION_WS}/notify?updateType=directories`, }), - [tokenId, wsBase, studyUuid] + [wsBase, studyUuid] ); }; diff --git a/src/redux/store.ts b/src/redux/store.ts index 3df2de4f12..232e79301b 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -8,7 +8,6 @@ import { configureStore } from '@reduxjs/toolkit'; import { reducer } from './reducer'; import { setCommonStore } from '@gridsuite/commons-ui'; -import { setUserStore } from './user-store'; import workspacesReducer from './slices/workspace-slice'; import { globalFiltersMiddleware } from './globalFiltersMiddleware'; @@ -35,7 +34,6 @@ export type RootState = ReturnType; export type AppDispatch = typeof store.dispatch; setCommonStore(store); -setUserStore(store); // to avoid to reset the state with HMR // https://redux.js.org/usage/configuring-your-store#hot-reloading diff --git a/src/redux/user-store.ts b/src/redux/user-store.ts deleted file mode 100644 index e4d9cd5bcf..0000000000 --- a/src/redux/user-store.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.ts:7:1 - at src/services/study/index.ts: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-ts'; - -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/utils.ts b/src/services/utils.ts index 407cddc2ac..06ce711401 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -5,8 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { catchErrorHandler, fetchStudyMetadata, StudyMetadata } from '@gridsuite/commons-ui'; -import { getUserToken } from '../redux/user-store'; - export const FetchStatus = { SUCCEED: 'SUCCEED', FAILED: 'FAILED', @@ -91,14 +89,6 @@ export const getQueryParamsList = (params: string[] | number[] | null | undefine return ''; }; -export function getUrlWithToken(baseUrl: string) { - if (baseUrl.includes('?')) { - return baseUrl + '&access_token=' + getUserToken(); - } else { - return baseUrl + '?access_token=' + getUserToken(); - } -} - export function fetchMapBoxToken() { console.info(`Fetching MapBoxToken...`); return fetchEnv().then((res) => res.mapBoxToken);