@@ -24,10 +24,12 @@ import {
24
24
import { Add as AddIcon } from '@mui/icons-material' ;
25
25
import { AgGridReact } from 'ag-grid-react' ;
26
26
import { SelectionForCopy } from '@gridsuite/commons-ui/dist/components/filter/filter.type' ;
27
+ import { CellContextMenuEvent } from 'ag-grid-community' ;
27
28
import { ContingencyListType , FilterType , NetworkModificationType } from '../utils/elementType' ;
28
29
import * as constants from '../utils/UIconstants' ;
29
30
import { setActiveDirectory , setSelectionForCopy } from '../redux/actions' ;
30
31
import { elementExists , getFilterById , updateElement } from '../utils/rest-api' ;
32
+ import { AnchorStatesType , defaultAnchorStates } from './menus/common-contextual-menu' ;
31
33
import ContentContextualMenu from './menus/content-contextual-menu' ;
32
34
import ContentToolbar from './toolbars/content-toolbar' ;
33
35
import DirectoryTreeContextualMenu from './menus/directory-tree-contextual-menu' ;
@@ -91,11 +93,6 @@ const styles = {
91
93
} ,
92
94
} ;
93
95
94
- const initialMousePosition = {
95
- mouseX : null ,
96
- mouseY : null ,
97
- } ;
98
-
99
96
const isStudyMetadata = ( metadata : Metadata ) : metadata is StudyMetadata => metadata . name === 'Study' ;
100
97
101
98
export default function DirectoryContent ( ) {
@@ -111,7 +108,6 @@ export default function DirectoryContent() {
111
108
const [ onGridReady , getRowStyle ] = useHighlightSearchedElement ( gridRef ?. current ?. api ?? null ) ;
112
109
113
110
const [ languageLocal ] = useParameterState ( PARAM_LANGUAGE ) ;
114
- const selectedTheme = useSelector ( ( state : AppState ) => state . theme ) ;
115
111
116
112
const dispatchSelectionForCopy = useCallback (
117
113
( selection : SelectionForCopy ) => {
@@ -150,10 +146,7 @@ export default function DirectoryContent() {
150
146
const [ checkedRows , setCheckedRows ] = useState < ElementAttributes [ ] > ( [ ] ) ;
151
147
152
148
/* Menu states */
153
- const [ mousePosition , setMousePosition ] = useState < {
154
- mouseX : number | null ;
155
- mouseY : number | null ;
156
- } > ( initialMousePosition ) ;
149
+ const [ directoryMenuAnchorStates , setDirectoryMenuAnchorStates ] = useState < AnchorStatesType > ( defaultAnchorStates ) ;
157
150
158
151
const [ openDialog , setOpenDialog ] = useState ( constants . DialogsId . NONE ) ;
159
152
const [ elementName , setElementName ] = useState ( '' ) ;
@@ -246,6 +239,36 @@ export default function DirectoryContent() {
246
239
event . stopPropagation ( ) ;
247
240
} ;
248
241
242
+ const onContextMenu = useCallback (
243
+ ( event : any , anchorStates : AnchorStatesType = defaultAnchorStates ) => {
244
+ if ( anchorStates . anchorReference === 'anchorPosition' ) {
245
+ // example : right click on empty space or on an element line
246
+ // then open popover on mouse position with a little shift
247
+ setDirectoryMenuAnchorStates ( {
248
+ ...anchorStates ,
249
+ anchorPosition : {
250
+ top : event . clientY + constants . VERTICAL_SHIFT ,
251
+ left : event . clientX + constants . HORIZONTAL_SHIFT ,
252
+ } ,
253
+ } ) ;
254
+ } else {
255
+ // else anchorEl
256
+ // example : left click on a 'create element' button
257
+ // then open popover attached to the component clicked
258
+ setDirectoryMenuAnchorStates ( anchorStates ) ;
259
+ }
260
+ // We check if the context menu was triggered from a row to prevent displaying both the directory and the content context menus
261
+ const isRow = ! ! event . target . closest ( `.${ CUSTOM_ROW_CLASS } ` ) ;
262
+ if ( ! isRow ) {
263
+ dispatch ( setActiveDirectory ( selectedDirectory ?. elementUuid ) ) ;
264
+ handleOpenDirectoryMenu ( event ) ;
265
+ } else {
266
+ handleOpenContentMenu ( event ) ;
267
+ }
268
+ } ,
269
+ [ dispatch , selectedDirectory ?. elementUuid ]
270
+ ) ;
271
+
249
272
/* User interactions */
250
273
const contextualMixPolicies = useMemo (
251
274
( ) => ( {
@@ -257,30 +280,26 @@ export default function DirectoryContent() {
257
280
const contextualMixPolicy = contextualMixPolicies . ALL ;
258
281
259
282
const onCellContextMenu = useCallback (
260
- ( event : any ) => {
261
- if ( event . data && event . data . uploading !== null ) {
262
- if ( event . data . type !== 'DIRECTORY' ) {
283
+ ( cellEvent : CellContextMenuEvent ) => {
284
+ if ( cellEvent . data && cellEvent . data . uploading !== null ) {
285
+ if ( cellEvent . data . type !== 'DIRECTORY' ) {
263
286
dispatch ( setActiveDirectory ( selectedDirectory ?. elementUuid ) ) ;
264
287
setActiveElement ( {
265
- hasMetadata : childrenMetadata [ event . data . elementUuid ] !== undefined ,
266
- specificMetadata : childrenMetadata [ event . data . elementUuid ] ?. specificMetadata ,
267
- ...event . data ,
288
+ hasMetadata : childrenMetadata [ cellEvent . data . elementUuid ] !== undefined ,
289
+ specificMetadata : childrenMetadata [ cellEvent . data . elementUuid ] ?. specificMetadata ,
290
+ ...cellEvent . data ,
268
291
} ) ;
269
292
if ( contextualMixPolicy === contextualMixPolicies . BIG ) {
270
293
// If some elements were already selected and the active element is not in them, we deselect the already selected elements.
271
- if ( isRowUnchecked ( event . data , checkedRows ) ) {
294
+ if ( isRowUnchecked ( cellEvent . data , checkedRows ) ) {
272
295
gridRef . current ?. api . deselectAll ( ) ;
273
296
}
274
- } else if ( isRowUnchecked ( event . data , checkedRows ) ) {
297
+ } else if ( isRowUnchecked ( cellEvent . data , checkedRows ) ) {
275
298
// If some elements were already selected, we add the active element to the selected list if not already in it.
276
- gridRef . current ?. api . getRowNode ( event . data . elementUuid ) ?. setSelected ( true ) ;
299
+ gridRef . current ?. api . getRowNode ( cellEvent . data . elementUuid ) ?. setSelected ( true ) ;
277
300
}
278
301
}
279
- setMousePosition ( {
280
- mouseX : event . event . clientX + constants . HORIZONTAL_SHIFT ,
281
- mouseY : event . event . clientY + constants . VERTICAL_SHIFT ,
282
- } ) ;
283
- handleOpenContentMenu ( event . event ) ;
302
+ onContextMenu ( cellEvent . event ) ;
284
303
}
285
304
} ,
286
305
[
@@ -290,26 +309,10 @@ export default function DirectoryContent() {
290
309
contextualMixPolicy ,
291
310
dispatch ,
292
311
selectedDirectory ?. elementUuid ,
312
+ onContextMenu ,
293
313
]
294
314
) ;
295
315
296
- const onContextMenu = useCallback (
297
- ( event : any ) => {
298
- // We check if the context menu was triggered from a row to prevent displaying both the directory and the content context menus
299
- const isRow = ! ! event . target . closest ( `.${ CUSTOM_ROW_CLASS } ` ) ;
300
- if ( ! isRow ) {
301
- dispatch ( setActiveDirectory ( selectedDirectory ?. elementUuid ) ) ;
302
-
303
- setMousePosition ( {
304
- mouseX : event . clientX + constants . HORIZONTAL_SHIFT ,
305
- mouseY : event . clientY + constants . VERTICAL_SHIFT ,
306
- } ) ;
307
- handleOpenDirectoryMenu ( event ) ;
308
- }
309
- } ,
310
- [ dispatch , selectedDirectory ?. elementUuid ]
311
- ) ;
312
-
313
316
const handleError = useCallback (
314
317
( message : string ) => {
315
318
snackError ( {
@@ -428,36 +431,20 @@ export default function DirectoryContent() {
428
431
</ Box >
429
432
) ;
430
433
431
- const handleMousePosition = useCallback (
432
- ( coordinates : DOMRect , isEmpty : boolean ) : { mouseX : number | null ; mouseY : number | null } => {
433
- if ( isEmpty ) {
434
- return {
435
- mouseX : coordinates . right ,
436
- mouseY : coordinates . top + 25 * constants . VERTICAL_SHIFT ,
437
- } ;
438
- }
439
- return {
440
- mouseX : coordinates . left ,
441
- mouseY : coordinates . bottom ,
442
- } ;
443
- } ,
444
- [ ]
445
- ) ;
446
-
447
- const handleDialog = useCallback (
448
- ( mouseEvent : MouseEvent < HTMLElement > , isEmpty : boolean ) => {
449
- const coordinates : DOMRect = ( mouseEvent . target as HTMLElement ) . getBoundingClientRect ( ) ;
450
- // set the contextualMenu position
451
- setMousePosition ( handleMousePosition ( coordinates , isEmpty ) ) ;
452
- setOpenDirectoryMenu ( true ) ;
453
-
454
- dispatch ( setActiveDirectory ( selectedDirectory ?. elementUuid ) ) ;
455
- } ,
456
- [ dispatch , selectedDirectory ?. elementUuid , handleMousePosition ]
457
- ) ;
458
-
459
434
const renderEmptyDirContent = ( ) => (
460
- < EmptyDirectory openDialog = { ( mouseEvent ) => handleDialog ( mouseEvent , true ) } theme = { selectedTheme } />
435
+ < EmptyDirectory
436
+ onCreateElementButtonClick = { ( mouseEvent ) =>
437
+ onContextMenu ( mouseEvent , {
438
+ anchorReference : 'anchorEl' ,
439
+ anchorEl : mouseEvent . currentTarget ,
440
+ anchorOrigin : { vertical : 'center' , horizontal : 'right' } ,
441
+ transformOrigin : {
442
+ vertical : 'center' ,
443
+ horizontal : 'left' ,
444
+ } ,
445
+ } )
446
+ }
447
+ />
461
448
) ;
462
449
463
450
const renderContent = ( ) => {
@@ -649,7 +636,14 @@ export default function DirectoryContent() {
649
636
variant = "contained"
650
637
endIcon = { < AddIcon /> }
651
638
sx = { styles . button }
652
- onClick = { ( mouseEvent ) => handleDialog ( mouseEvent , false ) }
639
+ onClick = { ( mouseEvent ) =>
640
+ onContextMenu ( mouseEvent , {
641
+ anchorReference : 'anchorEl' ,
642
+ anchorEl : mouseEvent . currentTarget ,
643
+ anchorOrigin : { vertical : 'bottom' , horizontal : 'left' } ,
644
+ transformOrigin : { vertical : 'top' , horizontal : 'left' } ,
645
+ } )
646
+ }
653
647
>
654
648
< FormattedMessage id = "createElement" />
655
649
</ Button >
@@ -675,15 +669,7 @@ export default function DirectoryContent() {
675
669
openDialog = { openDialog }
676
670
setOpenDialog = { setOpenDialog }
677
671
onClose = { handleCloseContentMenu }
678
- anchorReference = "anchorPosition"
679
- anchorPosition = {
680
- mousePosition . mouseY !== null && mousePosition . mouseX !== null
681
- ? {
682
- top : mousePosition . mouseY ,
683
- left : mousePosition . mouseX ,
684
- }
685
- : undefined
686
- }
672
+ { ...directoryMenuAnchorStates }
687
673
broadcastChannel = { broadcastChannel }
688
674
/>
689
675
) }
@@ -693,15 +679,7 @@ export default function DirectoryContent() {
693
679
openDialog = { openDialog }
694
680
setOpenDialog = { setOpenDialog }
695
681
onClose = { handleCloseDirectoryMenu }
696
- anchorReference = "anchorPosition"
697
- anchorPosition = {
698
- mousePosition . mouseY !== null && mousePosition . mouseX !== null
699
- ? {
700
- top : mousePosition . mouseY ,
701
- left : mousePosition . mouseX ,
702
- }
703
- : undefined
704
- }
682
+ { ...directoryMenuAnchorStates }
705
683
restrictMenuItems
706
684
/>
707
685
</ Box >
0 commit comments