Rift.IO OSM R1 Initial Submission
[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 var rw = require('utils/rw.js');
27 var API_SERVER = rw.getSearchParams(window.location).api_server;
28 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
29
30 //
31 // Internal classes/functions
32 //
33
34 class LogoutAppMenuItem extends React.Component {
35     handleLogout() {
36         Utils.clearAuthentication();
37     }
38     render() {
39         return (
40             <div className="app">
41                 <h2>
42                     <a onClick={this.handleLogout}>
43                         Logout
44                     </a>
45                 </h2>
46             </div>
47         );
48     }
49 }
50
51
52 //
53 // Exported classes and functions
54 //
55
56 //
57 /**
58  * Skyquake Nav Component. Provides navigation functionality between all plugins
59  */
60 export default class skyquakeNav extends React.Component {
61     constructor(props) {
62         super(props);
63         this.state = {};
64         this.state.validateErrorEvent = 0;
65         this.state.validateErrorMsg = '';
66     }
67     validateError = (msg) => {
68         this.setState({
69             validateErrorEvent: true,
70             validateErrorMsg: msg
71         });
72     }
73     validateReset = () => {
74         this.setState({
75             validateErrorEvent: false
76         });
77     }
78     returnCrouton = () => {
79         return <Crouton
80             id={Date.now()}
81             message={this.state.validateErrorMsg}
82             type={"error"}
83             hidden={!(this.state.validateErrorEvent && this.state.validateErrorMsg)}
84             onDismiss={this.validateReset}
85         />;
86     }
87     render() {
88         let html;
89         html = (
90                 <div>
91                 {this.returnCrouton()}
92             <nav className="skyquakeNav">
93                 {buildNav.call(this, this.props.nav, this.props.currentPlugin)}
94             </nav>
95
96             </div>
97         )
98         return html;
99     }
100 }
101 skyquakeNav.defaultProps = {
102     nav: {}
103 }
104 /**
105  * Returns a React Component
106  * @param  {object} link  Information about the nav link
107  * @param  {string} link.route Hash route that the SPA should resolve
108  * @param  {string} link.name Link name to be displayed
109  * @param  {number} index index of current array item
110  * @return {object} component A React LI Component
111  */
112 //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.
113 export function buildNavListItem (k, link, index) {
114     let html = false;
115     if (link.type == 'external') {
116         this.hasSubNav[k] = true;
117         html = (
118             <li key={index}>
119                 {returnLinkItem(link)}
120             </li>
121         );
122     }
123     return html;
124 }
125
126 /**
127  * Builds a link to a React Router route or a new plugin route.
128  * @param  {object} link Routing information from nav object.
129  * @return {object}  component   returns a react component that links to a new route.
130  */
131 export function returnLinkItem(link) {
132     let ref;
133     let route = link.route;
134     if(link.isExternal) {
135         ref = (
136             <a href={route}>{link.label}</a>
137         )
138     } else {
139         if(link.path && link.path.replace(' ', '') != '') {
140             route = link.path;
141         }
142         if(link.query) {
143             let query = {};
144             query[link.query] = '';
145             route = {
146                 pathname: route,
147                 query: query
148             }
149         }
150         ref = (
151            <Link to={route}>
152                 {link.label}
153             </Link>
154         )
155     }
156     return ref;
157 }
158
159 /**
160  * Constructs nav for each plugin, along with available subnavs
161  * @param  {array} nav List returned from /nav endpoint.
162  * @return {array}     List of constructed nav element for each plugin
163  */
164 export function buildNav(nav, currentPlugin) {
165     let navList = [];
166     let navListHTML = [];
167     let secondaryNav = [];
168     let self = this;
169     self.hasSubNav = {};
170     let secondaryNavHTML = (
171         <div className="secondaryNav" key="secondaryNav">
172         {secondaryNav}
173             <LogoutAppMenuItem />
174         </div>
175     )
176     for (let k in nav) {
177         if (nav.hasOwnProperty(k)) {
178             self.hasSubNav[k] = false;
179             let header = null;
180             let navClass = "app";
181             let routes = nav[k].routes;
182             let navItem = {};
183             //Primary plugin title and link to dashboard.
184             let route;
185             let NavList;
186             if (API_SERVER) {
187                 route = routes[0].isExternal ? '/' + k + '/index.html?api_server=' + API_SERVER + '' + '&upload_server=' + UPLOAD_SERVER + '' : '';
188             } else {
189                 route = routes[0].isExternal ? '/' + k + '/' : '';
190             }
191             let dashboardLink = returnLinkItem({
192                 isExternal: routes[0].isExternal,
193                 pluginName: nav[k].pluginName,
194                 label: nav[k].label || k,
195                 route: route
196             });
197             if (nav[k].pluginName == currentPlugin) {
198                 navClass += " active";
199             }
200             NavList = nav[k].routes.map(buildNavListItem.bind(self, k));
201             navItem.priority = nav[k].priority;
202             navItem.order = nav[k].order;
203             navItem.html = (
204                 <div key={k} className={navClass}>
205                     <h2>{dashboardLink} {self.hasSubNav[k] ? <span className="oi" data-glyph="caret-bottom"></span> : ''}</h2>
206                     <ul className="menu">
207                         {
208                             NavList
209                         }
210                     </ul>
211                 </div>
212             );
213             navList.push(navItem)
214         }
215     }
216     //Sorts nav items by order and returns only the markup
217     navListHTML = navList.sort((a,b) => a.order - b.order).map(function(n) {
218         if((n.priority  < 2)){
219             return n.html;
220         } else {
221             secondaryNav.push(n.html);
222         }
223     });
224     navListHTML.push(secondaryNavHTML);
225     return navListHTML;
226 }