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