96e259f8f0ffff74ce10a5bfc9dcb3728518e58e
[arvados-workbench2.git] / src / components / data-explorer / data-explorer.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
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, ContextMenuActions } from './context-menu';
14
15 interface DataExplorerProps {
16     items: DataItem[];
17     onItemClick: (item: DataItem) => void;
18     contextMenuActions: ContextMenuActions;
19 }
20
21 interface DataExplorerState {
22     columns: Array<DataColumn<DataItem>>;
23     contextMenu: {
24         anchorEl?: HTMLElement;
25         item?: DataItem;
26     };
27 }
28
29 class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState> {
30     state: DataExplorerState = {
31         contextMenu: {},
32         columns: [
33             {
34                 name: "Name",
35                 selected: true,
36                 render: item => this.renderName(item)
37             },
38             {
39                 name: "Status",
40                 selected: true,
41                 render: item => renderStatus(item.status)
42             },
43             {
44                 name: "Type",
45                 selected: true,
46                 render: item => renderType(item.type)
47             },
48             {
49                 name: "Owner",
50                 selected: true,
51                 render: item => renderOwner(item.owner)
52             },
53             {
54                 name: "File size",
55                 selected: true,
56                 render: item => renderFileSize(item.fileSize)
57             },
58             {
59                 name: "Last modified",
60                 selected: true,
61                 render: item => renderDate(item.lastModified)
62             },
63             {
64                 name: "Actions",
65                 selected: true,
66                 configurable: false,
67                 renderHeader: () => null,
68                 render: item => this.renderActions(item)
69             }
70         ]
71     };
72
73     render() {
74         return <Paper>
75             <ContextMenu
76                 {...this.state.contextMenu}
77                 onClose={this.closeContextMenu}
78                 actions={this.props.contextMenuActions} />
79             <Toolbar>
80                 <Grid container justify="flex-end">
81                     <ColumnSelector
82                         columns={this.state.columns}
83                         onColumnToggle={this.toggleColumn} />
84                 </Grid>
85             </Toolbar>
86             <DataTable
87                 columns={this.state.columns}
88                 items={this.props.items}
89                 onRowContextMenu={this.openItemMenuOnRowClick} />
90             <Toolbar />
91         </Paper>;
92     }
93
94     toggleColumn = (column: DataColumn<DataItem>) => {
95         const index = this.state.columns.indexOf(column);
96         const columns = this.state.columns.slice(0);
97         columns.splice(index, 1, { ...column, selected: !column.selected });
98         this.setState({ columns });
99     }
100
101     renderName = (item: DataItem) =>
102         <Grid
103             container
104             alignItems="center"
105             wrap="nowrap"
106             spacing={16}
107             onClick={() => this.props.onItemClick(item)}>
108             <Grid item>
109                 {renderIcon(item)}
110             </Grid>
111             <Grid item>
112                 <Typography color="primary">
113                     {item.name}
114                 </Typography>
115             </Grid>
116         </Grid>
117
118     renderActions = (item: DataItem) =>
119         <Grid container justify="flex-end">
120             <IconButton onClick={event => this.openItemMenuOnActionsClick(event, item)}>
121                 <MoreVertIcon />
122             </IconButton>
123         </Grid>
124
125     openItemMenuOnRowClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
126         event.preventDefault();
127         this.setState({
128             contextMenu: {
129                 anchorEl: mockAnchorFromMouseEvent(event),
130                 item
131             }
132         });
133     }
134
135     openItemMenuOnActionsClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
136         this.setState({
137             contextMenu: {
138                 anchorEl: event.currentTarget,
139                 item
140             }
141         });
142     }
143
144     closeContextMenu = () => {
145         this.setState({ contextMenu: {} });
146     }
147
148 }
149
150 const renderIcon = (dataItem: DataItem) => {
151     switch (dataItem.type) {
152         case "arvados#group":
153             return <i className="fas fa-folder fa-lg" />;
154         case "arvados#groupList":
155             return <i className="fas fa-th fa-lg" />;
156         default:
157             return <i />;
158     }
159 };
160
161 const renderDate = (date: string) =>
162     <Typography noWrap>
163         {formatDate(date)}
164     </Typography>;
165
166 const renderFileSize = (fileSize?: number) =>
167     <Typography noWrap>
168         {formatFileSize(fileSize)}
169     </Typography>;
170
171 const renderOwner = (owner: string) =>
172     <Typography noWrap color="primary">
173         {owner}
174     </Typography>;
175
176 const renderType = (type: string) =>
177     <Typography noWrap>
178         {type}
179     </Typography>;
180
181 const renderStatus = (status?: string) =>
182     <Typography noWrap align="center">
183         {status || "-"}
184     </Typography>;
185
186 export default DataExplorer;