diff --git a/demo/src/app.jsx b/demo/src/app.jsx index 55bc0fb2..0cc9508c 100644 --- a/demo/src/app.jsx +++ b/demo/src/app.jsx @@ -331,6 +331,8 @@ function AppContent({ language, onLanguageClick }) { const [openTreeViewFinderDialog, setOpenTreeViewFinderDialog] = useState(false); const [openTreeViewFinderDialogCustomDialog, setOpenTreeViewFinderDialogCustomDialog] = useState(false); + const [developerMode, setDeveloperMode] = useState(false); + // Can't use lazy initializer because useMatch is a hook const [initialMatchSilentRenewCallbackUrl] = useState(useMatch('/silent-renew-callback')); @@ -812,6 +814,7 @@ function AppContent({ language, onLanguageClick }) {
+ ); @@ -825,7 +828,8 @@ function AppContent({ language, onLanguageClick }) { appName="Demo" appColor="#808080" appLogo={} - onParametersClick={() => console.log('settings')} + onUserSettingsClick={() => console.log('user settings')} + developerMode={developerMode} onLogoutClick={() => logout(dispatch, userManager.instance)} onLogoClick={() => console.log('logo')} onThemeClick={handleThemeClick} diff --git a/src/components/topBar/MessageBanner.tsx b/src/components/topBar/MessageBanner.tsx new file mode 100644 index 00000000..dcb81d6c --- /dev/null +++ b/src/components/topBar/MessageBanner.tsx @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2025, 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 { ReactNode, useState } from 'react'; +import { Box, Theme } from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; +import WarningAmberIcon from '@mui/icons-material/WarningAmber'; +import { SystemStyleObject } from '@mui/system/styleFunctionSx/styleFunctionSx'; + +const styles = { + banner: (theme: Theme): SystemStyleObject => ({ + left: 0, + width: '100%', + backgroundColor: '#f6b26b', + color: 'black', + padding: theme.spacing(1), + textAlign: 'left', + boxShadow: '0px 2px 5px rgba(0, 0, 0, 0.1)', + zIndex: 1000, + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + }), + icon: (theme: Theme): SystemStyleObject => ({ + paddingRight: theme.spacing(0.75), + color: 'red', + marginTop: theme.spacing(0.5), + }), + message: { + flexGrow: 1, + }, + button: (theme: Theme): SystemStyleObject => ({ + backgroundColor: '#f6b26b', + border: 'none', + cursor: 'pointer', + borderRadius: theme.spacing(0.5), + marginRight: theme.spacing(0.5), + width: theme.spacing(3.5), + height: theme.spacing(3.5), + '&:hover': { + backgroundColor: '#e39648', + }, + '& svg': { + width: '100%', + height: '100%', + }, + }), +}; + +export interface MessageBannerProps { + children: ReactNode; +} + +function MessageBanner({ children }: MessageBannerProps) { + const [visible, setVisible] = useState(true); + + return ( + visible && ( + + + + + {children} + setVisible(false)}> + + + + ) + ); +} + +export default MessageBanner; diff --git a/src/components/topBar/TopBar.tsx b/src/components/topBar/TopBar.tsx index 2c29d1dc..2ab7c8ad 100644 --- a/src/components/topBar/TopBar.tsx +++ b/src/components/topBar/TopBar.tsx @@ -39,8 +39,8 @@ import { HelpOutline as HelpOutlineIcon, Person as PersonIcon, ManageAccounts, - Settings as SettingsIcon, WbSunny as WbSunnyIcon, + Badge as BadgeIcon, } from '@mui/icons-material'; import { styled } from '@mui/system'; @@ -58,6 +58,7 @@ import { LANG_SYSTEM, LIGHT_THEME, } from '../../utils/constants/browserConstants'; +import MessageBanner from './MessageBanner'; const styles = { grow: { @@ -165,7 +166,7 @@ export type GsTheme = typeof LIGHT_THEME | typeof DARK_THEME; export type TopBarProps = Omit & Omit & Omit & { - onParametersClick?: () => void; + onUserSettingsClick?: () => void; onLogoClick: GridLogoProps['onClick']; user?: User; onAboutClick?: () => void; @@ -177,6 +178,7 @@ export type TopBarProps = Omit & equipmentLabelling?: boolean; onLanguageClick: (value: GsLang) => void; language: GsLang; + developerMode?: boolean; }; export function TopBar({ @@ -186,7 +188,7 @@ export function TopBar({ appVersion, appLicense, logoAboutDialog, - onParametersClick, + onUserSettingsClick, onLogoutClick, onLogoClick, user, @@ -197,6 +199,7 @@ export function TopBar({ additionalModulesPromise, onThemeClick, theme, + developerMode, onEquipmentLabellingClick, equipmentLabelling, onLanguageClick, @@ -226,10 +229,10 @@ export function TopBar({ setAnchorElAppsMenu(null); }; - const onParametersClicked = () => { + const onUserSettingsClicked = () => { setAnchorElSettingsMenu(null); - if (onParametersClick) { - onParametersClick(); + if (onUserSettingsClick) { + onUserSettingsClick(); } }; @@ -291,6 +294,11 @@ export function TopBar({ return ( // @ts-ignore appBar style is not defined + {user && developerMode && ( + + + + )} {logoClickable} {children} @@ -401,6 +409,58 @@ export function TopBar({ + {/* User information */} + {!isHiddenUserInformation() && ( + + + + + + + + + + + )} + + {/* User settings */} + + + + + + + + + + + + {/* About */} + {/* If the callback onAboutClick is undefined, we open default about dialog */} + + + + + + + + + + + {/* Display mode */} - {/* /!* Equipment labelling *!/ */} - {/* If the callback onEquipmentLabellingClick is undefined, equipment labelling component should not be displayed */} + {/* Equipment labeling */} + {/* If the callback onEquipmentLabellingClick is undefined, equipment labeling component should not be displayed */} {onEquipmentLabellingClick && ( - {/* Settings */} - {/* If the callback onParametersClicked is undefined, parameters component should be disabled */} - {onParametersClick && ( - - - - - - - - - - - )} - - {/* User information */} - {!isHiddenUserInformation() && ( - - - - - - - - - - - )} - - {/* About */} - {/* If the callback onAboutClick is undefined, we open default about dialog */} - - - - - - - - - - - {/* Loggout */} diff --git a/src/components/topBar/tests/TopBar.test.tsx b/src/components/topBar/tests/TopBar.test.tsx index c5cc78b4..2587431b 100644 --- a/src/components/topBar/tests/TopBar.test.tsx +++ b/src/components/topBar/tests/TopBar.test.tsx @@ -51,7 +51,7 @@ it('renders', () => { appName="Demo" appColor="#808080" appLogo={} - onParametersClick={() => {}} + onUserSettingsClick={() => {}} onLogoutClick={() => {}} onLogoClick={() => {}} user={{ diff --git a/src/translations/en/topBarEn.ts b/src/translations/en/topBarEn.ts index f2a50d56..c2158611 100644 --- a/src/translations/en/topBarEn.ts +++ b/src/translations/en/topBarEn.ts @@ -6,17 +6,18 @@ */ export const topBarEn = { - 'top-bar/settings': 'Settings', + 'top-bar/userSettings': 'User settings', 'top-bar/logout': 'Logout', 'top-bar/goFullScreen': 'Full screen', 'top-bar/exitFullScreen': 'Exit full screen mode', - 'top-bar/user-information': 'User information', + 'top-bar/userInformation': 'User information', 'top-bar/about': 'About', 'top-bar/displayMode': 'Display mode', 'top-bar/equipmentLabel': 'Equipment label', 'top-bar/id': 'Id', 'top-bar/name': 'Name', 'top-bar/language': 'Language', + 'top-bar/developerModeWarning': 'Developer mode: Some features are incomplete and may not work as expected.', 'about-dialog/title': 'About', 'about-dialog/version': 'Version {version}', diff --git a/src/translations/fr/topBarFr.ts b/src/translations/fr/topBarFr.ts index 87d3c6fc..282a5162 100644 --- a/src/translations/fr/topBarFr.ts +++ b/src/translations/fr/topBarFr.ts @@ -6,7 +6,7 @@ */ export const topBarFr = { - 'top-bar/settings': 'Paramètres', + 'top-bar/userSettings': 'Paramètres utilisateur', 'top-bar/logout': 'Se déconnecter', 'top-bar/goFullScreen': 'Plein écran', 'top-bar/exitFullScreen': 'Quitter mode plein écran', @@ -17,6 +17,8 @@ export const topBarFr = { 'top-bar/id': 'Id', 'top-bar/name': 'Nom', 'top-bar/language': 'Langue', + 'top-bar/developerModeWarning': + 'Mode développeur : Certaines fonctionnalités ne sont pas complètes et peuvent ne pas fonctionner comme prévu.', 'about-dialog/title': 'À propos', 'about-dialog/version': 'Version {version}',