Extract major components from workbench
[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 { DispatchProp, connect } from 'react-redux';
9 import { DataColumns } from '~/components/data-table/data-table';
10 import { RouteComponentProps } from 'react-router';
11 import { RootState } from '~/store/store';
12 import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
13 import { ContainerRequestState } from '~/models/container-request';
14 import { SortDirection } from '~/components/data-table/data-column';
15 import { ResourceKind } from '~/models/resource';
16 import { resourceLabel } from '~/common/labels';
17 import { ArvadosTheme } from '~/common/custom-theme';
18 import { FAVORITE_PANEL_ID, loadFavoritePanel } from "~/store/favorite-panel/favorite-panel-action";
19 import { ResourceFileSize, ResourceLastModifiedDate, ProcessStatus, ResourceType, ResourceOwner, ResourceName } from '~/views-components/data-explorer/renderers';
20 import { FavoriteIcon } from '~/components/icon/icon';
21 import { Dispatch } from 'redux';
22 import { contextMenuActions } from '~/store/context-menu/context-menu-actions';
23 import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
24 import { loadDetailsPanel } from '../../store/details-panel/details-panel-action';
25 import { navigateToResource } from '~/store/navigation/navigation-action';
26
27 type CssRules = "toolbar" | "button";
28
29 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
30     toolbar: {
31         paddingBottom: theme.spacing.unit * 3,
32         textAlign: "right"
33     },
34     button: {
35         marginLeft: theme.spacing.unit
36     },
37 });
38
39 export enum FavoritePanelColumnNames {
40     NAME = "Name",
41     STATUS = "Status",
42     TYPE = "Type",
43     OWNER = "Owner",
44     FILE_SIZE = "File size",
45     LAST_MODIFIED = "Last modified"
46 }
47
48 export interface FavoritePanelFilter extends DataTableFilterItem {
49     type: ResourceKind | ContainerRequestState;
50 }
51
52 export const columns: DataColumns<string, FavoritePanelFilter> = [
53     {
54         name: FavoritePanelColumnNames.NAME,
55         selected: true,
56         configurable: true,
57         sortDirection: SortDirection.ASC,
58         filters: [],
59         render: uuid => <ResourceName uuid={uuid} />,
60         width: "450px"
61     },
62     {
63         name: "Status",
64         selected: true,
65         configurable: true,
66         sortDirection: SortDirection.NONE,
67         filters: [
68             {
69                 name: ContainerRequestState.COMMITTED,
70                 selected: true,
71                 type: ContainerRequestState.COMMITTED
72             },
73             {
74                 name: ContainerRequestState.FINAL,
75                 selected: true,
76                 type: ContainerRequestState.FINAL
77             },
78             {
79                 name: ContainerRequestState.UNCOMMITTED,
80                 selected: true,
81                 type: ContainerRequestState.UNCOMMITTED
82             }
83         ],
84         render: uuid => <ProcessStatus uuid={uuid} />,
85         width: "75px"
86     },
87     {
88         name: FavoritePanelColumnNames.TYPE,
89         selected: true,
90         configurable: true,
91         sortDirection: SortDirection.NONE,
92         filters: [
93             {
94                 name: resourceLabel(ResourceKind.COLLECTION),
95                 selected: true,
96                 type: ResourceKind.COLLECTION
97             },
98             {
99                 name: resourceLabel(ResourceKind.PROCESS),
100                 selected: true,
101                 type: ResourceKind.PROCESS
102             },
103             {
104                 name: resourceLabel(ResourceKind.PROJECT),
105                 selected: true,
106                 type: ResourceKind.PROJECT
107             }
108         ],
109         render: uuid => <ResourceType uuid={uuid} />,
110         width: "125px"
111     },
112     {
113         name: FavoritePanelColumnNames.OWNER,
114         selected: true,
115         configurable: true,
116         sortDirection: SortDirection.NONE,
117         filters: [],
118         render: uuid => <ResourceOwner uuid={uuid} />,
119         width: "200px"
120     },
121     {
122         name: FavoritePanelColumnNames.FILE_SIZE,
123         selected: true,
124         configurable: true,
125         sortDirection: SortDirection.NONE,
126         filters: [],
127         render: uuid => <ResourceFileSize uuid={uuid} />,
128         width: "50px"
129     },
130     {
131         name: FavoritePanelColumnNames.LAST_MODIFIED,
132         selected: true,
133         configurable: true,
134         sortDirection: SortDirection.NONE,
135         filters: [],
136         render: uuid => <ResourceLastModifiedDate uuid={uuid} />,
137         width: "150px"
138     }
139 ];
140
141 interface FavoritePanelDataProps {
142     currentItemId: string;
143 }
144
145 interface FavoritePanelActionProps {
146     onItemClick: (item: string) => void;
147     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: string) => void;
148     onDialogOpen: (ownerUuid: string) => void;
149     onItemDoubleClick: (item: string) => void;
150     onMount: () => void;
151 }
152
153 const mapDispatchToProps = (dispatch: Dispatch): FavoritePanelActionProps => ({
154     onContextMenu: (event, resourceUuid) => {
155         event.preventDefault();
156         dispatch(
157             contextMenuActions.OPEN_CONTEXT_MENU({
158                 position: { x: event.clientX, y: event.clientY },
159                 resource: { name: '', uuid: resourceUuid, kind: ContextMenuKind.RESOURCE }
160             })
161         );
162     },
163     onDialogOpen: (ownerUuid: string) => { return; },
164     onItemClick: (resourceUuid: string) => {
165         dispatch<any>(loadDetailsPanel(resourceUuid));
166     },
167     onItemDoubleClick: uuid => {
168         dispatch<any>(navigateToResource(uuid));
169     },
170     onMount: () => {
171         dispatch(loadFavoritePanel());
172     },
173 });
174
175 type FavoritePanelProps = FavoritePanelDataProps & FavoritePanelActionProps & DispatchProp
176     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
177
178 export const FavoritePanel = withStyles(styles)(
179     connect((state: RootState) => ({ currentItemId: state.projects.currentItemId }), mapDispatchToProps)(
180         class extends React.Component<FavoritePanelProps> {
181             render() {
182                 return <DataExplorer
183                     id={FAVORITE_PANEL_ID}
184                     columns={columns}
185                     onRowClick={this.props.onItemClick}
186                     onRowDoubleClick={this.props.onItemDoubleClick}
187                     onContextMenu={this.props.onContextMenu}
188                     defaultIcon={FavoriteIcon}
189                     defaultMessages={['Your favorites list is empty.']} />;
190             }
191
192             componentDidMount() {
193                 this.props.onMount();
194             }
195         }
196     )
197 );