21720:
[arvados.git] / services / workbench2 / 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 React from "react";
6 import { CustomStyleRulesCallback } from 'common/custom-theme';
7 import { WithStyles } from '@mui/styles';
8 import withStyles from '@mui/styles/withStyles';
9 import { DataExplorer } from "views-components/data-explorer/data-explorer";
10 import { connect, DispatchProp } from "react-redux";
11 import { DataColumns } from "components/data-table/data-table";
12 import { RouteComponentProps } from "react-router";
13 import { DataTableFilterItem } from "components/data-table-filters/data-table-filters";
14 import { SortDirection } from "components/data-table/data-column";
15 import { ResourceKind } from "models/resource";
16 import { ArvadosTheme } from "common/custom-theme";
17 import { ALL_PROCESSES_PANEL_ID } from "store/all-processes-panel/all-processes-panel-action";
18 import {
19     ProcessStatus,
20     ResourceName,
21     ResourceOwnerWithName,
22     ResourceType,
23     ContainerRunTime,
24     ResourceCreatedAtDate,
25 } from "views-components/data-explorer/renderers";
26 import { ProcessIcon } from "components/icon/icon";
27 import { openProcessContextMenu } from "store/context-menu/context-menu-actions";
28 import { loadDetailsPanel } from "store/details-panel/details-panel-action";
29 import { navigateTo } from "store/navigation/navigation-action";
30 import { ContainerRequestResource, ContainerRequestState } from "models/container-request";
31 import { RootState } from "store/store";
32 import { createTree } from "models/tree";
33 import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from "store/resource-type-filters/resource-type-filters";
34 import { getProcess } from "store/processes/process";
35 import { ResourcesState } from "store/resources/resources";
36 import { toggleOne, deselectAllOthers } from "store/multiselect/multiselect-actions";
37
38 type CssRules = "toolbar" | "button" | "root";
39
40 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
41     toolbar: {
42         paddingBottom: theme.spacing(3),
43         textAlign: "right",
44     },
45     button: {
46         marginLeft: theme.spacing(1),
47     },
48     root: {
49         width: "100%",
50     },
51 });
52
53 export enum AllProcessesPanelColumnNames {
54     NAME = "Name",
55     STATUS = "Status",
56     TYPE = "Type",
57     OWNER = "Owner",
58     CREATED_AT = "Created at",
59     RUNTIME = "Run Time",
60 }
61
62 export interface AllProcessesPanelFilter extends DataTableFilterItem {
63     type: ResourceKind | ContainerRequestState;
64 }
65
66 export const allProcessesPanelColumns: DataColumns<string, ContainerRequestResource> = [
67     {
68         name: AllProcessesPanelColumnNames.NAME,
69         selected: true,
70         configurable: true,
71         sort: { direction: SortDirection.NONE, field: "name" },
72         filters: createTree(),
73         render: uuid => <ResourceName uuid={uuid} />,
74     },
75     {
76         name: AllProcessesPanelColumnNames.STATUS,
77         selected: true,
78         configurable: true,
79         mutuallyExclusiveFilters: true,
80         filters: getInitialProcessStatusFilters(),
81         render: uuid => <ProcessStatus uuid={uuid} />,
82     },
83     {
84         name: AllProcessesPanelColumnNames.TYPE,
85         selected: true,
86         configurable: true,
87         filters: getInitialProcessTypeFilters(),
88         render: uuid => <ResourceType uuid={uuid} />,
89     },
90     {
91         name: AllProcessesPanelColumnNames.OWNER,
92         selected: true,
93         configurable: true,
94         filters: createTree(),
95         render: uuid => <ResourceOwnerWithName uuid={uuid} />,
96     },
97     {
98         name: AllProcessesPanelColumnNames.CREATED_AT,
99         selected: true,
100         configurable: true,
101         sort: { direction: SortDirection.DESC, field: "createdAt" },
102         filters: createTree(),
103         render: uuid => <ResourceCreatedAtDate uuid={uuid} />,
104     },
105     {
106         name: AllProcessesPanelColumnNames.RUNTIME,
107         selected: true,
108         configurable: true,
109         filters: createTree(),
110         render: uuid => <ContainerRunTime uuid={uuid} />,
111     },
112 ];
113
114 interface AllProcessesPanelDataProps {
115     resources: ResourcesState;
116 }
117
118 interface AllProcessesPanelActionProps {
119     onItemClick: (item: string) => void;
120     onDialogOpen: (ownerUuid: string) => void;
121     onItemDoubleClick: (item: string) => void;
122 }
123 const mapStateToProps = (state: RootState): AllProcessesPanelDataProps => ({
124     resources: state.resources,
125 });
126
127 type AllProcessesPanelProps = AllProcessesPanelDataProps &
128     AllProcessesPanelActionProps &
129     DispatchProp &
130     WithStyles<CssRules> &
131     RouteComponentProps<{ id: string }>;
132
133 export const AllProcessesPanel = withStyles(styles)(
134     connect(mapStateToProps)(
135         class extends React.Component<AllProcessesPanelProps> {
136             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
137                 const process = getProcess(resourceUuid)(this.props.resources);
138                 if (process) {
139                     this.props.dispatch<any>(openProcessContextMenu(event, process));
140                 }
141                 this.props.dispatch<any>(loadDetailsPanel(resourceUuid));
142             };
143
144             handleRowDoubleClick = (uuid: string) => {
145                 this.props.dispatch<any>(navigateTo(uuid));
146             };
147
148             handleRowClick = (uuid: string) => {
149                 this.props.dispatch<any>(toggleOne(uuid))
150                 this.props.dispatch<any>(deselectAllOthers(uuid))
151                 this.props.dispatch<any>(loadDetailsPanel(uuid));
152             };
153
154             render() {
155                 return (
156                     <div className={this.props.classes.root}>
157                         <DataExplorer
158                             id={ALL_PROCESSES_PANEL_ID}
159                             onRowClick={this.handleRowClick}
160                             onRowDoubleClick={this.handleRowDoubleClick}
161                             onContextMenu={this.handleContextMenu}
162                             contextMenuColumn={true}
163                             defaultViewIcon={ProcessIcon}
164                             defaultViewMessages={["Processes list empty."]}
165                         />
166                     </div>
167                 );
168             }
169         }
170     )
171 );