]> git.arvados.org - arvados.git/blob - services/workbench2/src/components/context-menu/context-menu.tsx
Merge branch '22206-apt-repo-pins'
[arvados.git] / services / workbench2 / src / components / context-menu / context-menu.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4 import React from "react";
5 import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@mui/material";
6 import { DefaultTransformOrigin } from "../popover/helpers";
7 import { IconType } from "../icon/icon";
8 import { RootState } from "store/store";
9 import { ContextMenuResource } from "store/context-menu/context-menu-actions";
10
11 export interface ContextMenuItem {
12     name?: string | React.ComponentType;
13     icon?: IconType;
14     component?: React.ComponentType<any>;
15     adminOnly?: boolean;
16     filters?: ((state: RootState, resource: ContextMenuResource) => boolean)[]
17 }
18
19 export type ContextMenuItemGroup = ContextMenuItem[];
20
21 export interface ContextMenuProps {
22     anchorEl?: HTMLElement;
23     items: ContextMenuItemGroup[];
24     open: boolean;
25     onItemClick: (action: ContextMenuItem) => void;
26     onClose: () => void;
27 }
28
29 export class ContextMenu extends React.PureComponent<ContextMenuProps> {
30     render() {
31         const { anchorEl, items, open, onClose, onItemClick } = this.props;
32         return <Popover
33             anchorEl={anchorEl}
34             open={open}
35             onClose={onClose}
36             transformOrigin={DefaultTransformOrigin}
37             anchorOrigin={DefaultTransformOrigin}
38             onContextMenu={this.handleContextMenu}>
39             <List data-cy='context-menu' dense>
40                 {items.map((group, groupIndex) =>
41                     <React.Fragment key={groupIndex}>
42                         {group.map((item, actionIndex) =>
43                             item.component
44                                 ? <item.component
45                                     key={actionIndex}
46                                     data-cy={item.name}
47                                     onClick={() => onItemClick(item)} />
48                                 : <ListItem
49                                     button
50                                     key={actionIndex}
51                                     data-cy={item.name}
52                                     onClick={() => onItemClick(item)}>
53                                     {item.icon &&
54                                         <ListItemIcon>
55                                             <item.icon />
56                                         </ListItemIcon>}
57                                     {item.name &&
58                                         <ListItemText>
59                                             {item.name}
60                                         </ListItemText>}
61                                 </ListItem>)}
62                         {
63                             items[groupIndex + 1] &&
64                             items[groupIndex + 1].length > 0 &&
65                             <Divider />
66                         }
67                     </React.Fragment>)}
68             </List>
69         </Popover>;
70     }
71
72     handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {
73         event.preventDefault();
74         this.props.onClose();
75     }
76 }