Apply code formatting and naming according to code review
[arvados.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, DataTableProps, DataColumn, ColumnSelector } from "../../components/data-table";
7 import { Typography, Grid, ListItem, Divider, List, ListItemIcon, ListItemText } from '@material-ui/core';
8 import IconButton, { IconButtonProps } from '@material-ui/core/IconButton';
9 import MoreVertIcon from "@material-ui/icons/MoreVert";
10 import Popover from '../popover/popover';
11 import { formatFileSize, formatDate } from '../../common/formatters';
12 import { DataItem } from './data-item';
13
14 interface DataExplorerProps {
15     items: DataItem[];
16     onItemClick: (item: DataItem) => void;
17 }
18
19 type DataExplorerState = Pick<DataTableProps<DataItem>, "columns">;
20
21 class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState> {
22     state: DataExplorerState = {
23         columns: [
24             {
25                 name: "Name",
26                 selected: true,
27                 render: item => this.renderName(item)
28             },
29             {
30                 name: "Status",
31                 selected: true,
32                 render: item => renderStatus(item.status)
33             },
34             {
35                 name: "Type",
36                 selected: true,
37                 render: item => renderType(item.type)
38             },
39             {
40                 name: "Owner",
41                 selected: true,
42                 render: item => renderOwner(item.owner)
43             },
44             {
45                 name: "File size",
46                 selected: true,
47                 render: (item) => renderFileSize(item.fileSize)
48             },
49             {
50                 name: "Last modified",
51                 selected: true,
52                 render: item => renderDate(item.lastModified)
53             },
54             {
55                 name: "Actions",
56                 selected: true,
57                 configurable: false,
58                 renderHeader: () => this.renderActionsHeader(),
59                 render: renderItemActions
60             }
61         ]
62     };
63
64     render() {
65         return <DataTable
66             columns={this.state.columns}
67             items={this.props.items} />;
68     }
69
70     toggleColumn = (column: DataColumn<DataItem>) => {
71         const index = this.state.columns.indexOf(column);
72         const columns = this.state.columns.slice(0);
73         columns.splice(index, 1, { ...column, selected: !column.selected });
74         this.setState({ columns });
75     }
76
77     renderActionsHeader = () =>
78         <Grid container justify="flex-end">
79             <ColumnSelector
80                 columns={this.state.columns}
81                 onColumnToggle={this.toggleColumn} />
82         </Grid>
83
84     renderName = (item: DataItem) =>
85         <Grid
86             container
87             alignItems="center"
88             wrap="nowrap"
89             spacing={16}
90             onClick={() => this.props.onItemClick(item)}>
91             <Grid item>
92                 {renderIcon(item)}
93             </Grid>
94             <Grid item>
95                 <Typography color="primary">
96                     {item.name}
97                 </Typography>
98             </Grid>
99         </Grid>
100
101 }
102
103 const renderIcon = (dataItem: DataItem) => {
104     switch (dataItem.type) {
105         case "arvados#group":
106             return <i className="fas fa-folder fa-lg" />;
107         case "arvados#groupList":
108             return <i className="fas fa-th fa-lg" />;
109         default:
110             return <i />;
111     }
112 };
113
114 const renderDate = (date: string) =>
115     <Typography noWrap>
116         {formatDate(date)}
117     </Typography>;
118
119 const renderFileSize = (fileSize?: number) =>
120     <Typography noWrap>
121         {formatFileSize(fileSize)}
122     </Typography>;
123
124 const renderOwner = (owner: string) =>
125     <Typography noWrap color="primary">
126         {owner}
127     </Typography>;
128
129 const renderType = (type: string) =>
130     <Typography noWrap>
131         {type}
132     </Typography>;
133
134 const renderStatus = (status?: string) =>
135     <Typography noWrap align="center">
136         {status || "-"}
137     </Typography>;
138
139 const renderItemActions = () =>
140     <Grid container justify="flex-end">
141         <Popover triggerComponent={ItemActionsTrigger}>
142             <List dense>
143                 {[{
144                     icon: "fas fa-users",
145                     label: "Share"
146                 },
147                 {
148                     icon: "fas fa-sign-out-alt",
149                     label: "Move to"
150                 },
151                 {
152                     icon: "fas fa-star",
153                     label: "Add to favourite"
154                 },
155                 {
156                     icon: "fas fa-edit",
157                     label: "Rename"
158                 },
159                 {
160                     icon: "fas fa-copy",
161                     label: "Make a copy"
162                 },
163                 {
164                     icon: "fas fa-download",
165                     label: "Download"
166                 }].map(renderAction)}
167                 < Divider />
168                 {renderAction({ icon: "fas fa-trash-alt", label: "Remove" })}
169             </List>
170         </Popover>
171     </Grid>;
172
173 const renderAction = (action: { label: string, icon: string }, index?: number) =>
174     <ListItem button key={index}>
175         <ListItemIcon>
176             <i className={action.icon} />
177         </ListItemIcon>
178         <ListItemText>
179             {action.label}
180         </ListItemText>
181     </ListItem>;
182
183 const ItemActionsTrigger: React.SFC<IconButtonProps> = (props) =>
184     <IconButton {...props}>
185         <MoreVertIcon />
186     </IconButton>;
187
188 export default DataExplorer;