Skip to content

Commit 6b533d5

Browse files
Apply updated gridsuite template (#13)
1 parent 6167e41 commit 6b533d5

27 files changed

+404
-207
lines changed

package-lock.json

Lines changed: 27 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"private": true,
77
"bugs": "https://github.com/gridsuite/gridadmin-app/issues",
88
"repository": {
9-
"type": "TODO",
9+
"type": "git",
1010
"url": "https://github.com/gridsuite/gridadmin-app"
1111
},
1212
"engines": {
@@ -41,6 +41,7 @@
4141
"react-window": "^1.8.5",
4242
"reconnecting-websocket": "^4.4.0",
4343
"redux": "^4.0.5",
44+
"type-fest": "^4.11.1",
4445
"typeface-roboto": "^1.0.0",
4546
"typescript": "^5.1.3",
4647
"yup": "^1.2.0"

src/components/app-top-bar.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,35 @@
1-
/**
1+
/*
22
* Copyright (c) 2021, RTE (http://www.rte-france.com)
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import React, { FunctionComponent, useEffect, useState } from 'react';
8+
import { FunctionComponent, useCallback, useEffect, useState } from 'react';
99
import { LIGHT_THEME, logout, TopBar } from '@gridsuite/commons-ui';
1010
import Parameters, { useParameterState } from './parameters';
1111
import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params';
1212
import { useDispatch, useSelector } from 'react-redux';
13-
import { AppsMetadataSrv, StudySrv } from '../services';
13+
import { AppsMetadataSrv, MetadataJson, StudySrv } from '../services';
1414
import { useNavigate } from 'react-router-dom';
1515
import { ReactComponent as PowsyblLogo } from '../images/powsybl_logo.svg';
1616
import AppPackage from '../../package.json';
1717
import { AppState } from '../redux/reducer';
18-
import { UserManager } from 'oidc-client';
1918

2019
export type AppTopBarProps = {
2120
user?: AppState['user'];
2221
userManager: {
23-
instance: UserManager | null;
22+
instance: unknown | null;
2423
error: string | null;
2524
};
2625
};
26+
2727
const AppTopBar: FunctionComponent<AppTopBarProps> = (props) => {
2828
const navigate = useNavigate();
2929

3030
const dispatch = useDispatch();
3131

32-
const [appsAndUrls, setAppsAndUrls] = useState<
33-
Awaited<ReturnType<typeof AppsMetadataSrv.fetchAppsAndUrls>>
34-
>([]);
32+
const [appsAndUrls, setAppsAndUrls] = useState<MetadataJson[]>([]);
3533

3634
const theme = useSelector((state: AppState) => state[PARAM_THEME]);
3735

@@ -41,6 +39,8 @@ const AppTopBar: FunctionComponent<AppTopBarProps> = (props) => {
4139
useParameterState(PARAM_LANGUAGE);
4240

4341
const [showParameters, setShowParameters] = useState(false);
42+
const displayParameters = useCallback(() => setShowParameters(true), []);
43+
const hideParameters = useCallback(() => setShowParameters(false), []);
4444

4545
useEffect(() => {
4646
if (props.user !== null) {
@@ -64,7 +64,7 @@ const AppTopBar: FunctionComponent<AppTopBarProps> = (props) => {
6464
}
6565
appVersion={AppPackage.version}
6666
appLicense={AppPackage.license}
67-
onParametersClick={() => setShowParameters(true)}
67+
onParametersClick={displayParameters}
6868
onLogoutClick={() =>
6969
logout(dispatch, props.userManager.instance)
7070
}
@@ -84,7 +84,7 @@ const AppTopBar: FunctionComponent<AppTopBarProps> = (props) => {
8484
/>
8585
<Parameters
8686
showParameters={showParameters}
87-
hideParameters={() => setShowParameters(false)}
87+
hideParameters={hideParameters}
8888
/>
8989
</>
9090
);

src/components/app-wrapper.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
/**
1+
/*
22
* Copyright (c) 2021, RTE (http://www.rte-france.com)
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

88
import App from './app';
9-
import React, { FunctionComponent } from 'react';
9+
import { FunctionComponent } from 'react';
10+
import { CssBaseline } from '@mui/material';
1011
import {
1112
createTheme,
1213
StyledEngineProvider,
@@ -27,12 +28,12 @@ import {
2728
import { IntlProvider } from 'react-intl';
2829
import { BrowserRouter } from 'react-router-dom';
2930
import { Provider, useSelector } from 'react-redux';
31+
import { SupportedLanguages } from '../utils/language';
3032
import messages_en from '../translations/en.json';
3133
import messages_fr from '../translations/fr.json';
3234
import messages_plugins_en from '../plugins/translations/en.json';
3335
import messages_plugins_fr from '../plugins/translations/fr.json';
3436
import { store } from '../redux/store';
35-
import CssBaseline from '@mui/material/CssBaseline';
3637
import { PARAM_THEME } from '../utils/config-params';
3738
import { IntlConfig } from 'react-intl/src/types';
3839
import { AppState } from '../redux/reducer';
@@ -89,15 +90,15 @@ const darkTheme: Theme = createTheme({
8990
mapboxStyle: 'mapbox://styles/mapbox/dark-v9',
9091
});
9192

92-
const getMuiTheme = (theme: unknown): Theme => {
93+
const getMuiTheme = (theme: string): Theme => {
9394
if (theme === LIGHT_THEME) {
9495
return lightTheme;
9596
} else {
9697
return darkTheme;
9798
}
9899
};
99100

100-
const messages: Record<string, IntlConfig['messages']> = {
101+
const messages: Record<SupportedLanguages, IntlConfig['messages']> = {
101102
en: {
102103
...messages_en,
103104
...login_en,
@@ -114,7 +115,7 @@ const messages: Record<string, IntlConfig['messages']> = {
114115
},
115116
};
116117

117-
const basename = new URL(document.querySelector('base')?.href || '').pathname;
118+
const basename = new URL(document.querySelector('base')?.href ?? '').pathname;
118119

119120
const AppWrapperWithRedux: FunctionComponent = () => {
120121
const computedLanguage = useSelector(

src/components/app.test.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import { SnackbarProvider } from '@gridsuite/commons-ui';
1717
import { CssBaseline } from '@mui/material';
1818

19-
let container: Element | any = null;
19+
let container: HTMLElement | null = null;
2020

2121
beforeEach(() => {
2222
// setup a DOM element as a render target
@@ -26,11 +26,14 @@ beforeEach(() => {
2626

2727
afterEach(() => {
2828
// cleanup on exiting
29-
container.remove();
29+
container?.remove();
3030
container = null;
3131
});
3232

3333
it('renders', async () => {
34+
if (container === null) {
35+
throw new Error('No container was defined');
36+
}
3437
const root = createRoot(container);
3538
await act(async () =>
3639
root.render(

src/components/app.tsx

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
/**
1+
/*
22
* Copyright (c) 2020, RTE (http://www.rte-france.com)
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import React, {
9-
FunctionComponent,
10-
useCallback,
11-
useEffect,
12-
useState,
13-
} from 'react';
8+
import { FunctionComponent, useCallback, useEffect, useState } from 'react';
149
import { useDispatch, useSelector } from 'react-redux';
1510
import {
1611
Navigate,
@@ -36,14 +31,12 @@ import {
3631
} from '../redux/actions';
3732
import { AppState } from '../redux/reducer';
3833
import {
39-
ConfigSrv,
34+
AppsMetadataSrv,
4035
ConfigNotif,
41-
ConfigParameter,
4236
ConfigParameters,
37+
ConfigSrv,
4338
UserAdminSrv,
44-
AppsMetadataSrv,
4539
} from '../services';
46-
import { UserManager } from 'oidc-client';
4740
import {
4841
APP_NAME,
4942
COMMON_APP_NAME,
@@ -53,12 +46,20 @@ import {
5346
import { getComputedLanguage } from '../utils/language';
5447
import AppTopBar, { AppTopBarProps } from './app-top-bar';
5548
import ReconnectingWebSocket from 'reconnecting-websocket';
49+
import { getErrorMessage } from '../utils/error';
5650

5751
const App: FunctionComponent = () => {
5852
const { snackError } = useSnackMessage();
53+
const dispatch = useDispatch();
54+
const navigate = useNavigate();
55+
const location = useLocation();
5956

6057
const user = useSelector((state: AppState) => state.user);
6158

59+
const [userManager, setUserManager] = useState<
60+
AppTopBarProps['userManager']
61+
>({ instance: null, error: null });
62+
6263
const signInCallbackError = useSelector(
6364
(state: AppState) => state.signInCallbackError
6465
);
@@ -69,20 +70,12 @@ const App: FunctionComponent = () => {
6970
(state: AppState) => state.showAuthenticationRouterLogin
7071
);
7172

72-
const [userManager, setUserManager] = useState<
73-
AppTopBarProps['userManager']
74-
>({ instance: null, error: null });
75-
76-
const navigate = useNavigate();
77-
78-
const dispatch = useDispatch();
79-
80-
const location = useLocation();
81-
82-
const updateParams: (p: ConfigParameters) => void = useCallback(
73+
const updateParams = useCallback(
8374
(params: ConfigParameters) => {
84-
console.debug('received UI parameters : ', params);
85-
params.forEach((param: ConfigParameter) => {
75+
console.groupCollapsed('received UI parameters');
76+
console.table(params);
77+
console.groupEnd();
78+
params.forEach((param) => {
8679
switch (param.name) {
8780
case PARAM_THEME:
8881
dispatch(selectTheme(param.value));
@@ -96,14 +89,15 @@ const App: FunctionComponent = () => {
9689
);
9790
break;
9891
default:
92+
break;
9993
}
10094
});
10195
},
10296
[dispatch]
10397
);
10498

105-
const connectNotificationsUpdateConfig: () => ReconnectingWebSocket =
106-
useCallback(() => {
99+
const connectNotificationsUpdateConfig =
100+
useCallback((): ReconnectingWebSocket => {
107101
const ws = ConfigNotif.connectNotificationsWsUpdateConfig();
108102
ws.onmessage = function (event) {
109103
let eventData = JSON.parse(event.data);
@@ -132,7 +126,7 @@ const App: FunctionComponent = () => {
132126
path: '/silent-renew-callback',
133127
})
134128
);
135-
const [initialMatchSignInCallbackUrl] = useState(
129+
const [initialMatchSigninCallbackUrl] = useState(
136130
useMatch({
137131
path: '/sign-in-callback',
138132
})
@@ -147,20 +141,23 @@ const App: FunctionComponent = () => {
147141
fetch('idpSettings.json'),
148142
UserAdminSrv.fetchValidateUser,
149143
authorizationCodeFlowEnabled,
150-
initialMatchSignInCallbackUrl != null
144+
initialMatchSigninCallbackUrl != null
151145
)
152146
)
153-
.then((userManager: UserManager | undefined) => {
154-
setUserManager({ instance: userManager || null, error: null });
147+
.then((userManager) => {
148+
setUserManager({ instance: userManager ?? null, error: null });
155149
})
156-
.catch((error: any) => {
157-
setUserManager({ instance: null, error: error.message });
150+
.catch((error: unknown) => {
151+
setUserManager({
152+
instance: null,
153+
error: getErrorMessage(error),
154+
});
158155
});
159-
// Note: initialize and initialMatchSilentRenewCallbackUrl & initialMatchSignInCallbackUrl won't change
156+
// Note: initialMatchSilentRenewCallbackUrl & initialMatchSigninCallbackUrl won't change
160157
}, [
161158
dispatch,
162159
initialMatchSilentRenewCallbackUrl,
163-
initialMatchSignInCallbackUrl,
160+
initialMatchSigninCallbackUrl,
164161
]);
165162

166163
useEffect(() => {

0 commit comments

Comments
 (0)