Handle resource type in type filters
[arvados-workbench2.git] / src / views / project-panel / project-panel.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 { ProjectPanelItem } from './project-panel-item';
7 import { Grid, Typography, Button, Toolbar, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
8 import { formatDate, formatFileSize } from '../../common/formatters';
9 import DataExplorer from "../../views-components/data-explorer/data-explorer";
10 import { ContextMenuAction } from '../../components/context-menu/context-menu';
11 import { DispatchProp, connect } from 'react-redux';
12 import { DataColumns } from '../../components/data-table/data-table';
13 import { RouteComponentProps } from 'react-router';
14 import { RootState } from '../../store/store';
15 import { ResourceKind } from '../../models/kinds';
16 import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
17
18 export const PROJECT_PANEL_ID = "projectPanel";
19
20 export interface ProjectPanelFilter extends DataTableFilterItem {
21     type: ResourceKind;
22 }
23
24 type ProjectPanelProps = {
25     currentItemId: string,
26     onItemClick: (item: ProjectPanelItem) => void,
27     onItemRouteChange: (itemId: string) => void
28 }
29     & DispatchProp
30     & WithStyles<CssRules>
31     & RouteComponentProps<{ id: string }>;
32 class ProjectPanel extends React.Component<ProjectPanelProps> {
33     render() {
34         return <div>
35             <div className={this.props.classes.toolbar}>
36                 <Button color="primary" variant="raised" className={this.props.classes.button}>
37                     Create a collection
38                 </Button>
39                 <Button color="primary" variant="raised" className={this.props.classes.button}>
40                     Run a process
41                 </Button>
42                 <Button color="primary" variant="raised" className={this.props.classes.button}>
43                     Create a project
44                 </Button>
45             </div>
46             <DataExplorer
47                 id={PROJECT_PANEL_ID}
48                 contextActions={contextMenuActions}
49                 onRowClick={this.props.onItemClick}
50                 onContextAction={this.executeAction} />;
51         </div>;
52     }
53
54     componentWillReceiveProps({ match, currentItemId }: ProjectPanelProps) {
55         if (match.params.id !== currentItemId) {
56             this.props.onItemRouteChange(match.params.id);
57         }
58     }
59
60     executeAction = (action: ContextMenuAction, item: ProjectPanelItem) => {
61         alert(`Executing ${action.name} on ${item.name}`);
62     }
63
64 }
65
66 type CssRules = "toolbar" | "button";
67
68 const styles: StyleRulesCallback<CssRules> = theme => ({
69     toolbar: {
70         paddingBottom: theme.spacing.unit * 3,
71         textAlign: "right"
72     },
73     button: {
74         marginLeft: theme.spacing.unit
75     }
76 });
77
78 const renderName = (item: ProjectPanelItem) =>
79     <Grid
80         container
81         alignItems="center"
82         wrap="nowrap"
83         spacing={16}>
84         <Grid item>
85             {renderIcon(item)}
86         </Grid>
87         <Grid item>
88             <Typography color="primary">
89                 {item.name}
90             </Typography>
91         </Grid>
92     </Grid>;
93
94
95 const renderIcon = (item: ProjectPanelItem) => {
96     switch (item.kind) {
97         case ResourceKind.Project:
98             return <i className="fas fa-folder fa-lg" />;
99         case ResourceKind.Collection:
100             return <i className="fas fa-archive fa-lg" />;
101         case ResourceKind.Process:
102         case ResourceKind.Workflow:
103             return <i className="fas fa-cogs fa-lg" />;
104         default:
105             return <i />;
106     }
107 };
108
109 const renderDate = (date: string) =>
110     <Typography noWrap>
111         {formatDate(date)}
112     </Typography>;
113
114 const renderFileSize = (fileSize?: number) =>
115     <Typography noWrap>
116         {formatFileSize(fileSize)}
117     </Typography>;
118
119 const renderOwner = (owner: string) =>
120     <Typography noWrap color="primary">
121         {owner}
122     </Typography>;
123
124
125
126 const typeToLabel = (type: string) => {
127     switch(type){
128         case ResourceKind.Collection:
129             return "Data collection";
130         case ResourceKind.Project:
131             return "Project";
132         case ResourceKind.Process: 
133             return "Process";
134         default:
135             return "Unknown";
136     }
137 };
138
139 const renderType = (type: string) => {
140     return <Typography noWrap>
141         {typeToLabel(type)}
142     </Typography>;
143 };
144
145 const renderStatus = (item: ProjectPanelItem) =>
146     <Typography noWrap align="center">
147         {item.status || "-"}
148     </Typography>;
149
150
151
152 export const columns: DataColumns<ProjectPanelItem, ProjectPanelFilter> = [{
153     name: "Name",
154     selected: true,
155     sortDirection: "desc",
156     render: renderName,
157     width: "450px"
158 }, {
159     name: "Status",
160     selected: true,
161     render: renderStatus,
162     width: "75px"
163 }, {
164     name: "Type",
165     selected: true,
166     filters: [{
167         name: typeToLabel(ResourceKind.Collection),
168         selected: true,
169         type: ResourceKind.Collection
170     }, {
171         name: typeToLabel(ResourceKind.Process),
172         selected: true,
173         type: ResourceKind.Process
174     }, {
175         name: typeToLabel(ResourceKind.Project),
176         selected: true,
177         type: ResourceKind.Project
178     }],
179     render: item => renderType(item.kind),
180     width: "125px"
181 }, {
182     name: "Owner",
183     selected: true,
184     render: item => renderOwner(item.owner),
185     width: "200px"
186 }, {
187     name: "File size",
188     selected: true,
189     render: item => renderFileSize(item.fileSize),
190     width: "50px"
191 }, {
192     name: "Last modified",
193     selected: true,
194     sortDirection: "none",
195     render: item => renderDate(item.lastModified),
196     width: "150px"
197 }];
198
199 const contextMenuActions = [[{
200     icon: "fas fa-users fa-fw",
201     name: "Share"
202 }, {
203     icon: "fas fa-sign-out-alt fa-fw",
204     name: "Move to"
205 }, {
206     icon: "fas fa-star fa-fw",
207     name: "Add to favourite"
208 }, {
209     icon: "fas fa-edit fa-fw",
210     name: "Rename"
211 }, {
212     icon: "fas fa-copy fa-fw",
213     name: "Make a copy"
214 }, {
215     icon: "fas fa-download fa-fw",
216     name: "Download"
217 }], [{
218     icon: "fas fa-trash-alt fa-fw",
219     name: "Remove"
220 }
221 ]];
222
223 export default withStyles(styles)(
224     connect((state: RootState) => ({ currentItemId: state.projects.currentItemId }))(
225         ProjectPanel));