Skip to content

Commit

Permalink
Refactor config notifications management with NotificationsProvider (#…
Browse files Browse the repository at this point in the history
…2425)

* refactor(): Replace config notifications management with NotificationsProvider from commons-ui

Signed-off-by: sBouzols <sylvain.bouzols@gmail.com>
  • Loading branch information
sBouzols authored Dec 19, 2024
1 parent 45a0228 commit c189418
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 18 deletions.
8 changes: 7 additions & 1 deletion src/components/app-wrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
importParamsFr,
exportParamsEn,
exportParamsFr,
NotificationsProvider,
} from '@gridsuite/commons-ui';
import { IntlProvider } from 'react-intl';
import { BrowserRouter } from 'react-router-dom';
Expand Down Expand Up @@ -79,6 +80,7 @@ import {
MAP_BASEMAP_CARTO,
MAP_BASEMAP_CARTO_NOLABEL,
} from '../utils/config-params';
import useNotificationsUrlGenerator from 'hooks/use-notifications-url-generator';

let lightTheme = createTheme({
components: {
Expand Down Expand Up @@ -327,6 +329,8 @@ const AppWrapperWithRedux = () => {

const theme = useSelector((state) => state[PARAM_THEME]);

const urlMapper = useNotificationsUrlGenerator();

return (
<IntlProvider locale={computedLanguage} messages={messages[computedLanguage]}>
<BrowserRouter basename={basename}>
Expand All @@ -335,7 +339,9 @@ const AppWrapperWithRedux = () => {
<SnackbarProvider hideIconVariant={false}>
<CssBaseline />
<CardErrorBoundary>
<App />
<NotificationsProvider urls={urlMapper}>
<App />
</NotificationsProvider>
</CardErrorBoundary>
</SnackbarProvider>
</ThemeProvider>
Expand Down
29 changes: 12 additions & 17 deletions src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getPreLoginPath,
initializeAuthenticationProd,
useSnackMessage,
useNotificationsListener,
} from '@gridsuite/commons-ui';
import PageNotFound from './page-not-found';
import { FormattedMessage } from 'react-intl';
Expand Down Expand Up @@ -55,7 +56,6 @@ import { getComputedLanguage } from '../utils/language';
import AppTopBar from './app-top-bar';
import { StudyContainer } from './study-container';
import { fetchValidateUser } from '../services/user-admin';
import { connectNotificationsWsUpdateConfig } from '../services/config-notification';
import { fetchConfigParameter, fetchConfigParameters } from '../services/config';
import { fetchDefaultParametersValues, fetchIdpSettings } from '../services/utils';
import { getOptionalServices } from '../services/study';
Expand Down Expand Up @@ -87,6 +87,7 @@ import {
setOptionalServices,
setParamsLoaded,
} from '../redux/actions';
import { NOTIFICATIONS_URL_KEYS } from './utils/notificationsProvider-utils';

const noUserManager = { instance: null, error: null };

Expand Down Expand Up @@ -270,10 +271,8 @@ const App = () => {
[dispatch, tablesNamesIndexes, tablesDefinitionIndexes]
);

const connectNotificationsUpdateConfig = useCallback(() => {
const ws = connectNotificationsWsUpdateConfig();

ws.onmessage = function (event) {
const updateConfig = useCallback(
(event) => {
let eventData = JSON.parse(event.data);
if (eventData.headers && eventData.headers['parameterName']) {
fetchConfigParameter(eventData.headers['parameterName'])
Expand All @@ -290,12 +289,13 @@ const App = () => {
})
);
}
};
ws.onerror = function (event) {
console.error('Unexpected Notification WebSocket error', event);
};
return ws;
}, [updateParams, snackError, dispatch]);
},
[dispatch, snackError, updateParams]
);

useNotificationsListener(NOTIFICATIONS_URL_KEYS.CONFIG, {
listenerCallbackMessage: updateConfig,
});

// Can't use lazy initializer because useRouteMatch is a hook
const [initialMatchSilentRenewCallbackUrl] = useState(
Expand Down Expand Up @@ -419,13 +419,8 @@ const App = () => {
headerId: 'paramsRetrievingError',
})
);

const ws = connectNotificationsUpdateConfig();
return function () {
ws.close();
};
}
}, [user, dispatch, updateParams, connectNotificationsUpdateConfig, snackError]);
}, [user, dispatch, updateParams, snackError]);

const onChangeTab = useCallback((newTabIndex) => {
setTabIndex(newTabIndex);
Expand Down
11 changes: 11 additions & 0 deletions src/components/utils/notificationsProvider-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) 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/.
*/
export enum NOTIFICATIONS_URL_KEYS {
CONFIG = 'CONFIG',
}

export const PREFIX_CONFIG_NOTIFICATION_WS = import.meta.env.VITE_WS_GATEWAY + '/config-notification';
42 changes: 42 additions & 0 deletions src/hooks/use-notifications-url-generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) 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 { NOTIFICATIONS_URL_KEYS, PREFIX_CONFIG_NOTIFICATION_WS } from 'components/utils/notificationsProvider-utils';
import { useCallback, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'redux/reducer';
import { getUrlWithToken, getWsBase } from 'services/utils';
import { APP_NAME } from 'utils/config-params';

const useNotificationsUrlGenerator = () => {
// The websocket API doesn't allow relative urls
const wsBase = getWsBase();
const tokenId = useSelector((state: AppState) => state.user?.id_token);
// Add params to Url
const urlParams = useCallback((mapper: Record<string, string>) => {
const usp = new URLSearchParams();
Object.entries(mapper).forEach(([key, value]) => {
usp.append(key, value);
});
return usp;
}, []);

const urlMapper = useMemo(() => {
// return a mapper with NOTIFICATIONS_URL_KEYS and undefined value if URL is not yet buildable (tokenId)
// it will be used to register listeners as soon as possible.
let mapper: Object = {
[NOTIFICATIONS_URL_KEYS.CONFIG]: tokenId
? getUrlWithToken(
`${wsBase}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?${urlParams({ appName: APP_NAME })}`
)
: undefined,
};
return mapper;
}, [wsBase, urlParams, tokenId]);
return urlMapper;
};

export default useNotificationsUrlGenerator;

0 comments on commit c189418

Please sign in to comment.