3 * Copyright 2016 RIFT.IO Inc
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
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';
25 import './skyquakeNav.scss';
26 import SelectOption from '../form_controls/selectOption.jsx';
27 import {FormSection} from '../form_controls/formControls.jsx';
28 import {isRBACValid, SkyquakeRBAC} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
30 //Temporary, until api server is on same port as webserver
31 import rw from 'utils/rw.js';
33 var API_SERVER = rw.getSearchParams(window.location).api_server;
34 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
37 // Internal classes/functions
40 class LogoutAppMenuItem extends React.Component {
42 Utils.clearAuthentication();
48 <a onClick={this.handleLogout}>
57 class SelectProject extends React.Component {
62 let value = JSON.parse(e.currentTarget.value);
63 console.log('selected project', value)
66 let props = this.props;
67 let currentValue = JSON.stringify(props.currentProject);
68 let projects = this.props.projects && this.props.projects.map((p,i) => {
74 let hasProjects = (this.props.projects && (this.props.projects.length > 0))
76 <div className="userSection app">
78 hasProjects ? 'Project:' : 'No Projects Assigned'
85 defaultValue={currentValue}
86 onChange={props.onSelectProject}
87 className="projectSelect" />
95 class UserNav extends React.Component {
100 Utils.clearAuthentication();
103 let value = JSON.parse(e.currentTarget.value)
104 console.log('selected project', value)
107 let props = this.props;
108 let userProfileLink = '';
109 this.props.nav['user_management'] && this.props.nav['user_management'].routes.map((r) => {
111 userProfileLink = returnLinkItem(r, props.currentUser)
115 <div className="app">
117 USER: {userProfileLink}
118 <span className="oi" data-glyph="caret-bottom"></span>
120 <ul className="menu">
122 <a onClick={this.handleLogout}>
132 UserNav.defaultProps = {
139 // Exported classes and functions
144 * Skyquake Nav Component. Provides navigation functionality between all plugins
146 export default class skyquakeNav extends React.Component {
150 this.state.validateErrorEvent = 0;
151 this.state.validateErrorMsg = '';
153 componentDidMount() {
154 this.props.store.openProjectSocket();
155 this.props.store.getUserProfile();
157 validateError = (msg) => {
159 validateErrorEvent: true,
160 validateErrorMsg: msg
163 validateReset = () => {
165 validateErrorEvent: false
168 returnCrouton = () => {
171 message={this.state.validateErrorMsg}
173 hidden={!(this.state.validateErrorEvent && this.state.validateErrorMsg)}
174 onDismiss={this.validateReset}
181 {this.returnCrouton()}
182 <nav className="skyquakeNav">
183 {buildNav.call(this, this.props.nav, this.props.currentPlugin, this.props)}
191 skyquakeNav.defaultProps = {
194 skyquakeNav.contextTypes = {
195 userProfile: React.PropTypes.object
198 * Returns a React Component
199 * @param {object} link Information about the nav link
200 * @param {string} link.route Hash route that the SPA should resolve
201 * @param {string} link.name Link name to be displayed
202 * @param {number} index index of current array item
203 * @return {object} component A React LI Component
205 //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.
206 export function buildNavListItem (k, link, index) {
208 if (link.type == 'external') {
209 this.hasSubNav[k] = true;
212 {returnLinkItem(link)}
220 * Builds a link to a React Router route or a new plugin route.
221 * @param {object} link Routing information from nav object.
222 * @return {object} component returns a react component that links to a new route.
224 export function returnLinkItem(link, label) {
226 let route = link.route;
227 if(link.isExternal) {
229 <a href={route}>{label || link.label}</a>
232 if(link.path && link.path.replace(' ', '') != '') {
237 query[link.query] = '';
245 {label || link.label}
256 * Constructs nav for each plugin, along with available subnavs
257 * @param {array} nav List returned from /nav endpoint.
258 * @return {array} List of constructed nav element for each plugin
260 export function buildNav(nav, currentPlugin, props) {
262 let navListHTML = [];
263 let secondaryNav = [];
266 const User = this.context.userProfile;
268 let secondaryNavHTML = (
269 <div className="secondaryNav" key="secondaryNav">
271 <div className="app admin">
274 ADMIN <span className="oi" data-glyph="caret-bottom"></span>
277 <ul className="menu">
284 onSelectProject={props.store.selectActiveProject}
285 projects={props.projects}
286 currentProject={props.currentProject} />
288 currentUser={props.currentUser}
293 if (nav.hasOwnProperty(k)) {
294 self.hasSubNav[k] = false;
296 let navClass = "app";
297 let routes = nav[k].routes;
299 //Primary plugin title and link to dashboard.
303 route = routes[0].isExternal ? '/' + k + '/index.html?api_server=' + API_SERVER + '' + '&upload_server=' + UPLOAD_SERVER + '' : '';
305 route = routes[0].isExternal ? '/' + k + '/' : '';
307 let dashboardLink = returnLinkItem({
308 isExternal: routes[0].isExternal,
309 pluginName: nav[k].pluginName,
310 label: nav[k].label || k,
313 let shouldAllow = nav[k].allow || ['*'];
314 if (nav[k].pluginName == currentPlugin) {
315 navClass += " active";
317 NavList = nav[k].routes.map(buildNavListItem.bind(self, k));
318 navItem.priority = nav[k].priority;
319 navItem.order = nav[k].order;
320 if(nav[k].admin_link) {
322 if (isRBACValid(User, shouldAllow) ){
324 <li key={nav[k].name}>
330 if (isRBACValid(User, shouldAllow) ){
332 <div key={k} className={navClass}>
333 <h2>{dashboardLink} {self.hasSubNav[k] ? <span className="oi" data-glyph="caret-bottom"></span> : ''}</h2>
334 <ul className="menu">
342 navList.push(navItem)
347 //Sorts nav items by order and returns only the markup
348 navListHTML = navList.sort((a,b) => a.order - b.order).map(function(n) {
349 if((n.priority < 2)){
352 secondaryNav.push(n.html);
355 navListHTML.push(secondaryNavHTML);