Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions src/components/app-wrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ const lightTheme = createTheme({
overlay: {
background: '#e6e6e6',
},
highlightColor: '#1976D214',
},
networkModificationPanel: {
backgroundColor: 'white',
Expand Down Expand Up @@ -309,6 +310,7 @@ const darkTheme = createTheme({
overlay: {
background: '#121212',
},
highlightColor: '#90CAF929',
},
networkModificationPanel: {
backgroundColor: '#252525',
Expand Down
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 React, { SetStateAction, useCallback, useMemo } from 'react';
import React, { useCallback, useMemo, SetStateAction, useRef } from 'react';
import {
CustomAGGrid,
type MuiStyles,
Expand All @@ -25,7 +25,7 @@ import type {
ValueGetterParams,
} from 'ag-grid-community';
import { RemoveRedEye as RemoveRedEyeIcon } from '@mui/icons-material';
import { Badge, Box } from '@mui/material';
import { Badge, Box, useTheme } from '@mui/material';
import { useSelector } from 'react-redux';
import { AppState } from 'redux/reducer';
import { useIntl } from 'react-intl';
Expand All @@ -38,6 +38,7 @@ import SwitchCellRenderer from './switch-cell-renderer';
import { AGGRID_LOCALES } from '../../../../translations/not-intl/aggrid-locales';
import { ExcludedNetworkModifications } from './network-modification-menu.type';
import { NetworkModificationNameCellRenderer } from 'components/custom-aggrid/cell-renderers';
import { AgGridReact } from 'ag-grid-react';

const styles = {
container: (theme) => ({
Expand Down Expand Up @@ -83,8 +84,12 @@ const NetworkModificationsTable: React.FC<NetworkModificationsTableProps> = ({
setModificationsToExclude,
...nameHeaderProps
}) => {
const gridRef = useRef<AgGridReact>(null);
const theme = useTheme();

const rootNetworks = useSelector((state: AppState) => state.rootNetworks);
const isMonoRootStudy = useSelector((state: AppState) => state.isMonoRootStudy);
const hightlightedModificationUuid = useSelector((state: AppState) => state.hightlightedModificationUuid);

const intl = useIntl();
const { computeLabel } = useModificationLabelComputer();
Expand Down Expand Up @@ -199,17 +204,26 @@ const NetworkModificationsTable: React.FC<NetworkModificationsTableProps> = ({

const getRowId = (params: GetRowIdParams<NetworkModificationMetadata>) => params.data.uuid;

const getRowStyle = useCallback((cellData: RowClassParams<NetworkModificationMetadata, unknown>) => {
const style: RowStyle = {};
if (!cellData?.data?.activated) {
style.opacity = 0.4;
}
return style;
}, []);
const getRowStyle = useCallback(
(cellData: RowClassParams<NetworkModificationMetadata, unknown>) => {
const style: RowStyle = {};
if (!cellData?.data?.activated) {
style.opacity = 0.4;
}
// Scroll and highlight the selected modification
if (cellData?.data?.uuid === hightlightedModificationUuid && cellData?.rowIndex !== null) {
style.backgroundColor = theme.aggrid.highlightColor;
gridRef.current?.api.ensureIndexVisible(cellData?.rowIndex, 'top');
}
return style;
},
[hightlightedModificationUuid, theme]
);

return (
<Box sx={styles.container}>
<CustomAGGrid
ref={gridRef}
rowData={modifications}
getRowId={getRowId}
rowSelection={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import NetworkModificationNodeEditor from './network-modification-node-editor';
import { ComputingType, type MuiStyles } from '@gridsuite/commons-ui';
import { useDispatch, useSelector } from 'react-redux';
import { setToggleOptions } from '../../../../redux/actions';

import { setHighlightModification, setToggleOptions } from '../../../../redux/actions';
import { Box } from '@mui/material';
import { AppState } from '../../../../redux/reducer';
import RunningStatus from 'components/utils/running-status';
Expand All @@ -35,6 +36,8 @@ const NodeEditor = () => {
const toggleOptions = useSelector((state: AppState) => state.toggleOptions);

const closeModificationsDrawer = () => {
dispatch(setHighlightModification(null));

dispatch(setToggleOptions(toggleOptions.filter((option) => option !== StudyDisplayMode.MODIFICATIONS)));
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,35 @@ import { useIntl } from 'react-intl';
import { useModificationLabelComputer } from '@gridsuite/commons-ui';
import { useCallback } from 'react';
import { Modification } from './root-network.types';
import { Typography } from '@mui/material';
import { Box, Theme, Typography } from '@mui/material';
import { UUID } from 'crypto';
import { AppState } from 'redux/reducer';
import { useDispatch, useSelector } from 'react-redux';
import { setCentedNode, setCurrentTreeNode, setHighlightModification, setModificationsDrawerOpen } from 'redux/actions';
import { StudyDisplayMode } from 'components/network-modification.type';
import { useDisplayModes } from 'hooks/use-display-modes';

interface ModificationResultsProps {
modifications: Modification[];
nodeUuid: UUID;
}

export const ModificationResults: React.FC<ModificationResultsProps> = ({ modifications }) => {
const styles = {
itemHover: (theme: Theme) => ({
borderRadius: 1,
cursor: 'pointer',
'&:hover': {
backgroundColor: theme.aggrid.highlightColor,
},
}),
};
export const ModificationResults: React.FC<ModificationResultsProps> = ({ modifications, nodeUuid }) => {
const intl = useIntl();
const { computeLabel } = useModificationLabelComputer();
const treeNodes = useSelector((state: AppState) => state.networkModificationTreeModel?.treeNodes);
const dispatch = useDispatch();
const toggleOptions = useSelector((state: AppState) => state.toggleOptions);
const { applyModes } = useDisplayModes();

const getModificationLabel = useCallback(
(modification?: Modification): React.ReactNode => {
Expand All @@ -28,18 +48,42 @@ export const ModificationResults: React.FC<ModificationResultsProps> = ({ modifi
{ id: 'network_modifications.' + modification.messageType },
{
// @ts-ignore
...computeLabel(modification),
...computeLabel(modification, false),
}
);
},
[computeLabel, intl]
);

const handleClick = useCallback(
(modification: Modification) => {
const node = treeNodes?.find((node) => node.id === nodeUuid);
if (node) {
dispatch(setCurrentTreeNode(node));
dispatch(setCentedNode(node));
}
if (toggleOptions.includes(StudyDisplayMode.EVENT_SCENARIO)) {
applyModes(toggleOptions.filter((option) => option !== StudyDisplayMode.EVENT_SCENARIO));
}
dispatch(setModificationsDrawerOpen());

dispatch(setHighlightModification(modification.modificationUuid));
},
[applyModes, dispatch, nodeUuid, toggleOptions, treeNodes]
);

return (
<>
{modifications.map((modification) => (
<Typography key={modification.impactedEquipmentId + modification.modificationUuid} variant="body2">
<strong>{modification.impactedEquipmentId + ' - '}</strong> {getModificationLabel(modification)}
</Typography>
<Box sx={styles.itemHover} key={modification.impactedEquipmentId + modification.modificationUuid}>
<Typography
variant="body2"
onClick={() => handleClick(modification)}
sx={{ cursor: 'pointer', pt: 0.5, pb: 0.5 }}
>
<strong>{modification.impactedEquipmentId + ' - '}</strong> {getModificationLabel(modification)}
</Typography>
</Box>
))}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const RootNetworkModificationsSearchResults: React.FC<RootNetworkModifica
<DeviceHubIcon style={styles.iconMinSize} />
<OverflowableText text={getName(result.nodeUuid)} sx={styles.text} maxLineCount={1} />
</Box>
<ModificationResults modifications={result.modifications} />
<ModificationResults modifications={result.modifications} nodeUuid={result.nodeUuid} />
<Divider sx={{ mt: 2 }} />
</Box>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
* 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, Divider, Theme } from '@mui/material';
import { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setCentedNode, setCurrentTreeNode } from 'redux/actions';
import { AppState } from 'redux/reducer';
import { DeviceHubIcon, type MuiStyles, OverflowableText } from '@gridsuite/commons-ui';
import { Box, Divider } from '@mui/material';
import React from 'react';

interface RootNetworkNodesSearchResultsProps {
Expand All @@ -20,24 +24,48 @@ const styles = {
rootNameTitle: {
display: 'flex',
alignItems: 'center',
pt: 1,
mb: 1,
},

itemHover: (theme: Theme) => ({
mb: 1,
borderRadius: 1,
cursor: 'pointer',
'&:hover': {
backgroundColor: theme.aggrid.highlightColor,
},
}),
iconMinSize: {
minHeight: '20px',
minWidth: '20px',
},
} as const satisfies MuiStyles;

export const RootNetworkNodesSearchResults: React.FC<RootNetworkNodesSearchResultsProps> = ({ results }) => {
const dispatch = useDispatch();
const treeNodes = useSelector((state: AppState) => state.networkModificationTreeModel?.treeNodes);

const handleClick = useCallback(
(nodeName: string) => {
const node = treeNodes?.find((node) => node.data.label === nodeName);
if (node) {
dispatch(setCurrentTreeNode(node));
dispatch(setCentedNode(node));
}
},
[dispatch, treeNodes]
);

return (
<Box sx={styles.container}>
{results.map((result) => (
<Box key={result + '_node'} sx={{ mb: 2 }}>
<Box sx={styles.rootNameTitle}>
<Box key={result + '_node'} sx={styles.itemHover}>
<Box sx={styles.rootNameTitle} onClick={() => handleClick(result)}>
<DeviceHubIcon style={styles.iconMinSize} />
<OverflowableText text={result} sx={{ marginLeft: '5px' }} maxLineCount={1} />
</Box>
<Divider sx={{ mt: 2 }} />
<Divider />
</Box>
))}
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { UUID } from 'crypto';
import { getCaseImportParameters, GetCaseImportParametersReturn } from 'services/network-conversion';
import { customizeCurrentParameters, formatCaseImportParameters } from '../../util/case-import-parameters';
import { useDispatch, useSelector } from 'react-redux';
import { setMonoRootStudy } from 'redux/actions';
import { setHighlightModification, setMonoRootStudy } from 'redux/actions';
import { CustomDialog } from 'components/utils/custom-dialog';
import SearchIcon from '@mui/icons-material/Search';

Expand Down Expand Up @@ -191,7 +191,8 @@ const RootNetworkPanelHeader: React.FC<RootNetworkPanelHeaderProps> = ({
const minimizeRootNetworkPanel = useCallback(() => {
setIsSearchActive(false);
setIsRootNetworkPanelMinimized((prev) => !prev);
}, [setIsRootNetworkPanelMinimized, setIsSearchActive]);
dispatch(setHighlightModification(null));
}, [dispatch, setIsRootNetworkPanelMinimized, setIsSearchActive]);

const openSearch = useCallback(() => {
setIsSearchActive(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import SearchBar from './root-network-search-bar';
import { RootNetworkNodesSearchResults } from './root-network-nodes-search-results';
import { useRootNetworkNodeSearch } from './use-root-network-node-search';
import { useRootNetworkModificationSearch } from './use-root-network-modification-search';
import { setHighlightModification } from 'redux/actions';
import { useDispatch } from 'react-redux';

enum TAB_VALUES {
modifications = 'MODIFICATIONS',
Expand Down Expand Up @@ -71,11 +73,12 @@ const RootNetworkSearchPanel: React.FC<RootNetworkSearchPanelProps> = ({ setIsSe

const isLoading = isNodeTab(tabValue) ? nodesSearch.isLoading : modificationsSearch.isLoading;
const searchTerm = isNodeTab(tabValue) ? nodesSearch.searchTerm : modificationsSearch.searchTerm;

const dispatch = useDispatch();
const leaveSearch = () => {
nodesSearch.reset();
modificationsSearch.reset();
setIsSearchActive(false);
dispatch(setHighlightModification(null));
};

const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
Expand Down
8 changes: 8 additions & 0 deletions src/components/network-modification-tree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ const NetworkModificationTree = ({ onNodeContextMenu, studyUuid, onTreePanelResi

const toggleOptions = useSelector((state) => state.toggleOptions);

const centeredNode = useSelector((state) => state.centeredNode);

const { fitView, setCenter, getZoom } = useReactFlow();

const draggedBranchIdRef = useRef(null);
Expand Down Expand Up @@ -298,6 +300,12 @@ const NetworkModificationTree = ({ onNodeContextMenu, studyUuid, onTreePanelResi
setCenter(centerX, centerY, { zoom: getZoom() });
}, [currentNode, nodes, setCenter, getZoom]);

useEffect(() => {
if (centeredNode) {
handleFocusNode();
}
}, [centeredNode, handleFocusNode]);

useEffect(() => {
if (onTreePanelResize) {
onTreePanelResize.current = handleFocusNode;
Expand Down
1 change: 1 addition & 0 deletions src/module-mui.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ declare module '@mui/material/styles' {
overlay: {
background: string;
};
highlightColor: string;
};
networkModificationPanel: {
backgroundColor: string;
Expand Down
24 changes: 24 additions & 0 deletions src/redux/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,30 @@ export function setCurrentTreeNode(currentTreeNode: CurrentTreeNode): CurrentTre
};
}

export const HIGHLIGHT_MODIFICATION = 'HIGHLIGHT_MODIFICATION';
export type HighlightModificationAction = Readonly<Action<typeof HIGHLIGHT_MODIFICATION>> & {
hightlightedModificationUuid: UUID | null;
};

export function setHighlightModification(modifficationUuid: UUID | null): HighlightModificationAction {
return {
type: HIGHLIGHT_MODIFICATION,
hightlightedModificationUuid: modifficationUuid,
};
}

export const CENTER_NODE = 'CENTER_NODE';
export type CenterNodeAction = Readonly<Action<typeof CENTER_NODE>> & {
centeredNode: CurrentTreeNode;
};

export function setCentedNode(centeredNode: CurrentTreeNode): CenterNodeAction {
return {
type: CENTER_NODE,
centeredNode: centeredNode,
};
}

export const CURRENT_ROOT_NETWORK_UUID = 'CURRENT_ROOT_NETWORK_UUID';
export type CurrentRootNetworkUuidAction = Readonly<Action<typeof CURRENT_ROOT_NETWORK_UUID>> & {
currentRootNetworkUuid: UUID;
Expand Down
Loading
Loading