492265603ab626b4f22966701e8e34354105713b
[arvados-workbench2.git] / 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 * 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 { DispatchProp, connect } from 'react-redux';
9 import { DataColumns } from '~/components/data-table/data-table';
10 import { RootState } from '~/store/store';
11 import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
12 import { SortDirection } from '~/components/data-table/data-column';
13 import { ResourceKind, TrashableResource } from '~/models/resource';
14 import { resourceLabel } from '~/common/labels';
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-action";
20 import { openContextMenu, resourceKindToContextMenuKind } from "~/store/context-menu/context-menu-actions";
21 import { getResource, ResourcesState } from "~/store/resources/resources";
22 import {
23     ResourceDeleteDate,
24     ResourceFileSize,
25     ResourceName,
26     ResourceTrashDate,
27     ResourceType
28 } from "~/views-components/data-explorer/renderers";
29 import { navigateTo } from "~/store/navigation/navigation-action";
30 import { loadDetailsPanel } from "~/store/details-panel/details-panel-action";
31
32 type CssRules = "toolbar" | "button";
33
34 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
35     toolbar: {
36         paddingBottom: theme.spacing.unit * 3,
37         textAlign: "right"
38     },
39     button: {
40         marginLeft: theme.spacing.unit
41     },
42 });
43
44 export enum TrashPanelColumnNames {
45     NAME = "Name",
46     TYPE = "Type",
47     FILE_SIZE = "File size",
48     TRASHED_DATE = "Trashed date",
49     TO_BE_DELETED = "To be deleted"
50 }
51
52 export interface TrashPanelFilter extends DataTableFilterItem {
53     type: ResourceKind;
54 }
55
56 export const trashPanelColumns: DataColumns<string, TrashPanelFilter> = [
57     {
58         name: TrashPanelColumnNames.NAME,
59         selected: true,
60         configurable: true,
61         sortDirection: SortDirection.ASC,
62         filters: [],
63         render: uuid => <ResourceName uuid={uuid}/>,
64         width: "450px"
65     },
66     {
67         name: TrashPanelColumnNames.TYPE,
68         selected: true,
69         configurable: true,
70         sortDirection: SortDirection.NONE,
71         filters: [
72             {
73                 name: resourceLabel(ResourceKind.COLLECTION),
74                 selected: true,
75                 type: ResourceKind.COLLECTION
76             },
77             {
78                 name: resourceLabel(ResourceKind.PROCESS),
79                 selected: true,
80                 type: ResourceKind.PROCESS
81             },
82             {
83                 name: resourceLabel(ResourceKind.PROJECT),
84                 selected: true,
85                 type: ResourceKind.PROJECT
86             }
87         ],
88         render: uuid => <ResourceType uuid={uuid}/>,
89         width: "125px"
90     },
91     {
92         name: TrashPanelColumnNames.FILE_SIZE,
93         selected: true,
94         configurable: true,
95         sortDirection: SortDirection.NONE,
96         filters: [],
97         render: uuid => <ResourceFileSize uuid={uuid} />,
98         width: "50px"
99     },
100     {
101         name: TrashPanelColumnNames.TRASHED_DATE,
102         selected: true,
103         configurable: true,
104         sortDirection: SortDirection.NONE,
105         filters: [],
106         render: uuid => <ResourceTrashDate uuid={uuid} />,
107         width: "50px"
108     },
109     {
110         name: TrashPanelColumnNames.TO_BE_DELETED,
111         selected: true,
112         configurable: true,
113         sortDirection: SortDirection.NONE,
114         filters: [],
115         render: uuid => <ResourceDeleteDate uuid={uuid} />,
116         width: "50px"
117     },
118 ];
119
120 interface TrashPanelDataProps {
121     currentItemId: string;
122     resources: ResourcesState;
123 }
124
125 type TrashPanelProps = TrashPanelDataProps & DispatchProp & WithStyles<CssRules>;
126
127 export const TrashPanel = withStyles(styles)(
128     connect((state: RootState) => ({
129         currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties),
130         resources: state.resources
131     }))(
132         class extends React.Component<TrashPanelProps> {
133             render() {
134                 return <DataExplorer
135                     id={TRASH_PANEL_ID}
136                     onRowClick={this.handleRowClick}
137                     onRowDoubleClick={this.handleRowDoubleClick}
138                     onContextMenu={this.handleContextMenu}
139                     defaultIcon={TrashIcon}
140                     defaultMessages={['Your trash list is empty.']}/>
141                 ;
142             }
143
144             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
145                 const kind = resourceKindToContextMenuKind(resourceUuid);
146                 const resource = getResource(resourceUuid)(this.props.resources) as TrashableResource;
147                 if (kind && resource) {
148                     this.props.dispatch<any>(openContextMenu(event, {
149                         name: '',
150                         uuid: resource.uuid,
151                         ownerUuid: resource.ownerUuid,
152                         isTrashed: resource.isTrashed,
153                         kind
154                     }));
155                 }
156             }
157
158             handleRowDoubleClick = (uuid: string) => {
159                 this.props.dispatch<any>(navigateTo(uuid));
160             }
161
162             handleRowClick = (uuid: string) => {
163                 this.props.dispatch(loadDetailsPanel(uuid));
164             }
165         }
166     )
167 );