18559: Add context menu filter system for more complex context menus on user profile.
[arvados-workbench2.git] / 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 "@material-ui/core";
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                                     onClick={() => onItemClick(item)} />
47                                 : <ListItem
48                                     button
49                                     key={actionIndex}
50                                     onClick={() => onItemClick(item)}>
51                                     {item.icon &&
52                                         <ListItemIcon>
53                                             <item.icon />
54                                         </ListItemIcon>}
55                                     {item.name &&
56                                         <ListItemText>
57                                             {item.name}
58                                         </ListItemText>}
59                                 </ListItem>)}
60                         {
61                             items[groupIndex + 1] &&
62                             items[groupIndex + 1].length > 0 &&
63                             <Divider />
64                         }
65                     </React.Fragment>)}
66             </List>
67         </Popover>;
68     }
69
70     handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {
71         event.preventDefault();
72         this.props.onClose();
73     }
74 }