Skip to content

Commit

Permalink
Developer mode banner (#679)
Browse files Browse the repository at this point in the history
* Developer mode banner

---------

Signed-off-by: BOUTIER Charly <[email protected]>
Co-authored-by: BOUTIER Charly <[email protected]>
Co-authored-by: souissimai <[email protected]>
  • Loading branch information
3 people authored Jan 28, 2025
1 parent 444ee2e commit 3f3542b
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 69 deletions.
6 changes: 5 additions & 1 deletion demo/src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'));

Expand Down Expand Up @@ -812,6 +814,7 @@ function AppContent({ language, onLanguageClick }) {
</div>
<hr />
<Crasher />
<Button onClick={() => setDeveloperMode(!developerMode)}>Toggle developer mode</Button>
</div>
);

Expand All @@ -825,7 +828,8 @@ function AppContent({ language, onLanguageClick }) {
appName="Demo"
appColor="#808080"
appLogo={<PowsyblLogo />}
onParametersClick={() => console.log('settings')}
onUserSettingsClick={() => console.log('user settings')}
developerMode={developerMode}
onLogoutClick={() => logout(dispatch, userManager.instance)}
onLogoClick={() => console.log('logo')}
onThemeClick={handleThemeClick}
Expand Down
75 changes: 75 additions & 0 deletions src/components/topBar/MessageBanner.tsx
Original file line number Diff line number Diff line change
@@ -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<Theme> => ({
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<Theme> => ({
paddingRight: theme.spacing(0.75),
color: 'red',
marginTop: theme.spacing(0.5),
}),
message: {
flexGrow: 1,
},
button: (theme: Theme): SystemStyleObject<Theme> => ({
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 && (
<Box sx={styles.banner}>
<Box sx={styles.icon}>
<WarningAmberIcon />
</Box>
<Box sx={styles.message}>{children}</Box>
<Box sx={styles.button} onClick={() => setVisible(false)}>
<CloseIcon />
</Box>
</Box>
)
);
}

export default MessageBanner;
133 changes: 69 additions & 64 deletions src/components/topBar/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -58,6 +58,7 @@ import {
LANG_SYSTEM,
LIGHT_THEME,
} from '../../utils/constants/browserConstants';
import MessageBanner from './MessageBanner';

const styles = {
grow: {
Expand Down Expand Up @@ -165,7 +166,7 @@ export type GsTheme = typeof LIGHT_THEME | typeof DARK_THEME;
export type TopBarProps = Omit<GridLogoProps, 'onClick'> &
Omit<LogoutProps, 'disabled'> &
Omit<AboutDialogProps, 'open' | 'onClose'> & {
onParametersClick?: () => void;
onUserSettingsClick?: () => void;
onLogoClick: GridLogoProps['onClick'];
user?: User;
onAboutClick?: () => void;
Expand All @@ -177,6 +178,7 @@ export type TopBarProps = Omit<GridLogoProps, 'onClick'> &
equipmentLabelling?: boolean;
onLanguageClick: (value: GsLang) => void;
language: GsLang;
developerMode?: boolean;
};

export function TopBar({
Expand All @@ -186,7 +188,7 @@ export function TopBar({
appVersion,
appLicense,
logoAboutDialog,
onParametersClick,
onUserSettingsClick,
onLogoutClick,
onLogoClick,
user,
Expand All @@ -197,6 +199,7 @@ export function TopBar({
additionalModulesPromise,
onThemeClick,
theme,
developerMode,
onEquipmentLabellingClick,
equipmentLabelling,
onLanguageClick,
Expand Down Expand Up @@ -226,10 +229,10 @@ export function TopBar({
setAnchorElAppsMenu(null);
};

const onParametersClicked = () => {
const onUserSettingsClicked = () => {
setAnchorElSettingsMenu(null);
if (onParametersClick) {
onParametersClick();
if (onUserSettingsClick) {
onUserSettingsClick();
}
};

Expand Down Expand Up @@ -291,6 +294,11 @@ export function TopBar({
return (
// @ts-ignore appBar style is not defined
<AppBar position="static" color="default" sx={styles.appBar}>
{user && developerMode && (
<MessageBanner>
<FormattedMessage id="top-bar/developerModeWarning" defaultMessage="Developer mode" />
</MessageBanner>
)}
<Toolbar>
{logoClickable}
<Box sx={styles.grow}>{children}</Box>
Expand Down Expand Up @@ -401,6 +409,58 @@ export function TopBar({
</ListItemText>
</StyledMenuItem>

{/* User information */}
{!isHiddenUserInformation() && (
<StyledMenuItem
style={{ opacity: '1' }}
onClick={onUserInformationDialogClicked}
>
<CustomListItemIcon>
<BadgeIcon fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage
id="top-bar/userInformation"
defaultMessage="User information"
/>
</Typography>
</ListItemText>
</StyledMenuItem>
)}

{/* User settings */}
<StyledMenuItem onClick={onUserSettingsClicked} sx={styles.borderBottom}>
<CustomListItemIcon>
<ManageAccounts fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage
id="top-bar/userSettings"
defaultMessage="Settings"
/>
</Typography>
</ListItemText>
</StyledMenuItem>

{/* About */}
{/* If the callback onAboutClick is undefined, we open default about dialog */}
<StyledMenuItem
sx={styles.borderBottom}
style={{ opacity: '1' }}
onClick={onAboutClicked}
>
<CustomListItemIcon>
<HelpOutlineIcon fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage id="top-bar/about" defaultMessage="About" />
</Typography>
</ListItemText>
</StyledMenuItem>

{/* Display mode */}
<StyledMenuItem
disabled
Expand Down Expand Up @@ -443,8 +503,8 @@ export function TopBar({
</ToggleButtonGroup>
</StyledMenuItem>

{/* /!* 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 && (
<StyledMenuItem
disabled
Expand Down Expand Up @@ -482,6 +542,7 @@ export function TopBar({
{/* Languages */}
<StyledMenuItem
disabled
sx={styles.borderBottom}
style={{
opacity: '1',
paddingTop: '10px',
Expand Down Expand Up @@ -524,62 +585,6 @@ export function TopBar({
</ToggleButtonGroup>
</StyledMenuItem>

{/* Settings */}
{/* If the callback onParametersClicked is undefined, parameters component should be disabled */}
{onParametersClick && (
<StyledMenuItem onClick={onParametersClicked} sx={styles.borderTop}>
<CustomListItemIcon>
<SettingsIcon fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage
id="top-bar/settings"
defaultMessage="Settings"
/>
</Typography>
</ListItemText>
</StyledMenuItem>
)}

{/* User information */}
{!isHiddenUserInformation() && (
<StyledMenuItem
sx={styles.borderBottom}
style={{ opacity: '1' }}
onClick={onUserInformationDialogClicked}
>
<CustomListItemIcon>
<ManageAccounts fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage
id="top-bar/userInformation"
defaultMessage="User information"
/>
</Typography>
</ListItemText>
</StyledMenuItem>
)}

{/* About */}
{/* If the callback onAboutClick is undefined, we open default about dialog */}
<StyledMenuItem
sx={styles.borderBottom}
style={{ opacity: '1' }}
onClick={onAboutClicked}
>
<CustomListItemIcon>
<HelpOutlineIcon fontSize="small" />
</CustomListItemIcon>
<ListItemText>
<Typography sx={styles.sizeLabel}>
<FormattedMessage id="top-bar/about" defaultMessage="About" />
</Typography>
</ListItemText>
</StyledMenuItem>

{/* Loggout */}
<StyledMenuItem onClick={onLogoutClick}>
<CustomListItemIcon>
Expand Down
2 changes: 1 addition & 1 deletion src/components/topBar/tests/TopBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ it('renders', () => {
appName="Demo"
appColor="#808080"
appLogo={<PowsyblLogo />}
onParametersClick={() => {}}
onUserSettingsClick={() => {}}
onLogoutClick={() => {}}
onLogoClick={() => {}}
user={{
Expand Down
5 changes: 3 additions & 2 deletions src/translations/en/topBarEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}',
Expand Down
4 changes: 3 additions & 1 deletion src/translations/fr/topBarFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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}',
Expand Down

0 comments on commit 3f3542b

Please sign in to comment.