Skip to content
Open
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
27 changes: 20 additions & 7 deletions src/components/dialogs/limits/limits-groups-contextual-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ 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 { OperationalLimitsGroupFormInfos } from '../network-modifications/line/modification/line-modification-type';
import { CurrentLimits } from '../../../services/network-modification-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 @@ -45,9 +49,8 @@ export function LimitsGroupsContextualMenu({
parentFormName,
indexSelectedLimitSet,
setIndexSelectedLimitSet,
menuAnchorEl,
handleCloseMenu,
activatedByMenuTabIndex,
contextMenuCoordinates,
startEditingLimitsGroup,
selectedLimitsGroups1,
selectedLimitsGroups2,
Expand Down Expand Up @@ -112,12 +115,22 @@ export function LimitsGroupsContextualMenu({
};

return (
<Menu anchorEl={menuAnchorEl} open={Boolean(menuAnchorEl)} onClose={handleCloseMenu}>
<Menu
open={contextMenuCoordinates.tabIndex != null}
onClose={handleCloseMenu}
anchorReference="anchorPosition"
anchorPosition={
contextMenuCoordinates.y !== null && contextMenuCoordinates.x !== null
? { top: contextMenuCoordinates.y, left: contextMenuCoordinates.x }
: undefined
}
>
{!isModification /* TODO : Remove this when the removal of operational limits groups will be possible in powsybl network store */ && (
<>
<MenuItem
onClick={() =>
activatedByMenuTabIndex != null && startEditingLimitsGroup(activatedByMenuTabIndex, null)
contextMenuCoordinates.tabIndex != null &&
startEditingLimitsGroup(contextMenuCoordinates.tabIndex, null)
}
>
<ListItemIcon>
Expand Down
95 changes: 95 additions & 0 deletions src/components/dialogs/limits/operational-limits-group-tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useCallback, useEffect, useState } from 'react';
import { OperationalLimitsGroupFormInfos } from '../network-modifications/line/modification/line-modification-type';
import { Stack, TextField, Typography } from '@mui/material';
import { FormattedMessage } from 'react-intl';
import { grey } from '@mui/material/colors';
import { APPLICABILITY } from '../../network/constants';
import { LimitsPropertiesStack } from './limits-properties-stack';
import { LIMITS_PROPERTIES, OPERATIONAL_LIMITS_GROUPS } from '../../utils/field-constants';

export interface OperationalLimitsGroupTabProps {
editing: boolean;
opLg: OperationalLimitsGroupFormInfos;
isAModification: boolean;
editionError: string;
parentFormName: string;
editedLimitGroupName: string;
index: number;
finishEditingLimitsGroup: () => void;
setEditedLimitGroupName: React.Dispatch<React.SetStateAction<string>>;
}

export function OperationalLimitsGroupTab({
editing,
opLg,
isAModification,
finishEditingLimitsGroup,
editionError,
parentFormName,
editedLimitGroupName,
setEditedLimitGroupName,
index,
}: Readonly<OperationalLimitsGroupTabProps>) {
// control of the focus on the edited tab
const [editLimitGroupRef, setEditLimitGroupRef] = useState<HTMLInputElement>();
useEffect(() => {
if (editing && editLimitGroupRef) {
editLimitGroupRef.focus();
}
}, [editing, editLimitGroupRef]);
const onRefSet = useCallback((ref: HTMLInputElement) => {
setEditLimitGroupRef(ref);
}, []);

const handleKeyDown = useCallback(
(event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
finishEditingLimitsGroup();
}
},
[finishEditingLimitsGroup]
);

return (
<>
{editing ? (
<TextField
value={editedLimitGroupName}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setEditedLimitGroupName(event.target.value);
}}
onKeyDown={handleKeyDown}
inputRef={onRefSet}
onBlur={() => finishEditingLimitsGroup()}
error={!!editionError}
helperText={!!editionError && <FormattedMessage id={editionError} />}
size="small"
fullWidth
/>
) : (
<Stack direction="row" spacing={1}>
<Stack spacing={0}>
{opLg.name}
{opLg?.applicability ? (
<Typography noWrap align="left" color={grey[500]}>
<FormattedMessage
id={
Object.values(APPLICABILITY).find((item) => item.id === opLg.applicability)
?.label
}
/>
</Typography>
) : (
''
)}
</Stack>
{!isAModification && (
<LimitsPropertiesStack
name={`${parentFormName}.${OPERATIONAL_LIMITS_GROUPS}[${index}].${LIMITS_PROPERTIES}`}
/>
)}
</Stack>
)}
</>
);
}
67 changes: 29 additions & 38 deletions src/components/dialogs/limits/operational-limits-groups-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@
} from '../../utils/field-constants';
import { useFormContext, useWatch } from 'react-hook-form';
import { CurrentLimitsData, 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 { APPLICABILITY } from '../../network/constants';
import { type MuiStyles, NAME } from '@gridsuite/commons-ui';
import { OperationalLimitsGroupFormInfos } from '../network-modifications/line/modification/line-modification-type';
import { OperationalLimitsGroupTabLabel } from './operational-limits-group-tab-label';

const limitsStyles = {
limitsBackground: {
tabBackground: {
flexBasis: 'fit-content',
p: 1,
minHeight: 60,
},
Expand Down Expand Up @@ -95,10 +95,12 @@
},
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 All @@ -109,17 +111,6 @@
name: `${parentFormName}.${SELECTED_LIMITS_GROUP_2}`,
});

// control of the focus on the edited tab
const [editLimitGroupRef, setEditLimitGroupRef] = useState<HTMLInputElement>();
const onRefSet = useCallback((ref: HTMLInputElement) => {
setEditLimitGroupRef(ref);
}, []);
useEffect(() => {
if (editingTabIndex !== -1 && editLimitGroupRef) {
editLimitGroupRef.focus();
}
}, [editingTabIndex, editLimitGroupRef]);

const handleTabChange = useCallback(
(event: React.SyntheticEvent, newValue: number): void => {
// if editing do not change index
Expand All @@ -132,19 +123,29 @@
);

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 @@ -250,15 +251,6 @@
checkLimitSetUnicity,
]);

const handleKeyDown = useCallback(
(event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
finishEditingLimitsGroup();
}
},
[finishEditingLimitsGroup]
);

const addNewLimitSet = useCallback(() => {
const formName: string = `${parentFormName}.${OPERATIONAL_LIMITS_GROUPS}`;
const operationalLimiSetGroups: OperationalLimitsGroup[] = getValues(formName);
Expand Down Expand Up @@ -292,9 +284,10 @@
>
{limitsGroups.map((opLg: OperationalLimitsGroupFormInfos, 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 @@ -306,7 +299,7 @@
inputRef={onRefSet}
onBlur={() => finishEditingLimitsGroup()}
error={!!editionError}
helperText={!!editionError && <FormattedMessage id={editionError} />}

Check failure on line 302 in src/components/dialogs/limits/operational-limits-groups-tabs.tsx

View workflow job for this annotation

GitHub Actions / build / build

'FormattedMessage' is not defined
size="small"
fullWidth
/>
Expand All @@ -321,17 +314,15 @@
/>
)
}
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