Implement filtering in project-panel
[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 { RouteComponentProps } from 'react-router';
7 import { ProjectState } from '../../store/project/project-reducer';
8 import { RootState } from '../../store/store';
9 import { connect, DispatchProp } from 'react-redux';
10 import { CollectionState } from "../../store/collection/collection-reducer";
11 import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
12 import ProjectExplorer from "../../views-components/project-explorer/project-explorer";
13 import { projectExplorerItems } from "./project-panel-selectors";
14 import { ProjectExplorerItem } from "../../views-components/project-explorer/project-explorer-item";
15 import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
16 import { DataColumn, SortDirection } from '../../components/data-table/data-column';
17 import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
18
19 interface ProjectPanelDataProps {
20     projects: ProjectState;
21     collections: CollectionState;
22 }
23
24 type ProjectPanelProps = ProjectPanelDataProps & RouteComponentProps<{ name: string }> & DispatchProp;
25
26 interface ProjectPanelState {
27     sort: {
28         columnName: string;
29         direction: SortDirection;
30     };
31     filters: string[];
32 }
33
34 class ProjectPanel extends React.Component<ProjectPanelProps & WithStyles<CssRules>, ProjectPanelState> {
35     state: ProjectPanelState = {
36         sort: {
37             columnName: "Name",
38             direction: "desc"
39         },
40         filters: ['collection', 'project']
41     };
42
43     render() {
44         const items = projectExplorerItems(
45             this.props.projects.items,
46             this.props.projects.currentItemId,
47             this.props.collections
48         );
49         const [goBackItem, ...otherItems] = items;
50         const filteredItems = otherItems.filter(i => this.state.filters.some(f => f === i.kind));
51         const sortedItems = sortItems(this.state.sort, filteredItems);
52         return (
53             <div>
54                 <div className={this.props.classes.toolbar}>
55                     <Button color="primary" variant="raised" className={this.props.classes.button}>
56                         Create a collection
57                     </Button>
58                     <Button color="primary" variant="raised" className={this.props.classes.button}>
59                         Run a process
60                     </Button>
61                     <Button color="primary" variant="raised" className={this.props.classes.button}>
62                         Create a project
63                     </Button>
64                 </div>
65                 <ProjectExplorer
66                     items={goBackItem ? [goBackItem, ...sortedItems] : sortedItems}
67                     onRowClick={this.goToItem}
68                     onToggleSort={this.toggleSort}
69                     onChangeFilters={this.changeFilters}
70                 />
71             </div>
72         );
73     }
74
75     goToItem = (item: ProjectExplorerItem) => {
76         this.props.dispatch<any>(setProjectItem(this.props.projects.items, item.uuid, item.kind, ItemMode.BOTH));
77     }
78
79     toggleSort = (column: DataColumn<ProjectExplorerItem>) => {
80         this.setState({
81             sort: {
82                 columnName: column.name,
83                 direction: column.sortDirection || "none"
84             }
85         });
86     }
87
88     changeFilters = (filters: DataTableFilterItem[]) => {
89         this.setState({ filters: filters.filter(f => f.selected).map(f => f.name.toLowerCase()) });
90     }
91 }
92
93 const sortItems = (sort: { columnName: string, direction: SortDirection }, items: ProjectExplorerItem[]) => {
94     const sortedItems = items.slice(0);
95     const direction = sort.direction === "asc" ? -1 : 1;
96     sortedItems.sort((a, b) => {
97         if (sort.columnName === "Last modified") {
98             return ((new Date(a.lastModified)).getTime() - (new Date(b.lastModified)).getTime()) * direction;
99         } else {
100             return a.name.localeCompare(b.name) * direction;
101         }
102     });
103     return sortedItems;
104 };
105
106 type CssRules = "toolbar" | "button";
107
108 const styles: StyleRulesCallback<CssRules> = theme => ({
109     toolbar: {
110         marginBottom: theme.spacing.unit * 3,
111         display: "flex",
112         justifyContent: "flex-end"
113     },
114     button: {
115         marginLeft: theme.spacing.unit
116     }
117 });
118
119 export default withStyles(styles)(
120     connect(
121         (state: RootState) => ({
122             projects: state.projects,
123             collections: state.collections
124         })
125     )(ProjectPanel));