Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .env
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
REACT_APP_USE_AUTHENTICATION=true
VITE_USE_AUTHENTICATION=true

REACT_APP_API_GATEWAY=api/gateway
REACT_APP_WS_GATEWAY=ws/gateway

EXTEND_ESLINT=true
VITE_API_GATEWAY=api/gateway
VITE_WS_GATEWAY=ws/gateway
4 changes: 2 additions & 2 deletions .env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
REACT_APP_USE_AUTHENTICATION=false
VITE_USE_AUTHENTICATION=false

REACT_APP_SRV_STUDY_URI=study-server
VITE_SRV_STUDY_URI=study-server
5 changes: 3 additions & 2 deletions public/index.html → index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<head>
<base href="%PUBLIC_URL%/" />
<base href="./" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate" />
<link rel="icon" href="favicon.ico" />
<link rel="icon" href="/favicon.ico" />
<title>GridXXXApp</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* 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 type { Config } from 'jest';

const config: Config = {
testEnvironment: 'jsdom',
moduleNameMapper: {
'^.+\\.svg\\?react$|@powsybl/network-viewer': '<rootDir>/src/_mocks_/svg.tsx',
'^.+\\.(css|less|scss)$': 'identity-obj-proxy',
},
transformIgnorePatterns: [
'node_modules/(?!@gridsuite/commons-ui|react-dnd|uuid|dnd-core|react-resizable-panels|@react-dnd)',
], // transform from ESM
moduleDirectories: ['node_modules', 'src'], // to allow absolute path from ./src
setupFiles: ['<rootDir>/jest.setup.ts'],
};

export default config;
5 changes: 4 additions & 1 deletion src/react-app-env.d.ts → jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/// <reference types="react-scripts" />
import { TextEncoder, TextDecoder } from 'util';

// fix for ReferenceError: TextDecoder / TextEncoder is not defined
Object.assign(global, { TextDecoder, TextEncoder });
24,959 changes: 7,379 additions & 17,580 deletions package-lock.json

Large diffs are not rendered by default.

48 changes: 19 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "gridXXX-app",
"version": "0.1.0",
"license": "MPL-2.0",
"homepage": ".",
"private": true,
"engines": {
"node": ">=18",
Expand All @@ -20,54 +19,42 @@
"@reduxjs/toolkit": "^2.2.3",
"core-js": "^3.36.1",
"notistack": "^3.0.1",
"oidc-client": "^1.11.5",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.2",
"react-intl": "^6.6.4",
"react-redux": "^9.1.0",
"react-router-dom": "^6.22.3",
"react-scripts": "^5.0.1",
"react-window": "^1.8.10",
"reconnecting-websocket": "^4.4.0",
"redux": "^5.0.1",
"typeface-roboto": "^1.1.13",
"yup": "^1.4.0"
},
"overrides": {
"react-scripts": {
"typescript": "$typescript"
}
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --watchAll=false",
"test:watch": "react-scripts test",
"test:coverage": "react-scripts test --coverage",
"eject": "react-scripts eject",
"lint": "eslint . --ext js,mjs,jsx,ts,mts,tsx --max-warnings 0",
"start": "vite",
"start:open": "vite --open",
"build": "vite build",
"serve": "vite preview",
"test": "jest",
"test:coverage": "jest --coverage",
Comment on lines +41 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
jq '.jest // empty' package.json
fd 'jest\.config\.(ts|js|cjs|mjs)$'

Repository: gridsuite/gridapp-template

Length of output: 278


Consolidate Jest configuration to a single source.

The repository has both a "jest" block in package.json and a standalone jest.config.ts file. Running jest with two config sources will cause it to fail or behave unpredictably. Remove the "jest" block from package.json and keep only jest.config.ts, or if using package.json as the source, remove jest.config.ts and invoke Jest with --config if needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 41 - 42, The repository contains two Jest
configuration sources; remove the "jest" configuration block from package.json
so Jest uses the single jest.config.ts file (keep the existing "test" and
"test:coverage" npm scripts), or alternatively delete/disable jest.config.ts and
ensure the npm scripts pass --config to package.json if you intend to keep that
block; pick one approach and eliminate the duplicate configuration (referenced
symbols: the "jest" block in package.json, the "test" and "test:coverage" npm
scripts, and jest.config.ts).

"type-check": "tsc",
"prebuild": "npm run lint && npm run type-check",
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix",
"lint:format": "prettier --check --cache .",
"licenses-check": "license-checker --summary --excludePrivatePackages --production --onlyAllow \"$( jq -r .onlyAllow[] license-checker-config.json | tr '\n' ';')\" --excludePackages \"$( jq -r .excludePackages[] license-checker-config.json | tr '\n' ';')\""
},
"jest": {
"moduleNameMapper": {
"\\.svg": "<rootDir>/src/__mocks__/svgrMock.js",
"^.+\\.(css|less|scss)$": "identity-obj-proxy"
},
"transformIgnorePatterns": [
"node_modules/(?!@gridsuite/commons-ui|react-dnd|dnd-core|@react-dnd)"
]
},
"eslintConfig": {
"extends": [
"react-app",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": "warn",
"curly": "error"
}
},
"browserslist": {
"production": [
">0.2%",
Expand All @@ -81,21 +68,24 @@
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@vitejs/plugin-react": "^5.0.0",
"@types/core-js": "^2.5.8",
"@types/eslint-config-prettier": "^6.11.3",
"@types/jest": "^27.5.2",
"@types/license-checker": "^25.0.6",
"@types/node": "^18.19.31",
"@types/node": "^20.19.0",
"@types/prop-types": "^15.7.12",
"@types/react": "^18.2.75",
"@types/react-dom": "^18.2.24",
"@types/react-window": "^1.8.8",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^4.2.1",
"http-proxy-middleware": "^2.0.6",
"jest": "^30.1.3",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
jq -r '.devDependencies.jest, .devDependencies["@types/jest"]' package.json

Repository: gridsuite/gridapp-template

Length of output: 85


Align Jest and @types/jest major versions.

Jest is at ^30.1.3 (line 83) but @types/jest remains at ^27.5.2 (line 74). This major version mismatch can break TypeScript test globals and matchers.

Upgrade @types/jest to ^30.x.x or explicitly remove the @types/jest dependency if no longer needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 83, Update the package.json test typings to match
Jest's major version: change the `@types/jest` dependency to a 30.x release (e.g.,
^30.0.0) or remove `@types/jest` if you no longer need it; ensure the dependency
entry for "@types/jest" aligns with "jest" (jest at ^30.1.3) so TypeScript test
globals and matchers resolve correctly and run npm/yarn install to update the
lockfile.

"license-checker": "^25.0.1",
"prettier": "^2.8.8",
"typescript": "5.1.6"
"typescript": "5.1.6",
"vite": "^7.1.7",
"vite-tsconfig-paths": "^5.1.4",
"vite-plugin-svgr": "^4.3.0"
}
}
4 changes: 2 additions & 2 deletions src/components/app.test.tsx → src/app/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { act } from 'react-dom/test-utils';
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 App from './App';
import { store } from './store';
import { createTheme, StyledEngineProvider, ThemeProvider } from '@mui/material/styles';
import { SnackbarProvider } from '@gridsuite/commons-ui';
import { CssBaseline } from '@mui/material';
Expand Down
72 changes: 23 additions & 49 deletions src/components/app.tsx → src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,41 @@

import React, { FunctionComponent, useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Navigate, Route, Routes, useLocation, useMatch, useNavigate } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { Box, Typography } from '@mui/material';
import { useLocation, useMatch, useNavigate } from 'react-router-dom';
import {
AuthenticationRouter,
CardErrorBoundary,
getPreLoginPath,
initializeAuthenticationDev,
initializeAuthenticationProd,
useSnackMessage,
} from '@gridsuite/commons-ui';
import { selectComputedLanguage, selectLanguage, selectTheme } from '../redux/actions';
import { AppState } from '../redux/reducer';
import { selectComputedLanguage, selectLanguage, selectTheme } from '../features/app-settings/store/actions';
import {
ConfigParameters,
connectNotificationsWsUpdateConfig,
fetchConfigParameter,
fetchConfigParameters,
fetchIdpSettings,
fetchValidateUser,
} from '../utils/rest-api';
import { APP_NAME, COMMON_APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params';
import { getComputedLanguage } from '../utils/language';
import AppTopBar, { AppTopBarProps } from './app-top-bar';
} from '../shared/api/config';
import { fetchIdpSettings, fetchValidateUser } from '../shared/api/auth';
import { APP_NAME, COMMON_APP_NAME } from './config/config';
import { PARAM_LANGUAGE, PARAM_THEME } from '../shared/config/parameters';
import { getComputedLanguage } from '../shared/lib/language';
import AppTopBar, { AppTopBarProps } from '../app/layout/AppTopBar';
import ReconnectingWebSocket from 'reconnecting-websocket';
import { getErrorMessage } from '../utils/error';
import { AppDispatch } from '../redux/store';
import { getErrorMessage } from '../shared/lib/error';
import { AppDispatch } from './store';
import { selectAuth, selectUser } from '../features/auth/model/selectors';
import AppLayout from '../app/layout/AppLayout';
import AppRouter from '../app/router/AppRouter';

const App: FunctionComponent = () => {
const { snackError } = useSnackMessage();

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

const signInCallbackError = useSelector((state: AppState) => state.signInCallbackError);
const authenticationRouterError = useSelector((state: AppState) => state.authenticationRouterError);
const showAuthenticationRouterLogin = useSelector((state: AppState) => state.showAuthenticationRouterLogin);
const user = useSelector(selectUser);
const auth = useSelector(selectAuth);
const signInCallbackError = auth.error;
const authenticationRouterError = auth.authenticationRouterError;
const showAuthenticationRouterLogin = auth.showLogin;

const [userManager, setUserManager] = useState<AppTopBarProps['userManager']>({ instance: null, error: null });

Expand Down Expand Up @@ -110,9 +109,9 @@ const App: FunctionComponent = () => {
// need subfunction when async as suggested by rule react-hooks/exhaustive-deps
(async function initializeAuthentication() {
try {
console.debug(`auth dev mode: ${process.env.REACT_APP_USE_AUTHENTICATION}`);
console.debug(`auth dev mode: ${import.meta.env.VITE_USE_AUTHENTICATION}`);
const initAuth =
process.env.REACT_APP_USE_AUTHENTICATION === 'true'
import.meta.env.VITE_USE_AUTHENTICATION === 'true'
? initializeAuthenticationProd(
dispatch,
initialMatchSilentRenewCallbackUrl != null,
Expand Down Expand Up @@ -166,35 +165,10 @@ const App: FunctionComponent = () => {
}, [user, dispatch, updateParams, snackError, connectNotificationsUpdateConfig]);

return (
<>
<AppTopBar user={user} userManager={userManager} />
<AppLayout topBar={<AppTopBar user={user} userManager={userManager} />}>
<CardErrorBoundary>
{user !== null ? (
<Routes>
<Route
path="/"
element={
<Box mt={20}>
<Typography variant="h3" color="textPrimary" align="center">
Connected
</Typography>
</Box>
}
/>
<Route path="/sign-in-callback" element={<Navigate replace to={getPreLoginPath() || '/'} />} />
<Route
path="/logout-callback"
element={<h1>Error: logout failed; you are still logged in.</h1>}
/>
<Route
path="*"
element={
<h1>
<FormattedMessage id="PageNotFound" />
</h1>
}
/>
</Routes>
<AppRouter />
) : (
<AuthenticationRouter
userManager={userManager}
Expand All @@ -207,7 +181,7 @@ const App: FunctionComponent = () => {
/>
)}
</CardErrorBoundary>
</>
</AppLayout>
);
};
export default App;
Expand Down
9 changes: 3 additions & 6 deletions src/utils/config-params.ts → src/app/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

export const COMMON_APP_NAME = 'common';
export const APP_NAME = 'XXX';
import { AppConfigParameter, PARAM_LANGUAGE, PARAM_THEME } from '@/shared/config/parameters';

export const PARAM_THEME = 'theme';
export const PARAM_LANGUAGE = 'language';
export const COMMON_APP_NAME = 'common';
export const APP_NAME = 'study'; // TODO, set back to template

const COMMON_CONFIG_PARAMS_NAMES = new Set([PARAM_THEME, PARAM_LANGUAGE]);

export type AppConfigParameter = typeof PARAM_THEME | typeof PARAM_LANGUAGE | string;

export type AppConfigType = typeof COMMON_APP_NAME | typeof APP_NAME;

/**
Expand Down
23 changes: 23 additions & 0 deletions src/app/layout/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2020, 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 React, { FunctionComponent, PropsWithChildren, ReactNode } from 'react';

export type AppLayoutProps = PropsWithChildren<{
topBar: ReactNode;
}>;

const AppLayout: FunctionComponent<AppLayoutProps> = ({ topBar, children }) => {
return (
<>
{topBar}
{children}
</>
);
};

export default AppLayout;
Loading
Loading