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
2 changes: 2 additions & 0 deletions src/components/app-wrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ const lightTheme = createTheme({
overlay: {
background: '#e6e6e6',
},
highlightColor: '#1976D214',
},
networkModificationPanel: {
backgroundColor: 'white',
Expand Down Expand Up @@ -311,6 +312,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, useEffect, 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,11 @@ 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 highlightedModificationUuid = useSelector((state: AppState) => state.highlightedModificationUuid);

const intl = useIntl();
const { computeLabel } = useModificationLabelComputer();
Expand Down Expand Up @@ -199,17 +203,37 @@ 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;
const getRowStyle = useCallback(
(cellData: RowClassParams<NetworkModificationMetadata, unknown>) => {
const style: RowStyle = {};
if (!cellData?.data?.activated) {
style.opacity = 0.4;
}
if (cellData?.data?.uuid === highlightedModificationUuid && cellData?.rowIndex !== null) {
style.backgroundColor = theme.aggrid.highlightColor;
}
return style;
},
[highlightedModificationUuid, theme]
);

const handleScroll = useCallback(() => {
if (highlightedModificationUuid && gridRef.current?.api) {
const selectedRow = gridRef.current.api.getRowNode(highlightedModificationUuid);
if (selectedRow) {
gridRef.current.api.ensureNodeVisible(selectedRow, 'top');
}
}
return style;
}, []);
}, [highlightedModificationUuid]);

useEffect(() => {
handleScroll();
}, [handleScroll, highlightedModificationUuid]);

return (
<Box sx={styles.container}>
<CustomAGGrid
ref={gridRef}
rowData={modifications}
getRowId={getRowId}
rowSelection={{
Expand All @@ -226,6 +250,7 @@ const NetworkModificationsTable: React.FC<NetworkModificationsTableProps> = ({
getRowStyle={getRowStyle}
onRowDragEnter={onRowDragStart}
onRowDragEnd={onRowDragEnd}
onFirstDataRendered={handleScroll}
rowDragManaged={!isRowDragDisabled}
suppressNoRowsOverlay={true}
overrideLocales={AGGRID_LOCALES}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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 +35,7 @@ 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,41 @@ 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 { setHighlightModification, setModificationsDrawerOpen } from 'redux/actions';
import { useSyncNavigationActions } from 'hooks/use-sync-navigation-actions';
import { useTreeNodeFocus } from 'hooks/use-tree-node-focus';

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,
},
}),
modificationLabel: {
cursor: 'pointer',
pt: 0.5,
pb: 0.5,
pl: 0.5,
},
};
export const ModificationResults: React.FC<ModificationResultsProps> = ({ modifications, nodeUuid }) => {
const intl = useIntl();
const { computeLabel } = useModificationLabelComputer();
const treeNodes = useSelector((state: AppState) => state.networkModificationTreeModel?.treeNodes);
const triggerTreeNodeFocus = useTreeNodeFocus();
const { setCurrentTreeNodeWithSync } = useSyncNavigationActions();
const dispatch = useDispatch();

const getModificationLabel = useCallback(
(modification?: Modification): React.ReactNode => {
Expand All @@ -28,18 +54,34 @@ 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) {
setCurrentTreeNodeWithSync(node);
triggerTreeNodeFocus();
}
dispatch(setModificationsDrawerOpen());
dispatch(setHighlightModification(modification.modificationUuid));
},
[dispatch, nodeUuid, setCurrentTreeNodeWithSync, treeNodes, triggerTreeNodeFocus]
);

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={styles.modificationLabel}>
<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,9 +4,13 @@
* 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 { useSelector } from 'react-redux';
import { AppState } from 'redux/reducer';
import { DeviceHubIcon, type MuiStyles, OverflowableText } from '@gridsuite/commons-ui';
import { Box, Divider } from '@mui/material';
import React from 'react';
import { useSyncNavigationActions } from 'hooks/use-sync-navigation-actions';
import { useTreeNodeFocus } from 'hooks/use-tree-node-focus';

interface RootNetworkNodesSearchResultsProps {
results: string[];
Expand All @@ -20,24 +24,49 @@ const styles = {
rootNameTitle: {
display: 'flex',
alignItems: 'center',
pt: 1,
pl: 0.5,
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 treeNodes = useSelector((state: AppState) => state.networkModificationTreeModel?.treeNodes);
const { setCurrentTreeNodeWithSync } = useSyncNavigationActions();
const triggerTreeNodeFocus = useTreeNodeFocus();

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

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,9 @@ 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, useSelector } from 'react-redux';
import { AppState } from '../../../../redux/reducer';

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

const nodesSearch = useRootNetworkNodeSearch();
const modificationsSearch = useRootNetworkModificationSearch();
const highlightedModificationUuid = useSelector((state: AppState) => state.highlightedModificationUuid);

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>) => {
const value = e.target.value;
if (isNodeTab(tabValue)) {
nodesSearch.search(value);
} else {
// remove the highlighted Modification before search
if (highlightedModificationUuid) {
dispatch(setHighlightModification(null));
}
modificationsSearch.search(value);
}
};
Expand Down
9 changes: 2 additions & 7 deletions src/components/network-modification-tree-pane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const noNodeSelectionForCopy = {

export const HTTP_MAX_NODE_BUILDS_EXCEEDED_MESSAGE = 'MAX_NODE_BUILDS_EXCEEDED';

export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid, onTreePanelResize }) => {
export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid }) => {
const dispatch = useDispatch();
const { snackError, snackWarning, snackInfo } = useSnackMessage();
const DownloadIframe = 'downloadIframe';
Expand Down Expand Up @@ -555,11 +555,7 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid,

return (
<>
<NetworkModificationTree
onNodeContextMenu={onNodeContextMenu}
studyUuid={studyUuid}
onTreePanelResize={onTreePanelResize}
/>
<NetworkModificationTree onNodeContextMenu={onNodeContextMenu} studyUuid={studyUuid} />
{createNodeMenu.display && (
<CreateNodeMenu
position={createNodeMenu.position}
Expand Down Expand Up @@ -611,5 +607,4 @@ export default NetworkModificationTreePane;
NetworkModificationTreePane.propTypes = {
studyUuid: PropTypes.string.isRequired,
currentRootNetworkUuid: PropTypes.string.isRequired,
onTreePanelResize: PropTypes.object.isRequired,
};
Loading
Loading