15012: Adds filtering by process type & ordering by name and created_at date.
[arvados-workbench2.git] / src / views / all-processes-panel / all-processes-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 { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
7 import { DataExplorer } from "~/views-components/data-explorer/data-explorer";
8 import { connect, DispatchProp } from 'react-redux';
9 import { DataColumns } from '~/components/data-table/data-table';
10 import { RouteComponentProps } from 'react-router';
11 import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
12 import { SortDirection } from '~/components/data-table/data-column';
13 import { ResourceKind } from '~/models/resource';
14 import { ArvadosTheme } from '~/common/custom-theme';
15 import { ALL_PROCESSES_PANEL_ID } from '~/store/all-processes-panel/all-processes-panel-action';
16 import {
17     ProcessStatus,
18     ResourceName,
19     ResourceOwner,
20     ResourceType,
21     ResourceCreatedAtDate
22 } from '~/views-components/data-explorer/renderers';
23 import { ProcessIcon } from '~/components/icon/icon';
24 import { openContextMenu, resourceKindToContextMenuKind } from '~/store/context-menu/context-menu-actions';
25 import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
26 import { navigateTo } from '~/store/navigation/navigation-action';
27 import { ContainerRequestState } from "~/models/container-request";
28 import { RootState } from '~/store/store';
29 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
30 import { createTree } from '~/models/tree';
31 import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from '~/store/resource-type-filters/resource-type-filters';
32
33 type CssRules = "toolbar" | "button";
34
35 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
36     toolbar: {
37         paddingBottom: theme.spacing.unit * 3,
38         textAlign: "right"
39     },
40     button: {
41         marginLeft: theme.spacing.unit
42     },
43 });
44
45 export enum AllProcessesPanelColumnNames {
46     NAME = "Name",
47     STATUS = "Status",
48     TYPE = "Type",
49     OWNER = "Owner",
50     CREATED_AT = "Started at"
51 }
52
53 export interface AllProcessesPanelFilter extends DataTableFilterItem {
54     type: ResourceKind | ContainerRequestState;
55 }
56
57 export const allProcessesPanelColumns: DataColumns<string> = [
58     {
59         name: AllProcessesPanelColumnNames.NAME,
60         selected: true,
61         configurable: true,
62         sortDirection: SortDirection.NONE,
63         filters: createTree(),
64         render: uuid => <ResourceName uuid={uuid} />
65     },
66     {
67         name: AllProcessesPanelColumnNames.STATUS,
68         selected: true,
69         configurable: true,
70         mutuallyExclusiveFilters: true,
71         filters: getInitialProcessStatusFilters(),
72         render: uuid => <ProcessStatus uuid={uuid} />
73     },
74     {
75         name: AllProcessesPanelColumnNames.TYPE,
76         selected: true,
77         configurable: true,
78         filters: getInitialProcessTypeFilters(),
79         render: uuid => <ResourceType uuid={uuid} />
80     },
81     {
82         name: AllProcessesPanelColumnNames.OWNER,
83         selected: true,
84         configurable: true,
85         filters: createTree(),
86         render: uuid => <ResourceOwner uuid={uuid} />
87     },
88     {
89         name: AllProcessesPanelColumnNames.CREATED_AT,
90         selected: true,
91         configurable: true,
92         sortDirection: SortDirection.DESC,
93         filters: createTree(),
94         render: uuid => <ResourceCreatedAtDate uuid={uuid} />
95     }
96 ];
97
98 interface AllProcessesPanelDataProps {
99     isAdmin: boolean;
100 }
101
102 interface AllProcessesPanelActionProps {
103     onItemClick: (item: string) => void;
104     onDialogOpen: (ownerUuid: string) => void;
105     onItemDoubleClick: (item: string) => void;
106 }
107 const mapStateToProps = (state : RootState): AllProcessesPanelDataProps => ({
108     isAdmin: state.auth.user!.isAdmin
109 });
110
111 type AllProcessesPanelProps = AllProcessesPanelDataProps & AllProcessesPanelActionProps & DispatchProp
112     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
113
114 export const AllProcessesPanel = withStyles(styles)(
115     connect(mapStateToProps)(
116         class extends React.Component<AllProcessesPanelProps> {
117             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
118                 const menuKind = resourceKindToContextMenuKind(resourceUuid, this.props.isAdmin);
119                 if (menuKind) {
120                     this.props.dispatch<any>(openContextMenu(event, {
121                         name: '',
122                         uuid: resourceUuid,
123                         ownerUuid: '',
124                         kind: ResourceKind.NONE,
125                         menuKind
126                     }));
127                 }
128                 this.props.dispatch<any>(loadDetailsPanel(resourceUuid));
129             }
130
131             handleRowDoubleClick = (uuid: string) => {
132                 this.props.dispatch<any>(navigateTo(uuid));
133             }
134
135             handleRowClick = (uuid: string) => {
136                 this.props.dispatch(loadDetailsPanel(uuid));
137             }
138
139             render() {
140                 return <DataExplorer
141                     id={ALL_PROCESSES_PANEL_ID}
142                     onRowClick={this.handleRowClick}
143                     onRowDoubleClick={this.handleRowDoubleClick}
144                     onContextMenu={this.handleContextMenu}
145                     contextMenuColumn={true}
146                     dataTableDefaultView={
147                         <DataTableDefaultView
148                             icon={ProcessIcon}
149                             messages={['Processes list empty.']}
150                             />
151                     } />;
152             }
153         }
154     )
155 );