Skip to content
Open
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
54 changes: 32 additions & 22 deletions src/components/dialogs/limits/limits-groups-contextual-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ import ListItemIcon from '@mui/material/ListItemIcon';
import { ContentCopy, Delete, Edit } 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<React.SetStateAction<number | null>>;
menuAnchorEl: PopoverProps['anchorEl'];
handleCloseMenu: () => void;
activatedByMenuTabIndex: number | null;
contextMenuCoordinates: ContextMenuCoordinates;
startEditingLimitsGroup: (index: number, name: string | null) => void;
selectedLimitsGroups1: string;
selectedLimitsGroups2: string;
Expand All @@ -44,9 +48,8 @@ export function LimitsGroupsContextualMenu({
parentFormName,
indexSelectedLimitSet,
setIndexSelectedLimitSet,
menuAnchorEl,
handleCloseMenu,
activatedByMenuTabIndex,
contextMenuCoordinates,
startEditingLimitsGroup,
selectedLimitsGroups1,
selectedLimitsGroups2,
Expand Down Expand Up @@ -112,25 +115,32 @@ export function LimitsGroupsContextualMenu({
]);

const handleRenameTab = useCallback(() => {
activatedByMenuTabIndex != null && startEditingLimitsGroup(activatedByMenuTabIndex, null);
}, [activatedByMenuTabIndex, startEditingLimitsGroup]);
contextMenuCoordinates.tabIndex != null && startEditingLimitsGroup(contextMenuCoordinates.tabIndex, null);
}, [contextMenuCoordinates.tabIndex, startEditingLimitsGroup]);

return (
<Menu anchorEl={menuAnchorEl} open={Boolean(menuAnchorEl)} onClose={handleCloseMenu}>
<>
<MenuItem onClick={handleRenameTab}>
<ListItemIcon>
<Edit fontSize="small" />
</ListItemIcon>
<ListItemText>{intl.formatMessage({ id: 'Rename' })}</ListItemText>
</MenuItem>
<MenuItem onClick={handleDeleteTab}>
<ListItemIcon>
<Delete fontSize="small" />
</ListItemIcon>
<ListItemText>{intl.formatMessage({ id: 'DeleteFromMenu' })}</ListItemText>
</MenuItem>
</>
<Menu
open={contextMenuCoordinates.tabIndex != null}
onClose={handleCloseMenu}
anchorReference="anchorPosition"
anchorPosition={
contextMenuCoordinates.y !== null && contextMenuCoordinates.x !== null
? { top: contextMenuCoordinates.y, left: contextMenuCoordinates.x }
: undefined
}
>
<MenuItem onClick={handleRenameTab}>
<ListItemIcon>
<Edit fontSize="small" />
</ListItemIcon>
<ListItemText>{intl.formatMessage({ id: 'Rename' })}</ListItemText>
</MenuItem>
<MenuItem onClick={handleDeleteTab}>
<ListItemIcon>
<Delete fontSize="small" />
</ListItemIcon>
<ListItemText>{intl.formatMessage({ id: 'DeleteFromMenu' })}</ListItemText>
</MenuItem>
<MenuItem onClick={handleDuplicateTab}>
<ListItemIcon>
<ContentCopy fontSize="small" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,25 @@
* 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 } 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, OPERATIONAL_LIMITS_GROUPS } from '../../utils/field-constants';
import { LimitsFormSchema, OperationalLimitsGroupFormSchema } from './operational-limits-groups-types';

interface OperationalLimitsGroupTabLabelProps {
operationalLimitsGroup: OperationalLimitsGroupFormSchema;
showIconButton: boolean;
editable: boolean;
limitsPropertiesName: string;
handleOpenMenu: (event: React.MouseEvent<HTMLButtonElement>, index: number) => void;
index: number;
}

export function OperationalLimitsGroupTabLabel({
operationalLimitsGroup,
showIconButton,
editable,
limitsPropertiesName,
handleOpenMenu,
index,
}: Readonly<OperationalLimitsGroupTabLabelProps>) {
const { errors } = useFormState<LimitsFormSchema>({ name: `${LIMITS}.${OPERATIONAL_LIMITS_GROUPS}` });
Expand All @@ -45,9 +37,19 @@ export function OperationalLimitsGroupTabLabel({
>
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
<Stack spacing={0}>
<Typography color={permanentLimitErrorMessage ? red[500] : undefined}>
{operationalLimitsGroup.name}
</Typography>
<Tooltip title={operationalLimitsGroup.name}>
<Typography
variant="body1"
color={permanentLimitErrorMessage ? red[500] : undefined}
sx={{
maxWidth: '100px',
textOverflow: 'ellipsis',
}}
noWrap
>
{operationalLimitsGroup.name}
</Typography>
</Tooltip>
{operationalLimitsGroup?.applicability ? (
<Typography noWrap align="left" color={grey[500]}>
<FormattedMessage
Expand All @@ -69,16 +71,6 @@ export function OperationalLimitsGroupTabLabel({
)}
<LimitsPropertiesStack name={limitsPropertiesName} />
</Stack>

{showIconButton && (
<IconButton
size="small"
onClick={(e: React.MouseEvent<HTMLButtonElement>) => handleOpenMenu(e, index)}
disabled={editable}
>
<MenuIcon fontSize="small" />
</IconButton>
)}
</Box>
);
}
67 changes: 44 additions & 23 deletions src/components/dialogs/limits/operational-limits-groups-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,31 @@ 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 { ContextMenuCoordinates, LimitsGroupsContextualMenu } from './limits-groups-contextual-menu';
import { isBlankOrEmpty } from '../../utils/validation-functions';
import { FormattedMessage } from 'react-intl';
import { tabStyles } from 'components/utils/tab-utils';
import { stylesLayout } from 'components/utils/tab-utils';
import { APPLICABILITY } from '../../network/constants';
import { type MuiStyles, NAME } from '@gridsuite/commons-ui';
import { OperationalLimitsGroupTabLabel } from './operational-limits-group-tab-label';
import { OperationalLimitsGroupFormSchema, TemporaryLimitFormSchema } from './operational-limits-groups-types';
import { CurrentLimitsData } from 'services/study/network-map.type';
import { FormattedMessage } from 'react-intl';

const limitsStyles = {
limitsBackground: {
tabs: () => ({
...stylesLayout.listDisplay,
'& .MuiTab-root': {
borderRight: '1px solid grey',
},
'.MuiTab-root.MuiButtonBase-root': {
textTransform: 'none', //tab text not upper-case
textAlign: 'left',
alignItems: 'stretch',
p: 0,
},
}),
tabBackground: {
flexBasis: 'fit-content',
p: 1,
minHeight: 60,
},
Expand Down Expand Up @@ -94,10 +107,12 @@ export const OperationalLimitsGroupsTabs = forwardRef<any, OperationalLimitsGrou
},
ref
) => {
const [hoveredRowIndex, setHoveredRowIndex] = useState(-1);
const [editingTabIndex, setEditingTabIndex] = useState<number>(-1);
const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
const [activatedByMenuTabIndex, setActivatedByMenuTabIndex] = useState<number | null>(null);
const [contextMenuCoordinates, setContextMenuCoordinates] = useState<ContextMenuCoordinates>({
x: null,
y: null,
tabIndex: null,
});
const [editedLimitGroupName, setEditedLimitGroupName] = useState('');
const [editionError, setEditionError] = useState<string>('');
const { setValue, getValues } = useFormContext();
Expand Down Expand Up @@ -142,19 +157,29 @@ export const OperationalLimitsGroupsTabs = forwardRef<any, OperationalLimitsGrou
);

const handleOpenMenu = useCallback(
(event: React.MouseEvent<HTMLButtonElement>, index: number): void => {
(event: React.MouseEvent<HTMLDivElement>, 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]);

const startEditingLimitsGroup = useCallback(
(index: number, name: string | null) => {
Expand Down Expand Up @@ -296,14 +321,15 @@ export const OperationalLimitsGroupsTabs = forwardRef<any, OperationalLimitsGrou
variant="fullWidth"
value={indexSelectedLimitSet !== null && indexSelectedLimitSet}
onChange={handleTabChange}
sx={tabStyles.listDisplay}
sx={limitsStyles.tabs}
visibleScrollbar
>
{limitsGroups.map((opLg: OperationalLimitsGroupFormSchema, index: number) => (
<Tab
onMouseEnter={() => setHoveredRowIndex(index)}
onMouseLeave={() => setHoveredRowIndex(-1)}
onContextMenu={(e) => handleOpenMenu(e, index)}
key={opLg.id + index}
disableRipple
sx={limitsStyles.tabBackground}
label={
editingTabIndex === index ? (
<TextField
Expand All @@ -322,25 +348,20 @@ export const OperationalLimitsGroupsTabs = forwardRef<any, OperationalLimitsGrou
) : (
<OperationalLimitsGroupTabLabel
operationalLimitsGroup={opLg}
showIconButton={index === hoveredRowIndex || index === activatedByMenuTabIndex}
editable={!editable || editingTabIndex !== -1}
limitsPropertiesName={`${parentFormName}.${OPERATIONAL_LIMITS_GROUPS}[${index}].${LIMITS_PROPERTIES}`}
handleOpenMenu={handleOpenMenu}
index={index}
/>
)
}
sx={limitsStyles.limitsBackground}
/>
))}
</Tabs>
<LimitsGroupsContextualMenu
parentFormName={parentFormName}
indexSelectedLimitSet={indexSelectedLimitSet}
setIndexSelectedLimitSet={setIndexSelectedLimitSet}
menuAnchorEl={menuAnchorEl}
handleCloseMenu={handleCloseMenu}
activatedByMenuTabIndex={activatedByMenuTabIndex}
contextMenuCoordinates={contextMenuCoordinates}
startEditingLimitsGroup={startEditingLimitsGroup}
selectedLimitsGroups1={selectedLimitsGroups1}
selectedLimitsGroups2={selectedLimitsGroups2}
Expand Down
Loading