79575c74626455579ee60d44c75e420209b2c6ef
[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     ResourceLastModifiedDate,
19     ResourceName,
20     ResourceOwner,
21     ResourceType
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 { getSimpleObjectTypeFilters, getInitialProcessStatusFilters } 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     LAST_MODIFIED = "Last modified"
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         // TODO: Only filter by process type (main, subprocess)
79         filters: getSimpleObjectTypeFilters(),
80         render: uuid => <ResourceType uuid={uuid} />
81     },
82     {
83         name: AllProcessesPanelColumnNames.OWNER,
84         selected: true,
85         configurable: true,
86         filters: createTree(),
87         render: uuid => <ResourceOwner uuid={uuid} />
88     },
89     {
90         name: AllProcessesPanelColumnNames.LAST_MODIFIED,
91         selected: true,
92         configurable: true,
93         sortDirection: SortDirection.DESC,
94         filters: createTree(),
95         render: uuid => <ResourceLastModifiedDate uuid={uuid} />
96     }
97 ];
98
99 interface AllProcessesPanelDataProps {
100     isAdmin: boolean;
101 }
102
103 interface AllProcessesPanelActionProps {
104     onItemClick: (item: string) => void;
105     onDialogOpen: (ownerUuid: string) => void;
106     onItemDoubleClick: (item: string) => void;
107 }
108 const mapStateToProps = (state : RootState): AllProcessesPanelDataProps => ({
109     isAdmin: state.auth.user!.isAdmin
110 });
111
112 type AllProcessesPanelProps = AllProcessesPanelDataProps & AllProcessesPanelActionProps & DispatchProp
113     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
114
115 export const AllProcessesPanel = withStyles(styles)(
116     connect(mapStateToProps)(
117         class extends React.Component<AllProcessesPanelProps> {
118             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
119                 const menuKind = resourceKindToContextMenuKind(resourceUuid, this.props.isAdmin);
120                 if (menuKind) {
121                     this.props.dispatch<any>(openContextMenu(event, {
122                         name: '',
123                         uuid: resourceUuid,
124                         ownerUuid: '',
125                         kind: ResourceKind.NONE,
126                         menuKind
127                     }));
128                 }
129                 this.props.dispatch<any>(loadDetailsPanel(resourceUuid));
130             }
131
132             handleRowDoubleClick = (uuid: string) => {
133                 this.props.dispatch<any>(navigateTo(uuid));
134             }
135
136             handleRowClick = (uuid: string) => {
137                 this.props.dispatch(loadDetailsPanel(uuid));
138             }
139
140             render() {
141                 return <DataExplorer
142                     id={ALL_PROCESSES_PANEL_ID}
143                     onRowClick={this.handleRowClick}
144                     onRowDoubleClick={this.handleRowDoubleClick}
145                     onContextMenu={this.handleContextMenu}
146                     contextMenuColumn={true}
147                     dataTableDefaultView={
148                         <DataTableDefaultView
149                             icon={ProcessIcon}
150                             messages={['All Processes list empty.']}
151                             />
152                     } />;
153             }
154         }
155     )
156 );