1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { DataTable, DataColumn, ColumnSelector } from "../../components/data-table";
7 import { Typography, Grid, Paper, Toolbar } from '@material-ui/core';
8 import IconButton from '@material-ui/core/IconButton';
9 import MoreVertIcon from "@material-ui/icons/MoreVert";
10 import { formatFileSize, formatDate } from '../../common/formatters';
11 import { DataItem } from './data-item';
12 import { mockAnchorFromMouseEvent } from '../popover/helpers';
13 import ContextMenu, { ContextMenuActionGroup } from '../context-menu/context-menu';
15 export interface DataExplorerContextActions {
16 onAddToFavourite: (dataIitem: DataItem) => void;
17 onCopy: (dataIitem: DataItem) => void;
18 onDownload: (dataIitem: DataItem) => void;
19 onMoveTo: (dataIitem: DataItem) => void;
20 onRemove: (dataIitem: DataItem) => void;
21 onRename: (dataIitem: DataItem) => void;
22 onShare: (dataIitem: DataItem) => void;
24 interface DataExplorerProps {
26 onItemClick: (item: DataItem) => void;
27 contextActions: DataExplorerContextActions;
30 interface DataExplorerState {
31 columns: Array<DataColumn<DataItem>>;
33 anchorEl?: HTMLElement;
35 actions: Array<ContextMenuActionGroup<DataItem>>;
39 class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState> {
40 state: DataExplorerState = {
43 icon: "fas fa-users fa-fw",
45 onClick: this.handleContextAction("onShare")
47 icon: "fas fa-sign-out-alt fa-fw",
49 onClick: this.handleContextAction("onMoveTo")
51 icon: "fas fa-star fa-fw",
52 name: "Add to favourite",
53 onClick: this.handleContextAction("onAddToFavourite")
55 icon: "fas fa-edit fa-fw",
57 onClick: this.handleContextAction("onRename")
59 icon: "fas fa-copy fa-fw",
61 onClick: this.handleContextAction("onCopy")
63 icon: "fas fa-download fa-fw",
65 onClick: this.handleContextAction("onDownload")
67 icon: "fas fa-trash-alt fa-fw",
69 onClick: this.handleContextAction("onRemove")
76 render: item => this.renderName(item)
80 render: item => renderStatus(item.status)
84 render: item => renderType(item.type)
88 render: item => renderOwner(item.owner)
92 render: item => renderFileSize(item.fileSize)
94 name: "Last modified",
96 render: item => renderDate(item.lastModified)
101 renderHeader: () => null,
102 render: item => this.renderActions(item)
109 {...this.state.contextMenu}
110 onClose={this.closeContextMenu} />
112 <Grid container justify="flex-end">
114 columns={this.state.columns}
115 onColumnToggle={this.toggleColumn} />
119 columns={this.state.columns}
120 items={this.props.items}
121 onRowContextMenu={this.openItemMenuOnRowClick} />
126 toggleColumn = (column: DataColumn<DataItem>) => {
127 const index = this.state.columns.indexOf(column);
128 const columns = this.state.columns.slice(0);
129 columns.splice(index, 1, { ...column, selected: !column.selected });
130 this.setState({ columns });
133 renderName = (item: DataItem) =>
139 onClick={() => this.props.onItemClick(item)}>
144 <Typography color="primary">
150 renderActions = (item: DataItem) =>
151 <Grid container justify="flex-end">
152 <IconButton onClick={event => this.openItemMenuOnActionsClick(event, item)}>
157 openItemMenuOnRowClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
158 event.preventDefault();
159 this.setContextMenuState({
160 anchorEl: mockAnchorFromMouseEvent(event),
165 openItemMenuOnActionsClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
166 this.setContextMenuState({
167 anchorEl: event.currentTarget,
172 closeContextMenu = () => {
173 this.setContextMenuState({});
176 setContextMenuState = (contextMenu: { anchorEl?: HTMLElement; item?: DataItem; }) => {
177 this.setState(prev => ({ contextMenu: { ...contextMenu, actions: prev.contextMenu.actions } }));
180 handleContextAction(action: keyof DataExplorerContextActions) {
181 return (item: DataItem) => {
182 this.closeContextMenu();
183 this.props.contextActions[action](item);
189 const renderIcon = (dataItem: DataItem) => {
190 switch (dataItem.type) {
191 case "arvados#group":
192 return <i className="fas fa-folder fa-lg" />;
193 case "arvados#groupList":
194 return <i className="fas fa-th fa-lg" />;
200 const renderDate = (date: string) =>
205 const renderFileSize = (fileSize?: number) =>
207 {formatFileSize(fileSize)}
210 const renderOwner = (owner: string) =>
211 <Typography noWrap color="primary">
215 const renderType = (type: string) =>
220 const renderStatus = (status?: string) =>
221 <Typography noWrap align="center">
225 export default DataExplorer;