Skip to content
Merged
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
21 changes: 13 additions & 8 deletions src/components/graph/nodes/network-modification-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { NodeProps, Position } from '@xyflow/react';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import { useSelector } from 'react-redux';
import Box from '@mui/material/Box';
import { LIGHT_THEME, type MuiStyles, OverflowableText } from '@gridsuite/commons-ui';
import { LIGHT_THEME, type MuiStyles } from '@gridsuite/commons-ui';
import { getLocalStorageTheme } from '../../../redux/session-storage/local-storage';
import { BUILD_STATUS } from '../../network/constants';
import { AppState } from 'redux/reducer';
Expand All @@ -21,6 +21,7 @@ import NodeOverlaySpinner from './node-overlay-spinner';
import BuildStatusChip from './build-status-chip';
import React from 'react';
import { BuildButton } from './build-button';
import { Typography } from '@mui/material';

const styles = {
networkModificationSelected: (theme) => ({
Expand All @@ -43,12 +44,19 @@ const styles = {
marginRight: theme.spacing(1),
marginBottom: theme.spacing(1),
}),
overflowText: (theme) => ({
typographyText: (theme) => ({
color: theme.palette.text.primary,
fontSize: '20px',
fontWeight: 400,
lineHeight: 'normal',
textAlign: 'left',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: 2,
overflow: 'hidden',
width: 'auto',
textOverflow: 'ellipsis',
wordBreak: 'break-word',
}),
footerBox: (theme) => ({
display: 'flex',
Expand Down Expand Up @@ -118,12 +126,9 @@ const NetworkModificationNode = (props: NodeProps<ModificationNode>) => {
]}
>
<Box sx={styles.contentBox}>
<OverflowableText
text={props.data.label}
sx={styles.overflowText}
tooltipSx={styles.tooltip}
maxLineCount={2}
/>
<Typography variant="body1" sx={styles.typographyText}>
{props.data.label}
</Typography>
</Box>

<Box sx={styles.footerBox}>
Expand Down
187 changes: 125 additions & 62 deletions src/components/network-modification-tree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Box } from '@mui/material';
import { Box, Tooltip } from '@mui/material';
import { Controls, ReactFlow, useEdgesState, useNodesState, useReactFlow } from '@xyflow/react';
import CenterFocusIcon from '@mui/icons-material/CenterFocusStrong';
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from 'react';
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { reorderNetworkModificationTreeNodes, setModificationsDrawerOpen, setToggleOptions } from '../redux/actions';
import { useDispatch, useSelector } from 'react-redux';
import { isSameNode } from './graph/util/model-functions';
import { isRootNode, isSameNode } from './graph/util/model-functions';
import PropTypes from 'prop-types';
import CropFreeIcon from '@mui/icons-material/CropFree';
import { nodeTypes } from './graph/util/model-constants';
Expand All @@ -31,21 +31,32 @@ import { groupIdSuffix } from './graph/nodes/labeled-group-node.type';
import { StudyDisplayMode } from './network-modification.type';
import { useSyncNavigationActions } from 'hooks/use-sync-navigation-actions';
import { NodeType } from './graph/tree-node.type';

const styles = (theme) => ({
flexGrow: 1,
height: '100%',
backgroundColor: theme.reactflow.backgroundColor,
'.react-flow': {
'--xy-edge-stroke': theme.reactflow.edge.stroke,
},
'.react-flow__attribution a': {
color: theme.palette.text.primary,
},
'.react-flow__attribution': {
backgroundColor: theme.palette.background.paper,
},
});
import { useIntl } from 'react-intl';

const styles = {
modificationTree: (theme) => ({
flexGrow: 1,
height: '100%',
backgroundColor: theme.reactflow.backgroundColor,
'.react-flow': {
'--xy-edge-stroke': theme.reactflow.edge.stroke,
},
'.react-flow__attribution a': {
color: theme.palette.text.primary,
},
'.react-flow__attribution': {
backgroundColor: theme.palette.background.paper,
},
}),
labelBox: (theme) => ({
flexGrow: 1,
display: 'flex',
alignItems: 'flex-end',
whiteSpace: 'normal',
wordBreak: 'break-word',
fontWeight: 'bold',
}),
};

const NetworkModificationTree = ({ onNodeContextMenu, studyUuid, onTreePanelResize }) => {
const dispatch = useDispatch();
Expand All @@ -65,8 +76,13 @@ const NetworkModificationTree = ({ onNodeContextMenu, studyUuid, onTreePanelResi
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);

const [tooltipOpen, setTooltipOpen] = useState(false);
const [tooltipContent, setTooltipContent] = useState();

const nodesMap = useMemo(() => new Map(nodes.map((n) => [n.id, n])), [nodes]);

const intl = useIntl();

const updateNodePositions = useCallback(() => {
if (treeModel && treeModel.treeNodes?.length > 0) {
const [treeNodeWithUpdatedPosition, securityGroupNodes] = getTreeNodesWithUpdatedPositions(
Expand Down Expand Up @@ -304,55 +320,102 @@ const NetworkModificationTree = ({ onNodeContextMenu, studyUuid, onTreePanelResi
}
}, [onTreePanelResize, handleFocusNode]);

const handleNodeMouseEnter = useCallback(
(event, node) => {
if (!node?.data || isRootNode(node)) {
return;
}

const content = (
<Box style={{ whiteSpace: 'pre-line' }}>
<Box sx={styles.labelBox}>{node.data.label}</Box>
<Box>
{intl.formatMessage({ id: 'nodeStatus' })} :{' '}
{node.data.globalBuildStatus
? intl.formatMessage({ id: node.data.globalBuildStatus })
: intl.formatMessage({ id: 'NOT_BUILT' })}
</Box>
<Box>
{intl.formatMessage({ id: 'nodeType' })} : {intl.formatMessage({ id: node.data.nodeType })}
</Box>
</Box>
);

setTooltipContent(content);
setTooltipOpen(true);
},
[intl]
);

const handleNodeMouseLeave = useCallback(() => {
setTooltipOpen(false);
}, []);

return (
<Box sx={styles}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={onEdgesChange}
fitView
snapToGrid
snapGrid={snapGrid}
onNodeContextMenu={onNodeContextMenu}
onNodeClick={onNodeClick}
elementsSelectable
selectNodesOnDrag={false}
nodeTypes={nodeTypes}
minZoom={0.1} // Lower value allows for more zoom out
//maxZoom={2} // Higher value allows for more zoom in
onNodeDragStop={handlePostNodeDragging}
nodeClickDistance={5} // to avoid triggering onNodeDragStop instead of onNodeClick sometimes
disableKeyboardA11y
deleteKeyCode={null}
defaultEdgeOptions={{
type: 'smoothstep',
pathOptions: {
// TODO This negative offset and borderRadius values are needed to have round corners on the edge,
// but because the nodes are not totally opaque, we can see the edges behind the nodes.
// When the nodes are redesigned and hopefully the colors are set without transparency, we can use
// the round edges by un-commenting the two lines below.
//offset: -24,
//borderRadius: 48,
<Box sx={styles.modificationTree}>
<Tooltip
open={tooltipOpen}
title={tooltipContent}
componentsProps={{
tooltip: {
sx: {
maxWidth: '720px',
},
},
}}
followCursor
placement="right"
>
<Controls
position="bottom-right"
style={{ margin: '10px', marginBottom: '30px' }}
showZoom={false}
showInteractive={false}
showFitView={false}
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={onEdgesChange}
fitView
snapToGrid
snapGrid={snapGrid}
onNodeContextMenu={onNodeContextMenu}
onNodeClick={onNodeClick}
onNodeMouseEnter={handleNodeMouseEnter}
onNodeMouseLeave={handleNodeMouseLeave}
elementsSelectable
selectNodesOnDrag={false}
nodeTypes={nodeTypes}
minZoom={0.1} // Lower value allows for more zoom out
//maxZoom={2} // Higher value allows for more zoom in
onNodeDragStop={handlePostNodeDragging}
nodeClickDistance={5} // to avoid triggering onNodeDragStop instead of onNodeClick sometimes
disableKeyboardA11y
deleteKeyCode={null}
defaultEdgeOptions={{
type: 'smoothstep',
pathOptions: {
// TODO This negative offset and borderRadius values are needed to have round corners on the edge,
// but because the nodes are not totally opaque, we can see the edges behind the nodes.
// When the nodes are redesigned and hopefully the colors are set without transparency, we can use
// the round edges by un-commenting the two lines below.
//offset: -24,
//borderRadius: 48,
},
}}
>
<TreeControlButton titleId="DisplayTheWholeTree" onClick={fitView}>
<CropFreeIcon />
</TreeControlButton>
<TreeControlButton titleId="CenterSelectedNode" onClick={handleFocusNode}>
<CenterFocusIcon />
</TreeControlButton>
</Controls>
<RootNetworkPanel />
</ReactFlow>
<Controls
position="bottom-right"
style={{ margin: '10px', marginBottom: '30px' }}
showZoom={false}
showInteractive={false}
showFitView={false}
>
<TreeControlButton titleId="DisplayTheWholeTree" onClick={fitView}>
<CropFreeIcon />
</TreeControlButton>
<TreeControlButton titleId="CenterSelectedNode" onClick={handleFocusNode}>
<CenterFocusIcon />
</TreeControlButton>
</Controls>
<RootNetworkPanel />
</ReactFlow>
</Tooltip>
</Box>
);
};
Expand Down
6 changes: 5 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1615,5 +1615,9 @@
"Object": "Object",
"Array": "Array",
"Boolean": "Boolean",
"Enum": "Enumeration"
"Enum": "Enumeration",
"nodeType": "Type",
"nodeStatus": "Status",
"CONSTRUCTION": "Construction",
"SECURITY": "Security"
}
6 changes: 5 additions & 1 deletion src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1611,5 +1611,9 @@
"Object": "Objet",
"Array": "Tableau",
"Boolean": "Booléen",
"Enum": "Énumération"
"Enum": "Énumération",
"nodeType": "Type",
"nodeStatus": "Statut",
"CONSTRUCTION": "Construction",
"SECURITY": "Sécurité"
}
Loading