Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / views / shared-with-me-panel / shared-with-me-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 { 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 { RootState } from 'store/store';
10 import { ArvadosTheme } from 'common/custom-theme';
11 import { ShareMeIcon } from 'components/icon/icon';
12 import { ResourcesState, getResource } from 'store/resources/resources';
13 import { ResourceKind } from 'models/resource';
14 import { navigateTo } from "store/navigation/navigation-action";
15 import { loadDetailsPanel } from "store/details-panel/details-panel-action";
16 import { SHARED_WITH_ME_PANEL_ID } from 'store/shared-with-me-panel/shared-with-me-panel-actions';
17 import {
18     openContextMenu,
19     resourceUuidToContextMenuKind
20 } from 'store/context-menu/context-menu-actions';
21 import {
22     ResourceName,
23     ProcessStatus as ResourceStatus,
24     ResourceType,
25     ResourceOwnerWithNameLink,
26     ResourcePortableDataHash,
27     ResourceFileSize,
28     ResourceFileCount,
29     ResourceUUID,
30     ResourceContainerUuid,
31     ContainerRunTime,
32     ResourceOutputUuid,
33     ResourceLogUuid,
34     ResourceParentProcess,
35     ResourceModifiedByUserUuid,
36     ResourceVersion,
37     ResourceCreatedAtDate,
38     ResourceLastModifiedDate,
39     ResourceTrashDate,
40     ResourceDeleteDate,
41 } from 'views-components/data-explorer/renderers';
42 import { DataTableFilterItem } from 'components/data-table-filters/data-table-filters';
43 import { GroupContentsResource } from 'services/groups-service/groups-service';
44 import { toggleOne } from 'store/multiselect/multiselect-actions';
45 import { DataColumns } from 'components/data-table/data-table';
46 import { ContainerRequestState } from 'models/container-request';
47 import { ProjectResource } from 'models/project';
48 import { createTree } from 'models/tree';
49 import { SortDirection } from 'components/data-table/data-column';
50 import { getInitialResourceTypeFilters, getInitialProcessStatusFilters } from 'store/resource-type-filters/resource-type-filters';
51
52 type CssRules = "toolbar" | "button" | "root";
53
54 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
55     toolbar: {
56         paddingBottom: theme.spacing.unit * 3,
57         textAlign: "right"
58     },
59     button: {
60         marginLeft: theme.spacing.unit
61     },
62     root: {
63         width: '100%',
64     },
65 });
66
67 export enum SharedWithMePanelColumnNames {
68     NAME = 'Name',
69     STATUS = 'Status',
70     TYPE = 'Type',
71     OWNER = 'Owner',
72     PORTABLE_DATA_HASH = 'Portable Data Hash',
73     FILE_SIZE = 'File Size',
74     FILE_COUNT = 'File Count',
75     UUID = 'UUID',
76     CONTAINER_UUID = 'Container UUID',
77     RUNTIME = 'Runtime',
78     OUTPUT_UUID = 'Output UUID',
79     LOG_UUID = 'Log UUID',
80     PARENT_PROCESS = 'Parent Process UUID',
81     MODIFIED_BY_USER_UUID = 'Modified by User UUID',
82     VERSION = 'Version',
83     CREATED_AT = 'Date Created',
84     LAST_MODIFIED = 'Last Modified',
85     TRASH_AT = 'Trash at',
86     DELETE_AT = 'Delete at',
87 }
88
89 export interface ProjectPanelFilter extends DataTableFilterItem {
90     type: ResourceKind | ContainerRequestState;
91 }
92
93 export const sharedWithMePanelColumns: DataColumns<string, ProjectResource> = [
94     {
95         name: SharedWithMePanelColumnNames.NAME,
96         selected: true,
97         configurable: true,
98         sort: { direction: SortDirection.NONE, field: 'name' },
99         filters: createTree(),
100         render: (uuid) => <ResourceName uuid={uuid} />,
101     },
102     {
103         name: SharedWithMePanelColumnNames.STATUS,
104         selected: true,
105         configurable: true,
106         mutuallyExclusiveFilters: true,
107         filters: getInitialProcessStatusFilters(),
108         render: (uuid) => <ResourceStatus uuid={uuid} />,
109     },
110     {
111         name: SharedWithMePanelColumnNames.TYPE,
112         selected: true,
113         configurable: true,
114         filters: getInitialResourceTypeFilters(),
115         render: (uuid) => <ResourceType uuid={uuid} />,
116     },
117     {
118         name: SharedWithMePanelColumnNames.OWNER,
119         selected: true,
120         configurable: true,
121         filters: createTree(),
122         render: (uuid) => <ResourceOwnerWithNameLink uuid={uuid} />,
123     },
124     {
125         name: SharedWithMePanelColumnNames.PORTABLE_DATA_HASH,
126         selected: false,
127         configurable: true,
128         filters: createTree(),
129         render: (uuid) => <ResourcePortableDataHash uuid={uuid} />,
130     },
131     {
132         name: SharedWithMePanelColumnNames.FILE_SIZE,
133         selected: true,
134         configurable: true,
135         filters: createTree(),
136         render: (uuid) => <ResourceFileSize uuid={uuid} />,
137     },
138     {
139         name: SharedWithMePanelColumnNames.FILE_COUNT,
140         selected: false,
141         configurable: true,
142         filters: createTree(),
143         render: (uuid) => <ResourceFileCount uuid={uuid} />,
144     },
145     {
146         name: SharedWithMePanelColumnNames.UUID,
147         selected: false,
148         configurable: true,
149         filters: createTree(),
150         render: (uuid) => <ResourceUUID uuid={uuid} />,
151     },
152     {
153         name: SharedWithMePanelColumnNames.CONTAINER_UUID,
154         selected: false,
155         configurable: true,
156         filters: createTree(),
157         render: (uuid) => <ResourceContainerUuid uuid={uuid} />,
158     },
159     {
160         name: SharedWithMePanelColumnNames.RUNTIME,
161         selected: false,
162         configurable: true,
163         filters: createTree(),
164         render: (uuid) => <ContainerRunTime uuid={uuid} />,
165     },
166     {
167         name: SharedWithMePanelColumnNames.OUTPUT_UUID,
168         selected: false,
169         configurable: true,
170         filters: createTree(),
171         render: (uuid) => <ResourceOutputUuid uuid={uuid} />,
172     },
173     {
174         name: SharedWithMePanelColumnNames.LOG_UUID,
175         selected: false,
176         configurable: true,
177         filters: createTree(),
178         render: (uuid) => <ResourceLogUuid uuid={uuid} />,
179     },
180     {
181         name: SharedWithMePanelColumnNames.PARENT_PROCESS,
182         selected: false,
183         configurable: true,
184         filters: createTree(),
185         render: (uuid) => <ResourceParentProcess uuid={uuid} />,
186     },
187     {
188         name: SharedWithMePanelColumnNames.MODIFIED_BY_USER_UUID,
189         selected: false,
190         configurable: true,
191         filters: createTree(),
192         render: (uuid) => <ResourceModifiedByUserUuid uuid={uuid} />,
193     },
194     {
195         name: SharedWithMePanelColumnNames.VERSION,
196         selected: false,
197         configurable: true,
198         filters: createTree(),
199         render: (uuid) => <ResourceVersion uuid={uuid} />,
200     },
201     {
202         name: SharedWithMePanelColumnNames.CREATED_AT,
203         selected: false,
204         configurable: true,
205         sort: { direction: SortDirection.NONE, field: 'createdAt' },
206         filters: createTree(),
207         render: (uuid) => <ResourceCreatedAtDate uuid={uuid} />,
208     },
209     {
210         name: SharedWithMePanelColumnNames.LAST_MODIFIED,
211         selected: true,
212         configurable: true,
213         sort: { direction: SortDirection.DESC, field: 'modifiedAt' },
214         filters: createTree(),
215         render: (uuid) => <ResourceLastModifiedDate uuid={uuid} />,
216     },
217     {
218         name: SharedWithMePanelColumnNames.TRASH_AT,
219         selected: false,
220         configurable: true,
221         sort: { direction: SortDirection.NONE, field: 'trashAt' },
222         filters: createTree(),
223         render: (uuid) => <ResourceTrashDate uuid={uuid} />,
224     },
225     {
226         name: SharedWithMePanelColumnNames.DELETE_AT,
227         selected: false,
228         configurable: true,
229         sort: { direction: SortDirection.NONE, field: 'deleteAt' },
230         filters: createTree(),
231         render: (uuid) => <ResourceDeleteDate uuid={uuid} />,
232     },
233 ];
234
235
236 interface SharedWithMePanelDataProps {
237     resources: ResourcesState;
238     userUuid: string;
239 }
240
241 type SharedWithMePanelProps = SharedWithMePanelDataProps & DispatchProp & WithStyles<CssRules>;
242
243 export const SharedWithMePanel = withStyles(styles)(
244     connect((state: RootState) => ({
245         resources: state.resources,
246         userUuid: state.auth.user!.uuid,
247     }))(
248         class extends React.Component<SharedWithMePanelProps> {
249             render() {
250                 return <div className={this.props.classes.root}><DataExplorer
251                     id={SHARED_WITH_ME_PANEL_ID}
252                     onRowClick={this.handleRowClick}
253                     onRowDoubleClick={this.handleRowDoubleClick}
254                     onContextMenu={this.handleContextMenu}
255                     contextMenuColumn={false}
256                     defaultViewIcon={ShareMeIcon}
257                     defaultViewMessages={['No shared items']} />
258                 </div>;
259             }
260
261             handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
262                 const { resources } = this.props;
263                 const resource = getResource<GroupContentsResource>(resourceUuid)(resources);
264                 const menuKind = this.props.dispatch<any>(resourceUuidToContextMenuKind(resourceUuid));
265                 if (menuKind && resource) {
266                     this.props.dispatch<any>(openContextMenu(event, {
267                         name: resource.name,
268                         uuid: resource.uuid,
269                         description: resource.description,
270                         ownerUuid: resource.ownerUuid,
271                         isTrashed: ('isTrashed' in resource) ? resource.isTrashed: false,
272                         kind: resource.kind,
273                         menuKind
274                     }));
275                 }
276                 this.props.dispatch<any>(loadDetailsPanel(resourceUuid));
277             }
278
279             handleRowDoubleClick = (uuid: string) => {
280                 this.props.dispatch<any>(navigateTo(uuid));
281             }
282
283             handleRowClick = (uuid: string) => {
284                 this.props.dispatch<any>(toggleOne(uuid))
285                 this.props.dispatch<any>(loadDetailsPanel(uuid));
286             }
287         }
288     )
289 );