Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
31 changes: 1 addition & 30 deletions src/components/app-top-bar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,10 @@ import { PARAM_USE_NAME } from '../utils/config-params';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import AppPackage from '../../package.json';
import { isNodeBuilt, isNodeReadOnly } from './graph/util/model-functions';
import { getServersInfos } from '../services/study';
import { fetchVersion } from '../services/utils';
import { RunButtonContainer } from './run-button-container';
import { useParameterState } from './dialogs/parameters/use-parameters-state';
import StudyNavigationSyncToggle from './study-navigation-sync-toggle';
import { WorkspaceToolbar } from './workspace/core/workspace-toolbar';
import { WorkspaceSwitcher } from './workspace/core/workspace-switcher';

const styles = {
boxContent: (theme) => ({
Expand All @@ -39,23 +35,12 @@ const styles = {
width: '100%',
marginLeft: theme.spacing(1),
}),
runButtonContainer: {
display: 'flex',
alignItems: 'center',
marginRight: 1.5,
},
syncToggleContainer: {
display: 'flex',
alignItems: 'center',
marginRight: 1.5,
},
};

const AppTopBar = ({ userProfile, userManager }) => {
const dispatch = useDispatch();
const theme = useSelector((state) => state[PARAM_THEME]);
const studyUuid = useSelector((state) => state.studyUuid);
const currentNode = useSelector((state) => state.currentTreeNode);
const currentRootNetworkUuid = useSelector((state) => state.currentRootNetworkUuid);

const [appsAndUrls, setAppsAndUrls] = useState([]);
Expand Down Expand Up @@ -97,23 +82,9 @@ const AppTopBar = ({ userProfile, userManager }) => {
>
{userProfile && studyUuid && currentRootNetworkUuid && (
<Box sx={styles.boxContent}>
<Box sx={{ display: 'flex', alignItems: 'center', marginLeft: 1.5, marginRight: 'auto' }}>
<Box sx={{ display: 'flex', alignItems: 'center', marginLeft: 1.5 }}>
<WorkspaceToolbar />
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', marginRight: 1.5, marginLeft: 'auto' }}>
<WorkspaceSwitcher />
</Box>
<Box sx={styles.runButtonContainer}>
<RunButtonContainer
studyUuid={studyUuid}
currentNode={currentNode}
currentRootNetworkUuid={currentRootNetworkUuid}
disabled={!isNodeBuilt(currentNode) || isNodeReadOnly(currentNode)}
/>
</Box>
<Box sx={styles.syncToggleContainer}>
<StudyNavigationSyncToggle />
</Box>
</Box>
)}
</TopBar>
Expand Down
95 changes: 95 additions & 0 deletions src/components/breadcrumbs/current-selection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* 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 { Box, CircularProgress, Paper, Tooltip } from '@mui/material';
import { BuildStatusChip, type MuiStyles } from '@gridsuite/commons-ui';
import type { UUID } from 'node:crypto';
import { useIntl } from 'react-intl';
import { useSelector } from 'react-redux';
import { CurrentTreeNode, NodeType } from '../graph/tree-node.type';
import { RootNetworkMetadata } from '../graph/menus/network-modifications/network-modification-menu.type';
import { AppState } from '../../redux/reducer.type';
import { NodeActivityChip, NodeActivityDetails } from '../utils/node-activity-display';
import { useBlockingActivity, useNodeActivity } from '../utils/use-node-activity';
import RootNetworkSelect from './root-network-select';

const styles = {
container: {
display: 'flex',
alignItems: 'center',
borderRadius: '8px',
minHeight: 32,
px: 1,
},
label: (theme) => ({
display: { xs: 'none', lg: 'block' },
mr: 1,
fontSize: theme.typography.fontSize,
}),
rootNetworkSlot: {
display: 'flex',
alignItems: 'center',
mr: 1,
},
nodeLabel: (theme) => ({
maxWidth: 500,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
fontSize: theme.typography.fontSize,
}),
chipSlot: {
display: 'flex',
alignItems: 'center',
ml: 1,
},
blockedSpinner: {
ml: 1,
},
} as const satisfies MuiStyles;

export default function CurrentSelection() {
const intl = useIntl();
const currentNode: CurrentTreeNode | null = useSelector((state: AppState) => state.currentTreeNode);
const currentRootNetworkUuid: UUID | null = useSelector((state: AppState) => state.currentRootNetworkUuid);
const rootNetworks: RootNetworkMetadata[] = useSelector((state: AppState) => state.rootNetworks);
const isRootNode = currentNode?.type === NodeType.ROOT;
const nodeLabel = isRootNode ? intl.formatMessage({ id: 'root' }) : currentNode?.data.label;
const activity = useNodeActivity(currentNode?.id);
const blockingActivity = useBlockingActivity(currentNode?.id);

return (
<Paper elevation={1} sx={styles.container}>
{rootNetworks.length > 1 && (
<>
<Box sx={styles.label}>{intl.formatMessage({ id: 'root' })}</Box>
<Box sx={styles.rootNetworkSlot}>
<RootNetworkSelect
currentRootNetworkUuid={currentRootNetworkUuid}
rootNetworks={rootNetworks}
/>
</Box>
</>
)}
<Box sx={styles.label}>{intl.formatMessage({ id: 'node' })}</Box>
<Tooltip title={nodeLabel || ''}>
<Box sx={styles.nodeLabel}>{nodeLabel}</Box>
</Tooltip>
<Box sx={styles.chipSlot}>
{activity && <NodeActivityChip activity={activity} />}
{!activity && currentNode && !isRootNode && (
<BuildStatusChip buildStatus={currentNode.data.globalBuildStatus} />
)}
</Box>
{!activity && blockingActivity && (
<Tooltip title={<NodeActivityDetails activity={blockingActivity} />} placement="bottom">
<CircularProgress size={20} sx={styles.blockedSpinner} />
</Tooltip>
)}
</Paper>
);
}
26 changes: 18 additions & 8 deletions src/components/breadcrumbs/root-network-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Box, ListItemText, MenuItem, Select } from '@mui/material';
import { Box, MenuItem, Select } from '@mui/material';
import type { UUID } from 'node:crypto';
import { RemoveRedEye, VisibilityOff } from '@mui/icons-material';
import { RootNetworkMetadata } from '../graph/menus/network-modifications/network-modification-menu.type';
Expand All @@ -15,12 +15,22 @@ import { mergeSx, type MuiStyles } from '@gridsuite/commons-ui';
const styles = {
selectRoot: (theme) => ({
height: theme.spacing(4),
width: theme.spacing(15),
width: 'fit-content',
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1),
'& .MuiOutlinedInput-notchedOutline': { border: 'none' },
'& .MuiSelect-select.MuiSelect-select': { paddingLeft: 0, paddingRight: theme.spacing(3.5) },
}),
selectInput: (theme) => ({
display: 'flex',
gap: 1,
alignItems: 'center',
fontSize: theme.typography.fontSize,
}),
selectItem: (theme) => ({
gap: 1,
fontSize: theme.typography.fontSize,
}),
selectInput: { display: 'flex', gap: 1, alignItems: 'center' },
selectItem: { gap: 1 },
hiddenItem: { display: 'none' },
} as const satisfies MuiStyles;

Expand All @@ -45,8 +55,8 @@ export default function RootNetworkSelect({ currentRootNetworkUuid, rootNetworks
const tag = rootNetworks.find((item) => item.rootNetworkUuid === value)?.tag;
return (
<Box sx={styles.selectInput}>
<RemoveRedEye />
<ListItemText primary={tag} />
{tag}
<RemoveRedEye fontSize="small" />
</Box>
);
}}
Expand All @@ -60,8 +70,8 @@ export default function RootNetworkSelect({ currentRootNetworkUuid, rootNetworks
item.rootNetworkUuid === currentRootNetworkUuid ? styles.hiddenItem : undefined
)}
>
<VisibilityOff />
<ListItemText primary={item.tag} />
{item.tag}
<VisibilityOff fontSize="small" />
</MenuItem>
))}
</Select>
Expand Down
51 changes: 17 additions & 34 deletions src/components/breadcrumbs/study-path-breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,10 @@
*/

import { MoreHoriz } from '@mui/icons-material';
import { Box, Breadcrumbs as MuiBreadcrumbs, Tooltip } from '@mui/material';
import { Box, Breadcrumbs as MuiBreadcrumbs, type Theme, Tooltip, useMediaQuery } from '@mui/material';
import { type MuiStyles } from '@gridsuite/commons-ui';
import { CurrentTreeNode, NodeType } from '../graph/tree-node.type';
import { useSelector } from 'react-redux';
import { AppState } from '../../redux/reducer.type';
import { RootNetworkMetadata } from '../graph/menus/network-modifications/network-modification-menu.type';
import type { UUID } from 'node:crypto';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import RootNetworkSelect from './root-network-select';
import { useIntl } from 'react-intl';
import CurrentSelection from './current-selection';

const styles = {
tooltipItem: {
Expand All @@ -29,6 +23,12 @@ const styles = {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
parentDirectoryItem: {
maxWidth: 200,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
} as const satisfies MuiStyles;

export interface StudyPathBreadcrumbsProps {
Expand All @@ -40,13 +40,8 @@ export default function StudyPathBreadcrumbs({
studyName,
parentDirectoriesNames,
}: Readonly<StudyPathBreadcrumbsProps>) {
const intl = useIntl();
const currentNode: CurrentTreeNode | null = useSelector((state: AppState) => state.currentTreeNode);
const currentRootNetworkUuid: UUID | null = useSelector((state: AppState) => state.currentRootNetworkUuid);
const rootNetworks: RootNetworkMetadata[] = useSelector((state: AppState) => state.rootNetworks);
const currentRootNetworkTag = rootNetworks.find((item) => item.rootNetworkUuid === currentRootNetworkUuid)?.tag;
const isRootNode = currentNode?.type === NodeType.ROOT;
const nodeLabel = isRootNode ? intl.formatMessage({ id: 'root' }) : currentNode?.data.label;
const nearestParentDirectoryName = parentDirectoriesNames?.at(-1);
const showParentDirectory = useMediaQuery((theme: Theme) => theme.breakpoints.up('md'));

return (
<MuiBreadcrumbs
Expand All @@ -64,17 +59,7 @@ export default function StudyPathBreadcrumbs({
<KeyboardArrowRightIcon fontSize="small" />
</Box>
))}
<Box sx={styles.tooltipItem}>
{studyName}
<KeyboardArrowRightIcon fontSize="small" />
</Box>
<Box sx={styles.tooltipItem}>{nodeLabel}</Box>
{rootNetworks?.length > 1 && (
<Box sx={styles.tooltipItem}>
<KeyboardArrowRightIcon fontSize="small" />
{currentRootNetworkTag}
</Box>
)}
<Box sx={styles.tooltipItem}>{studyName}</Box>
</Box>
}
slotProps={{
Expand All @@ -87,17 +72,15 @@ export default function StudyPathBreadcrumbs({
>
<MoreHoriz sx={{ display: 'flex', alignItems: 'center' }} />
</Tooltip>
{showParentDirectory && nearestParentDirectoryName && (
<Tooltip title={nearestParentDirectoryName}>
<Box sx={styles.parentDirectoryItem}>{nearestParentDirectoryName}</Box>
</Tooltip>
)}
<Tooltip title={studyName || ''}>
<Box sx={styles.breadcrumbItem}>{studyName}</Box>
</Tooltip>
<Tooltip title={nodeLabel || ''}>
<Box sx={styles.breadcrumbItem}>{nodeLabel}</Box>
</Tooltip>
{rootNetworks && rootNetworks.length > 1 && (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<RootNetworkSelect currentRootNetworkUuid={currentRootNetworkUuid} rootNetworks={rootNetworks} />
</Box>
)}
<CurrentSelection />
</MuiBreadcrumbs>
);
}
Loading
Loading