From 73db8780be3eafb3e4bbf1fce387c46d4dd68a8c Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Mon, 8 Jun 2026 14:32:57 +0200 Subject: [PATCH 01/16] use user Profile instead of user --- src/components/parameters-tabs.tsx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/components/parameters-tabs.tsx b/src/components/parameters-tabs.tsx index 53a2427bc1..e75362279e 100644 --- a/src/components/parameters-tabs.tsx +++ b/src/components/parameters-tabs.tsx @@ -96,8 +96,11 @@ enum TAB_VALUES { const ParametersTabs: FunctionComponent = () => { const dispatch = useDispatch(); const attemptedLeaveParametersTabIndex = useSelector((state: AppState) => state.attemptedLeaveParametersTabIndex); - const user = useSelector((state: AppState) => state.user); - const studyUuid = useSelector((state: AppState) => state.studyUuid); + const userProfile = useSelector( + (state: AppState) => state.user?.profile ?? null, + (a, b) => + a === b || (a?.sub === b?.sub && a?.name === b?.name && a?.email === b?.email && a?.profile === b?.profile) + ); const studyUuid = useSelector((state: AppState) => state.studyUuid); const currentNode = useSelector((state: AppState) => state.currentTreeNode ?? null); const currentNodeUuid = useSelector((state: AppState) => state.currentTreeNode?.id ?? null); const currentNodeBuildStatus = useSelector((state: AppState) => state.currentTreeNode?.data.globalBuildStatus); @@ -147,7 +150,7 @@ const ParametersTabs: FunctionComponent = () => { }, [computationStatus, shortCircuitOneBusStatus, tabValue]); const loadFlowParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.LOAD_FLOW, OptionalServicesStatus.Up, @@ -162,7 +165,7 @@ const ParametersTabs: FunctionComponent = () => { useParametersNotification(ComputingType.LOAD_FLOW, OptionalServicesStatus.Up, loadFlowParametersBackend); const securityAnalysisParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.SECURITY_ANALYSIS, securityAnalysisAvailability, @@ -192,7 +195,7 @@ const ParametersTabs: FunctionComponent = () => { ); const sensitivityAnalysisBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.SENSITIVITY_ANALYSIS, sensitivityAnalysisAvailability, @@ -208,7 +211,7 @@ const ParametersTabs: FunctionComponent = () => { ); const shortCircuitParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.SHORT_CIRCUIT, shortCircuitAvailability, @@ -221,7 +224,7 @@ const ParametersTabs: FunctionComponent = () => { useParametersNotification(ComputingType.SHORT_CIRCUIT, shortCircuitAvailability, shortCircuitParametersBackend); const dynamicSimulationParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.DYNAMIC_SIMULATION, dynamicSimulationAvailability, @@ -238,7 +241,7 @@ const ParametersTabs: FunctionComponent = () => { ); const dynamicSecurityAnalysisParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.DYNAMIC_SECURITY_ANALYSIS, dynamicSecurityAnalysisAvailability, @@ -255,7 +258,7 @@ const ParametersTabs: FunctionComponent = () => { ); const dynamicMarginCalculationParametersBackend = useParametersBackend( - user, + userProfile, studyUuid, ComputingType.DYNAMIC_MARGIN_CALCULATION, dynamicMarginCalculationAvailability, @@ -444,7 +447,7 @@ const ParametersTabs: FunctionComponent = () => { ); @@ -467,7 +470,7 @@ const ParametersTabs: FunctionComponent = () => { currentNode?.type, shortCircuitParametersBackend, pccMinParameters, - user, + userProfile, dynamicSimulationParametersBackend, dynamicSecurityAnalysisParametersBackend, dynamicMarginCalculationParametersBackend, From baeeed9f9f9f0936f80295cc10535eca1ee6518b Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Mon, 8 Jun 2026 15:09:21 +0200 Subject: [PATCH 02/16] fix prettier --- src/components/parameters-tabs.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/parameters-tabs.tsx b/src/components/parameters-tabs.tsx index e75362279e..9ae88927cc 100644 --- a/src/components/parameters-tabs.tsx +++ b/src/components/parameters-tabs.tsx @@ -100,7 +100,8 @@ const ParametersTabs: FunctionComponent = () => { (state: AppState) => state.user?.profile ?? null, (a, b) => a === b || (a?.sub === b?.sub && a?.name === b?.name && a?.email === b?.email && a?.profile === b?.profile) - ); const studyUuid = useSelector((state: AppState) => state.studyUuid); + ); + const studyUuid = useSelector((state: AppState) => state.studyUuid); const currentNode = useSelector((state: AppState) => state.currentTreeNode ?? null); const currentNodeUuid = useSelector((state: AppState) => state.currentTreeNode?.id ?? null); const currentNodeBuildStatus = useSelector((state: AppState) => state.currentTreeNode?.data.globalBuildStatus); From 9dd48f7ee838b4a99e41d136c0cf5b47f6989ce2 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Tue, 16 Jun 2026 15:20:23 +0200 Subject: [PATCH 03/16] Avoid booting the full app inside the OIDC silent-renew iframe --- src/components/silent-renew-app.tsx | 42 +++++++++++++++++++++++++++++ src/{index.jsx => index.tsx} | 10 +++++-- src/services/utils.ts | 29 +++++++++++++++++--- 3 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 src/components/silent-renew-app.tsx rename src/{index.jsx => index.tsx} (69%) diff --git a/src/components/silent-renew-app.tsx b/src/components/silent-renew-app.tsx new file mode 100644 index 0000000000..4b6023eba9 --- /dev/null +++ b/src/components/silent-renew-app.tsx @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2026, 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 { useCallback, useEffect, useState } from 'react'; +import type { UserManager } from 'oidc-client-ts'; +import { + handleSilentRenewCallback, + initializeAuthenticationProd, + SilentRenewCallbackHandler, +} from '@gridsuite/commons-ui'; +import { getCachedIdpSettings } from 'services/utils'; + +export default function SilentRenewApp() { + const [userManager, setUserManager] = useState(null); + + useEffect(() => { + initializeAuthenticationProd( + () => undefined /* dispatch: unused when isSilentRenew=true */, + true /* isSilentRenew */, + getCachedIdpSettings /* reads the cache instead of fetching idpSettings.json */, + false /* isSigningCallback */ + ) + .then(setUserManager) + .catch((e) => console.error('Silent renew init failed:', e)); + }, []); + + const handleSilentRenewCallbackClosure = useCallback(() => { + if (userManager) { + handleSilentRenewCallback(userManager); + } + }, [userManager]); + + return ( + + ); +} diff --git a/src/index.jsx b/src/index.tsx similarity index 69% rename from src/index.jsx rename to src/index.tsx index 70fb6048ce..c41f6fba53 100644 --- a/src/index.jsx +++ b/src/index.tsx @@ -16,7 +16,13 @@ import './index.css'; import './configure-yup-init'; import AppWrapper from './components/app-wrapper'; +import SilentRenewApp from './components/silent-renew-app'; const container = document.getElementById('root'); -const root = createRoot(container); -root.render(); +const root = createRoot(container!); + +if (window.location.pathname.endsWith('/silent-renew-callback')) { + root.render(); +} else { + root.render(); +} diff --git a/src/services/utils.ts b/src/services/utils.ts index 06ce711401..3ce5483395 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -4,7 +4,7 @@ * 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 { catchErrorHandler, fetchStudyMetadata, StudyMetadata } from '@gridsuite/commons-ui'; +import { catchErrorHandler, fetchStudyMetadata, IdpSettings, StudyMetadata } from '@gridsuite/commons-ui'; export const FetchStatus = { SUCCEED: 'SUCCEED', FAILED: 'FAILED', @@ -13,7 +13,7 @@ export const FetchStatus = { }; export const MAX_INT32: number = 2147483647; - +const IDP_SETTINGS_CACHE_KEY = 'gridsuite-idp-settings'; type DefaultParameters = StudyMetadata['defaultParametersValues']; export const getWsBase = () => document.baseURI.replace(/^http:\/\//, 'ws://').replace(/^https:\/\//, 'wss://'); @@ -49,8 +49,29 @@ function fetchEnv() { return fetch('env.json').then((res) => res.json()); } -export function fetchIdpSettings() { - return fetch('idpSettings.json').then((res) => res.json()); +// Always hits the network: picks up config changes on each full app load +// AND refreshes the cache read by the silent-renew iframe. +export function fetchIdpSettings(): Promise { + return fetch('idpSettings.json') + .then((res) => res.json()) + .then((settings: IdpSettings) => { + localStorage.setItem(IDP_SETTINGS_CACHE_KEY, JSON.stringify(settings)); + return settings; + }); +} + +// Used only on the silent-renew path: reads the cache (no network), +// falls back to a real fetch if the cache is missing/corrupted. +export function getCachedIdpSettings(): Promise { + const cached = localStorage.getItem(IDP_SETTINGS_CACHE_KEY); + if (cached) { + try { + return Promise.resolve(JSON.parse(cached) as IdpSettings); + } catch { + // corrupted cache -> fall back to a fresh fetch + } + } + return fetchIdpSettings(); } export function fetchVersion() { From a54b761689d30ac4806b4e06df55db956a99c8e6 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 18 Jun 2026 10:34:35 +0200 Subject: [PATCH 04/16] avoid loading full app bundle in silent renew iframe --- index.html | 2 +- src/index.tsx | 25 ++++++++++++------------- src/vite-env.d.ts | 2 ++ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/index.html b/index.html index 80a65c821f..7dc1e8fbd5 100644 --- a/index.html +++ b/index.html @@ -17,6 +17,6 @@
- + diff --git a/src/index.tsx b/src/index.tsx index c41f6fba53..b0a485adc4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,24 +5,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import 'core-js/es/array/flat-map'; - -import 'typeface-roboto'; - import { createRoot } from 'react-dom/client'; - -import '@xyflow/react/dist/base.css'; -import './index.css'; -import './configure-yup-init'; - -import AppWrapper from './components/app-wrapper'; import SilentRenewApp from './components/silent-renew-app'; const container = document.getElementById('root'); const root = createRoot(container!); -if (window.location.pathname.endsWith('/silent-renew-callback')) { - root.render(); -} else { +async function renderApp() { + if (window.location.pathname.endsWith('/silent-renew-callback')) { + root.render(); + return; + } + await import('core-js/es/array/flat-map'); + await import('typeface-roboto'); + await import('@xyflow/react/dist/base.css'); + await import('./index.css'); + await import('./configure-yup-init'); + const { default: AppWrapper } = await import('./components/app-wrapper'); root.render(); } +renderApp().catch((error) => console.error(error)); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index db95603f78..78edcc676a 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -7,3 +7,5 @@ /// /// +declare module 'typeface-roboto'; +declare module 'core-js/es/array/flat-map'; From cd6282a319149da630cc6ac106827010226b3e21 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 18 Jun 2026 14:31:35 +0200 Subject: [PATCH 05/16] serve a minimal HTML on the silent renew callback route --- silent-renew-callback.html | 12 ++++++++++++ src/components/app.jsx | 19 +++++++++++++++++++ src/index.tsx | 19 ++----------------- src/silent-renew.tsx | 11 +++++++++++ vite.config.ts | 28 ++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 silent-renew-callback.html create mode 100644 src/silent-renew.tsx diff --git a/silent-renew-callback.html b/silent-renew-callback.html new file mode 100644 index 0000000000..6f0fbe75f1 --- /dev/null +++ b/silent-renew-callback.html @@ -0,0 +1,12 @@ + + + + + + Silent renew + + +
+ + + diff --git a/src/components/app.jsx b/src/components/app.jsx index 4ed4b0617e..538bc7d7c5 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -77,6 +77,7 @@ import { useGlobalFilterOptions } from './results/common/global-filter/use-globa import { updateComputationColumnFilters, updateComputationGlobalFilters } from './results/common/utils.ts'; import { isEditingGlobalFilter } from '../utils/editing-global-filter-sync.ts'; import { cleanupStaleStudyData } from '../redux/session-storage/local-storage'; +import { Button } from '@mui/material'; const noUserManager = { instance: null, error: null }; @@ -399,6 +400,19 @@ const App = () => { updateNetworkVisualizationsParams, resetTableDefinitions, ]); + const CTX = window === window.parent ? 'PARENT' : 'IFRAME'; + const triggerSilentRenew = useCallback(async () => { + if (userManager.instance) { + console.log(`====[${CTX}][signinSilent] start/done`); + console.log('====[debug] signinSilent start'); + try { + await userManager.instance.signinSilent(); + console.log('====[debug] signinSilent done'); + } catch (e) { + console.error('====[debug] signinSilent error', e); + } + } + }, [CTX, userManager.instance]); return (
{ }} > + {import.meta.env.DEV && ( + + )}
); - return; - } - await import('core-js/es/array/flat-map'); - await import('typeface-roboto'); - await import('@xyflow/react/dist/base.css'); - await import('./index.css'); - await import('./configure-yup-init'); - const { default: AppWrapper } = await import('./components/app-wrapper'); - root.render(); -} -renderApp().catch((error) => console.error(error)); +createRoot(container!).render(); diff --git a/src/silent-renew.tsx b/src/silent-renew.tsx new file mode 100644 index 0000000000..185ba39c18 --- /dev/null +++ b/src/silent-renew.tsx @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2026, 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 { createRoot } from 'react-dom/client'; +import SilentRenewApp from './components/silent-renew-app'; + +const container = document.getElementById('root'); +createRoot(container!).render(); diff --git a/vite.config.ts b/vite.config.ts index a5a2fce97b..bd2d9e88d1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,27 @@ import { CommonServerOptions, defineConfig } from 'vite'; import checker from 'vite-plugin-checker'; import svgr from 'vite-plugin-svgr'; import tsconfigPaths from 'vite-tsconfig-paths'; +import { resolve } from 'node:path'; +import fs from 'node:fs'; +import type { ViteDevServer } from 'vite'; + +const silentRenewPlugin = { + name: 'silent-renew-route', + configureServer(server: ViteDevServer) { + server.middlewares.use(async (req, res, next) => { + if (req.url?.split('?')[0] !== '/silent-renew-callback') { + return next(); + } + const html = await server.transformIndexHtml( + req.url, + fs.readFileSync(resolve(__dirname, 'silent-renew-callback.html'), 'utf-8') + ); + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.end(html); + }); + }, +}; const serverSettings: CommonServerOptions = { port: 3004, @@ -55,11 +76,18 @@ export default defineConfig((_config) => ({ }), svgr(), // works on every import with the pattern "**/*.svg?react" tsconfigPaths(), // to resolve absolute path via tsconfig cf https://stackoverflow.com/a/68250175/5092999 + silentRenewPlugin, ], base: './', server: serverSettings, // for npm run start preview: serverSettings, // for npm run serve (use local build) build: { outDir: 'build', + rollupOptions: { + input: { + main: resolve(__dirname, 'index.html'), + silentRenew: resolve(__dirname, 'silent-renew-callback.html'), + }, + }, }, })); From 1ce33c89bb9eb4a820d6229c53e5cc75914863c7 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Tue, 23 Jun 2026 10:59:57 +0200 Subject: [PATCH 06/16] Revert "serve a minimal HTML on the silent renew callback route" This reverts commit cd6282a319149da630cc6ac106827010226b3e21. --- silent-renew-callback.html | 12 ------------ src/components/app.jsx | 19 ------------------- src/index.tsx | 19 +++++++++++++++++-- src/silent-renew.tsx | 11 ----------- vite.config.ts | 28 ---------------------------- 5 files changed, 17 insertions(+), 72 deletions(-) delete mode 100644 silent-renew-callback.html delete mode 100644 src/silent-renew.tsx diff --git a/silent-renew-callback.html b/silent-renew-callback.html deleted file mode 100644 index 6f0fbe75f1..0000000000 --- a/silent-renew-callback.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Silent renew - - -
- - - diff --git a/src/components/app.jsx b/src/components/app.jsx index 538bc7d7c5..4ed4b0617e 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -77,7 +77,6 @@ import { useGlobalFilterOptions } from './results/common/global-filter/use-globa import { updateComputationColumnFilters, updateComputationGlobalFilters } from './results/common/utils.ts'; import { isEditingGlobalFilter } from '../utils/editing-global-filter-sync.ts'; import { cleanupStaleStudyData } from '../redux/session-storage/local-storage'; -import { Button } from '@mui/material'; const noUserManager = { instance: null, error: null }; @@ -400,19 +399,6 @@ const App = () => { updateNetworkVisualizationsParams, resetTableDefinitions, ]); - const CTX = window === window.parent ? 'PARENT' : 'IFRAME'; - const triggerSilentRenew = useCallback(async () => { - if (userManager.instance) { - console.log(`====[${CTX}][signinSilent] start/done`); - console.log('====[debug] signinSilent start'); - try { - await userManager.instance.signinSilent(); - console.log('====[debug] signinSilent done'); - } catch (e) { - console.error('====[debug] signinSilent error', e); - } - } - }, [CTX, userManager.instance]); return (
{ }} > - {import.meta.env.DEV && ( - - )}
); +const root = createRoot(container!); + +async function renderApp() { + if (window.location.pathname.endsWith('/silent-renew-callback')) { + root.render(); + return; + } + await import('core-js/es/array/flat-map'); + await import('typeface-roboto'); + await import('@xyflow/react/dist/base.css'); + await import('./index.css'); + await import('./configure-yup-init'); + const { default: AppWrapper } = await import('./components/app-wrapper'); + root.render(); +} +renderApp().catch((error) => console.error(error)); diff --git a/src/silent-renew.tsx b/src/silent-renew.tsx deleted file mode 100644 index 185ba39c18..0000000000 --- a/src/silent-renew.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright (c) 2026, 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 { createRoot } from 'react-dom/client'; -import SilentRenewApp from './components/silent-renew-app'; - -const container = document.getElementById('root'); -createRoot(container!).render(); diff --git a/vite.config.ts b/vite.config.ts index bd2d9e88d1..a5a2fce97b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,27 +10,6 @@ import { CommonServerOptions, defineConfig } from 'vite'; import checker from 'vite-plugin-checker'; import svgr from 'vite-plugin-svgr'; import tsconfigPaths from 'vite-tsconfig-paths'; -import { resolve } from 'node:path'; -import fs from 'node:fs'; -import type { ViteDevServer } from 'vite'; - -const silentRenewPlugin = { - name: 'silent-renew-route', - configureServer(server: ViteDevServer) { - server.middlewares.use(async (req, res, next) => { - if (req.url?.split('?')[0] !== '/silent-renew-callback') { - return next(); - } - const html = await server.transformIndexHtml( - req.url, - fs.readFileSync(resolve(__dirname, 'silent-renew-callback.html'), 'utf-8') - ); - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.end(html); - }); - }, -}; const serverSettings: CommonServerOptions = { port: 3004, @@ -76,18 +55,11 @@ export default defineConfig((_config) => ({ }), svgr(), // works on every import with the pattern "**/*.svg?react" tsconfigPaths(), // to resolve absolute path via tsconfig cf https://stackoverflow.com/a/68250175/5092999 - silentRenewPlugin, ], base: './', server: serverSettings, // for npm run start preview: serverSettings, // for npm run serve (use local build) build: { outDir: 'build', - rollupOptions: { - input: { - main: resolve(__dirname, 'index.html'), - silentRenew: resolve(__dirname, 'silent-renew-callback.html'), - }, - }, }, })); From b347286646f9a19549ffbd33d40d324d60118234 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Tue, 23 Jun 2026 11:30:55 +0200 Subject: [PATCH 07/16] rabbit remarks --- src/services/utils.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/services/utils.ts b/src/services/utils.ts index 3ce5483395..b586e3ab85 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -55,7 +55,11 @@ export function fetchIdpSettings(): Promise { return fetch('idpSettings.json') .then((res) => res.json()) .then((settings: IdpSettings) => { - localStorage.setItem(IDP_SETTINGS_CACHE_KEY, JSON.stringify(settings)); + try { + localStorage.setItem(IDP_SETTINGS_CACHE_KEY, JSON.stringify(settings)); + } catch (e) { + console.warn('Failed to cache IdP settings:', e); + } return settings; }); } @@ -63,13 +67,14 @@ export function fetchIdpSettings(): Promise { // Used only on the silent-renew path: reads the cache (no network), // falls back to a real fetch if the cache is missing/corrupted. export function getCachedIdpSettings(): Promise { - const cached = localStorage.getItem(IDP_SETTINGS_CACHE_KEY); - if (cached) { - try { + try { + const cached = localStorage.getItem(IDP_SETTINGS_CACHE_KEY); + if (cached) { return Promise.resolve(JSON.parse(cached) as IdpSettings); - } catch { - // corrupted cache -> fall back to a fresh fetch } + } catch (e) { + // localStorage unavailable, or cache corrupted -> fall back to fresh fetch + +console.warn('Failed to read cached IdP settings:', e); } return fetchIdpSettings(); } From a29740dc85ea76769b0b05fedcd0e72fe267cb41 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Tue, 23 Jun 2026 11:33:09 +0200 Subject: [PATCH 08/16] typo fix --- src/services/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/utils.ts b/src/services/utils.ts index b586e3ab85..069a1bf96c 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -74,7 +74,7 @@ export function getCachedIdpSettings(): Promise { } } catch (e) { // localStorage unavailable, or cache corrupted -> fall back to fresh fetch - +console.warn('Failed to read cached IdP settings:', e); + console.warn('Failed to read cached IdP settings:', e); } return fetchIdpSettings(); } From 044337be3b1cffa90e44ee61b63255dd2425b573 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 24 Jun 2026 11:03:36 +0200 Subject: [PATCH 09/16] code review remarks --- src/components/{silent-renew-app.tsx => silent-renew.tsx} | 2 +- src/index.tsx | 7 ++++--- src/module-core-js-array-flat-map.d.ts | 8 ++++++++ src/module-typeface-roboto.d.ts | 8 ++++++++ src/services/utils.ts | 1 + src/vite-env.d.ts | 2 -- 6 files changed, 22 insertions(+), 6 deletions(-) rename src/components/{silent-renew-app.tsx => silent-renew.tsx} (97%) create mode 100644 src/module-core-js-array-flat-map.d.ts create mode 100644 src/module-typeface-roboto.d.ts diff --git a/src/components/silent-renew-app.tsx b/src/components/silent-renew.tsx similarity index 97% rename from src/components/silent-renew-app.tsx rename to src/components/silent-renew.tsx index 4b6023eba9..64abbd1f8e 100644 --- a/src/components/silent-renew-app.tsx +++ b/src/components/silent-renew.tsx @@ -13,7 +13,7 @@ import { } from '@gridsuite/commons-ui'; import { getCachedIdpSettings } from 'services/utils'; -export default function SilentRenewApp() { +export default function SilentRenew() { const [userManager, setUserManager] = useState(null); useEffect(() => { diff --git a/src/index.tsx b/src/index.tsx index b0a485adc4..0ed9b9f940 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,14 +6,15 @@ */ import { createRoot } from 'react-dom/client'; -import SilentRenewApp from './components/silent-renew-app'; +import SilentRenew from './components/silent-renew'; +import { SILENT_RENEW_CALLBACK_PATH } from './services/utils'; const container = document.getElementById('root'); const root = createRoot(container!); async function renderApp() { - if (window.location.pathname.endsWith('/silent-renew-callback')) { - root.render(); + if (window.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { + root.render(); return; } await import('core-js/es/array/flat-map'); diff --git a/src/module-core-js-array-flat-map.d.ts b/src/module-core-js-array-flat-map.d.ts new file mode 100644 index 0000000000..55f96692d8 --- /dev/null +++ b/src/module-core-js-array-flat-map.d.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2026, 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/. + */ + +declare module 'core-js/es/array/flat-map'; diff --git a/src/module-typeface-roboto.d.ts b/src/module-typeface-roboto.d.ts new file mode 100644 index 0000000000..01671d4749 --- /dev/null +++ b/src/module-typeface-roboto.d.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2026, 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/. + */ + +declare module 'typeface-roboto'; diff --git a/src/services/utils.ts b/src/services/utils.ts index 069a1bf96c..ccecd6200c 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -14,6 +14,7 @@ export const FetchStatus = { export const MAX_INT32: number = 2147483647; const IDP_SETTINGS_CACHE_KEY = 'gridsuite-idp-settings'; +export const SILENT_RENEW_CALLBACK_PATH = '/silent-renew-callback'; type DefaultParameters = StudyMetadata['defaultParametersValues']; export const getWsBase = () => document.baseURI.replace(/^http:\/\//, 'ws://').replace(/^https:\/\//, 'wss://'); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 78edcc676a..db95603f78 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -7,5 +7,3 @@ /// /// -declare module 'typeface-roboto'; -declare module 'core-js/es/array/flat-map'; From 0f75bc9c746f4a9d4847f432c353865127272dcb Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 24 Jun 2026 15:23:57 +0200 Subject: [PATCH 10/16] code review remarks --- src/module-core-js-array-flat-map.d.ts | 8 -------- src/vite-env.d.ts | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 src/module-core-js-array-flat-map.d.ts diff --git a/src/module-core-js-array-flat-map.d.ts b/src/module-core-js-array-flat-map.d.ts deleted file mode 100644 index 55f96692d8..0000000000 --- a/src/module-core-js-array-flat-map.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2026, 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/. - */ - -declare module 'core-js/es/array/flat-map'; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index db95603f78..379ed1ef8e 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -7,3 +7,4 @@ /// /// +declare module 'core-js/es/array/flat-map'; From e36f369984b6c3e432fa377e721129b8ab2a83f9 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 24 Jun 2026 16:44:16 +0200 Subject: [PATCH 11/16] Revert "code review remarks" This reverts commit 0f75bc9c746f4a9d4847f432c353865127272dcb. --- src/module-core-js-array-flat-map.d.ts | 8 ++++++++ src/vite-env.d.ts | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 src/module-core-js-array-flat-map.d.ts diff --git a/src/module-core-js-array-flat-map.d.ts b/src/module-core-js-array-flat-map.d.ts new file mode 100644 index 0000000000..55f96692d8 --- /dev/null +++ b/src/module-core-js-array-flat-map.d.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2026, 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/. + */ + +declare module 'core-js/es/array/flat-map'; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 379ed1ef8e..db95603f78 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -7,4 +7,3 @@ /// /// -declare module 'core-js/es/array/flat-map'; From 44682ccee0bd87ebfe50e34b4c1f3d8cd6463875 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 25 Jun 2026 11:12:44 +0200 Subject: [PATCH 12/16] upgrade commons-ui version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index de9440efc3..ae633c62fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@gridsuite/commons-ui": "0.236.0", + "@gridsuite/commons-ui": "0.237.0", "@hello-pangea/dnd": "^18.0.1", "@hookform/resolvers": "^4.1.3", "@mui/icons-material": "^6.5.0", @@ -3287,9 +3287,9 @@ } }, "node_modules/@gridsuite/commons-ui": { - "version": "0.236.0", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.236.0.tgz", - "integrity": "sha512-MFbfFK/preckX5EzVnjTaxNMNMezaC3eTnQw9x/Bjj479sxedX8PUukEVnYFqVJ45v8z+82Gp8GbdgFffZfiag==", + "version": "0.237.0", + "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.237.0.tgz", + "integrity": "sha512-iB2gle7cOdBjj0Nyr6YJ6pkLREJ36eJHI9VAugZ1MX0kdXTHDN+eUYF7nArs0Oqrcv274PKDtgjhinflKLsC0w==", "license": "MPL-2.0", "dependencies": { "@ag-grid-community/locale": "^35.3.1", diff --git a/package.json b/package.json index b5f02408b2..2c4e4fafca 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@gridsuite/commons-ui": "0.236.0", + "@gridsuite/commons-ui": "0.237.0", "@hello-pangea/dnd": "^18.0.1", "@hookform/resolvers": "^4.1.3", "@mui/icons-material": "^6.5.0", From ee75d93b30856cd88f0dc7191133d08b92091ef8 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 25 Jun 2026 14:12:48 +0200 Subject: [PATCH 13/16] fix sonar issue --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 0ed9b9f940..3c31ff8859 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -13,7 +13,7 @@ const container = document.getElementById('root'); const root = createRoot(container!); async function renderApp() { - if (window.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { + if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { root.render(); return; } From 445ac893e453ef530e0aaf9de53eee5d104fcaa4 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 25 Jun 2026 15:40:50 +0200 Subject: [PATCH 14/16] fix sonar issue --- src/index.tsx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 3c31ff8859..199314b7ee 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -12,17 +12,18 @@ import { SILENT_RENEW_CALLBACK_PATH } from './services/utils'; const container = document.getElementById('root'); const root = createRoot(container!); -async function renderApp() { - if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { - root.render(); - return; - } - await import('core-js/es/array/flat-map'); - await import('typeface-roboto'); - await import('@xyflow/react/dist/base.css'); - await import('./index.css'); - await import('./configure-yup-init'); - const { default: AppWrapper } = await import('./components/app-wrapper'); - root.render(); +if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { + root.render(); +} else { + Promise.all([ + import('core-js/es/array/flat-map'), + import('typeface-roboto'), + import('@xyflow/react/dist/base.css'), + import('./index.css'), + import('./configure-yup-init'), + ]) + .then(() => import('./components/app-wrapper')) + .then(({ default: AppWrapper }) => { + root.render(); + }); } -renderApp().catch((error) => console.error(error)); From 132e553eb0ed42c6168adc8f4d03517170dc12c0 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 25 Jun 2026 15:55:39 +0200 Subject: [PATCH 15/16] fix sonar issue --- src/index.tsx | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 199314b7ee..522ecaefbd 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -12,18 +12,19 @@ import { SILENT_RENEW_CALLBACK_PATH } from './services/utils'; const container = document.getElementById('root'); const root = createRoot(container!); -if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { - root.render(); -} else { - Promise.all([ - import('core-js/es/array/flat-map'), +(async () => { + if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { + root.render(); + return; + } + const appWrapper = import('./components/app-wrapper'); + await Promise.all([ import('typeface-roboto'), import('@xyflow/react/dist/base.css'), import('./index.css'), import('./configure-yup-init'), - ]) - .then(() => import('./components/app-wrapper')) - .then(({ default: AppWrapper }) => { - root.render(); - }); -} + appWrapper, + ]); + const { default: AppWrapper } = await appWrapper; + root.render(); +})(); From 6e1b052a3c9f0284175261507c2c8ec345928889 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 25 Jun 2026 16:12:19 +0200 Subject: [PATCH 16/16] fix sonar issue --- src/index.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 522ecaefbd..1fbe5ffdb1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -12,19 +12,17 @@ import { SILENT_RENEW_CALLBACK_PATH } from './services/utils'; const container = document.getElementById('root'); const root = createRoot(container!); -(async () => { - if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { - root.render(); - return; - } - const appWrapper = import('./components/app-wrapper'); - await Promise.all([ +if (globalThis.location.pathname.endsWith(SILENT_RENEW_CALLBACK_PATH)) { + root.render(); +} else { + Promise.all([ + import('core-js/es/array/flat-map'), import('typeface-roboto'), import('@xyflow/react/dist/base.css'), import('./index.css'), import('./configure-yup-init'), - appWrapper, - ]); - const { default: AppWrapper } = await appWrapper; - root.render(); -})(); + import('./components/app-wrapper'), + ]).then(([, , , , , { default: AppWrapper }]) => { + root.render(); + }); +}