15610: Replaces the 'loading files...' string with a circular spinner.
[arvados-workbench2.git] / src / components / collection-panel-files / collection-panel-files.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 { TreeItem, TreeItemStatus } from '~/components/tree/tree';
7 import { FileTreeData } from '~/components/file-tree/file-tree-data';
8 import { FileTree } from '~/components/file-tree/file-tree';
9 import { IconButton, Grid, Typography, StyleRulesCallback, withStyles, WithStyles, CardHeader, Card, Button, Tooltip, CircularProgress } from '@material-ui/core';
10 import { CustomizeTableIcon } from '~/components/icon/icon';
11 import { DownloadIcon } from '~/components/icon/icon';
12
13 export interface CollectionPanelFilesProps {
14     items: Array<TreeItem<FileTreeData>>;
15     isWritable: boolean;
16     isLoading: boolean;
17     tooManyFiles: boolean;
18     onUploadDataClick: () => void;
19     onItemMenuOpen: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>, isWritable: boolean) => void;
20     onOptionsMenuOpen: (event: React.MouseEvent<HTMLElement>, isWritable: boolean) => void;
21     onSelectionToggle: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>) => void;
22     onCollapseToggle: (id: string, status: TreeItemStatus) => void;
23     onFileClick: (id: string) => void;
24     loadFilesFunc: () => void;
25     currentItemUuid?: string;
26 }
27
28 type CssRules = 'root' | 'cardSubheader' | 'nameHeader' | 'fileSizeHeader' | 'uploadIcon' | 'button' | 'centeredLabel';
29
30 const styles: StyleRulesCallback<CssRules> = theme => ({
31     root: {
32         paddingBottom: theme.spacing.unit,
33         height: '100%'
34     },
35     cardSubheader: {
36         paddingTop: 0,
37         paddingBottom: 0
38     },
39     nameHeader: {
40         marginLeft: '75px'
41     },
42     fileSizeHeader: {
43         marginRight: '65px'
44     },
45     uploadIcon: {
46         transform: 'rotate(180deg)'
47     },
48     button: {
49         marginRight: -theme.spacing.unit,
50         marginTop: '0px'
51     },
52     centeredLabel: {
53         fontSize: '0.875rem',
54         textAlign: 'center'
55     },
56 });
57
58 export const CollectionPanelFiles =
59     withStyles(styles)(
60         ({ onItemMenuOpen, onOptionsMenuOpen, onUploadDataClick, classes,
61             isWritable, isLoading, tooManyFiles, loadFilesFunc, ...treeProps }: CollectionPanelFilesProps & WithStyles<CssRules>) =>
62             <Card data-cy='collection-files-panel' className={classes.root}>
63                 <CardHeader
64                     title="Files"
65                     className={classes.cardSubheader}
66                     classes={{ action: classes.button }}
67                     action={<>
68                         {isWritable &&
69                         <Button
70                             data-cy='upload-button'
71                             onClick={onUploadDataClick}
72                             variant='contained'
73                             color='primary'
74                             size='small'>
75                             <DownloadIcon className={classes.uploadIcon} />
76                             Upload data
77                         </Button>}
78                         {!tooManyFiles &&
79                         <Tooltip title="More options" disableFocusListener>
80                             <IconButton
81                                 data-cy='collection-files-panel-options-btn'
82                                 onClick={(ev) => onOptionsMenuOpen(ev, isWritable)}>
83                                 <CustomizeTableIcon />
84                             </IconButton>
85                         </Tooltip>}
86                     </>
87                 } />
88                 { tooManyFiles
89                 ? <div className={classes.centeredLabel}>
90                         File listing may take some time, please click to browse: <Button onClick={loadFilesFunc}><DownloadIcon/>Show files</Button>
91                 </div>
92                 : <>
93                     <Grid container justify="space-between">
94                         <Typography variant="caption" className={classes.nameHeader}>
95                             Name
96                         </Typography>
97                         <Typography variant="caption" className={classes.fileSizeHeader}>
98                             File size
99                         </Typography>
100                     </Grid>
101                     { isLoading
102                     ? <div className={classes.centeredLabel}><CircularProgress /></div>
103                     : <div style={{height: 'calc(100% - 60px)'}}><FileTree onMenuOpen={(ev, item) => onItemMenuOpen(ev, item, isWritable)} {...treeProps} /></div> }
104                 </>
105                 }
106             </Card>);