RIFT-15726 - optimize download size -> lodash usage in UI
[osm/UI.git] / skyquake / framework / widgets / skyquake_container / skyquakeNav.jsx
1 /*
2  * 
3  *   Copyright 2016 RIFT.IO Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18
19 import React from 'react';
20 import { Link } from 'react-router';
21 import Utils from 'utils/utils.js';
22 import Crouton from 'react-crouton';
23 import 'style/common.scss';
24
25 //Temporary, until api server is on same port as webserver
26 import rw from 'utils/rw.js';
27
28 var API_SERVER = rw.getSearchParams(window.location).api_server;
29 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
30
31 //
32 // Internal classes/functions
33 //
34
35 class LogoutAppMenuItem extends React.Component {
36     handleLogout() {
37         Utils.clearAuthentication();
38     }
39     render() {
40         return (
41             <div className="app">
42                 <h2>
43                     <a onClick={this.handleLogout}>
44                         Logout
45                     </a>
46                 </h2>
47             </div>
48         );
49     }
50 }
51
52
53 //
54 // Exported classes and functions
55 //
56
57 //
58 /**
59  * Skyquake Nav Component. Provides navigation functionality between all plugins
60  */
61 export default class skyquakeNav extends React.Component {
62     constructor(props) {
63         super(props);
64         this.state = {};
65         this.state.validateErrorEvent = 0;
66         this.state.validateErrorMsg = '';
67     }
68     validateError = (msg) => {
69         this.setState({
70             validateErrorEvent: true,
71             validateErrorMsg: msg
72         });
73     }
74     validateReset = () => {
75         this.setState({
76             validateErrorEvent: false
77         });
78     }
79     returnCrouton = () => {
80         return <Crouton
81             id={Date.now()}
82             message={this.state.validateErrorMsg}
83             type={"error"}
84             hidden={!(this.state.validateErrorEvent && this.state.validateErrorMsg)}
85             onDismiss={this.validateReset}
86         />;
87     }
88     render() {
89         let html;
90         html = (
91                 <div>
92                 {this.returnCrouton()}
93             <nav className="skyquakeNav">
94                 {buildNav.call(this, this.props.nav, this.props.currentPlugin)}
95             </nav>
96
97             </div>
98         )
99         return html;
100     }
101 }
102 skyquakeNav.defaultProps = {
103     nav: {}
104 }
105 /**
106  * Returns a React Component
107  * @param  {object} link  Information about the nav link
108  * @param  {string} link.route Hash route that the SPA should resolve
109  * @param  {string} link.name Link name to be displayed
110  * @param  {number} index index of current array item
111  * @return {object} component A React LI Component
112  */
113 //This should be extended to also make use of internal/external links and determine if the link should refer to an outside plugin or itself.
114 export function buildNavListItem (k, link, index) {
115     let html = false;
116     if (link.type == 'external') {
117         this.hasSubNav[k] = true;
118         html = (
119             <li key={index}>
120                 {returnLinkItem(link)}
121             </li>
122         );
123     }
124     return html;
125 }
126
127 /**
128  * Builds a link to a React Router route or a new plugin route.
129  * @param  {object} link Routing information from nav object.
130  * @return {object}  component   returns a react component that links to a new route.
131  */
132 export function returnLinkItem(link) {
133     let ref;
134     let route = link.route;
135     if(link.isExternal) {
136         ref = (
137             <a href={route}>{link.label}</a>
138         )
139     } else {
140         if(link.path && link.path.replace(' ', '') != '') {
141             route = link.path;
142         }
143         if(link.query) {
144             let query = {};
145             query[link.query] = '';
146             route = {
147                 pathname: route,
148                 query: query
149             }
150         }
151         ref = (
152            <Link to={route}>
153                 {link.label}
154             </Link>
155         )
156     }
157     return ref;
158 }
159
160 /**
161  * Constructs nav for each plugin, along with available subnavs
162  * @param  {array} nav List returned from /nav endpoint.
163  * @return {array}     List of constructed nav element for each plugin
164  */
165 export function buildNav(nav, currentPlugin) {
166     let navList = [];
167     let navListHTML = [];
168     let secondaryNav = [];
169     let self = this;
170     self.hasSubNav = {};
171     let secondaryNavHTML = (
172         <div className="secondaryNav" key="secondaryNav">
173         {secondaryNav}
174             <LogoutAppMenuItem />
175         </div>
176     )
177     for (let k in nav) {
178         if (nav.hasOwnProperty(k)) {
179             self.hasSubNav[k] = false;
180             let header = null;
181             let navClass = "app";
182             let routes = nav[k].routes;
183             let navItem = {};
184             //Primary plugin title and link to dashboard.
185             let route;
186             let NavList;
187             if (API_SERVER) {
188                 route = routes[0].isExternal ? '/' + k + '/index.html?api_server=' + API_SERVER + '' + '&upload_server=' + UPLOAD_SERVER + '' : '';
189             } else {
190                 route = routes[0].isExternal ? '/' + k + '/' : '';
191             }
192             let dashboardLink = returnLinkItem({
193                 isExternal: routes[0].isExternal,
194                 pluginName: nav[k].pluginName,
195                 label: nav[k].label || k,
196                 route: route
197             });
198             if (nav[k].pluginName == currentPlugin) {
199                 navClass += " active";
200             }
201             NavList = nav[k].routes.map(buildNavListItem.bind(self, k));
202             navItem.priority = nav[k].priority;
203             navItem.order = nav[k].order;
204             navItem.html = (
205                 <div key={k} className={navClass}>
206                     <h2>{dashboardLink} {self.hasSubNav[k] ? <span className="oi" data-glyph="caret-bottom"></span> : ''}</h2>
207                     <ul className="menu">
208                         {
209                             NavList
210                         }
211                     </ul>
212                 </div>
213             );
214             navList.push(navItem)
215         }
216     }
217     //Sorts nav items by order and returns only the markup
218     navListHTML = navList.sort((a,b) => a.order - b.order).map(function(n) {
219         if((n.priority  < 2)){
220             return n.html;
221         } else {
222             secondaryNav.push(n.html);
223         }
224     });
225     navListHTML.push(secondaryNavHTML);
226     return navListHTML;
227 }