From 2d1e3f365f1beb1738ee4b727523fe2e9fc7d00f Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 21:30:04 +0100 Subject: [PATCH 1/7] add logo --- public/favicon.ico | Bin 1150 -> 117560 bytes src/components/app-top-bar.tsx | 21 ++++++++--------- src/images/GridAdmin_logo_dark.svg | 20 ++++++++++++++++ src/images/GridAdmin_logo_light.svg | 20 ++++++++++++++++ src/images/powsybl_logo.svg | 35 ---------------------------- 5 files changed, 50 insertions(+), 46 deletions(-) create mode 100644 src/images/GridAdmin_logo_dark.svg create mode 100644 src/images/GridAdmin_logo_light.svg delete mode 100644 src/images/powsybl_logo.svg diff --git a/public/favicon.ico b/public/favicon.ico index 6f357a0eddc3770e933f54127ad9cba654fb05cd..222b983ea78c5fb4069f81840dc0dd106887d050 100644 GIT binary patch literal 117560 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 B8#4d^ diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index ae49f77..2184d20 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -6,15 +6,17 @@ */ import { FunctionComponent, useCallback, useEffect, useState } from 'react'; -import { LIGHT_THEME, logout, TopBar } from '@gridsuite/commons-ui'; +import { logout, TopBar } from '@gridsuite/commons-ui'; import Parameters, { useParameterState } from './parameters'; import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; import { AppsMetadataSrv, MetadataJson, StudySrv } from '../services'; import { useNavigate } from 'react-router-dom'; -import { ReactComponent as PowsyblLogo } from '../images/powsybl_logo.svg'; +import { ReactComponent as GridAdminLogoLight } from '../images/GridAdmin_logo_light.svg'; +import { ReactComponent as GridAdminLogoDark } from '../images/GridAdmin_logo_dark.svg'; import AppPackage from '../../package.json'; import { AppState } from '../redux/reducer'; +import { useTheme } from '@mui/material'; export type AppTopBarProps = { user?: AppState['user']; @@ -26,15 +28,12 @@ export type AppTopBarProps = { const AppTopBar: FunctionComponent = (props) => { const navigate = useNavigate(); - + const theme = useTheme(); const dispatch = useDispatch(); const [appsAndUrls, setAppsAndUrls] = useState([]); - const theme = useSelector((state: AppState) => state[PARAM_THEME]); - const [themeLocal, handleChangeTheme] = useParameterState(PARAM_THEME); - const [languageLocal, handleChangeLanguage] = useParameterState(PARAM_LANGUAGE); @@ -54,12 +53,12 @@ const AppTopBar: FunctionComponent = (props) => { <> //GridAdminLogoLight + theme.palette.mode === 'light' ? ( + ) : ( - //GridAdminLogoDark + ) } appVersion={AppPackage.version} diff --git a/src/images/GridAdmin_logo_dark.svg b/src/images/GridAdmin_logo_dark.svg new file mode 100644 index 0000000..26be3e5 --- /dev/null +++ b/src/images/GridAdmin_logo_dark.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/src/images/GridAdmin_logo_light.svg b/src/images/GridAdmin_logo_light.svg new file mode 100644 index 0000000..e69b1bb --- /dev/null +++ b/src/images/GridAdmin_logo_light.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/src/images/powsybl_logo.svg b/src/images/powsybl_logo.svg deleted file mode 100644 index 93c9724..0000000 --- a/src/images/powsybl_logo.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 5e0d1f91dc9e2dd200a0c4f5903d92bb80646f75 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 21:36:10 +0100 Subject: [PATCH 2/7] fix string case problem with `APP_NAME` --- src/components/app-top-bar.tsx | 6 +++--- src/components/app.tsx | 2 +- src/services/config-notification.ts | 2 +- src/utils/config-params.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index 2184d20..024ae76 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -6,17 +6,17 @@ */ import { FunctionComponent, useCallback, useEffect, useState } from 'react'; +import { capitalize, useTheme } from '@mui/material'; import { logout, TopBar } from '@gridsuite/commons-ui'; import Parameters, { useParameterState } from './parameters'; import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; +import { useNavigate } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { AppsMetadataSrv, MetadataJson, StudySrv } from '../services'; -import { useNavigate } from 'react-router-dom'; import { ReactComponent as GridAdminLogoLight } from '../images/GridAdmin_logo_light.svg'; import { ReactComponent as GridAdminLogoDark } from '../images/GridAdmin_logo_dark.svg'; import AppPackage from '../../package.json'; import { AppState } from '../redux/reducer'; -import { useTheme } from '@mui/material'; export type AppTopBarProps = { user?: AppState['user']; @@ -52,7 +52,7 @@ const AppTopBar: FunctionComponent = (props) => { return ( <> { }) ); - ConfigSrv.fetchConfigParameters(APP_NAME.toLowerCase()) + ConfigSrv.fetchConfigParameters(APP_NAME) .then((params) => updateParams(params)) .catch((error) => snackError({ diff --git a/src/services/config-notification.ts b/src/services/config-notification.ts index 1da21e7..48bf662 100644 --- a/src/services/config-notification.ts +++ b/src/services/config-notification.ts @@ -12,7 +12,7 @@ import { getUrlWithToken, getWsBase } from '../utils/api-ws'; const PREFIX_CONFIG_NOTIFICATION_WS = `${process.env.REACT_APP_WS_GATEWAY}/config-notification`; export function connectNotificationsWsUpdateConfig(): ReconnectingWebSocket { - const webSocketUrl = `${getWsBase()}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?appName=${APP_NAME.toLowerCase()}`; + const webSocketUrl = `${getWsBase()}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?appName=${APP_NAME}`; const reconnectingWebSocket = new ReconnectingWebSocket( () => getUrlWithToken(webSocketUrl), undefined, diff --git a/src/utils/config-params.ts b/src/utils/config-params.ts index cba6391..6fd3b22 100644 --- a/src/utils/config-params.ts +++ b/src/utils/config-params.ts @@ -8,7 +8,7 @@ import { LiteralUnion } from 'type-fest'; export const COMMON_APP_NAME = 'common'; -export const APP_NAME = 'Admin'; +export const APP_NAME = 'admin'; export const PARAM_THEME = 'theme'; export const PARAM_LANGUAGE = 'language'; From b2835f78460243fc32efbfb5dd0c74ec9988a856 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 21:46:27 +0100 Subject: [PATCH 3/7] Move app components in sub-folder --- src/components/{ => App}/app-top-bar.tsx | 14 +++++++------- src/components/{ => App}/app-wrapper.tsx | 16 ++++++++-------- src/components/{ => App}/app.test.tsx | 2 +- src/components/{ => App}/app.tsx | 12 ++++++------ src/components/App/index.ts | 1 + src/index.tsx | 2 +- 6 files changed, 24 insertions(+), 23 deletions(-) rename src/components/{ => App}/app-top-bar.tsx (85%) rename src/components/{ => App}/app-wrapper.tsx (89%) rename src/components/{ => App}/app.test.tsx (97%) rename src/components/{ => App}/app.tsx (97%) create mode 100644 src/components/App/index.ts diff --git a/src/components/app-top-bar.tsx b/src/components/App/app-top-bar.tsx similarity index 85% rename from src/components/app-top-bar.tsx rename to src/components/App/app-top-bar.tsx index 024ae76..267a875 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/App/app-top-bar.tsx @@ -8,15 +8,15 @@ import { FunctionComponent, useCallback, useEffect, useState } from 'react'; import { capitalize, useTheme } from '@mui/material'; import { logout, TopBar } from '@gridsuite/commons-ui'; -import Parameters, { useParameterState } from './parameters'; -import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; +import Parameters, { useParameterState } from '../parameters'; +import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../../utils/config-params'; import { useNavigate } from 'react-router-dom'; import { useDispatch } from 'react-redux'; -import { AppsMetadataSrv, MetadataJson, StudySrv } from '../services'; -import { ReactComponent as GridAdminLogoLight } from '../images/GridAdmin_logo_light.svg'; -import { ReactComponent as GridAdminLogoDark } from '../images/GridAdmin_logo_dark.svg'; -import AppPackage from '../../package.json'; -import { AppState } from '../redux/reducer'; +import { AppsMetadataSrv, MetadataJson, StudySrv } from '../../services'; +import { ReactComponent as GridAdminLogoLight } from '../../images/GridAdmin_logo_light.svg'; +import { ReactComponent as GridAdminLogoDark } from '../../images/GridAdmin_logo_dark.svg'; +import AppPackage from '../../../package.json'; +import { AppState } from '../../redux/reducer'; export type AppTopBarProps = { user?: AppState['user']; diff --git a/src/components/app-wrapper.tsx b/src/components/App/app-wrapper.tsx similarity index 89% rename from src/components/app-wrapper.tsx rename to src/components/App/app-wrapper.tsx index 30a17b3..b7ccb4e 100644 --- a/src/components/app-wrapper.tsx +++ b/src/components/App/app-wrapper.tsx @@ -28,15 +28,15 @@ import { import { IntlProvider } from 'react-intl'; import { BrowserRouter } from 'react-router-dom'; import { Provider, useSelector } from 'react-redux'; -import { SupportedLanguages } from '../utils/language'; -import messages_en from '../translations/en.json'; -import messages_fr from '../translations/fr.json'; -import messages_plugins_en from '../plugins/translations/en.json'; -import messages_plugins_fr from '../plugins/translations/fr.json'; -import { store } from '../redux/store'; -import { PARAM_THEME } from '../utils/config-params'; +import { SupportedLanguages } from '../../utils/language'; +import messages_en from '../../translations/en.json'; +import messages_fr from '../../translations/fr.json'; +import messages_plugins_en from '../../plugins/translations/en.json'; +import messages_plugins_fr from '../../plugins/translations/fr.json'; +import { store } from '../../redux/store'; +import { PARAM_THEME } from '../../utils/config-params'; import { IntlConfig } from 'react-intl/src/types'; -import { AppState } from '../redux/reducer'; +import { AppState } from '../../redux/reducer'; const lightTheme: Theme = createTheme({ palette: { diff --git a/src/components/app.test.tsx b/src/components/App/app.test.tsx similarity index 97% rename from src/components/app.test.tsx rename to src/components/App/app.test.tsx index be4ffd1..950285f 100644 --- a/src/components/app.test.tsx +++ b/src/components/App/app.test.tsx @@ -7,7 +7,7 @@ import { IntlProvider } from 'react-intl'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import App from './app'; -import { store } from '../redux/store'; +import { store } from '../../redux/store'; import { createTheme, StyledEngineProvider, diff --git a/src/components/app.tsx b/src/components/App/app.tsx similarity index 97% rename from src/components/app.tsx rename to src/components/App/app.tsx index 62ca49a..856f8a7 100644 --- a/src/components/app.tsx +++ b/src/components/App/app.tsx @@ -28,25 +28,25 @@ import { selectComputedLanguage, selectLanguage, selectTheme, -} from '../redux/actions'; -import { AppState } from '../redux/reducer'; +} from '../../redux/actions'; +import { AppState } from '../../redux/reducer'; import { AppsMetadataSrv, ConfigNotif, ConfigParameters, ConfigSrv, UserAdminSrv, -} from '../services'; +} from '../../services'; import { APP_NAME, COMMON_APP_NAME, PARAM_LANGUAGE, PARAM_THEME, -} from '../utils/config-params'; -import { getComputedLanguage } from '../utils/language'; +} from '../../utils/config-params'; +import { getComputedLanguage } from '../../utils/language'; import AppTopBar, { AppTopBarProps } from './app-top-bar'; import ReconnectingWebSocket from 'reconnecting-websocket'; -import { getErrorMessage } from '../utils/error'; +import { getErrorMessage } from '../../utils/error'; const App: FunctionComponent = () => { const { snackError } = useSnackMessage(); diff --git a/src/components/App/index.ts b/src/components/App/index.ts new file mode 100644 index 0000000..05cce66 --- /dev/null +++ b/src/components/App/index.ts @@ -0,0 +1 @@ +export { default as AppWrapper } from './app-wrapper'; diff --git a/src/index.tsx b/src/index.tsx index 0c6c8f8..698e4ad 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,7 +10,7 @@ import 'typeface-roboto'; import React from 'react'; import { createRoot } from 'react-dom/client'; import './index.css'; -import AppWrapper from './components/app-wrapper'; +import { AppWrapper } from './components/App'; const container = document.getElementById('root'); if (container) { From 12f104b5ccbb215d6ea95800d0711615f639526a Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 21:52:22 +0100 Subject: [PATCH 4/7] remove unused parameters --- src/components/App/app-top-bar.tsx | 75 ++++++++---------- src/components/parameters.tsx | 121 +---------------------------- 2 files changed, 33 insertions(+), 163 deletions(-) diff --git a/src/components/App/app-top-bar.tsx b/src/components/App/app-top-bar.tsx index 267a875..dcf1557 100644 --- a/src/components/App/app-top-bar.tsx +++ b/src/components/App/app-top-bar.tsx @@ -5,11 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { FunctionComponent, useCallback, useEffect, useState } from 'react'; +import { FunctionComponent, useEffect, useState } from 'react'; import { capitalize, useTheme } from '@mui/material'; import { logout, TopBar } from '@gridsuite/commons-ui'; -import Parameters, { useParameterState } from '../parameters'; -import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../../utils/config-params'; +import { useParameterState } from '../parameters'; +import { + APP_NAME, + PARAM_LANGUAGE, + PARAM_THEME, +} from '../../utils/config-params'; import { useNavigate } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { AppsMetadataSrv, MetadataJson, StudySrv } from '../../services'; @@ -37,10 +41,6 @@ const AppTopBar: FunctionComponent = (props) => { const [languageLocal, handleChangeLanguage] = useParameterState(PARAM_LANGUAGE); - const [showParameters, setShowParameters] = useState(false); - const displayParameters = useCallback(() => setShowParameters(true), []); - const hideParameters = useCallback(() => setShowParameters(false), []); - useEffect(() => { if (props.user !== null) { AppsMetadataSrv.fetchAppsAndUrls().then((res) => { @@ -50,42 +50,31 @@ const AppTopBar: FunctionComponent = (props) => { }, [props.user]); return ( - <> - - ) : ( - - ) - } - appVersion={AppPackage.version} - appLicense={AppPackage.license} - onParametersClick={displayParameters} - onLogoutClick={() => - logout(dispatch, props.userManager.instance) - } - onLogoClick={() => navigate('/', { replace: true })} - user={props.user} - appsAndUrls={appsAndUrls} - globalVersionPromise={() => - AppsMetadataSrv.fetchVersion().then( - (res) => res?.deployVersion - ) - } - additionalModulesPromise={StudySrv.getServersInfos} - onThemeClick={handleChangeTheme} - theme={themeLocal} - onLanguageClick={handleChangeLanguage} - language={languageLocal} - /> - - + + ) : ( + + ) + } + appVersion={AppPackage.version} + appLicense={AppPackage.license} + onLogoutClick={() => logout(dispatch, props.userManager.instance)} + onLogoClick={() => navigate('/', { replace: true })} + user={props.user} + appsAndUrls={appsAndUrls} + globalVersionPromise={() => + AppsMetadataSrv.fetchVersion().then((res) => res?.deployVersion) + } + additionalModulesPromise={StudySrv.getServersInfos} + onThemeClick={handleChangeTheme} + theme={themeLocal} + onLanguageClick={handleChangeLanguage} + language={languageLocal} + /> ); }; export default AppTopBar; diff --git a/src/components/parameters.tsx b/src/components/parameters.tsx index e756b24..bf13895 100644 --- a/src/components/parameters.tsx +++ b/src/components/parameters.tsx @@ -5,49 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { - FunctionComponent, - PropsWithChildren, - ReactElement, - useCallback, - useEffect, - useState, -} from 'react'; -import { FormattedMessage } from 'react-intl'; +import { useCallback, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { - Box, - Button, - Container, - Dialog, - DialogContent, - DialogTitle, - Grid, - Tab, - Tabs, - Typography, - TypographyTypeMap, -} from '@mui/material'; -import { CSSObject, Theme } from '@emotion/react'; import { ConfigSrv } from '../services'; import { useSnackMessage } from '@gridsuite/commons-ui'; import { AppState, AppStateKey } from '../redux/reducer'; -const styles = { - title: (theme: Theme): CSSObject => ({ - padding: theme.spacing(2), - }), - grid: (theme: Theme): CSSObject => ({ - padding: theme.spacing(2), - }), - controlItem: { - justifyContent: 'flex-end', - } as CSSObject, - button: { - marginBottom: '30px', - } as CSSObject, -}; - export function useParameterState( paramName: K ): [AppState[K], (value: AppState[K]) => void] { @@ -76,85 +39,3 @@ export function useParameterState( return [paramLocalState, handleChangeParamLocalState]; } - -function GUITab(): ReactElement { - return ; -} - -type TabPanelProps = PropsWithChildren< - TypographyTypeMap<{ index: number; value: number }, 'div'>['props'] ->; -function TabPanel({ - children, - value, - index, - ...typoProps -}: TabPanelProps): ReactElement { - return ( - - ); -} - -export type ParametersProps = PropsWithChildren<{ - showParameters: boolean; - hideParameters: () => void; -}>; -const Parameters: FunctionComponent = (props) => { - const [tabIndex, setTabIndex] = useState(0); - - return ( - - - - - - - - - setTabIndex(newValue)} - aria-label="parameters" - > - } /> - - - - - - - - - - - - - ); -}; - -export default Parameters; From db623c334c2cd496413b4698faa9be051d66941a Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 22:58:23 +0100 Subject: [PATCH 5/7] remove unused plugins folder --- src/components/App/app-wrapper.tsx | 4 --- src/plugins/README.md | 52 ------------------------------ src/plugins/index.ts | 1 - src/plugins/translations/en.json | 2 -- src/plugins/translations/fr.json | 2 -- 5 files changed, 61 deletions(-) delete mode 100644 src/plugins/README.md delete mode 100644 src/plugins/index.ts delete mode 100644 src/plugins/translations/en.json delete mode 100644 src/plugins/translations/fr.json diff --git a/src/components/App/app-wrapper.tsx b/src/components/App/app-wrapper.tsx index b7ccb4e..1f0e43d 100644 --- a/src/components/App/app-wrapper.tsx +++ b/src/components/App/app-wrapper.tsx @@ -31,8 +31,6 @@ import { Provider, useSelector } from 'react-redux'; import { SupportedLanguages } from '../../utils/language'; import messages_en from '../../translations/en.json'; import messages_fr from '../../translations/fr.json'; -import messages_plugins_en from '../../plugins/translations/en.json'; -import messages_plugins_fr from '../../plugins/translations/fr.json'; import { store } from '../../redux/store'; import { PARAM_THEME } from '../../utils/config-params'; import { IntlConfig } from 'react-intl/src/types'; @@ -104,14 +102,12 @@ const messages: Record = { ...login_en, ...top_bar_en, ...card_error_boundary_en, - ...messages_plugins_en, // keep it at the end to allow translation overwriting }, fr: { ...messages_fr, ...login_fr, ...top_bar_fr, ...card_error_boundary_fr, - ...messages_plugins_fr, // keep it at the end to allow translation overwriting }, }; diff --git a/src/plugins/README.md b/src/plugins/README.md deleted file mode 100644 index fd2ae97..0000000 --- a/src/plugins/README.md +++ /dev/null @@ -1,52 +0,0 @@ - -# How to add plugins - -Add a plugin component or object in the corresponding group represented as folders. - -```ts -// plugins/myPluginGroup/myNewPlugin.ts -const MyNewPlugin = { - ... -}; -export default MyNewPlugin; -``` - -Edit `index.ts` to export your new plugin in the corresponding group -```ts -import MyNewPlugin from './myPluginGroup/myNewPlugin'; -... -export const MyPluginGroupPlugins = [ - { - id: 'MyNewPlugin', // must be unique in a group - Component: MyNewPlugin, - }, -]; -``` - -Defining and adding a group of plugins needs to add some code in the target component - -```tsx -import { FunctionComponent } from 'react'; -// Plugins -import { MyPluginGroupPlugins } from '../plugins'; -//... - -const MyPluggableComponent: FunctionComponent = () => { - //... - return ( - <> - {/*...*/} - {MyPluginGroupPlugins.map((plugin) => { - return ; - })} - {/*...*/} - - ); -}; -``` - -# How to overwrite translations - -Add your private translations to the following files to complete or overwrite existing translations -* `src/plugins/translations/en.json` -* `src/plugins/translations/fr.json` diff --git a/src/plugins/index.ts b/src/plugins/index.ts deleted file mode 100644 index fe78b97..0000000 --- a/src/plugins/index.ts +++ /dev/null @@ -1 +0,0 @@ -// This file will contain exported plugin collections diff --git a/src/plugins/translations/en.json b/src/plugins/translations/en.json deleted file mode 100644 index 2c63c08..0000000 --- a/src/plugins/translations/en.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/src/plugins/translations/fr.json b/src/plugins/translations/fr.json deleted file mode 100644 index 2c63c08..0000000 --- a/src/plugins/translations/fr.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} From e7069abc5191ff9a7e00894ebfa1af464d13c407 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 22:55:16 +0100 Subject: [PATCH 6/7] remove comments --- src/module-commons-ui.d.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/module-commons-ui.d.ts b/src/module-commons-ui.d.ts index 0c0aa8c..1d78d56 100644 --- a/src/module-commons-ui.d.ts +++ b/src/module-commons-ui.d.ts @@ -1,4 +1,2 @@ //TODO: remove when commons-ui will include typescript definitions -declare module '@gridsuite/commons-ui' /*{ - export = typeof import('@gridsuite/commons-ui'); -}*/; +declare module '@gridsuite/commons-ui'; From 0deac69f9fbe1bc1aa6a7ece21990344f7b2c0bd Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 7 Mar 2024 23:23:06 +0100 Subject: [PATCH 7/7] Add missing MUI translations --- src/components/App/app-wrapper.tsx | 35 +++++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/components/App/app-wrapper.tsx b/src/components/App/app-wrapper.tsx index 1f0e43d..3b64c33 100644 --- a/src/components/App/app-wrapper.tsx +++ b/src/components/App/app-wrapper.tsx @@ -6,18 +6,21 @@ */ import App from './app'; -import { FunctionComponent } from 'react'; -import { CssBaseline } from '@mui/material'; +import { FunctionComponent, useMemo } from 'react'; +import { CssBaseline, responsiveFontSizes, ThemeOptions } from '@mui/material'; import { createTheme, StyledEngineProvider, Theme, ThemeProvider, } from '@mui/material/styles'; +import { enUS as MuiCoreEnUS, frFR as MuiCoreFrFR } from '@mui/material/locale'; import { card_error_boundary_en, card_error_boundary_fr, CardErrorBoundary, + LANG_ENGLISH, + LANG_FRENCH, LIGHT_THEME, login_en, login_fr, @@ -36,7 +39,7 @@ import { PARAM_THEME } from '../../utils/config-params'; import { IntlConfig } from 'react-intl/src/types'; import { AppState } from '../../redux/reducer'; -const lightTheme: Theme = createTheme({ +const lightTheme: ThemeOptions = { palette: { mode: 'light', }, @@ -60,9 +63,9 @@ const lightTheme: Theme = createTheme({ color: 'blue', }, mapboxStyle: 'mapbox://styles/mapbox/light-v9', -}); +}; -const darkTheme: Theme = createTheme({ +const darkTheme: ThemeOptions = { palette: { mode: 'dark', }, @@ -86,14 +89,15 @@ const darkTheme: Theme = createTheme({ color: 'green', }, mapboxStyle: 'mapbox://styles/mapbox/dark-v9', -}); +}; -const getMuiTheme = (theme: string): Theme => { - if (theme === LIGHT_THEME) { - return lightTheme; - } else { - return darkTheme; - } +const getMuiTheme = (theme: unknown, locale: SupportedLanguages): Theme => { + return responsiveFontSizes( + createTheme( + theme === LIGHT_THEME ? lightTheme : darkTheme, + locale === LANG_FRENCH ? MuiCoreFrFR : MuiCoreEnUS // MUI core translations + ) + ); }; const messages: Record = { @@ -118,14 +122,19 @@ const AppWrapperWithRedux: FunctionComponent = () => { (state: AppState) => state.computedLanguage ); const theme = useSelector((state: AppState) => state[PARAM_THEME]); + const themeCompiled = useMemo( + () => getMuiTheme(theme, computedLanguage), + [computedLanguage, theme] + ); return ( - +