Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / framework / src / components / titleBar.tsx
1 /**
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt odlux
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 import React from 'react';
19 import { withRouter, RouteComponentProps } from 'react-router-dom';
20
21 import { Theme } from '@mui/material/styles';
22 import { WithStyles } from '@mui/styles';
23 import withStyles from '@mui/styles/withStyles';
24 import createStyles from '@mui/styles/createStyles';
25 import AppBar from '@mui/material/AppBar';
26 import Toolbar from '@mui/material/Toolbar';
27 import Typography from '@mui/material/Typography';
28 import Button from '@mui/material/Button';
29 import IconButton from '@mui/material/IconButton';
30 import AccountCircle from '@mui/icons-material/AccountCircle';
31 import MenuItem from '@mui/material/MenuItem';
32 import Menu from '@mui/material/Menu';
33
34 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
35 import { faBan } from '@fortawesome/free-solid-svg-icons';
36 import { faDotCircle } from '@fortawesome/free-solid-svg-icons';
37
38 import { logoutUser } from '../actions/authentication';
39 import { PushAction, ReplaceAction } from '../actions/navigationActions';
40
41 import { connect, Connect, IDispatcher } from '../flux/connect';
42 import { MenuAction, MenuClosedByUser } from '../actions/menuAction';
43
44 import MenuIcon from './icons/menuIcon';
45 import Logo from './logo';
46
47 const styles = (theme: Theme) => createStyles({
48   appBar: {
49     zIndex: theme.zIndex.drawer + 1,
50   },
51   grow: {
52     flexGrow: 1,
53   },
54   menuButton: {
55     marginLeft: -12,
56     marginRight: 20,
57   },
58   icon: {
59     marginLeft: 16,
60     marginRight: 8,
61     marginBottom: -2,
62   },
63   connected: {
64     color: "green"
65   },
66   notConnected: {
67     color: "red"
68   },
69   notificationInfo: {
70     marginLeft: 5
71   }
72 });
73
74 const mapDispatch = (dispatcher: IDispatcher) => {
75   return {
76     logout: () => {
77       dispatcher.dispatch(logoutUser());
78       dispatcher.dispatch(new ReplaceAction("/login"));
79     },
80     openSettings : () =>{
81       dispatcher.dispatch(new PushAction("/settings"));
82     },
83     toggleMainMenu: (value: boolean, value2: boolean) => {
84       dispatcher.dispatch(new MenuAction(value));
85       dispatcher.dispatch(new MenuClosedByUser(value2))
86     }
87   }
88 };
89
90 type TitleBarProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<undefined, typeof mapDispatch>
91
92 class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLElement | null }> {
93
94   constructor(props: TitleBarProps) {
95     super(props);
96     this.state = {
97       anchorEl: null
98     }
99
100   }
101   render(): JSX.Element {
102     const { classes, state, history, location } = this.props;
103     const open = !!this.state.anchorEl;
104     let toolbarElements: Array<JSX.Element>;
105     toolbarElements = [];
106
107     // create notificationInfo element
108     const notificationInfo = state.framework.applicationState.isWebsocketAvailable != undefined ?
109       (state.framework.applicationState.isWebsocketAvailable ?
110         <Typography aria-label="notifications-are-active" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.connected} icon={faDotCircle} />  |</Typography> : <Typography aria-label="notifications-are-inactive" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.notConnected} icon={faBan} /> |</Typography>)
111       : <Typography variant="body1" aria-label="notifications-are-not-available" className={classes.notificationInfo}>Notifications N/A |</Typography>;
112
113
114     // add notificationInfo element before help
115     if (state.framework.applicationRegistration) {
116       let isNotificationInfoAdded = false;
117       Object.keys(state.framework.applicationRegistration).map(key => {
118         const reg = state.framework.applicationRegistration[key];
119         if (reg && reg.statusBarElement) {
120           if (key === "help") {
121             isNotificationInfoAdded = true;
122             toolbarElements.push(notificationInfo);
123           }
124           toolbarElements.push(<reg.statusBarElement key={key} />);
125         }
126       });
127
128       // add notificationInfo in case help wasn't found
129       if (!isNotificationInfoAdded) {
130         toolbarElements.push(notificationInfo);
131       }
132     }
133
134     const stateIcon = state.framework.applicationState.icon;
135     const customIconHeight = 22; 
136     const icon = !stateIcon
137       ? null
138       : (typeof stateIcon === 'string'
139         ? <img className={classes.icon} height={customIconHeight} src={stateIcon} />
140         : <FontAwesomeIcon className={classes.icon} icon={stateIcon} />)
141     
142
143     return (
144       <AppBar enableColorOnDark position="absolute" className={classes.appBar}>
145         <Toolbar>
146           <IconButton
147             className={classes.menuButton}
148             color="inherit"
149             aria-label="Menu"
150             onClick={this.toggleMainMenu}
151             size="large">
152             <MenuIcon />
153           </IconButton>
154           <Logo />
155           <Typography variant="h6" color="inherit" >
156             {icon}
157             {state.framework.applicationState.title}
158           </Typography>
159           <div className={classes.grow}></div>
160           {
161             // render toolbar
162             toolbarElements.map((item) => {
163               return item
164             })
165           }
166
167           {state.framework.authenticationState.user
168             ? (<div>
169               <Button aria-label="current user menu button"
170                 aria-owns={open ? 'menu-appbar' : undefined}
171                 aria-haspopup="true"
172                 onClick={this.openMenu}
173                 color="inherit"
174               >
175                 <AccountCircle />
176                 {state.framework.authenticationState.user.user}
177               </Button>
178               <Menu
179                 id="menu-appbar"
180                 anchorEl={this.state.anchorEl}
181                 anchorOrigin={{
182                   vertical: 'top',
183                   horizontal: 'right',
184                 }}
185                 transformOrigin={{
186                   vertical: 'top',
187                   horizontal: 'right',
188                 }}
189                 open={open}
190                 onClose={this.closeMenu}
191               >
192                 {/* <MenuItem onClick={ this.closeMenu }>Profile</MenuItem> */}
193                 <MenuItem 
194                  aria-label="settings-button"
195                  onClick={ () =>{
196                     this.props.openSettings();
197                     this.closeMenu(); }}>Settings</MenuItem>
198                 <MenuItem
199                 aria-label="logout-button"
200                 onClick={() => {
201                   this.props.logout();
202                   this.closeMenu();
203                 }}>Logout</MenuItem>
204               </Menu>
205             </div>)
206             : (<Button onClick={() => { history.push('/login') }} color="inherit" disabled={location.pathname == "/login"}>Login</Button>)}
207         </Toolbar>
208       </AppBar>
209     );
210   };
211
212   private toggleMainMenu = (event: React.MouseEvent<HTMLElement>) => {
213     console.log(this.props);
214     if (this.props.state.framework.authenticationState.user && this.props.state.framework.authenticationState.user.isValid) {
215       const isMainMenuOpen = this.props.state.framework.applicationState.isMenuOpen
216       const isClosedByUser = this.props.state.framework.applicationState.isMenuClosedByUser
217       this.props.toggleMainMenu(!isMainMenuOpen, !isClosedByUser);
218     }
219   }
220
221   private openMenu = (event: React.MouseEvent<HTMLElement>) => {
222     this.setState({ anchorEl: event.currentTarget });
223   };
224
225   private closeMenu = () => {
226     this.setState({ anchorEl: null });
227   };
228 }
229
230 //todo: ggf. https://github.com/acdlite/recompose verwenden zur Vereinfachung
231
232 export const TitleBar = withStyles(styles)(withRouter(connect(undefined, mapDispatch)(TitleBarComponent)));
233 export default TitleBar;