[ARVADOS-WORKBENCH2] updated: 1.1.4-104-g04895cf
Git user
git at public.curoverse.com
Tue Jun 19 07:41:51 EDT 2018
Summary of changes:
.../context-menu.test.tsx | 37 +++---
src/components/context-menu/context-menu.tsx | 52 ++++++++
src/components/data-explorer/context-menu.tsx | 110 ----------------
src/components/data-explorer/data-explorer.tsx | 146 +++++++++++++--------
src/views/data-explorer/data-explorer.tsx | 6 +-
5 files changed, 167 insertions(+), 184 deletions(-)
rename src/components/{data-explorer => context-menu}/context-menu.test.tsx (50%)
create mode 100644 src/components/context-menu/context-menu.tsx
delete mode 100644 src/components/data-explorer/context-menu.tsx
via 04895cf6825dab872f91bf86941b51d5b00cb39a (commit)
from a93f9562ce74d8cfb1cb7a5808e2b355e8e370c2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 04895cf6825dab872f91bf86941b51d5b00cb39a
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Tue Jun 19 13:36:06 2018 +0200
Extract generic context-menu component
Feature #13634
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --git a/src/components/data-explorer/context-menu.test.tsx b/src/components/context-menu/context-menu.test.tsx
similarity index 50%
rename from src/components/data-explorer/context-menu.test.tsx
rename to src/components/context-menu/context-menu.test.tsx
index 8921808..9e4a9a4 100644
--- a/src/components/data-explorer/context-menu.test.tsx
+++ b/src/components/context-menu/context-menu.test.tsx
@@ -5,7 +5,7 @@
import * as React from "react";
import { mount, configure, shallow } from "enzyme";
import * as Adapter from "enzyme-adapter-react-16";
-import { ContextMenu } from "./context-menu";
+import ContextMenu from "./context-menu";
import { ListItem } from "@material-ui/core";
configure({ adapter: new Adapter() });
@@ -19,15 +19,20 @@ describe("<ContextMenu />", () => {
type: ""
};
- const actions = {
- onAddToFavourite: jest.fn(),
- onCopy: jest.fn(),
- onDownload: jest.fn(),
- onMoveTo: jest.fn(),
- onRemove: jest.fn(),
- onRename: jest.fn(),
- onShare: jest.fn()
- };
+ const actions = [[{
+ icon: "",
+ name: "Action 1.1",
+ onClick: jest.fn()
+ },
+ {
+ icon: "",
+ name: "Action 1.2",
+ onClick: jest.fn()
+ },], [{
+ icon: "",
+ name: "Action 2.1",
+ onClick: jest.fn()
+ }]];
it("calls provided actions with provided item", () => {
const contextMenu = mount(<ContextMenu
@@ -35,12 +40,12 @@ describe("<ContextMenu />", () => {
onClose={jest.fn()}
{...{ actions, item }} />);
- for (let index = 0; index < Object.keys(actions).length; index++) {
- contextMenu.find(ListItem).at(index).simulate("click");
- }
+ contextMenu.find(ListItem).at(0).simulate("click");
+ contextMenu.find(ListItem).at(1).simulate("click");
+ contextMenu.find(ListItem).at(2).simulate("click");
- Object.keys(actions).forEach(key => {
- expect(actions[key]).toHaveBeenCalledWith(item);
- });
+ expect(actions[0][0].onClick).toHaveBeenCalledWith(item);
+ expect(actions[0][1].onClick).toHaveBeenCalledWith(item);
+ expect(actions[1][0].onClick).toHaveBeenCalledWith(item);
});
});
\ No newline at end of file
diff --git a/src/components/context-menu/context-menu.tsx b/src/components/context-menu/context-menu.tsx
new file mode 100644
index 0000000..c86c517
--- /dev/null
+++ b/src/components/context-menu/context-menu.tsx
@@ -0,0 +1,52 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+import * as React from "react";
+import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@material-ui/core";
+import { DefaultTransformOrigin } from "../popover/helpers";
+
+export interface ContextMenuAction<T> {
+ name: string;
+ icon: string;
+ onClick: (item: T) => void;
+}
+
+export type ContextMenuActionGroup<T> = Array<ContextMenuAction<T>>;
+
+export interface ContextMenuProps<T> {
+ anchorEl?: HTMLElement;
+ item?: T;
+ onClose: () => void;
+ actions: Array<ContextMenuActionGroup<T>>;
+}
+
+export default class ContextMenu<T> extends React.PureComponent<ContextMenuProps<T>> {
+ render() {
+ const { anchorEl, onClose, actions, item } = this.props;
+ return <Popover
+ anchorEl={anchorEl}
+ open={Boolean(anchorEl)}
+ onClose={onClose}
+ transformOrigin={DefaultTransformOrigin}
+ anchorOrigin={DefaultTransformOrigin}>
+ <List dense>
+ {actions.map((group, groupIndex) =>
+ <React.Fragment key={groupIndex}>
+ {group.map((action, actionIndex) =>
+ <ListItem
+ button
+ key={actionIndex}
+ onClick={() => item && action.onClick(item)}>
+ <ListItemIcon>
+ <i className={action.icon} />
+ </ListItemIcon>
+ <ListItemText>
+ {action.name}
+ </ListItemText>
+ </ListItem>)}
+ {groupIndex < actions.length - 1 && <Divider />}
+ </React.Fragment>)}
+ </List>
+ </Popover>;
+ }
+}
diff --git a/src/components/data-explorer/context-menu.tsx b/src/components/data-explorer/context-menu.tsx
deleted file mode 100644
index 0b0a029..0000000
--- a/src/components/data-explorer/context-menu.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-import * as React from "react";
-import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@material-ui/core";
-import { DefaultTransformOrigin } from "../popover/helpers";
-import { DataItem } from "./data-item";
-
-export type ContextMenuAction = (item: DataItem) => void;
-export interface ContextMenuActions {
- onShare: ContextMenuAction;
- onMoveTo: ContextMenuAction;
- onAddToFavourite: ContextMenuAction;
- onRename: ContextMenuAction;
- onCopy: ContextMenuAction;
- onDownload: ContextMenuAction;
- onRemove: ContextMenuAction;
-}
-export interface ContextMenuProps {
- anchorEl?: HTMLElement;
- item?: DataItem;
- onClose: () => void;
- actions: ContextMenuActions;
-}
-
-export const ContextMenu: React.SFC<ContextMenuProps> = ({ anchorEl, onClose, actions, item }) =>
- <Popover
- anchorEl={anchorEl}
- open={Boolean(anchorEl)}
- onClose={onClose}
- transformOrigin={DefaultTransformOrigin}
- anchorOrigin={DefaultTransformOrigin}>
- <Actions {...{ actions, item, onClose }} />
- </Popover>;
-
-interface ActionsProps {
- actions: ContextMenuActions;
- item?: DataItem;
- onClose: () => void;
-}
-
-const Actions: React.SFC<ActionsProps> = ({ actions, item, onClose }) =>
- <List dense>
- {[{
- icon: "fas fa-users",
- label: "Share",
- onClick: actions.onShare
- },
- {
- icon: "fas fa-sign-out-alt",
- label: "Move to",
- onClick: actions.onMoveTo
- },
- {
- icon: "fas fa-star",
- label: "Add to favourite",
- onClick: actions.onAddToFavourite
- },
- {
- icon: "fas fa-edit",
- label: "Rename",
- onClick: actions.onRename
- },
- {
- icon: "fas fa-copy",
- label: "Make a copy",
- onClick: actions.onCopy
- },
- {
- icon: "fas fa-download",
- label: "Download",
- onClick: actions.onDownload
- }].map((props, index) =>
- <Action
- item={item}
- onClose={onClose}
- key={index}
- {...props} />)}
- < Divider />
- <Action
- icon="fas fa-trash-alt"
- label="Remove"
- item={item}
- onClose={onClose}
- onClick={actions.onRemove} />
- </List>;
-
-interface ActionProps {
- onClick: ContextMenuAction;
- item?: DataItem;
- icon: string;
- label: string;
- onClose: () => void;
-}
-
-const Action: React.SFC<ActionProps> = ({ onClick, onClose, item, icon, label }) =>
- <ListItem button onClick={() => {
- if (item) {
- onClick(item);
- onClose();
- }
- }}>
- <ListItemIcon>
- <i className={icon} />
- </ListItemIcon>
- <ListItemText>
- {label}
- </ListItemText>
- </ListItem >;
-
diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index 96e259f..40d6ae6 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -10,12 +10,21 @@ import MoreVertIcon from "@material-ui/icons/MoreVert";
import { formatFileSize, formatDate } from '../../common/formatters';
import { DataItem } from './data-item';
import { mockAnchorFromMouseEvent } from '../popover/helpers';
-import { ContextMenu, ContextMenuActions } from './context-menu';
-
+import ContextMenu, { ContextMenuActionGroup } from '../context-menu/context-menu';
+
+export interface DataExplorerContextActions {
+ onAddToFavourite: (dataIitem: DataItem) => void;
+ onCopy: (dataIitem: DataItem) => void;
+ onDownload: (dataIitem: DataItem) => void;
+ onMoveTo: (dataIitem: DataItem) => void;
+ onRemove: (dataIitem: DataItem) => void;
+ onRename: (dataIitem: DataItem) => void;
+ onShare: (dataIitem: DataItem) => void;
+}
interface DataExplorerProps {
items: DataItem[];
onItemClick: (item: DataItem) => void;
- contextMenuActions: ContextMenuActions;
+ contextActions: DataExplorerContextActions;
}
interface DataExplorerState {
@@ -23,59 +32,82 @@ interface DataExplorerState {
contextMenu: {
anchorEl?: HTMLElement;
item?: DataItem;
+ actions: Array<ContextMenuActionGroup<DataItem>>;
};
}
class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState> {
state: DataExplorerState = {
- contextMenu: {},
- columns: [
- {
- name: "Name",
- selected: true,
- render: item => this.renderName(item)
- },
- {
- name: "Status",
- selected: true,
- render: item => renderStatus(item.status)
- },
- {
- name: "Type",
- selected: true,
- render: item => renderType(item.type)
- },
- {
- name: "Owner",
- selected: true,
- render: item => renderOwner(item.owner)
- },
- {
- name: "File size",
- selected: true,
- render: item => renderFileSize(item.fileSize)
- },
- {
- name: "Last modified",
- selected: true,
- render: item => renderDate(item.lastModified)
- },
- {
- name: "Actions",
- selected: true,
- configurable: false,
- renderHeader: () => null,
- render: item => this.renderActions(item)
+ contextMenu: {
+ actions: [[{
+ icon: "fas fa-users fa-fw",
+ name: "Share",
+ onClick: this.handleContextAction("onShare")
+ }, {
+ icon: "fas fa-sign-out-alt fa-fw",
+ name: "Move to",
+ onClick: this.handleContextAction("onMoveTo")
+ }, {
+ icon: "fas fa-star fa-fw",
+ name: "Add to favourite",
+ onClick: this.handleContextAction("onAddToFavourite")
+ }, {
+ icon: "fas fa-edit fa-fw",
+ name: "Rename",
+ onClick: this.handleContextAction("onRename")
+ }, {
+ icon: "fas fa-copy fa-fw",
+ name: "Make a copy",
+ onClick: this.handleContextAction("onCopy")
+ }, {
+ icon: "fas fa-download fa-fw",
+ name: "Download",
+ onClick: this.handleContextAction("onDownload")
+ }], [{
+ icon: "fas fa-trash-alt fa-fw",
+ name: "Remove",
+ onClick: this.handleContextAction("onRemove")
}
- ]
+ ]]
+ },
+ columns: [{
+ name: "Name",
+ selected: true,
+ render: item => this.renderName(item)
+ }, {
+ name: "Status",
+ selected: true,
+ render: item => renderStatus(item.status)
+ }, {
+ name: "Type",
+ selected: true,
+ render: item => renderType(item.type)
+ }, {
+ name: "Owner",
+ selected: true,
+ render: item => renderOwner(item.owner)
+ }, {
+ name: "File size",
+ selected: true,
+ render: item => renderFileSize(item.fileSize)
+ }, {
+ name: "Last modified",
+ selected: true,
+ render: item => renderDate(item.lastModified)
+ }, {
+ name: "Actions",
+ selected: true,
+ configurable: false,
+ renderHeader: () => null,
+ render: item => this.renderActions(item)
+ }]
};
render() {
return <Paper>
<ContextMenu
{...this.state.contextMenu}
- onClose={this.closeContextMenu}
- actions={this.props.contextMenuActions} />
+ onClose={this.closeContextMenu} />
<Toolbar>
<Grid container justify="flex-end">
<ColumnSelector
@@ -124,25 +156,29 @@ class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState>
openItemMenuOnRowClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
event.preventDefault();
- this.setState({
- contextMenu: {
- anchorEl: mockAnchorFromMouseEvent(event),
- item
- }
+ this.setContextMenuState({
+ anchorEl: mockAnchorFromMouseEvent(event),
+ item
});
}
openItemMenuOnActionsClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
- this.setState({
- contextMenu: {
- anchorEl: event.currentTarget,
- item
- }
+ this.setContextMenuState({
+ anchorEl: event.currentTarget,
+ item
});
}
closeContextMenu = () => {
- this.setState({ contextMenu: {} });
+ this.setContextMenuState({});
+ }
+
+ setContextMenuState = (contextMenu: { anchorEl?: HTMLElement; item?: DataItem; }) => {
+ this.setState(prev => ({ contextMenu: { ...contextMenu, actions: prev.contextMenu.actions } }));
+ }
+
+ handleContextAction(action: keyof DataExplorerContextActions) {
+ return (item: DataItem) => this.props.contextActions[action](item);
}
}
diff --git a/src/views/data-explorer/data-explorer.tsx b/src/views/data-explorer/data-explorer.tsx
index bb19a26..da09b69 100644
--- a/src/views/data-explorer/data-explorer.tsx
+++ b/src/views/data-explorer/data-explorer.tsx
@@ -13,7 +13,7 @@ import { push } from 'react-router-redux';
import projectActions from "../../store/project/project-action";
import { DataExplorer, DataItem } from '../../components/data-explorer';
import { TreeItem } from '../../components/tree/tree';
-import { ContextMenuActions } from '../../components/data-explorer/context-menu';
+import { DataExplorerContextActions } from '../../components/data-explorer/data-explorer';
interface DataExplorerViewDataProps {
projects: ProjectState;
@@ -36,12 +36,12 @@ class DataExplorerView extends React.Component<DataExplorerViewProps, DataExplor
<DataExplorer
items={projectItems.map(mapTreeItem)}
onItemClick={this.goToProject}
- contextMenuActions={this.contextMenuActions}
+ contextActions={this.contextActions}
/>
);
}
- contextMenuActions: ContextMenuActions = {
+ contextActions: DataExplorerContextActions = {
onAddToFavourite: console.log,
onCopy: console.log,
onDownload: console.log,
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list