]> git.arvados.org - arvados.git/blob - services/workbench2/src/views/public-favorites-panel/public-favorites-panel.tsx
Merge branch 'main' into 22793-unify-tab-view
[arvados.git] / services / workbench2 / src / views / public-favorites-panel / public-favorites-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 { DataColumns } from 'components/data-table/data-column';
12 import { RouteComponentProps } from 'react-router';
13 import { DataTableFilterItem } from 'components/data-table-filters/data-table-filters';
14 import { ResourceKind } from 'models/resource';
15 import { ArvadosTheme } from 'common/custom-theme';
16 import {
17     ProcessStatus,
18     ResourceFileSize,
19     ResourceLastModifiedDate,
20     ResourceType,
21     ResourceName,
22     ResourceOwnerWithName
23 } from 'views-components/data-explorer/renderers';
24 import { PublicFavoriteIcon } from 'components/icon/icon';
25 import { Dispatch } from 'redux';
26 import {
27     openContextMenuAndSelect,
28 } from 'store/context-menu/context-menu-actions';
29 import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
30 import { navigateTo } from 'store/navigation/navigation-action';
31 import { ContainerRequestState } from "models/container-request";
32 import { RootState } from 'store/store';
33 import { createTree } from 'models/tree';
34 import { getSimpleObjectTypeFilters } from 'store/resource-type-filters/resource-type-filters';
35 import { PUBLIC_FAVORITE_PANEL_ID } from 'store/public-favorites-panel/public-favorites-action';
36 import { PublicFavoritesState } from 'store/public-favorites/public-favorites-reducer';
37 import { getResource, ResourcesState } from 'store/resources/resources';
38 import { GroupContentsResource } from 'services/groups-service/groups-service';
39 import { CollectionResource } from 'models/collection';
40 import { toggleOne, deselectAllOthers } from 'store/multiselect/multiselect-actions';
41 import { resourceToMenuKind } from 'common/resource-to-menu-kind';
42
43 type CssRules = "toolbar" | "button" | "root";
44
45 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
46     toolbar: {
47         paddingBottom: theme.spacing(3),
48         textAlign: "right"
49     },
50     button: {
51         marginLeft: theme.spacing(1)
52     },
53     root: {
54         width: '100%',
55         boxShadow: "0px 1px 3px 0px rgb(0 0 0 / 20%), 0px 1px 1px 0px rgb(0 0 0 / 14%), 0px 2px 1px -1px rgb(0 0 0 / 12%)",
56     },
57 });
58
59 export enum PublicFavoritePanelColumnNames {
60     NAME = "Name",
61     STATUS = "Status",
62     TYPE = "Type",
63     OWNER = "Owner",
64     FILE_SIZE = "File size",
65     LAST_MODIFIED = "Last modified"
66 }
67
68 export interface FavoritePanelFilter extends DataTableFilterItem {
69     type: ResourceKind | ContainerRequestState;
70 }
71
72 export const publicFavoritePanelColumns: DataColumns<string, GroupContentsResource> = [
73     {
74         name: PublicFavoritePanelColumnNames.NAME,
75         selected: true,
76         configurable: true,
77         filters: createTree(),
78         render: uuid => <ResourceName uuid={uuid} />
79     },
80     {
81         name: "Status",
82         selected: true,
83         configurable: true,
84         filters: createTree(),
85         render: uuid => <ProcessStatus uuid={uuid} />
86     },
87     {
88         name: PublicFavoritePanelColumnNames.TYPE,
89         selected: true,
90         configurable: true,
91         filters: getSimpleObjectTypeFilters(),
92         render: uuid => <ResourceType uuid={uuid} />
93     },
94     {
95         name: PublicFavoritePanelColumnNames.OWNER,
96         selected: false,
97         configurable: true,
98         filters: createTree(),
99         render: uuid => <ResourceOwnerWithName uuid={uuid} />
100     },
101     {
102         name: PublicFavoritePanelColumnNames.FILE_SIZE,
103         selected: true,
104         configurable: true,
105         filters: createTree(),
106         render: uuid => <ResourceFileSize uuid={uuid} />
107     },
108     {
109         name: PublicFavoritePanelColumnNames.LAST_MODIFIED,
110         selected: true,
111         configurable: true,
112         filters: createTree(),
113         render: uuid => <ResourceLastModifiedDate uuid={uuid} />
114     }
115 ];
116
117 interface PublicFavoritePanelDataProps {
118     publicFavorites: PublicFavoritesState;
119     resources: ResourcesState;
120 }
121
122 interface PublicFavoritePanelActionProps {
123     onItemClick: (item: string) => void;
124     onContextMenu: (resources: ResourcesState) => (event: React.MouseEvent<HTMLElement>, item: string) => void;
125     onDialogOpen: (ownerUuid: string) => void;
126     onItemDoubleClick: (item: string) => void;
127 }
128 const mapStateToProps = ({ publicFavorites, resources }: RootState): PublicFavoritePanelDataProps => ({
129     publicFavorites,
130     resources,
131 });
132
133 const mapDispatchToProps = (dispatch: Dispatch): PublicFavoritePanelActionProps => ({
134     onContextMenu: (resources: ResourcesState) => (event, resourceUuid) => {
135         const resource = getResource<GroupContentsResource>(resourceUuid)(resources);
136         const kind = dispatch<any>(resourceToMenuKind(resourceUuid));
137         if (kind && resource) {
138             dispatch<any>(openContextMenuAndSelect(event, {
139                 name: resource.name,
140                 description: resource.description,
141                 storageClassesDesired: (resource as CollectionResource).storageClassesDesired,
142                 uuid: resourceUuid,
143                 ownerUuid: '',
144                 kind: ResourceKind.NONE,
145                 menuKind: kind
146             }));
147         }
148         dispatch<any>(loadDetailsPanel(resourceUuid));
149     },
150     onDialogOpen: (ownerUuid: string) => { return; },
151     onItemClick: (uuid: string) => {
152                 dispatch<any>(toggleOne(uuid))
153                 dispatch<any>(deselectAllOthers(uuid))
154                 dispatch<any>(loadDetailsPanel(uuid));
155     },
156     onItemDoubleClick: uuid => {
157         dispatch<any>(navigateTo(uuid));
158     }
159 });
160
161 type FavoritePanelProps = PublicFavoritePanelDataProps & PublicFavoritePanelActionProps & DispatchProp
162     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
163
164 export const PublicFavoritePanel = withStyles(styles)(
165     connect(mapStateToProps, mapDispatchToProps)(
166         class extends React.Component<FavoritePanelProps> {
167             render() {
168                 return <div className={this.props.classes.root}><DataExplorer
169                     id={PUBLIC_FAVORITE_PANEL_ID}
170                     onRowClick={this.props.onItemClick}
171                     onRowDoubleClick={this.props.onItemDoubleClick}
172                     onContextMenu={this.props.onContextMenu(this.props.resources)}
173                     contextMenuColumn={false}
174                     defaultViewIcon={PublicFavoriteIcon}
175                     defaultViewMessages={['Public favorites list is empty.']} />
176                 </div>;
177             }
178         }
179     )
180 );