Replace typesafe-actions with unionize, add fetching user details action
[arvados-workbench2.git] / src / views / workbench / workbench.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
7 import { StyleRulesCallback, Theme, WithStyles, withStyles } from '@material-ui/core/styles';
8 import Drawer from '@material-ui/core/Drawer';
9 import AppBar from '@material-ui/core/AppBar';
10 import Toolbar from '@material-ui/core/Toolbar';
11 import Typography from '@material-ui/core/Typography';
12 import { connect, DispatchProp } from "react-redux";
13 import Tree from "../../components/tree/tree";
14 import { Project } from "../../models/project";
15 import { RootState } from "../../store/root-reducer";
16 import ProjectList from "../../components/project-list/project-list";
17 import { Route, Switch } from "react-router";
18 import { Link } from "react-router-dom";
19 import Button from "@material-ui/core/Button/Button";
20 import authActions from "../../store/auth-action";
21 import { authService } from "../../services/services";
22 import IconButton from "@material-ui/core/IconButton/IconButton";
23 import Menu from "@material-ui/core/Menu/Menu";
24 import MenuItem from "@material-ui/core/MenuItem/MenuItem";
25 import { AccountCircle } from "@material-ui/icons";
26 import { AnyAction } from "redux";
27
28 const drawerWidth = 240;
29
30 type CssRules = 'root' | 'appBar' | 'drawerPaper' | 'content' | 'toolbar';
31
32 const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
33     root: {
34         flexGrow: 1,
35         zIndex: 1,
36         overflow: 'hidden',
37         position: 'relative',
38         display: 'flex',
39         width: '100vw',
40         height: '100vh'
41     },
42     appBar: {
43         zIndex: theme.zIndex.drawer + 1,
44         backgroundColor: '#692498'
45     },
46     drawerPaper: {
47         position: 'relative',
48         width: drawerWidth,
49     },
50     content: {
51         flexGrow: 1,
52         backgroundColor: theme.palette.background.default,
53         padding: theme.spacing.unit * 3,
54         height: '100%',
55         minWidth: 0,
56     },
57     toolbar: theme.mixins.toolbar
58 });
59
60 interface WorkbenchDataProps {
61     projects: Project[];
62 }
63
64 interface WorkbenchActionProps {
65 }
66
67 type WorkbenchProps = WorkbenchDataProps & WorkbenchActionProps & DispatchProp & WithStyles<CssRules>;
68
69 interface WorkbenchState {
70     anchorEl: any;
71 }
72
73 class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
74     constructor(props: WorkbenchProps) {
75         super(props);
76         this.state = {
77             anchorEl: null
78         }
79     }
80
81     login = () => {
82         this.props.dispatch(authActions.LOGIN() as AnyAction);
83     };
84
85     logout = () => {
86         this.handleClose();
87         this.props.dispatch(authActions.LOGOUT() as AnyAction);
88     };
89
90     handleOpenMenu = (event: React.MouseEvent<any>) => {
91         this.setState({
92             anchorEl: event.currentTarget
93         });
94     };
95
96     handleClose = () => {
97         this.setState({
98             anchorEl: null
99         });
100     };
101
102     render() {
103         const {classes} = this.props;
104         const userLoggedIn = authService.isUserLoggedIn();
105         return (
106             <div className={classes.root}>
107                 <AppBar position="absolute" className={classes.appBar}>
108                     <Toolbar>
109                         <Typography variant="title" color="inherit" noWrap style={{flexGrow: 1}}>
110                             <span>Arvados</span><br/><span style={{fontSize: 12}}>Workbench 2</span>
111                         </Typography>
112                         {userLoggedIn ?
113                             <div>
114                                 <IconButton
115                                       aria-owns={this.state.anchorEl ? 'menu-appbar' : undefined}
116                                       aria-haspopup="true"
117                                       onClick={this.handleOpenMenu}
118                                       color="inherit">
119                                   <AccountCircle/>
120                                 </IconButton>
121                                 <Menu
122                                   id="menu-appbar"
123                                   anchorEl={this.state.anchorEl}
124                                   anchorOrigin={{
125                                     vertical: 'top',
126                                     horizontal: 'right',
127                                   }}
128                                   transformOrigin={{
129                                     vertical: 'top',
130                                     horizontal: 'right',
131                                   }}
132                                   open={!!this.state.anchorEl}
133                                   onClose={this.handleClose}>
134                                   <MenuItem onClick={this.logout}>Logout</MenuItem>
135                                   <MenuItem onClick={this.handleClose}>My account</MenuItem>
136                                 </Menu>
137                             </div>
138                             :
139                             <Button color="inherit" onClick={this.login}>Login</Button>
140                         }
141                     </Toolbar>
142                 </AppBar>
143                 {userLoggedIn &&
144                 <Drawer
145                     variant="permanent"
146                     classes={{
147                         paper: classes.drawerPaper,
148                     }}>
149                     <div className={classes.toolbar}/>
150                     <Tree items={this.props.projects} render={(p: Project) =>
151                         <Link to={`/project/${p.name}`}>{p.name}</Link>
152                     }/>
153                 </Drawer>}
154                 <main className={classes.content}>
155                     <div className={classes.toolbar}/>
156                     <Switch>
157                         <Route path="/project/:name" component={ProjectList}/>
158                     </Switch>
159                 </main>
160             </div>
161         );
162     }
163 }
164
165 export default connect<WorkbenchDataProps>(
166     (state: RootState) => ({
167         projects: state.projects
168     })
169 )(
170     withStyles(styles)(Workbench)
171 );