import CommonResourceService from "./common-resource-service";
import axios from "axios";
-import MockAdapter from "axios-mock-adapter";
+import MockAdapter from "axios-mock-adapter/types";
describe("CommonResourceService", () => {
const axiosInstance = axios.create();
import * as React from 'react';
import Typography from '@material-ui/core/Typography';
import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
-import { ArvadosTheme } from 'src/common/custom-theme';
+import { ArvadosTheme } from '../../common/custom-theme';
interface AttributeDataProps {
label: string;
import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@material-ui/core";
import { DefaultTransformOrigin } from "../popover/helpers";
-export interface ContextMenuAction {
+export interface ContextMenuItem {
name: string;
icon: string;
- openCreateDialog?: boolean;
}
-export type ContextMenuActionGroup = ContextMenuAction[];
+export type ContextMenuItemGroup = ContextMenuItem[];
export interface ContextMenuProps {
anchorEl?: HTMLElement;
- actions: ContextMenuActionGroup[];
- onActionClick: (action: ContextMenuAction) => void;
+ items: ContextMenuItemGroup[];
+ onItemClick: (action: ContextMenuItem) => void;
onClose: () => void;
}
export default class ContextMenu extends React.PureComponent<ContextMenuProps> {
render() {
- const { anchorEl, actions, onClose, onActionClick } = this.props;
+ const { anchorEl, items, onClose, onItemClick } = this.props;
return <Popover
anchorEl={anchorEl}
open={!!anchorEl}
anchorOrigin={DefaultTransformOrigin}
onContextMenu={this.handleContextMenu}>
<List dense>
- {actions.map((group, groupIndex) =>
+ {items.map((group, groupIndex) =>
<React.Fragment key={groupIndex}>
- {group.map((action, actionIndex) =>
+ {group.map((item, actionIndex) =>
<ListItem
button
key={actionIndex}
- onClick={() => onActionClick(action)}>
+ onClick={() => onItemClick(item)}>
<ListItemIcon>
- <i className={action.icon} />
+ <i className={item.icon} />
</ListItemIcon>
<ListItemText>
- {action.name}
+ {item.name}
</ListItemText>
</ListItem>)}
- {groupIndex < actions.length - 1 && <Divider />}
+ {groupIndex < items.length - 1 && <Divider />}
</React.Fragment>)}
</List>
</Popover>;
import * as React from 'react';
import { Grid, Paper, Toolbar, StyleRulesCallback, withStyles, Theme, WithStyles, TablePagination, IconButton } from '@material-ui/core';
import MoreVertIcon from "@material-ui/icons/MoreVert";
-import ColumnSelector from "../../components/column-selector/column-selector";
-import DataTable, { DataColumns } from "../../components/data-table/data-table";
-import { DataColumn } from "../../components/data-table/data-column";
-import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
+import ColumnSelector from "../column-selector/column-selector";
+import DataTable, { DataColumns } from "../data-table/data-table";
+import { DataColumn } from "../data-table/data-column";
+import { DataTableFilterItem } from '../data-table-filters/data-table-filters';
import SearchInput from '../search-input/search-input';
interface DataExplorerProps<T> {
import * as React from 'react';
import Typography from '@material-ui/core/Typography';
import { WithStyles, withStyles, StyleRulesCallback } from '@material-ui/core/styles';
-import { ArvadosTheme } from 'src/common/custom-theme';
+import { ArvadosTheme } from '../../common/custom-theme';
import IconBase, { IconTypes } from '../icon/icon';
export interface EmptyStateDataProps {
// SPDX-License-Identifier: AGPL-3.0
import axios from "axios";
-import MockAdapter from "axios-mock-adapter";
+import MockAdapter from "axios-mock-adapter/types";
import GroupsService from "./groups-service";
describe("GroupsService", () => {
// SPDX-License-Identifier: AGPL-3.0
import axios from "axios";
-import MockAdapter from "axios-mock-adapter";
+import MockAdapter from "axios-mock-adapter/types";
import ProjectService from "./project-service";
import FilterBuilder from "../../common/api/filter-builder";
import { ProjectResource } from "../../models/project";
export interface ContextMenuResource {
uuid: string;
- kind: ContextMenuKind;
-}
-
-export enum ContextMenuKind {
- RootProject = "RootProject",
- Project = "Project",
- Collection = "Collection"
+ kind: string;
}
const initialState = {
// SPDX-License-Identifier: AGPL-3.0
import { Middleware } from "redux";
-import actions from "../../store/data-explorer/data-explorer-action";
+import actions from "../data-explorer/data-explorer-action";
import { PROJECT_PANEL_ID, columns, ProjectPanelFilter, ProjectPanelColumnNames } from "../../views/project-panel/project-panel";
import { groupsService } from "../../services/services";
-import { RootState } from "../../store/store";
-import { getDataExplorer, DataExplorerState } from "../../store/data-explorer/data-explorer-reducer";
+import { RootState } from "../store";
+import { getDataExplorer, DataExplorerState } from "../data-explorer/data-explorer-reducer";
import { resourceToDataItem, ProjectPanelItem } from "../../views/project-panel/project-panel-item";
import FilterBuilder from "../../common/api/filter-builder";
import { DataColumns } from "../../components/data-table/data-table";
import sidePanelReducer, { SidePanelState } from './side-panel/side-panel-reducer';
import authReducer, { AuthState } from "./auth/auth-reducer";
import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer';
-import { projectPanelMiddleware } from '../store/project-panel/project-panel-middleware';
+import { projectPanelMiddleware } from './project-panel/project-panel-middleware';
import detailsPanelReducer, { DetailsPanelState } from './details-panel/details-panel-reducer';
import contextMenuReducer, { ContextMenuState } from './context-menu/context-menu-reducer';
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from "redux";
+import { ContextMenuItemGroup, ContextMenuItem } from "../../components/context-menu/context-menu";
+import { ContextMenuResource } from "../../store/context-menu/context-menu-reducer";
+
+export interface ContextMenuItemSet {
+ handleItem (dispatch: Dispatch, action: ContextMenuItem, resource: ContextMenuResource): void;
+ getItems (): ContextMenuItemGroup[];
+}
import { connect, Dispatch, DispatchProp } from "react-redux";
import { RootState } from "../../store/store";
import actions from "../../store/context-menu/context-menu-actions";
-import ContextMenu, { ContextMenuAction, ContextMenuProps } from "../../components/context-menu/context-menu";
+import ContextMenu, { ContextMenuProps, ContextMenuItem } from "../../components/context-menu/context-menu";
import { createAnchorAt } from "../../components/popover/helpers";
-import projectActions from "../../store/project/project-action";
-import { ContextMenuResource, ContextMenuKind } from "../../store/context-menu/context-menu-reducer";
+import { ContextMenuResource } from "../../store/context-menu/context-menu-reducer";
+import { ContextMenuItemSet } from "./context-menu-item-set";
+import { emptyItemSet } from "./empty-item-set";
-
-type DataProps = Pick<ContextMenuProps, "anchorEl" | "actions"> & { resource?: ContextMenuResource };
+type DataProps = Pick<ContextMenuProps, "anchorEl" | "items"> & { resource?: ContextMenuResource };
const mapStateToProps = (state: RootState): DataProps => {
const { position, resource } = state.contextMenu;
return {
anchorEl: resource ? createAnchorAt(position) : undefined,
- actions: resource ? menuActions[resource.kind] : [],
+ items: getMenuItemSet(resource).getItems(),
resource
};
};
-type ActionProps = Pick<ContextMenuProps, "onClose"> & { onActionClick: (action: ContextMenuAction, resource?: ContextMenuResource) => void };
+type ActionProps = Pick<ContextMenuProps, "onClose"> & { onItemClick: (item: ContextMenuItem, resource?: ContextMenuResource) => void };
const mapDispatchToProps = (dispatch: Dispatch): ActionProps => ({
onClose: () => {
dispatch(actions.CLOSE_CONTEXT_MENU());
},
- onActionClick: (action: ContextMenuAction, resource?: ContextMenuResource) => {
+ onItemClick: (item: ContextMenuItem, resource?: ContextMenuResource) => {
dispatch(actions.CLOSE_CONTEXT_MENU());
if (resource) {
- if (action.name === "New project") {
- dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid }));
- }
+ getMenuItemSet(resource).handleItem(dispatch, item, resource);
}
}
});
const mergeProps = ({ resource, ...dataProps }: DataProps, actionProps: ActionProps): ContextMenuProps => ({
...dataProps,
...actionProps,
- onActionClick: (action: ContextMenuAction) => {
- actionProps.onActionClick(action, resource);
+ onItemClick: item => {
+ actionProps.onItemClick(item, resource);
}
});
-export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(ContextMenu);
+export const ContextMenuHOC = connect(mapStateToProps, mapDispatchToProps, mergeProps)(ContextMenu);
-const menuActions = {
- [ContextMenuKind.RootProject]: [[{
- icon: "fas fa-plus fa-fw",
- name: "New project"
- }]],
- [ContextMenuKind.Project]: [[{
- icon: "fas fa-plus fa-fw",
- name: "New project"
- }, {
- icon: "fas fa-users fa-fw",
- name: "Share"
- }, {
- icon: "fas fa-sign-out-alt fa-fw",
- name: "Move to"
- }, {
- icon: "fas fa-star fa-fw",
- name: "Add to favourite"
- }, {
- icon: "fas fa-edit fa-fw",
- name: "Rename"
- }, {
- icon: "fas fa-copy fa-fw",
- name: "Make a copy"
- }, {
- icon: "fas fa-download fa-fw",
- name: "Download"
- }], [{
- icon: "fas fa-trash-alt fa-fw",
- name: "Remove"
- }
- ]],
- [ContextMenuKind.Collection]: [[{
- icon: "fas fa-users fa-fw",
- name: "Share"
- }, {
- icon: "fas fa-sign-out-alt fa-fw",
- name: "Move to"
- }, {
- icon: "fas fa-star fa-fw",
- name: "Add to favourite"
- }, {
- icon: "fas fa-edit fa-fw",
- name: "Rename"
- }, {
- icon: "fas fa-copy fa-fw",
- name: "Make a copy"
- }, {
- icon: "fas fa-download fa-fw",
- name: "Download"
- }], [{
- icon: "fas fa-trash-alt fa-fw",
- name: "Remove"
- }
- ]]
+const menuItemSets = new Map<string, ContextMenuItemSet>();
+
+export const addMenuItemsSet = (name: string, itemSet: ContextMenuItemSet) => {
+ menuItemSets.set(name, itemSet);
};
+
+const getMenuItemSet = (resource?: ContextMenuResource): ContextMenuItemSet => {
+ return resource ? menuItemSets.get(resource.kind) || emptyItemSet : emptyItemSet;
+};
+
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuItemGroup } from "../../components/context-menu/context-menu";
+import { ContextMenuItemSet } from "./context-menu-item-set";
+
+export const emptyItemSet: ContextMenuItemSet = {
+ getItems: () => items,
+ handleItem: () => { return; }
+};
+
+const items: ContextMenuItemGroup[] = [];
\ No newline at end of file
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuHOC, addMenuItemsSet } from "./context-menu";
+import { projectItemSet } from "./project-item-set";
+import { rootProjectItemSet } from "./root-project-item-set";
+
+export default ContextMenuHOC;
+
+export enum ContextMenuKind {
+ RootProject = "RootProject",
+ Project = "Project"
+}
+
+addMenuItemsSet(ContextMenuKind.RootProject, rootProjectItemSet);
+addMenuItemsSet(ContextMenuKind.Project, projectItemSet);
\ No newline at end of file
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuItemGroup } from "../../components/context-menu/context-menu";
+import { ContextMenuItemSet } from "./context-menu-item-set";
+import actions from "../../store/project/project-action";
+
+export const projectItemSet: ContextMenuItemSet = {
+ getItems: () => items,
+ handleItem: (dispatch, item, resource) => {
+ if (item.name === "New project") {
+ dispatch(actions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid }));
+ }
+ }
+};
+
+const items: ContextMenuItemGroup[] = [[{
+ icon: "fas fa-plus fa-fw",
+ name: "New project"
+}, {
+ icon: "fas fa-users fa-fw",
+ name: "Share"
+}, {
+ icon: "fas fa-sign-out-alt fa-fw",
+ name: "Move to"
+}, {
+ icon: "fas fa-star fa-fw",
+ name: "Add to favourite"
+}, {
+ icon: "fas fa-edit fa-fw",
+ name: "Rename"
+}, {
+ icon: "fas fa-copy fa-fw",
+ name: "Make a copy"
+}, {
+ icon: "fas fa-download fa-fw",
+ name: "Download"
+}], [{
+ icon: "fas fa-trash-alt fa-fw",
+ name: "Remove"
+}
+]];
\ No newline at end of file
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuItemGroup } from "../../components/context-menu/context-menu";
+import { ContextMenuItemSet } from "./context-menu-item-set";
+import actions from "../../store/project/project-action";
+
+export const rootProjectItemSet: ContextMenuItemSet = {
+ getItems: () => items,
+ handleItem: (dispatch, item, resource) => {
+ if (item.name === "New project") {
+ dispatch(actions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid }));
+ }
+ }
+};
+
+const items: ContextMenuItemGroup[] = [[{
+ icon: "fas fa-plus fa-fw",
+ name: "New project"
+}]];
\ No newline at end of file
// SPDX-License-Identifier: AGPL-3.0
import { connect } from "react-redux";
-import { Dispatch } from "../../../node_modules/redux";
+import { Dispatch } from "redux";
import { RootState } from "../../store/store";
import DialogProjectCreate from "../dialog-create/dialog-project-create";
import actions, { createProject, getProjectList } from "../../store/project/project-action";
import ProjectPanel from "../project-panel/project-panel";
import DetailsPanel from '../../views-components/details-panel/details-panel';
import { ArvadosTheme } from '../../common/custom-theme';
-import ContextMenu from "../../views-components/context-menu/context-menu";
+import ContextMenu, { ContextMenuKind } from "../../views-components/context-menu";
import CreateProjectDialog from "../../views-components/create-project-dialog/create-project-dialog";
import { authService } from '../../services/services';
import { SidePanelIdentifiers } from '../../store/side-panel/side-panel-reducer';
import { ProjectResource } from '../../models/project';
import { ResourceKind } from '../../models/resource';
-import { ContextMenuKind } from '../../store/context-menu/context-menu-reducer';
const drawerWidth = 240;
const appBarHeight = 100;
<ProjectTree
projects={this.props.projects}
toggleOpen={itemId => this.props.dispatch<any>(setProjectItem(itemId, ItemMode.OPEN))}
- onContextMenu={(event, item) => this.openContextMenu(event, item.data.uuid, ContextMenuKind.Project)}
+ onContextMenu={(event, item) => this.openContextMenu(event, item.data.uuid, ContextMenuKind.Project)}
toggleActive={itemId => {
this.props.dispatch<any>(setProjectItem(itemId, ItemMode.ACTIVE));
this.props.dispatch<any>(loadDetails(itemId, ResourceKind.Project));