diff --git a/src/components/dialogs/limits/limits-groups-contextual-menu.tsx b/src/components/dialogs/limits/limits-groups-contextual-menu.tsx index 1c73e5c17f..0412270dc8 100644 --- a/src/components/dialogs/limits/limits-groups-contextual-menu.tsx +++ b/src/components/dialogs/limits/limits-groups-contextual-menu.tsx @@ -13,19 +13,23 @@ import ListItemIcon from '@mui/material/ListItemIcon'; import { ContentCopy, Delete } from '@mui/icons-material'; import ListItemText from '@mui/material/ListItemText'; import { useIntl } from 'react-intl'; -import { PopoverProps } from '@mui/material/Popover'; import { APPLICABILITY } from '../../network/constants'; import { useCallback } from 'react'; import { CurrentLimitsData } from '../../../services/study/network-map.type'; import { OperationalLimitsGroupFormSchema } from './operational-limits-groups-types'; +export interface ContextMenuCoordinates { + x: null | number; + y: null | number; + tabIndex: null | number; +} + export interface LimitsGroupsContextualMenuProps { parentFormName: string; indexSelectedLimitSet: number | null; setIndexSelectedLimitSet: React.Dispatch>; - menuAnchorEl: PopoverProps['anchorEl']; handleCloseMenu: () => void; - activatedByMenuTabIndex: number | null; + contextMenuCoordinates: ContextMenuCoordinates; selectedLimitsGroups1: string; selectedLimitsGroups2: string; currentLimitsToModify: CurrentLimitsData[]; @@ -43,8 +47,8 @@ export function LimitsGroupsContextualMenu({ parentFormName, indexSelectedLimitSet, setIndexSelectedLimitSet, - menuAnchorEl, handleCloseMenu, + contextMenuCoordinates, selectedLimitsGroups1, selectedLimitsGroups2, operationalLimitsGroups, @@ -109,7 +113,16 @@ export function LimitsGroupsContextualMenu({ ]); return ( - + diff --git a/src/components/dialogs/limits/limits-pane.tsx b/src/components/dialogs/limits/limits-pane.tsx index 83579ed427..03e798c235 100644 --- a/src/components/dialogs/limits/limits-pane.tsx +++ b/src/components/dialogs/limits/limits-pane.tsx @@ -154,7 +154,7 @@ export function LimitsPane({ @@ -162,9 +162,6 @@ export function LimitsPane({ - - - + {limitsProperties?.map((property: LimitsProperty, index: number) => ( ))} {!isEditing && ( - setIsEditing(true)} + startIcon={} disabled={disabled} > - - + + )} {isEditing && !disabled ? ( diff --git a/src/components/dialogs/limits/limits-side-pane.tsx b/src/components/dialogs/limits/limits-side-pane.tsx index d700084afb..bcbf441390 100644 --- a/src/components/dialogs/limits/limits-side-pane.tsx +++ b/src/components/dialogs/limits/limits-side-pane.tsx @@ -225,15 +225,13 @@ export function LimitsSidePane({ return ( + {name && ( - + )} - - - - - + + ); } diff --git a/src/components/dialogs/limits/operational-limits-group-tab-label.tsx b/src/components/dialogs/limits/operational-limits-group-tab-label.tsx index 0898686eae..fcb60f689e 100644 --- a/src/components/dialogs/limits/operational-limits-group-tab-label.tsx +++ b/src/components/dialogs/limits/operational-limits-group-tab-label.tsx @@ -5,31 +5,28 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Box, FormHelperText, Stack, Typography } from '@mui/material'; +import { Box, FormHelperText, Stack, Typography, Tooltip, IconButton } from '@mui/material'; import { FormattedMessage } from 'react-intl'; import { APPLICABILITY } from '../../network/constants'; import { LimitsPropertiesStack } from './limits-properties-stack'; import { grey, red } from '@mui/material/colors'; -import IconButton from '@mui/material/IconButton'; -import MenuIcon from '@mui/icons-material/Menu'; import { useFormState } from 'react-hook-form'; import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined'; import { LIMITS, OLG_IS_DUPLICATE, OPERATIONAL_LIMITS_GROUPS } from '../../utils/field-constants'; import { LimitsFormSchema, OperationalLimitsGroupFormSchema } from './operational-limits-groups-types'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; interface OperationalLimitsGroupTabLabelProps { operationalLimitsGroup: OperationalLimitsGroupFormSchema; showIconButton: boolean; - editable: boolean; limitsPropertiesName: string; - handleOpenMenu: (event: React.MouseEvent, index: number) => void; + handleOpenMenu: (event: React.MouseEvent, index: number) => void; index: number; } export function OperationalLimitsGroupTabLabel({ operationalLimitsGroup, showIconButton, - editable, limitsPropertiesName, handleOpenMenu, index, @@ -43,18 +40,37 @@ export function OperationalLimitsGroupTabLabel({ return ( - - {operationalLimitsGroup.name} - {hasError && ( - - - - )} - + + + + {operationalLimitsGroup.name} + + {hasError && ( + + + + )} + + {operationalLimitsGroup?.applicability ? ( - {showIconButton && ( - ) => handleOpenMenu(e, index)} - disabled={editable} - > - + handleOpenMenu(e, index)}> + )} diff --git a/src/components/dialogs/limits/operational-limits-groups-styles.ts b/src/components/dialogs/limits/operational-limits-groups-styles.ts index d7d3856fc6..39ab02ef4b 100644 --- a/src/components/dialogs/limits/operational-limits-groups-styles.ts +++ b/src/components/dialogs/limits/operational-limits-groups-styles.ts @@ -6,9 +6,33 @@ */ import type { MuiStyles } from '@gridsuite/commons-ui'; +import { stylesLayout } from '../../utils/tab-utils'; +import { blue } from '@mui/material/colors'; export const limitsStyles = { - limitsBackground: { + tabs: () => ({ + ...stylesLayout.listDisplay, + maxHeight: '45vh', + height: '100%', + borderRight: 1, + borderColor: 'divider', + transition: 'transform 0.3s ease-in-out', + '& .MuiTabs-indicator': { + borderRight: `3px solid ${blue[700]}`, + }, + '.MuiTab-root.MuiButtonBase-root': { + textTransform: 'none', + textAlign: 'left', + alignItems: 'stretch', + p: 0, + }, + }), + tabBackground: { + '&:hover': { + backgroundColor: 'rgba(25, 118, 210, 0.05)', // blue[700] + }, + maxWidth: 600, + width: '100%', p: 1, minHeight: 60, }, diff --git a/src/components/dialogs/limits/operational-limits-groups-tabs.tsx b/src/components/dialogs/limits/operational-limits-groups-tabs.tsx index 9b3ce17025..7dbf76b06f 100644 --- a/src/components/dialogs/limits/operational-limits-groups-tabs.tsx +++ b/src/components/dialogs/limits/operational-limits-groups-tabs.tsx @@ -5,8 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Tab, Tabs } from '@mui/material'; -import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'; +import { Grid, Tab, Tabs } from '@mui/material'; +import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'; import { LIMITS_PROPERTIES, OPERATIONAL_LIMITS_GROUPS, @@ -15,8 +15,7 @@ import { } from '../../utils/field-constants'; import { useFieldArray, useFormContext, useWatch } from 'react-hook-form'; import { OperationalLimitsGroup } from '../../../services/network-modification-types'; -import { LimitsGroupsContextualMenu } from './limits-groups-contextual-menu'; -import { tabStyles } from 'components/utils/tab-utils'; +import { ContextMenuCoordinates, LimitsGroupsContextualMenu } from './limits-groups-contextual-menu'; import { OperationalLimitsGroupTabLabel } from './operational-limits-group-tab-label'; import { OperationalLimitsGroupFormSchema } from './operational-limits-groups-types'; import { CurrentLimitsData } from 'services/study/network-map.type'; @@ -45,8 +44,11 @@ export const OperationalLimitsGroupsTabs = forwardRef { const [hoveredRowIndex, setHoveredRowIndex] = useState(-1); - const [menuAnchorEl, setMenuAnchorEl] = useState(null); - const [activatedByMenuTabIndex, setActivatedByMenuTabIndex] = useState(null); + const [contextMenuCoordinates, setContextMenuCoordinates] = useState({ + x: null, + y: null, + tabIndex: null, + }); const { getValues } = useFormContext(); const operationalLimitsGroupsFormName: string = `${parentFormName}.${OPERATIONAL_LIMITS_GROUPS}`; const { @@ -67,19 +69,29 @@ export const OperationalLimitsGroupsTabs = forwardRef, index: number): void => { + (event: React.MouseEvent, index: number): void => { + if (!editable) { + return; + } + event.preventDefault(); event.stopPropagation(); - setMenuAnchorEl(event.currentTarget); setIndexSelectedLimitSet(index); - setActivatedByMenuTabIndex(index); + setContextMenuCoordinates({ + x: event.clientX, + y: event.clientY, + tabIndex: index, + }); }, - [setMenuAnchorEl, setIndexSelectedLimitSet, setActivatedByMenuTabIndex] + [editable, setIndexSelectedLimitSet] ); const handleCloseMenu = useCallback(() => { - setMenuAnchorEl(null); - setActivatedByMenuTabIndex(null); - }, [setMenuAnchorEl, setActivatedByMenuTabIndex]); + setContextMenuCoordinates({ + x: null, + y: null, + tabIndex: null, + }); + }, [setContextMenuCoordinates]); useEffect(() => { // as long as there are limit sets, one should be selected @@ -97,12 +109,12 @@ export const OperationalLimitsGroupsTabs = forwardRef { const formName: string = `${parentFormName}.${OPERATIONAL_LIMITS_GROUPS}`; - const operationalLimiSetGroups: OperationalLimitsGroup[] = getValues(formName); + const operationalLimitSetGroups: OperationalLimitsGroup[] = getValues(formName); let name = 'DEFAULT'; // Try to generate unique name - if (operationalLimiSetGroups?.length > 0) { - const ids: string[] = operationalLimiSetGroups.map((l) => l.name); + if (operationalLimitSetGroups?.length > 0) { + const ids: string[] = operationalLimitSetGroups.map((l) => l.name); name = generateUniqueId('DEFAULT', ids); } prependEmptyOperationalLimitsGroup(name); @@ -112,38 +124,37 @@ export const OperationalLimitsGroupsTabs = forwardRef ({ addNewLimitSet })); const handleTabChange = useCallback( - (event: React.SyntheticEvent, newValue: number): void => { + (_event: React.SyntheticEvent, newValue: number): void => { setIndexSelectedLimitSet(newValue); }, [setIndexSelectedLimitSet] ); return ( - <> + {limitsGroups.map((opLg: OperationalLimitsGroupFormSchema, index: number) => ( setHoveredRowIndex(index)} - onMouseLeave={() => setHoveredRowIndex(-1)} + onContextMenu={(e) => handleOpenMenu(e, index)} key={opLg.id + index} + disableRipple + sx={limitsStyles.tabBackground} label={ } - sx={limitsStyles.limitsBackground} /> ))} @@ -151,9 +162,8 @@ export const OperationalLimitsGroupsTabs = forwardRef - + ); } ); diff --git a/src/components/dialogs/limits/temporary-limits-table.tsx b/src/components/dialogs/limits/temporary-limits-table.tsx index c2dc11d38b..499fbcc1e8 100644 --- a/src/components/dialogs/limits/temporary-limits-table.tsx +++ b/src/components/dialogs/limits/temporary-limits-table.tsx @@ -157,11 +157,7 @@ function TemporaryLimitsTable({ return ( - + {renderTableHead()} {renderTableBody()}