add 'New' button with 3 options and clean code
[arvados-workbench2.git] / src / views-components / side-panel-button / side-panel-button.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 { connect, DispatchProp } from 'react-redux';
7 import { RootState } from '~/store/store';
8 import { getProperty } from '~/store/properties/properties';
9 import { PROJECT_PANEL_CURRENT_UUID } from '~/store/project-panel/project-panel-action';
10 import { ArvadosTheme } from '~/common/custom-theme';
11 import { PopoverOrigin } from '@material-ui/core/Popover';
12 import { StyleRulesCallback, WithStyles, withStyles, Toolbar, Grid, Button, MenuItem, Menu } from '@material-ui/core';
13 import { AddIcon, CollectionIcon, ProcessIcon, ProjectIcon } from '~/components/icon/icon';
14 import { openProjectCreateDialog } from '~/store/projects/project-create-actions';
15 import { openCollectionCreateDialog } from '~/store/collections/collection-create-actions';
16
17 type CssRules = 'button' | 'menuItem' | 'icon';
18
19 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
20     button: {
21         boxShadow: 'none',
22         padding: '2px 10px 2px 5px',
23         fontSize: '0.75rem'
24     },
25     menuItem: {
26         fontSize: '0.875rem',
27         color: theme.palette.grey["700"]
28     },
29     icon: {
30         marginRight: theme.spacing.unit
31     }
32 });
33
34 interface SidePanelDataProps {
35     currentItemId: string;
36 }
37
38 interface SidePanelState {
39     anchorEl: any;
40 }
41
42 type SidePanelProps = SidePanelDataProps & DispatchProp & WithStyles<CssRules>;
43
44 export const SidePanelButton = withStyles(styles)(
45     connect((state: RootState) => ({
46         currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties)
47     }))(
48         class extends React.Component<SidePanelProps> {
49
50             state: SidePanelState = {
51                 anchorEl: undefined
52             };
53
54             transformOrigin: PopoverOrigin = {
55                 vertical: -50,
56                 horizontal: 25
57             };
58
59             render() {
60                 const { classes } = this.props;
61                 const { anchorEl } = this.state;
62                 return <Toolbar>
63                     <Grid container>
64                         <Grid container item xs alignItems="center" justify="center">
65                             <Button variant="contained" color="primary" size="small" className={classes.button}
66                                 aria-owns={anchorEl ? 'aside-menu-list' : undefined}
67                                 aria-haspopup="true"
68                                 onClick={this.handleOpen}>
69                                 <AddIcon />
70                                 New
71                             </Button>
72                             <Menu
73                                 id='aside-menu-list'
74                                 anchorEl={anchorEl}
75                                 open={Boolean(anchorEl)}
76                                 onClose={this.handleClose}
77                                 onClick={this.handleClose}
78                                 transformOrigin={this.transformOrigin}>
79                                 <MenuItem className={classes.menuItem} onClick={this.handleNewCollectionClick}>
80                                     <CollectionIcon className={classes.icon} /> New collection
81                                 </MenuItem>
82                                 <MenuItem className={classes.menuItem}>
83                                     <ProcessIcon className={classes.icon} /> Run a process
84                                 </MenuItem>
85                                 <MenuItem className={classes.menuItem} onClick={this.handleNewProjectClick}>
86                                     <ProjectIcon className={classes.icon} /> New project
87                                 </MenuItem>
88                             </Menu>
89                         </Grid>
90                     </Grid>
91                 </Toolbar>;
92             }
93
94             handleNewProjectClick = () => {
95                 this.props.dispatch<any>(openProjectCreateDialog(this.props.currentItemId));
96             }
97
98             handleNewCollectionClick = () => {
99                 this.props.dispatch<any>(openCollectionCreateDialog(this.props.currentItemId));
100             }
101
102             handleClose = () => {
103                 this.setState({ anchorEl: undefined });
104             }
105
106             handleOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
107                 this.setState({ anchorEl: event.currentTarget });
108             }
109         }
110     )
111 );