diff --git a/package-lock.json b/package-lock.json index 21f45d5..bac31bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.61.3", + "@gridsuite/commons-ui": "0.61.3-2", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "^5.0.0-alpha.169", @@ -2753,9 +2753,10 @@ } }, "node_modules/@gridsuite/commons-ui": { - "version": "0.61.3", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.61.3.tgz", - "integrity": "sha512-3jCqUmwMFts3Ya8IV2bzjLttSKiT5fTEcxT552FdOTiYYyZPHuaCujn9MuAl6Eh2Pf+YXZmVPAscw6D3pIOnuQ==", + "version": "0.61.3+2", + "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.61.3-2.tgz", + "integrity": "sha512-7qdI1oAof3dJwe8EOh3zhyTYg3VcBHbr2Qwy1sxGkL93tM/jSLvSXuQURO1cyHkDTSKb6LfguE7ZR8YMe4eSOQ==", + "license": "MPL-2.0", "dependencies": { "@react-querybuilder/dnd": "^7.2.0", "@react-querybuilder/material": "^7.2.0", diff --git a/package.json b/package.json index 25f247e..4874756 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.61.3", + "@gridsuite/commons-ui": "0.61.3+2", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "^5.0.0-alpha.169", diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index f5d7a46..645bbe8 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -11,7 +11,12 @@ import React, { useEffect, useState, } from 'react'; -import { LIGHT_THEME, logout, TopBar } from '@gridsuite/commons-ui'; +import { + LIGHT_THEME, + logout, + TopBar, + UserManagerState, +} 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'; @@ -29,10 +34,7 @@ import { AppDispatch } from '../redux/store'; export type AppTopBarProps = { user?: AppState['user']; - userManager: { - instance: unknown | null; - error: string | null; - }; + userManager: UserManagerState; }; const AppTopBar: FunctionComponent = (props) => { const navigate = useNavigate(); diff --git a/src/components/app-wrapper.tsx b/src/components/app-wrapper.tsx index a24233a..0803483 100644 --- a/src/components/app-wrapper.tsx +++ b/src/components/app-wrapper.tsx @@ -18,6 +18,7 @@ import { card_error_boundary_en, card_error_boundary_fr, CardErrorBoundary, + GsLangUser, LIGHT_THEME, login_en, login_fr, @@ -28,7 +29,6 @@ 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'; @@ -98,7 +98,7 @@ const getMuiTheme = (theme: string): Theme => { } }; -const messages: Record = { +const messages: Record = { en: { ...messages_en, ...login_en, diff --git a/src/components/app.tsx b/src/components/app.tsx index 6df62b7..b1f8ec6 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -55,6 +55,7 @@ import AppTopBar, { AppTopBarProps } from './app-top-bar'; import ReconnectingWebSocket from 'reconnecting-websocket'; import { getErrorMessage } from '../utils/error'; import { AppDispatch } from '../redux/store'; +import { UserManager } from 'oidc-client'; const App: FunctionComponent = () => { const { snackError } = useSnackMessage(); @@ -140,7 +141,7 @@ const App: FunctionComponent = () => { }) ); - const initialize = useCallback((): Promise => { + const initialize = useCallback((): Promise => { if (process.env.REACT_APP_USE_AUTHENTICATION === 'true') { return fetchAuthorizationCodeFlowFeatureFlag().then( (authorizationCodeFlowEnabled) => diff --git a/src/redux/actions.ts b/src/redux/actions.ts index de549a8..65aa3cf 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -5,15 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { GsTheme } from '@gridsuite/commons-ui'; import { PARAM_LANGUAGE } from '../utils/config-params'; import { Action } from 'redux'; import { AppState } from './reducer'; export const SELECT_THEME = 'SELECT_THEME'; export type ThemeAction = Readonly> & { - theme: string; + theme: GsTheme; }; -export function selectTheme(theme: string): ThemeAction { + +export function selectTheme(theme: GsTheme): ThemeAction { return { type: SELECT_THEME, theme: theme }; } @@ -21,6 +23,7 @@ export const SELECT_LANGUAGE = 'SELECT_LANGUAGE'; export type LanguageAction = Readonly> & { [PARAM_LANGUAGE]: AppState['language']; }; + export function selectLanguage(language: AppState['language']): LanguageAction { return { type: SELECT_LANGUAGE, [PARAM_LANGUAGE]: language }; } @@ -31,6 +34,7 @@ export type ComputedLanguageAction = Readonly< > & { computedLanguage: AppState['computedLanguage']; }; + export function selectComputedLanguage( computedLanguage: AppState['computedLanguage'] ): ComputedLanguageAction { diff --git a/src/redux/local-storage.ts b/src/redux/local-storage.ts index f709f69..f38ddab 100644 --- a/src/redux/local-storage.ts +++ b/src/redux/local-storage.ts @@ -5,30 +5,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { DARK_THEME, LANG_SYSTEM } from '@gridsuite/commons-ui'; +import { + DARK_THEME, + GsLang, + GsLangUser, + GsTheme, + LANG_SYSTEM, +} from '@gridsuite/commons-ui'; import { getComputedLanguage } from '../utils/language'; import { APP_NAME } from '../utils/config-params'; -import { AppState } from './reducer'; const LOCAL_STORAGE_THEME_KEY = (APP_NAME + '_THEME').toUpperCase(); const LOCAL_STORAGE_LANGUAGE_KEY = (APP_NAME + '_LANGUAGE').toUpperCase(); -export function getLocalStorageTheme(): string { - return localStorage.getItem(LOCAL_STORAGE_THEME_KEY) || DARK_THEME; +export function getLocalStorageTheme() { + return ( + (localStorage.getItem(LOCAL_STORAGE_THEME_KEY) as GsTheme) || DARK_THEME + ); } -export function saveLocalStorageTheme(theme: string): void { +export function saveLocalStorageTheme(theme: GsTheme): void { localStorage.setItem(LOCAL_STORAGE_THEME_KEY, theme); } -export function getLocalStorageLanguage(): AppState['language'] { - return localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) || LANG_SYSTEM; +export function getLocalStorageLanguage() { + return ( + (localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) as GsLang) || + LANG_SYSTEM + ); } -export function saveLocalStorageLanguage(language: AppState['language']): void { +export function saveLocalStorageLanguage(language: GsLang): void { localStorage.setItem(LOCAL_STORAGE_LANGUAGE_KEY, language); } -export function getLocalStorageComputedLanguage(): AppState['computedLanguage'] { +export function getLocalStorageComputedLanguage(): GsLangUser { return getComputedLanguage(getLocalStorageLanguage()); } diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index 7acbd27..e6f54e5 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -5,8 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { AnyAction, createReducer, Draft } from '@reduxjs/toolkit'; -import { User } from 'oidc-client'; +import { createReducer, Draft } from '@reduxjs/toolkit'; import { getLocalStorageComputedLanguage, getLocalStorageLanguage, @@ -21,26 +20,37 @@ import { ThemeAction, } from './actions'; import { + AuthenticationRouterErrorAction, + AuthenticationRouterErrorState, + CommonActions, + CommonStoreState, + GsLang, + GsLangUser, + GsTheme, LOGOUT_ERROR, + LogoutErrorAction, RESET_AUTHENTICATION_ROUTER_ERROR, SHOW_AUTH_INFO_LOGIN, + ShowAuthenticationRouterLoginAction, SIGNIN_CALLBACK_ERROR, + SignInCallbackErrorAction, UNAUTHORIZED_USER_INFO, + UnauthorizedUserAction, USER, USER_VALIDATION_ERROR, + UserAction, + UserValidationErrorAction, } from '@gridsuite/commons-ui'; import { PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; import { ReducerWithInitialState } from '@reduxjs/toolkit/dist/createReducer'; -import { LanguageParameters, SupportedLanguages } from '../utils/language'; -export type AppState = { - computedLanguage: SupportedLanguages; - [PARAM_THEME]: string; - [PARAM_LANGUAGE]: LanguageParameters; +export type AppState = CommonStoreState & { + computedLanguage: GsLangUser; + [PARAM_THEME]: GsTheme; + [PARAM_LANGUAGE]: GsLang; - user: User | null; //TODO use true definition when commons-ui passed to typescript - signInCallbackError: unknown; - authenticationRouterError: unknown; + signInCallbackError: string | null; + authenticationRouterError: AuthenticationRouterErrorState | null; showAuthenticationRouterLogin: boolean; }; @@ -57,7 +67,11 @@ const initialState: AppState = { computedLanguage: getLocalStorageComputedLanguage(), }; -export type Actions = AnyAction | ThemeAction | LanguageAction | ComputedLanguageAction; +export type Actions = + | CommonActions + | ThemeAction + | LanguageAction + | ComputedLanguageAction; export type AppStateKey = keyof AppState; @@ -72,20 +86,20 @@ export const reducer: ReducerWithInitialState = createReducer( } ); - builder.addCase(USER, (state: Draft, action: AnyAction) => { + builder.addCase(USER, (state: Draft, action: UserAction) => { state.user = action.user; }); builder.addCase( SIGNIN_CALLBACK_ERROR, - (state: Draft, action: AnyAction) => { + (state: Draft, action: SignInCallbackErrorAction) => { state.signInCallbackError = action.signInCallbackError; } ); builder.addCase( UNAUTHORIZED_USER_INFO, - (state: Draft, action: AnyAction) => { + (state: Draft, action: UnauthorizedUserAction) => { state.authenticationRouterError = action.authenticationRouterError; } @@ -93,7 +107,7 @@ export const reducer: ReducerWithInitialState = createReducer( builder.addCase( LOGOUT_ERROR, - (state: Draft, action: AnyAction) => { + (state: Draft, action: LogoutErrorAction) => { state.authenticationRouterError = action.authenticationRouterError; } @@ -101,7 +115,7 @@ export const reducer: ReducerWithInitialState = createReducer( builder.addCase( USER_VALIDATION_ERROR, - (state: Draft, action: AnyAction) => { + (state: Draft, action: UserValidationErrorAction) => { state.authenticationRouterError = action.authenticationRouterError; } @@ -109,14 +123,20 @@ export const reducer: ReducerWithInitialState = createReducer( builder.addCase( RESET_AUTHENTICATION_ROUTER_ERROR, - (state: Draft, action: AnyAction) => { + ( + state: Draft, + action: AuthenticationRouterErrorAction + ) => { state.authenticationRouterError = null; } ); builder.addCase( SHOW_AUTH_INFO_LOGIN, - (state: Draft, action: AnyAction) => { + ( + state: Draft, + action: ShowAuthenticationRouterLoginAction + ) => { state.showAuthenticationRouterLogin = action.showAuthenticationRouterLogin; } diff --git a/src/utils/language.ts b/src/utils/language.ts index 9620e00..aa7003a 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -5,26 +5,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { LANG_ENGLISH, LANG_FRENCH, LANG_SYSTEM } from '@gridsuite/commons-ui'; +import { + GsLang, + GsLangUser, + LANG_ENGLISH, + LANG_FRENCH, + LANG_SYSTEM, +} from '@gridsuite/commons-ui'; const supportedLanguages = [LANG_FRENCH, LANG_ENGLISH]; -//export type SupportedLanguagesType = typeof supportedLanguages[number]; //TODO when commons-ui in typescript -export type SupportedLanguages = 'en' | 'fr'; -//export type LanguageParameters = SupportedLanguages | typeof LANG_SYSTEM; //TODO when commons-ui in typescript -export type LanguageParameters = SupportedLanguages | 'sys'; -export function getSystemLanguage(): SupportedLanguages { +export function getSystemLanguage(): GsLangUser { const systemLanguage = navigator.language.split(/[-_]/)[0]; return supportedLanguages.includes(systemLanguage) - ? systemLanguage + ? (systemLanguage as GsLangUser) : LANG_ENGLISH; } -export function getComputedLanguage( - language: LanguageParameters -): SupportedLanguages { - return language === LANG_SYSTEM - ? getSystemLanguage() - : (language as SupportedLanguages); - //TODO remove cast when commons-ui in typescript +export function getComputedLanguage(language: GsLang) { + return language === LANG_SYSTEM ? getSystemLanguage() : language; } diff --git a/src/utils/rest-api.ts b/src/utils/rest-api.ts index b425a54..a4d5999 100644 --- a/src/utils/rest-api.ts +++ b/src/utils/rest-api.ts @@ -15,8 +15,8 @@ import { import { store } from '../redux/store'; import ReconnectingWebSocket, { Event } from 'reconnecting-websocket'; import { AppState } from '../redux/reducer'; -import { LanguageParameters } from './language'; import { getErrorMessage } from './error'; +import { GsLangUser, GsTheme } from '@gridsuite/commons-ui'; export interface ErrorWithStatus extends Error { status?: number; @@ -271,13 +271,14 @@ export function fetchAppsAndUrls(): Promise { export type ConfigParameter = | { readonly name: typeof PARAM_LANGUAGE; - value: LanguageParameters; + value: GsLangUser; } | { readonly name: typeof PARAM_THEME; - value: string; + value: GsTheme; }; export type ConfigParameters = ConfigParameter[]; + export function fetchConfigParameters( appName: string = APP_NAME ): Promise {