dbff20e18717d227909f524ec5748225cbe484eb
[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 { DataColumn, toggleSortDirection } from '../../components/data-table/data-column';
11 import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
12 import { ContextMenuAction } from '../../components/context-menu/context-menu';
13 import { DispatchProp, connect } from 'react-redux';
14 import actions from "../../store/data-explorer/data-explorer-action";
15 import { setProjectItem } from "../../store/navigation/navigation-action";
16 import { DataColumns } from '../../components/data-table/data-table';
17 import { ResourceKind } from "../../models/resource";
18
19 export const PROJECT_PANEL_ID = "projectPanel";
20 class ProjectPanel extends React.Component<DispatchProp & WithStyles<CssRules>> {
21     render() {
22         return <div>
23             <div className={this.props.classes.toolbar}>
24                 <Button color="primary" variant="raised" className={this.props.classes.button}>
25                     Create a collection
26                 </Button>
27                 <Button color="primary" variant="raised" className={this.props.classes.button}>
28                     Run a process
29                 </Button>
30                 <Button color="primary" variant="raised" className={this.props.classes.button}>
31                     Create a project
32                 </Button>
33             </div>
34             <DataExplorer
35                 id={PROJECT_PANEL_ID}
36                 contextActions={contextMenuActions}
37                 onColumnToggle={this.toggleColumn}
38                 onFiltersChange={this.changeFilters}
39                 onRowClick={this.openProject}
40                 onSortToggle={this.toggleSort}
41                 onSearch={this.search}
42                 onContextAction={this.executeAction}
43                 onChangePage={this.changePage}
44                 onChangeRowsPerPage={this.changeRowsPerPage} />;
45         </div>;
46     }
47
48     componentDidMount() {
49         this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_PANEL_ID, columns }));
50     }
51
52     toggleColumn = (toggledColumn: DataColumn<ProjectPanelItem>) => {
53         this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_PANEL_ID, columnName: toggledColumn.name }));
54     }
55
56     toggleSort = (column: DataColumn<ProjectPanelItem>) => {
57         this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_PANEL_ID, columnName: column.name }));
58     }
59
60     changeFilters = (filters: DataTableFilterItem[], column: DataColumn<ProjectPanelItem>) => {
61         this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_PANEL_ID, columnName: column.name, filters }));
62     }
63
64     executeAction = (action: ContextMenuAction, item: ProjectPanelItem) => {
65         alert(`Executing ${action.name} on ${item.name}`);
66     }
67
68     search = (searchValue: string) => {
69         this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_PANEL_ID, searchValue }));
70     }
71
72     changePage = (page: number) => {
73         this.props.dispatch(actions.SET_PAGE({ id: PROJECT_PANEL_ID, page }));
74     }
75
76     changeRowsPerPage = (rowsPerPage: number) => {
77         this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_PANEL_ID, rowsPerPage }));
78     }
79
80     openProject = (item: ProjectPanelItem) => {
81         this.props.dispatch<any>(setProjectItem(item.uuid));
82     }
83 }
84
85 type CssRules = "toolbar" | "button";
86
87 const styles: StyleRulesCallback<CssRules> = theme => ({
88     toolbar: {
89         paddingBottom: theme.spacing.unit * 3,
90         textAlign: "right"
91     },
92     button: {
93         marginLeft: theme.spacing.unit
94     }
95 });
96
97 const renderName = (item: ProjectPanelItem) =>
98     <Grid
99         container
100         alignItems="center"
101         wrap="nowrap"
102         spacing={16}>
103         <Grid item>
104             {renderIcon(item)}
105         </Grid>
106         <Grid item>
107             <Typography color="primary">
108                 {item.name}
109             </Typography>
110         </Grid>
111     </Grid>;
112
113
114 const renderIcon = (item: ProjectPanelItem) => {
115     switch (item.kind) {
116         case ResourceKind.LEVEL_UP:
117             return <i className="icon-level-up" style={{ fontSize: "1rem" }} />;
118         case ResourceKind.PROJECT:
119             return <i className="fas fa-folder fa-lg" />;
120         case ResourceKind.COLLECTION:
121             return <i className="fas fa-th fa-lg" />;
122         default:
123             return <i />;
124     }
125 };
126
127 const renderDate = (date: string) =>
128     <Typography noWrap>
129         {formatDate(date)}
130     </Typography>;
131
132 const renderFileSize = (fileSize?: number) =>
133     <Typography noWrap>
134         {formatFileSize(fileSize)}
135     </Typography>;
136
137 const renderOwner = (owner: string) =>
138     <Typography noWrap color="primary">
139         {owner}
140     </Typography>;
141
142 const renderType = (type: string) =>
143     <Typography noWrap>
144         {type}
145     </Typography>;
146
147 const renderStatus = (item: ProjectPanelItem) =>
148     <Typography noWrap align="center">
149         {item.status || "-"}
150     </Typography>;
151
152 const columns: DataColumns<ProjectPanelItem> = [{
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: "Collection",
168         selected: true
169     }, {
170         name: "Project",
171         selected: true
172     }],
173     render: item => renderType(item.kind),
174     width: "125px"
175 }, {
176     name: "Owner",
177     selected: true,
178     render: item => renderOwner(item.owner),
179     width: "200px"
180 }, {
181     name: "File size",
182     selected: true,
183     render: item => renderFileSize(item.fileSize),
184     width: "50px"
185 }, {
186     name: "Last modified",
187     selected: true,
188     sortDirection: "none",
189     render: item => renderDate(item.lastModified),
190     width: "150px"
191 }];
192
193 const contextMenuActions = [[{
194     icon: "fas fa-users fa-fw",
195     name: "Share"
196 }, {
197     icon: "fas fa-sign-out-alt fa-fw",
198     name: "Move to"
199 }, {
200     icon: "fas fa-star fa-fw",
201     name: "Add to favourite"
202 }, {
203     icon: "fas fa-edit fa-fw",
204     name: "Rename"
205 }, {
206     icon: "fas fa-copy fa-fw",
207     name: "Make a copy"
208 }, {
209     icon: "fas fa-download fa-fw",
210     name: "Download"
211 }], [{
212     icon: "fas fa-trash-alt fa-fw",
213     name: "Remove"
214 }
215 ]];
216
217 export default withStyles(styles)(connect()(ProjectPanel));