195706d2824a51f48d55024986f82a40b0b0607d
[ccsdk/features.git] / sdnr / wt / odlux / framework / src / components / navigationMenu.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 * as React from 'react';
19 import { Theme } from '@mui/material/styles';
20
21 import { WithStyles } from '@mui/styles';
22 import withStyles from '@mui/styles/withStyles';
23 import createStyles from '@mui/styles/createStyles';
24
25 import { faHome, faAddressBook } from '@fortawesome/free-solid-svg-icons';
26
27 import Drawer from '@mui/material/Drawer';
28 import List from '@mui/material/List';
29
30 import Divider from '@mui/material/Divider';
31
32 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
33 import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
34
35 import ListItemLink from '../components/material-ui/listItemLink';
36
37 import connect, { Connect } from '../flux/connect';
38 import { MenuAction } from '../actions/menuAction';
39 import * as classNames from 'classnames';
40 import { transportPCEUrl } from '../app';
41
42
43 const drawerWidth = 240;
44
45 const extraLinks = (window as any)._odluxExtraLinks as [string, string][];
46
47 const styles = (theme: Theme) => createStyles({
48   drawerPaper: {
49     position: 'relative',
50     width: drawerWidth,
51   },
52   toolbar: theme.mixins.toolbar as any,
53
54   drawerOpen: {
55     width: drawerWidth,
56     transition: theme.transitions.create('width', {
57       easing: theme.transitions.easing.sharp,
58       duration: theme.transitions.duration.enteringScreen,
59     }),
60   },
61   drawerClose: {
62     transition: theme.transitions.create('width', {
63       easing: theme.transitions.easing.sharp,
64       duration: theme.transitions.duration.leavingScreen,
65     }),
66     overflowX: 'hidden',
67     width: theme.spacing(7),
68     [theme.breakpoints.up('sm')]: {
69       width: theme.spacing(9),
70     },
71   },
72   drawer: {
73
74   },
75   menu: {
76     flex: "1 0 0%",
77   },
78   optLinks: {
79     borderTop: "2px solid #cfcfcf",
80     display: "flex",
81     flexDirection: "row",
82     flexWrap: "wrap",
83     justifyContent: "space-around"
84   },
85   link: {
86     margin: theme.spacing(1)+1,
87     fontSize: theme.typography.fontSize-2,
88   },
89 });
90
91 const tabletWidthBreakpoint = 768;
92
93 export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, dispatch }: WithStyles<typeof styles> & Connect & Connect) => {
94   const { user } = state.framework.authenticationState;
95   const isOpen = state.framework.applicationState.isMenuOpen;
96   const closedByUser = state.framework.applicationState.isMenuClosedByUser;
97   const transportUrl = state.framework.applicationState.transportpceUrl;
98
99   const [responsive, setResponsive] = React.useState(false);
100
101   //collapse menu on mount if necessary
102   React.useEffect(()=>{
103
104     if(isOpen && window.innerWidth <= tabletWidthBreakpoint){
105
106       setResponsive(true);
107       dispatch(new MenuAction(false));
108     }
109
110   },[]);
111
112   React.useEffect(() => {
113
114     function handleResize() {
115       if (user && user.isValid) {
116         if (window.innerWidth < tabletWidthBreakpoint && !responsive) {
117           setResponsive(true);
118           if (!closedByUser) {
119             dispatch(new MenuAction(false));
120           }
121
122         } else if (window.innerWidth > tabletWidthBreakpoint && responsive) {
123           setResponsive(false);
124           if (!closedByUser) {
125             dispatch(new MenuAction(true));
126           }
127
128         }
129       }
130     }
131     window.addEventListener("resize", handleResize);
132
133
134     return () => {
135       window.removeEventListener("resize", handleResize);
136     }
137   })
138
139   React.useEffect(()=>{
140     // trigger a resize if menu changed in case elements have to re-arrange
141     window.dispatchEvent(new Event('menu-resized'));
142   }, [isOpen])
143
144   let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
145     const reg = state.framework.applicationRegistraion[key];
146     const icon = !reg.icon ? null :( typeof reg.icon === 'string' ? <img height={22} src={reg.icon} /> : <FontAwesomeIcon icon={reg.icon} /> )
147     return reg && (
148       <ListItemLink
149         key={reg.name}
150         to={reg.path || `/${reg.name}`}
151         primary={reg.menuEntry || reg.name}
152         secondary={reg.subMenuEntry}
153         icon={icon} />
154     ) || null;
155   }) || null;
156
157   if(transportUrl.length>0){
158
159     const transportPCELink = <ListItemLink
160       key={"transportPCE"}
161       to={transportUrl}
162       primary={"TransportPCE"}
163       icon={<FontAwesomeIcon icon={faProjectDiagram} />}
164       external />;
165
166     const linkFound = menuItems.find(obj => obj.key === "linkCalculation");
167     
168     if (linkFound) {
169       const index = menuItems.indexOf(linkFound);
170       menuItems.splice(index + 1, 0, transportPCELink);
171     } else {
172       menuItems.push(transportPCELink);
173     }
174   }
175   
176
177   return (
178     <Drawer
179       variant="permanent"
180       className={
181         classNames(classes.drawer, {
182           [classes.drawerOpen]: isOpen,
183           [classes.drawerClose]: !isOpen
184         })
185       }
186       classes={{
187         paper: classes.drawerPaper,
188       }}
189     >
190       {user && user.isValid && <>
191         <div className={classes.toolbar} />
192         { /* https://fiffty.github.io/react-treeview-mui/ */}
193         <List className={classes.menu} component="nav">
194           <ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} />
195           <Divider />
196           {
197           menuItems
198           }
199           <Divider />
200           <ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} />
201           {(false && process.env.NODE_ENV === "development")
202             ? <>
203               <Divider />
204               <ListItemLink to="/test" primary="Test" icon={<FontAwesomeIcon icon={faHome} />} />
205             </>
206             : null
207           }
208         </List>
209         {isOpen && extraLinks && <div className={classes.optLinks}>
210           {extraLinks.map(linkInfo => (<a className={classes.link} href={linkInfo[1]}>{linkInfo[0]}</a>))}
211         </div> || null}
212       </> || null
213       }
214     </Drawer>)
215 }));
216
217 export default NavigationMenu;