17585: Project change should trigger loader
[arvados-workbench2.git] / src / views / collection-content-address-panel / collection-content-address-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 {
7     StyleRulesCallback,
8     WithStyles,
9     withStyles,
10     Grid,
11     Button
12 } from '@material-ui/core';
13 import { CollectionIcon } from 'components/icon/icon';
14 import { ArvadosTheme } from 'common/custom-theme';
15 import { BackIcon } from 'components/icon/icon';
16 import { DataTableDefaultView } from 'components/data-table-default-view/data-table-default-view';
17 import { COLLECTIONS_CONTENT_ADDRESS_PANEL_ID } from 'store/collections-content-address-panel/collections-content-address-panel-actions';
18 import { DataExplorer } from "views-components/data-explorer/data-explorer";
19 import { Dispatch } from 'redux';
20 import {
21     resourceUuidToContextMenuKind,
22     openContextMenu
23 } from 'store/context-menu/context-menu-actions';
24 import { ResourceKind } from 'models/resource';
25 import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
26 import { connect } from 'react-redux';
27 import { navigateTo } from 'store/navigation/navigation-action';
28 import { DataColumns } from 'components/data-table/data-table';
29 import { SortDirection } from 'components/data-table/data-column';
30 import { createTree } from 'models/tree';
31 import {
32     ResourceName,
33     ResourceOwnerName,
34     ResourceLastModifiedDate,
35     ResourceStatus
36 } from 'views-components/data-explorer/renderers';
37 import { getResource, ResourcesState } from 'store/resources/resources';
38 import { RootState } from 'store/store';
39 import { CollectionResource } from 'models/collection';
40
41 type CssRules = 'backLink' | 'backIcon' | 'card' | 'title' | 'iconHeader' | 'link';
42
43 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
44     backLink: {
45         fontSize: '14px',
46         fontWeight: 600,
47         display: 'flex',
48         alignItems: 'center',
49         padding: theme.spacing.unit,
50         marginBottom: theme.spacing.unit,
51         color: theme.palette.grey["700"],
52     },
53     backIcon: {
54         marginRight: theme.spacing.unit
55     },
56     card: {
57         width: '100%'
58     },
59     title: {
60         color: theme.palette.grey["700"]
61     },
62     iconHeader: {
63         fontSize: '1.875rem',
64         color: theme.customs.colors.green700
65     },
66     link: {
67         fontSize: '0.875rem',
68         color: theme.palette.primary.main,
69         textAlign: 'right',
70         '&:hover': {
71             cursor: 'pointer'
72         }
73     }
74 });
75
76 enum CollectionContentAddressPanelColumnNames {
77     COLLECTION_WITH_THIS_ADDRESS = "Collection with this address",
78     STATUS = "Status",
79     LOCATION = "Location",
80     LAST_MODIFIED = "Last modified"
81 }
82
83 export const collectionContentAddressPanelColumns: DataColumns<string> = [
84     {
85         name: CollectionContentAddressPanelColumnNames.COLLECTION_WITH_THIS_ADDRESS,
86         selected: true,
87         configurable: true,
88         sortDirection: SortDirection.NONE,
89         filters: createTree(),
90         render: uuid => <ResourceName uuid={uuid} />
91     },
92     {
93         name: CollectionContentAddressPanelColumnNames.STATUS,
94         selected: true,
95         configurable: true,
96         filters: createTree(),
97         render: uuid => <ResourceStatus uuid={uuid} />
98     },
99     {
100         name: CollectionContentAddressPanelColumnNames.LOCATION,
101         selected: true,
102         configurable: true,
103         filters: createTree(),
104         render: uuid => <ResourceOwnerName uuid={uuid} />
105     },
106     {
107         name: CollectionContentAddressPanelColumnNames.LAST_MODIFIED,
108         selected: true,
109         configurable: true,
110         sortDirection: SortDirection.DESC,
111         filters: createTree(),
112         render: uuid => <ResourceLastModifiedDate uuid={uuid} />
113     }
114 ];
115
116 interface CollectionContentAddressPanelActionProps {
117     onContextMenu: (resources: ResourcesState) => (event: React.MouseEvent<any>, uuid: string) => void;
118     onItemClick: (item: string) => void;
119     onItemDoubleClick: (item: string) => void;
120 }
121
122 interface CollectionContentAddressPanelDataProps {
123     resources: ResourcesState;
124 }
125
126 const mapStateToProps = ({ resources }: RootState): CollectionContentAddressPanelDataProps => ({
127     resources
128 })
129
130 const mapDispatchToProps = (dispatch: Dispatch): CollectionContentAddressPanelActionProps => ({
131     onContextMenu: (resources: ResourcesState) => (event, resourceUuid) => {
132         const resource = getResource<CollectionResource>(resourceUuid)(resources);
133         const kind = dispatch<any>(resourceUuidToContextMenuKind(resourceUuid));
134         if (kind) {
135             dispatch<any>(openContextMenu(event, {
136                 name: resource ? resource.name : '',
137                 description: resource ? resource.description : '',
138                 storageClassesDesired: resource ? resource.storageClassesDesired : [],
139                 uuid: resourceUuid,
140                 ownerUuid: '',
141                 kind: ResourceKind.NONE,
142                 menuKind: kind
143             }));
144         }
145         dispatch<any>(loadDetailsPanel(resourceUuid));
146     },
147     onItemClick: (uuid: string) => {
148         dispatch<any>(loadDetailsPanel(uuid));
149     },
150     onItemDoubleClick: uuid => {
151         dispatch<any>(navigateTo(uuid));
152     }
153 });
154
155 interface CollectionContentAddressDataProps {
156     match: {
157         params: { id: string }
158     };
159 }
160
161 export const CollectionsContentAddressPanel = withStyles(styles)(
162     connect(mapStateToProps, mapDispatchToProps)(
163         class extends React.Component<CollectionContentAddressPanelActionProps & CollectionContentAddressPanelDataProps & CollectionContentAddressDataProps & WithStyles<CssRules>> {
164             render() {
165                 return <Grid item xs={12}>
166                     <Button
167                         onClick={() => window.history.back()}
168                         className={this.props.classes.backLink}>
169                         <BackIcon className={this.props.classes.backIcon} />
170                         Back
171                     </Button>
172                     <DataExplorer
173                         id={COLLECTIONS_CONTENT_ADDRESS_PANEL_ID}
174                         hideSearchInput
175                         onRowClick={this.props.onItemClick}
176                         onRowDoubleClick={this.props.onItemDoubleClick}
177                         onContextMenu={this.props.onContextMenu(this.props.resources)}
178                         contextMenuColumn={true}
179                         title={`Content address: ${this.props.match.params.id}`}
180                         dataTableDefaultView={
181                             <DataTableDefaultView
182                                 icon={CollectionIcon}
183                                 messages={['Collections with this content address not found.']} />
184                         } />;
185                     </Grid >;
186             }
187         }
188     )
189 );