22159: fixed Trash, Groups, and All-Processes context manus
[arvados.git] / services / workbench2 / src / views / trash-panel / trash-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 { RootState } from 'store/store';
12 import { DataTableFilterItem } from 'components/data-table-filters/data-table-filters';
13 import { DataColumns, SortDirection } from 'components/data-table/data-column';
14 import { ResourceKind, TrashableResource } from 'models/resource';
15 import { ArvadosTheme } from 'common/custom-theme';
16 import { TrashIcon } from 'components/icon/icon';
17 import { TRASH_PANEL_ID } from "store/trash-panel/trash-panel-action";
18 import { getProperty } from "store/properties/properties";
19 import { PROJECT_PANEL_CURRENT_UUID } from "store/project-panel/project-panel";
20 import { openContextMenu } from "store/context-menu/context-menu-actions";
21 import { ResourcesState } from "store/resources/resources";
22 import {
23     renderType,
24     RenderName,
25     renderFileSize,
26     renderTrashDate,
27     renderDeleteDate,
28     RestoreFromTrash,
29 } from "views-components/data-explorer/renderers";
30 import { navigateTo } from "store/navigation/navigation-action";
31 import { loadDetailsPanel } from "store/details-panel/details-panel-action";
32 import { ContextMenuKind } from 'views-components/context-menu/menu-item-sort';
33 import { createTree } from 'models/tree';
34 import {
35     getTrashPanelTypeFilters
36 } from 'store/resource-type-filters/resource-type-filters';
37 import { CollectionResource } from 'models/collection';
38 import { toggleOne, deselectAllOthers } from 'store/multiselect/multiselect-actions';
39
40 type CssRules = "toolbar" | "button" | "root";
41
42 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
43     toolbar: {
44         paddingBottom: theme.spacing(3),
45         textAlign: "right"
46     },
47     button: {
48         marginLeft: theme.spacing(1)
49     },
50     root: {
51         width: '100%',
52     },
53 });
54
55 export enum TrashPanelColumnNames {
56     NAME = "Name",
57     TYPE = "Type",
58     FILE_SIZE = "File size",
59     TRASHED_DATE = "Trashed date",
60     TO_BE_DELETED = "To be deleted"
61 }
62
63 export interface TrashPanelFilter extends DataTableFilterItem {
64     type: ResourceKind;
65 }
66
67 export const trashPanelColumns: DataColumns<string, CollectionResource> = [
68     {
69         name: TrashPanelColumnNames.NAME,
70         selected: true,
71         configurable: true,
72         sort: {direction: SortDirection.NONE, field: "name"},
73         filters: createTree(),
74         render: (resource) => <RenderName resource={resource as CollectionResource} />,
75     },
76     {
77         name: TrashPanelColumnNames.TYPE,
78         selected: true,
79         configurable: true,
80         filters: getTrashPanelTypeFilters(),
81         render: (resource) => renderType(resource as CollectionResource),
82     },
83     {
84         name: TrashPanelColumnNames.FILE_SIZE,
85         selected: true,
86         configurable: true,
87         sort: {direction: SortDirection.NONE, field: "fileSizeTotal"},
88         filters: createTree(),
89         render: (resource) => renderFileSize(resource as CollectionResource),
90     },
91     {
92         name: TrashPanelColumnNames.TRASHED_DATE,
93         selected: true,
94         configurable: true,
95         sort: {direction: SortDirection.DESC, field: "trashAt"},
96         filters: createTree(),
97         render: (resource) => renderTrashDate(resource as CollectionResource),
98     },
99     {
100         name: TrashPanelColumnNames.TO_BE_DELETED,
101         selected: true,
102         configurable: true,
103         sort: {direction: SortDirection.NONE, field: "deleteAt"},
104         filters: createTree(),
105         render: (resource) => renderDeleteDate(resource as CollectionResource),
106     },
107     {
108         name: '',
109         selected: true,
110         configurable: false,
111         filters: createTree(),
112         render: (resource) => <RestoreFromTrash resource={resource as TrashableResource} />
113     }
114 ];
115
116 interface TrashPanelDataProps {
117     currentItemId: string;
118     resources: ResourcesState;
119 }
120
121 type TrashPanelProps = TrashPanelDataProps & DispatchProp & WithStyles<CssRules>;
122
123 export const TrashPanel = withStyles(styles)(
124     connect((state: RootState) => ({
125         currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties),
126         resources: state.resources
127     }))(
128         class extends React.Component<TrashPanelProps> {
129             render() {
130                 return <div className={this.props.classes.root}><DataExplorer
131                     id={TRASH_PANEL_ID}
132                     onRowClick={this.handleRowClick}
133                     onRowDoubleClick={this.handleRowDoubleClick}
134                     onContextMenu={this.handleContextMenu}
135                     contextMenuColumn={false}
136                     defaultViewIcon={TrashIcon}
137                     defaultViewMessages={['Your trash list is empty.']} />
138                 </div>;
139             }
140
141             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resource: TrashableResource) => {
142                 if (resource) {
143                     this.props.dispatch<any>(openContextMenu(event, {
144                         name: '',
145                         uuid: resource.uuid,
146                         ownerUuid: resource.ownerUuid,
147                         isTrashed: resource.isTrashed,
148                         kind: resource.kind,
149                         menuKind: ContextMenuKind.TRASH
150                     }));
151                 }
152                 this.props.dispatch<any>(loadDetailsPanel(resource.uuid));
153             }
154
155             handleRowDoubleClick = (uuid: string) => {
156                 this.props.dispatch<any>(navigateTo(uuid));
157             }
158
159             handleRowClick = ({uuid}: CollectionResource) => {
160                 this.props.dispatch<any>(toggleOne(uuid))
161                 this.props.dispatch<any>(deselectAllOthers(uuid))
162                 this.props.dispatch<any>(loadDetailsPanel(uuid));
163             }
164         }
165     )
166 );