refs #13828 Merge branch 'origin/13828-trash-view'
[arvados.git] / src / views / favorite-panel / favorite-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 { resourceLabel } from '~/common/labels';
15 import { ArvadosTheme } from '~/common/custom-theme';
16 import { FAVORITE_PANEL_ID } from "~/store/favorite-panel/favorite-panel-action";
17 import {
18     ProcessStatus,
19     ResourceFileSize,
20     ResourceLastModifiedDate,
21     ResourceName,
22     ResourceOwner,
23     ResourceType
24 } from '~/views-components/data-explorer/renderers';
25 import { FavoriteIcon } from '~/components/icon/icon';
26 import { Dispatch } from 'redux';
27 import { openContextMenu, resourceKindToContextMenuKind } 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 { ContainerRequestState } from "~/models/container-request";
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 FavoritePanelColumnNames {
45     NAME = "Name",
46     STATUS = "Status",
47     TYPE = "Type",
48     OWNER = "Owner",
49     FILE_SIZE = "File size",
50     LAST_MODIFIED = "Last modified"
51 }
52
53 export interface FavoritePanelFilter extends DataTableFilterItem {
54     type: ResourceKind | ContainerRequestState;
55 }
56
57 export const favoritePanelColumns: DataColumns<string, FavoritePanelFilter> = [
58     {
59         name: FavoritePanelColumnNames.NAME,
60         selected: true,
61         configurable: true,
62         sortDirection: SortDirection.ASC,
63         filters: [],
64         render: uuid => <ResourceName uuid={uuid} />,
65         width: "450px"
66     },
67     {
68         name: "Status",
69         selected: true,
70         configurable: true,
71         sortDirection: SortDirection.NONE,
72         filters: [
73             {
74                 name: ContainerRequestState.COMMITTED,
75                 selected: true,
76                 type: ContainerRequestState.COMMITTED
77             },
78             {
79                 name: ContainerRequestState.FINAL,
80                 selected: true,
81                 type: ContainerRequestState.FINAL
82             },
83             {
84                 name: ContainerRequestState.UNCOMMITTED,
85                 selected: true,
86                 type: ContainerRequestState.UNCOMMITTED
87             }
88         ],
89         render: uuid => <ProcessStatus uuid={uuid} />,
90         width: "75px"
91     },
92     {
93         name: FavoritePanelColumnNames.TYPE,
94         selected: true,
95         configurable: true,
96         sortDirection: SortDirection.NONE,
97         filters: [
98             {
99                 name: resourceLabel(ResourceKind.COLLECTION),
100                 selected: true,
101                 type: ResourceKind.COLLECTION
102             },
103             {
104                 name: resourceLabel(ResourceKind.PROCESS),
105                 selected: true,
106                 type: ResourceKind.PROCESS
107             },
108             {
109                 name: resourceLabel(ResourceKind.PROJECT),
110                 selected: true,
111                 type: ResourceKind.PROJECT
112             }
113         ],
114         render: uuid => <ResourceType uuid={uuid} />,
115         width: "125px"
116     },
117     {
118         name: FavoritePanelColumnNames.OWNER,
119         selected: true,
120         configurable: true,
121         sortDirection: SortDirection.NONE,
122         filters: [],
123         render: uuid => <ResourceOwner uuid={uuid} />,
124         width: "200px"
125     },
126     {
127         name: FavoritePanelColumnNames.FILE_SIZE,
128         selected: true,
129         configurable: true,
130         sortDirection: SortDirection.NONE,
131         filters: [],
132         render: uuid => <ResourceFileSize uuid={uuid} />,
133         width: "50px"
134     },
135     {
136         name: FavoritePanelColumnNames.LAST_MODIFIED,
137         selected: true,
138         configurable: true,
139         sortDirection: SortDirection.NONE,
140         filters: [],
141         render: uuid => <ResourceLastModifiedDate uuid={uuid} />,
142         width: "150px"
143     }
144 ];
145
146 interface FavoritePanelDataProps {
147     currentItemId: string;
148 }
149
150 interface FavoritePanelActionProps {
151     onItemClick: (item: string) => void;
152     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: string) => void;
153     onDialogOpen: (ownerUuid: string) => void;
154     onItemDoubleClick: (item: string) => void;
155 }
156
157 const mapDispatchToProps = (dispatch: Dispatch): FavoritePanelActionProps => ({
158     onContextMenu: (event, resourceUuid) => {
159         const kind = resourceKindToContextMenuKind(resourceUuid);
160         if (kind) {
161             dispatch<any>(openContextMenu(event, {
162                 name: '',
163                 uuid: resourceUuid,
164                 ownerUuid: '',
165                 kind: ResourceKind.NONE,
166                 menuKind: kind
167             }));
168         }
169     },
170     onDialogOpen: (ownerUuid: string) => { return; },
171     onItemClick: (resourceUuid: string) => {
172         dispatch<any>(loadDetailsPanel(resourceUuid));
173     },
174     onItemDoubleClick: uuid => {
175         dispatch<any>(navigateTo(uuid));
176     }
177 });
178
179 type FavoritePanelProps = FavoritePanelDataProps & FavoritePanelActionProps & DispatchProp
180     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
181
182 export const FavoritePanel = withStyles(styles)(
183     connect(undefined, mapDispatchToProps)(
184         class extends React.Component<FavoritePanelProps> {
185             render() {
186                 return <DataExplorer
187                     id={FAVORITE_PANEL_ID}
188                     onRowClick={this.props.onItemClick}
189                     onRowDoubleClick={this.props.onItemDoubleClick}
190                     onContextMenu={this.props.onContextMenu}
191                     defaultIcon={FavoriteIcon}
192                     defaultMessages={['Your favorites list is empty.']}
193                     contextMenuColumn={true}/>;
194             }
195         }
196     )
197 );