Rift.IO OSM R1 Initial Submission

Signed-off-by: Jeremy Mordkoff <jeremy.mordkoff@riftio.com>
diff --git a/skyquake/framework/widgets/header/header.jsx b/skyquake/framework/widgets/header/header.jsx
new file mode 100644
index 0000000..21f4c10
--- /dev/null
+++ b/skyquake/framework/widgets/header/header.jsx
@@ -0,0 +1,152 @@
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+import React from 'react';
+import './header.scss';
+import Crouton from 'react-crouton';
+import HeaderStore from './headerStore.js';
+import ScreenLoader from '../screen-loader/screenLoader.jsx';
+export default class AppHeader extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {};
+        this.state.validateErrorEvent = 0;
+        this.state.validateErrorMsg = '';
+    }
+    componentDidMount() {
+        HeaderStore.listen(this.storeListener);
+    }
+    componentWillUnmount(){
+        HeaderStore.unlisten(this.storeListener);
+    }
+    closeError() {
+        LaunchpadFleetActions.validateReset()
+    }
+    storeListener = (state) => {
+        this.setState(state);
+    }
+    render() {
+        let html;
+        let navItems = this.props.nav.map(function(nav, i) {
+            if (nav.href || nav.onClick) {
+                return <li key={i}><a {...nav}>{nav.name}</a></li>
+            } else {
+                return <li key={i}><span className="current"> {nav.name} </span></li>
+            }
+        });
+        let errorMessage = <Crouton
+                id={Date.now()}
+                message={this.state.validateErrorMsg}
+                type={"error"}
+                hidden={!(this.state.validateErrorEvent && this.state.validateErrorMsg)}
+                onDismiss={HeaderStore.validateReset}
+            />
+
+        // html = (
+        //     <header className="header-app-component">
+        //     {errorMessage}
+        //     <ScreenLoader show={this.props.isLoading}/>
+        //     <div className="header-app-main">
+        //         <h1>{this.props.title}</h1>
+        //         <CommonLinks></CommonLinks>
+        //     </div>
+        //     <div className="header-app-nav">
+        //         <ul>
+        //             {navItems}
+        //         </ul>
+        //     </div>
+        //     </header>
+        // );
+
+        html = (
+            <header className="header-app-component">
+            {errorMessage}
+            <ScreenLoader show={this.props.isLoading}/>
+            <div className="header-app-nav">
+                <ul>
+                    {navItems}
+                </ul>
+            </div>
+            </header>
+        );
+
+        return html;
+    }
+}
+export class CommonLinks extends React.Component {
+    constructor(props) {
+        super(props);
+    }
+    openAbout() {
+        generateRefPage();
+        navigateTo('about')
+    }
+    openDebug() {
+        generateRefPage();
+        navigateTo('debug');
+    }
+    render() {
+        let links = [];
+        setContext();
+        links.push(<li key={'about'} onClick={this.openAbout}><a>About</a></li>);
+        links.push(<li  key={'debug'} onClick={this.openDebug}><a>Debug</a></li>);
+        let html;
+        html = (
+            <nav>
+                <ul>
+                    {links}
+                </ul>
+            </nav>
+        );
+        return html;
+    }
+}
+AppHeader.defaultProps = {
+    nav: [],
+    isLoading: false
+}
+function generateRefPage() {
+    let applicationContext = window.sessionStorage.getItem('applicationContext') || 'launchpad';
+    let hash = window.location.hash.split('/');
+    let pageTitle = 'Dashboard';
+    if (applicationContext === 'launchpad') {
+        hash = '#/launchpad/' + hash[2];
+    } else {
+        hash = "#/"
+    }
+    let refPage = {
+        'hash': hash,
+        'title': pageTitle
+    };
+    window.sessionStorage.setItem('refPage', JSON.stringify(refPage));
+    return refPage;
+}
+function navigateTo(loc) {
+    window.location.hash = '#/' + loc;
+}
+function setContext() {
+     let applicationContext;
+     let hashOne = window.location.hash.split('/')[1];
+    if(hashOne == "launchpad") {
+      applicationContext = "launchpad";
+    } else {
+      applicationContext = "missioncontrol";
+    }
+    if(hashOne != 'about' && hashOne != 'debug'){
+        window.sessionStorage.setItem('applicationContext', applicationContext);}
+}
diff --git a/skyquake/framework/widgets/header/header.scss b/skyquake/framework/widgets/header/header.scss
new file mode 100644
index 0000000..9238c22
--- /dev/null
+++ b/skyquake/framework/widgets/header/header.scss
@@ -0,0 +1,87 @@
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+header.header-app-component {
+    padding: 20px 0px;
+    display:flex;
+    flex-direction:column;
+    .header-app-main {
+        display:flex;
+        flex-direction:row;
+        justify-content:space-between;
+        align-items:center;
+    }
+    h1 {
+        background: url('../../style/img/header-logo.png') no-repeat;
+        background-size:contain;
+        height: 51px;
+        line-height: 51px;
+        margin-left: 20px;
+        padding-left: 100px;
+        left: 0;
+        text-transform: uppercase;
+        font-size: 1.625rem;
+        font-weight: 400;
+        position:relative;
+        flex: 1 0 auto;
+
+    }
+    ul {
+            display:flex;
+        }
+        li {
+            display:flex;
+             flex:1 1 auto;
+             border-right:1px solid #e5e5e5;
+             padding: 0 1rem;
+            &:last-child {
+                border:none;
+            }
+            a {
+                cursor:pointer;
+                // padding: 0.125rem;
+                // border-bottom:1px solid black;
+                text-decoration:underline;
+            }
+        }
+    .header-app-nav {
+        display:flex;
+        margin-left: 0.25rem;
+        a,span {
+            text-transform:uppercase;
+        }
+        a {
+            cursor: pointer;
+            margin-left: 0.5rem;
+            font-weight: normal;
+            color: black;
+        }
+
+        .spacer {
+
+        }
+        .current {
+            font-weight: bold;
+        }
+    }
+    nav {
+        display:flex;
+        flex:0 1 auto;
+        align-items:center;
+    }
+}
diff --git a/skyquake/framework/widgets/header/headerActions.js b/skyquake/framework/widgets/header/headerActions.js
new file mode 100644
index 0000000..e71e79f
--- /dev/null
+++ b/skyquake/framework/widgets/header/headerActions.js
@@ -0,0 +1,20 @@
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+import Alt from '../skyquake_container/skyquakeAltInstance';
+export default Alt.generateActions('showError', 'resetError');
diff --git a/skyquake/framework/widgets/header/headerStore.js b/skyquake/framework/widgets/header/headerStore.js
new file mode 100644
index 0000000..4ee86ff
--- /dev/null
+++ b/skyquake/framework/widgets/header/headerStore.js
@@ -0,0 +1,46 @@
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+import HeaderActions from './headerActions.js';
+import Alt from '../skyquake_container/skyquakeAltInstance';
+
+class HeaderStoreConstructor {
+    constructor() {
+        var self = this;
+        this.validateErrorEvent = 0;
+        this.validateErrorMsg = '';
+        this.bindActions(HeaderActions);
+        this.exportPublicMethods({
+            validateReset: self.validateReset
+        })
+    }
+    showError = (msg) => {
+        console.log('message received');
+        this.setState({
+            validateErrorEvent: true,
+            validateErrorMsg: msg
+        });
+    }
+    validateReset = () => {
+        this.setState({
+            validateErrorEvent: false
+        });
+    }
+}
+
+export default Alt.createStore(HeaderStoreConstructor)