Merge branch '18874-merge-wb2'
[arvados.git] / services / workbench2 / src / components / context-menu / context-menu.tsx
diff --git a/services/workbench2/src/components/context-menu/context-menu.tsx b/services/workbench2/src/components/context-menu/context-menu.tsx
new file mode 100644 (file)
index 0000000..a44e8b7
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+import React from "react";
+import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@material-ui/core";
+import { DefaultTransformOrigin } from "../popover/helpers";
+import { IconType } from "../icon/icon";
+import { RootState } from "store/store";
+import { ContextMenuResource } from "store/context-menu/context-menu-actions";
+
+export interface ContextMenuItem {
+    name?: string | React.ComponentType;
+    icon?: IconType;
+    component?: React.ComponentType<any>;
+    adminOnly?: boolean;
+    filters?: ((state: RootState, resource: ContextMenuResource) => boolean)[]
+}
+
+export type ContextMenuItemGroup = ContextMenuItem[];
+
+export interface ContextMenuProps {
+    anchorEl?: HTMLElement;
+    items: ContextMenuItemGroup[];
+    open: boolean;
+    onItemClick: (action: ContextMenuItem) => void;
+    onClose: () => void;
+}
+
+export class ContextMenu extends React.PureComponent<ContextMenuProps> {
+    render() {
+        const { anchorEl, items, open, onClose, onItemClick } = this.props;
+        return <Popover
+            anchorEl={anchorEl}
+            open={open}
+            onClose={onClose}
+            transformOrigin={DefaultTransformOrigin}
+            anchorOrigin={DefaultTransformOrigin}
+            onContextMenu={this.handleContextMenu}>
+            <List data-cy='context-menu' dense>
+                {items.map((group, groupIndex) =>
+                    <React.Fragment key={groupIndex}>
+                        {group.map((item, actionIndex) =>
+                            item.component
+                                ? <item.component
+                                    key={actionIndex}
+                                    onClick={() => onItemClick(item)} />
+                                : <ListItem
+                                    button
+                                    key={actionIndex}
+                                    onClick={() => onItemClick(item)}>
+                                    {item.icon &&
+                                        <ListItemIcon>
+                                            <item.icon />
+                                        </ListItemIcon>}
+                                    {item.name &&
+                                        <ListItemText>
+                                            {item.name}
+                                        </ListItemText>}
+                                </ListItem>)}
+                        {
+                            items[groupIndex + 1] &&
+                            items[groupIndex + 1].length > 0 &&
+                            <Divider />
+                        }
+                    </React.Fragment>)}
+            </List>
+        </Popover>;
+    }
+
+    handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {
+        event.preventDefault();
+        this.props.onClose();
+    }
+}