Added logout

Change-Id: If09690e089976244ded58a27b1f35a3a850ae2d1
diff --git a/conf/app/interfaces.ts b/conf/app/interfaces.ts
index 1080481..39f085d 100644
--- a/conf/app/interfaces.ts
+++ b/conf/app/interfaces.ts
@@ -1,8 +1,10 @@
 import {IXosNavigationRoute} from '../../src/app/core/services/navigation';
 export interface IStyleConfig {
   projectName: string;
+  payoff: string;
   favicon: string;
   background: string;
+  logo: string;
   routes: IXosNavigationRoute[];
 }
 
diff --git a/conf/app/style.config.cord.ts b/conf/app/style.config.cord.ts
index 68c568f..c43cac8 100644
--- a/conf/app/style.config.cord.ts
+++ b/conf/app/style.config.cord.ts
@@ -3,6 +3,8 @@
     projectName: 'CORD',
     favicon: 'cord-favicon.png',
     background: 'cord-bg.jpg',
+    payoff: 'Your VNF orchestrator',
+    logo: 'cord-logo.png',
     routes: [
         {
             label: 'Slices',
diff --git a/conf/app/style.config.opencloud.ts b/conf/app/style.config.opencloud.ts
index 2585dd2..c001344 100644
--- a/conf/app/style.config.opencloud.ts
+++ b/conf/app/style.config.opencloud.ts
@@ -3,6 +3,8 @@
     projectName: 'OpenCloud',
     favicon: 'opencloud-favicon.png',
     background: 'opencloud-bg.jpg',
+    payoff: 'Your OS resource manager',
+    logo: 'opencloud-logo.png',
     routes: [
         {
             label: 'Slices',
diff --git a/package.json b/package.json
index fc73480..1ce1f7c 100644
--- a/package.json
+++ b/package.json
@@ -1,4 +1,5 @@
 {
+  "version": "1.0.0",
   "dependencies": {
     "angular": "^1.5.0",
     "angular-animate": "^1.6.0",
diff --git a/src/app/config/interfaces.ts b/src/app/config/interfaces.ts
index f1e27ad..ddf3126 100644
--- a/src/app/config/interfaces.ts
+++ b/src/app/config/interfaces.ts
@@ -1,8 +1,10 @@
 import {IXosNavigationRoute} from '../core/services/navigation';
 export interface IStyleConfig {
   projectName: string;
+  payoff: string;
   favicon: string;
   background: string;
+  logo: string;
   routes: IXosNavigationRoute[];
 }
 
diff --git a/src/app/config/style.config.ts b/src/app/config/style.config.ts
index 2585dd2..c43cac8 100644
--- a/src/app/config/style.config.ts
+++ b/src/app/config/style.config.ts
@@ -1,12 +1,22 @@
 import {IStyleConfig} from './interfaces';
 export const StyleConfig: IStyleConfig = {
-    projectName: 'OpenCloud',
-    favicon: 'opencloud-favicon.png',
-    background: 'opencloud-bg.jpg',
+    projectName: 'CORD',
+    favicon: 'cord-favicon.png',
+    background: 'cord-bg.jpg',
+    payoff: 'Your VNF orchestrator',
+    logo: 'cord-logo.png',
     routes: [
         {
             label: 'Slices',
             state: 'xos.core.slices'
+        },
+        {
+            label: 'Instances',
+            state: 'xos.core.instances'
+        },
+        {
+            label: 'Nodes',
+            state: 'xos.core.nodes'
         }
     ]
 };
diff --git a/src/app/core/header/header.html b/src/app/core/header/header.html
index db25904..0a90822 100644
--- a/src/app/core/header/header.html
+++ b/src/app/core/header/header.html
@@ -27,8 +27,8 @@
         <minimaliza-menu></minimaliza-menu>
       </div>
       <a class="navbar-brand" href="#/">
-        <em class="brand-title">{{vm.title}}</em>
-        <span>v.1.2</span>
+        <img class="img-responsive" ng-src="{{vm.getLogo()}}" alt="">
+        <span>v.{{vm.version}}</span>
       </a>
     </div>
     <div id="navbar" class="navbar-collapse collapse">
@@ -45,7 +45,7 @@
         <!--</li>-->
         <li class=" profil-link">
           <a ui-sref="commonviews.login">
-            <span class="profile-address">luna@company.io</span>
+            <span class="profile-address">{{vm.userEmail}}</span>
             <img src="../../images/profile.jpg" class="img-circle" alt="">
           </a>
         </li>
diff --git a/src/app/core/header/header.scss b/src/app/core/header/header.scss
index 8a1664f..a1be115 100644
--- a/src/app/core/header/header.scss
+++ b/src/app/core/header/header.scss
@@ -1,3 +1,21 @@
 #toast-container [toast]:not(:first-child) {
   margin-top: 10px !important;
+}
+
+xos-header {
+  .navbar-brand {
+    padding: 10px 30px !important;
+    position: relative;
+    background: #24262d !important;
+    span {
+      position: absolute;
+      right: 30px;
+      bottom: 0;
+      color: #24262d;
+    }
+  }
+
+  .navbar-default {
+    background: #2a2d35 !important;
+  }
 }
\ No newline at end of file
diff --git a/src/app/core/header/header.spec.ts b/src/app/core/header/header.spec.ts
index c8dffe7..c115a4e 100644
--- a/src/app/core/header/header.spec.ts
+++ b/src/app/core/header/header.spec.ts
@@ -5,7 +5,6 @@
 import * as angular from 'angular';
 import 'angular-mocks';
 import {xosHeader, INotification} from './header';
-import {StyleConfig} from '../../config/style.config';
 import {Subject} from 'rxjs';
 
 let element, scope: angular.IRootScopeService, compile: ng.ICompileService, isolatedScope;
@@ -19,14 +18,16 @@
   };
 };
 
-interface ImockToastr {
-  info(msg: string, title: string): void;
-}
-
-const MockToastr: ImockToastr = {
+const MockToastr = {
   info: jasmine.createSpy('info')
 };
 
+const MockAuth = {
+  getUser: () => {
+    return {email: 'test@xos.us'};
+  }
+};
+
 const MockToastrConfig = {};
 
 const infoNotification = {
@@ -36,7 +37,7 @@
     pk: 1,
     object: {
       name: 'TestName',
-      backend_status: '1 - Test Status'
+      backend_status: '0 - In Progress'
     }
   }
 };
@@ -48,7 +49,8 @@
       .component('xosHeader', xosHeader)
       .service('SynchronizerStore', MockStore)
       .value('toastr', MockToastr)
-      .value('toastrConfig', MockToastrConfig);
+      .value('toastrConfig', MockToastrConfig)
+      .value('AuthService', MockAuth);
     angular.mock.module('xosHeader');
   });
 
@@ -63,13 +65,14 @@
     isolatedScope.notifications = [];
   }));
 
-  it('should render the appropriate title', () => {
-    const header = $('a.navbar-brand .brand-title', element).text();
-    expect(header.trim()).toEqual(StyleConfig.projectName);
+  it('should render the appropriate logo', () => {
+    const header = $('a.navbar-brand img', element).attr('src');
+    // webpack convert img to base64, how to test?
+    expect(header.trim()).not.toBeNull();
   });
 
-  it('should set the appropriate favicon', () => {
-    console.log($('#favicon').attr('href'));
+  it('should print user email', () => {
+    expect($('.profile-address', element).text()).toBe('test@xos.us');
   });
 
   it('should configure toastr', () => {
diff --git a/src/app/core/header/header.ts b/src/app/core/header/header.ts
index 6e057bc..efaa385 100644
--- a/src/app/core/header/header.ts
+++ b/src/app/core/header/header.ts
@@ -2,24 +2,27 @@
 import {StyleConfig} from '../../config/style.config';
 import {IWSEvent} from '../../datasources/websocket/global';
 import {IStoreService} from '../../datasources/stores/synchronizer.store';
+import {IXosAuthService} from '../../datasources/rest/auth.rest';
 
 export interface INotification extends IWSEvent {
   viewed?: boolean;
 }
 
 class HeaderController {
-  static $inject = ['$scope', 'SynchronizerStore', 'toastr', 'toastrConfig'];
-  public title: string;
+  static $inject = ['$scope', 'AuthService', 'SynchronizerStore', 'toastr', 'toastrConfig'];
   public notifications: INotification[] = [];
   public newNotifications: INotification[] = [];
+  public version: string;
+  public userEmail: string;
 
   constructor(
     private $scope: angular.IScope,
+    private authService: IXosAuthService,
     private syncStore: IStoreService,
     private toastr: ng.toastr.IToastrService,
     private toastrConfig: ng.toastr.IToastrConfig
   ) {
-
+    this.version = require('../../../../package.json').version;
     angular.extend(this.toastrConfig, {
       newestOnTop: false,
       positionClass: 'toast-top-right',
@@ -32,7 +35,7 @@
       // tapToDismiss: false
     });
 
-    this.title = StyleConfig.projectName;
+    this.userEmail = this.authService.getUser().email;
 
     this.syncStore.query()
       .subscribe(
@@ -40,11 +43,11 @@
           $scope.$evalAsync(() => {
             let toastrMsg: string;
             let toastrLevel: string;
-            if (event.msg.object.backend_status.indexOf('1') > -1) {
+            if (event.msg.object.backend_status.indexOf('0') > -1) {
               toastrMsg = 'Synchronization started for:';
               toastrLevel = 'info';
             }
-            else if (event.msg.object.backend_status.indexOf('0') > -1) {
+            else if (event.msg.object.backend_status.indexOf('1') > -1) {
               toastrMsg = 'Synchronization succedeed for:';
               toastrLevel = 'success';
             }
@@ -56,24 +59,28 @@
             if (toastrLevel && toastrMsg) {
               this.toastr[toastrLevel](`${toastrMsg} ${event.msg.object.name}`, event.model);
             }
-            this.notifications.unshift(event);
-            this.newNotifications = this.getNewNotifications(this.notifications);
+            // this.notifications.unshift(event);
+            // this.newNotifications = this.getNewNotifications(this.notifications);
           });
         }
       );
   }
 
-  // TODO display a list of notification in the template
-  public viewNotification = (notification: INotification) => {
-    notification.viewed = true;
-    this.newNotifications = this.getNewNotifications(this.notifications);
-  };
+  public getLogo(): string {
+    return require(`../../images/brand/${StyleConfig.logo}`);
+  }
 
-  private getNewNotifications = (notifications: INotification[]) => {
-    return this.notifications.filter((n: INotification) => {
-      return !n.viewed;
-    });
-  };
+  // TODO display a list of notification in the template (if it make sense)
+  // public viewNotification = (notification: INotification) => {
+  //   notification.viewed = true;
+  //   this.newNotifications = this.getNewNotifications(this.notifications);
+  // };
+  //
+  // private getNewNotifications = (notifications: INotification[]) => {
+  //   return this.notifications.filter((n: INotification) => {
+  //     return !n.viewed;
+  //   });
+  // };
 }
 
 export const xosHeader: angular.IComponentOptions = {
diff --git a/src/app/core/login/login.html b/src/app/core/login/login.html
index 6f23959..4fa78dc 100644
--- a/src/app/core/login/login.html
+++ b/src/app/core/login/login.html
@@ -25,12 +25,12 @@
           <div class="form-group">
             <label class="control-label" for="username">Username</label>
             <input type="text" ng-model="username" placeholder="example@gmail.com" title="Please enter you username" required="" value="" name="username" id="username" class="form-control">
-            <span class="help-block small">Your unique username to app</span>
+            <!--<span class="help-block small">Your unique username to app</span>-->
           </div>
           <div class="form-group">
             <label class="control-label" for="password">Password</label>
             <input type="password" ng-model="password" title="Please enter your password" placeholder="******" required="" value="" name="password" id="password" class="form-control">
-            <span class="help-block small">Your strong password</span>
+            <!--<span class="help-block small">Your strong password</span>-->
           </div>
           <div>
             <button ng-click="vm.login(username, password)" class="btn btn-accent">Login</button>
diff --git a/src/app/core/login/login.scss b/src/app/core/login/login.scss
index 88a907a..8fe8a57 100644
--- a/src/app/core/login/login.scss
+++ b/src/app/core/login/login.scss
@@ -2,6 +2,8 @@
   .content {
     background-repeat: no-repeat;
     background-size: cover;
+    background-position: center;
+    min-height: 100%;
   }
 
   .container-center {
diff --git a/src/app/core/login/login.ts b/src/app/core/login/login.ts
index 11642f1..334ad08 100644
--- a/src/app/core/login/login.ts
+++ b/src/app/core/login/login.ts
@@ -19,7 +19,6 @@
   }
 
   public login(username: string, password: string) {
-    console.log(username, password);
     this.authService.login({
       username: username,
       password: password
diff --git a/src/app/core/nav/nav.html b/src/app/core/nav/nav.html
index fe96460..37d2f76 100644
--- a/src/app/core/nav/nav.html
+++ b/src/app/core/nav/nav.html
@@ -22,11 +22,26 @@
         </ul>
       </li>
       <li class="nav-info">
-        <i class="pe pe-7s-shield text-accent"></i>
-
-        <div class="m-t-xs">
-          <span class="c-white">{{vm.appName}}</span>
-          monitoring and administration for networks applications.
+        <div class="row">
+          <div class="col-sm-4">
+            <i class="pe pe-7s-shield text-accent"></i>
+          </div>
+          <div class="col-sm-8">
+            <h4 class="c-white">{{vm.appName}}</h4>
+          </div>
+        </div>
+        <div class="row">
+          <div class="col-xs-12">
+            <span class="c-white">{{vm.payoff}}</span>
+          </div>
+        </div>
+        <div class="row">
+          <div class="col-sm-4">
+            <i class="pe pe-7s-lock text-accent"></i>
+          </div>
+          <div class="col-sm-8">
+            <a ng-click="vm.logout()" class="btn btn-accent btn-block btn-logout">Logout</a>
+          </div>
         </div>
       </li>
     </ul>
diff --git a/src/app/core/nav/nav.scss b/src/app/core/nav/nav.scss
index e69de29..7646cd9 100644
--- a/src/app/core/nav/nav.scss
+++ b/src/app/core/nav/nav.scss
@@ -0,0 +1,7 @@
+xos-nav {
+  .nav-info {
+    .row + .row:last-child {
+      margin-top: 20px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/app/core/nav/nav.spec.ts b/src/app/core/nav/nav.spec.ts
index 6a70f4c..3c18e4d 100644
--- a/src/app/core/nav/nav.spec.ts
+++ b/src/app/core/nav/nav.spec.ts
@@ -18,12 +18,17 @@
   this.query = () => baseRoutes;
 };
 
+const AuthMock = {
+  logout: jasmine.createSpy('logout')
+};
+
 describe('Nav component', () => {
   beforeEach(() => {
     angular
       .module('xosNav', ['app/core/nav/nav.html', 'ui.router'])
       .component('xosNav', xosNav)
-      .service('NavigationService', NavigationService);
+      .service('NavigationService', NavigationService)
+      .value('AuthService', AuthMock);
     angular.mock.module('xosNav');
   });
 
@@ -54,4 +59,13 @@
     const childRouteContainer = $('.nav-second li', element);
     expect(childRouteContainer.length).toBe(1);
   });
+
+  it('should call the logout method', () => {
+    // NOTE upgrade to test the ng-click binding
+    // const btn = $(element).find('.nav-info .btn-block');
+    // btn.click();
+    // scope.$digest();
+    isolatedScope.vm.logout();
+    expect(AuthMock.logout).toHaveBeenCalled();
+  });
 });
diff --git a/src/app/core/nav/nav.ts b/src/app/core/nav/nav.ts
index edaeb24..43f62b3 100644
--- a/src/app/core/nav/nav.ts
+++ b/src/app/core/nav/nav.ts
@@ -1,17 +1,20 @@
 import './nav.scss';
 import {IXosNavigationService, IXosNavigationRoute} from '../services/navigation';
 import {StyleConfig} from '../../config/style.config';
+import {IXosAuthService} from '../../datasources/rest/auth.rest';
 
 class NavCtrl {
-  static $inject = ['$scope', '$state', 'NavigationService'];
+  static $inject = ['$scope', '$state', 'NavigationService', 'AuthService'];
   public routes: IXosNavigationRoute[];
   public navSelected: string;
   public appName: string;
+  public payoff: string;
 
   constructor(
     private $scope: ng.IScope,
     private $state: angular.ui.IStateService,
-    private navigationService: IXosNavigationService
+    private navigationService: IXosNavigationService,
+    private authService: IXosAuthService
   ) {
     // NOTE we'll need to have:
     // - Base routes (defined from configuration based on BRAND)
@@ -22,6 +25,7 @@
       this.routes = routes;
     });
     this.appName = StyleConfig.projectName;
+    this.payoff = StyleConfig.payoff;
   }
 
   activateRoute(route: IXosNavigationRoute) {
@@ -52,7 +56,10 @@
     else {
       return true;
     }
+  }
 
+  logout() {
+    this.authService.logout();
   }
 }
 
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index 9d0c191..f9b76f0 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -74,7 +74,7 @@
         prop: f.name
       };
 
-      if (f.name === 'id') {
+      if (f.name === 'id' || f.name === 'name') {
         // NOTE can we find a better method to generalize?
         col.link = item => `#/core${baseUrl.replace(':id?', item.id)}`;
       }
@@ -93,6 +93,7 @@
           }
         };
       }
+
       return col;
     })
       .filter(v => angular.isDefined(v));
diff --git a/src/app/core/services/navigation.ts b/src/app/core/services/navigation.ts
index c840878..d184fc2 100644
--- a/src/app/core/services/navigation.ts
+++ b/src/app/core/services/navigation.ts
@@ -23,16 +23,20 @@
   constructor() {
     const defaultRoutes = [
       {
+        label: 'Home',
+        state: 'xos.dashboard'
+      },
+      {
         label: 'Core',
         state: 'xos.core'
       },
-      {
-        label: 'Home',
-        state: 'xos.dashboard'
-      }
     ];
     // adding configuration defined routes
-    this.routes = StyleConfig.routes.concat(defaultRoutes).reverse();
+    // this.routes = StyleConfig.routes.concat(defaultRoutes).reverse();
+    this.routes = defaultRoutes;
+    StyleConfig.routes.forEach(r => {
+      this.add(r);
+    });
   }
 
   query() {
diff --git a/src/app/datasources/rest/auth.rest.spec.ts b/src/app/datasources/rest/auth.rest.spec.ts
index 85aefb4..16c0f8d 100644
--- a/src/app/datasources/rest/auth.rest.spec.ts
+++ b/src/app/datasources/rest/auth.rest.spec.ts
@@ -69,9 +69,9 @@
     it('should remove user auth from cookies', (done) => {
       service.logout()
         .then((res) => {
-          expect($cookies.get('xoscsrftoken')).toEqual(null);
-          expect($cookies.get('xossessionid')).toEqual(null);
-          expect($cookies.get('xosuser')).toEqual(null);
+          expect($cookies.get('xoscsrftoken')).toEqual(undefined);
+          expect($cookies.get('xossessionid')).toEqual(undefined);
+          expect($cookies.get('xosuser')).toEqual(undefined);
           done();
         })
         .catch(e => {
diff --git a/src/app/datasources/rest/auth.rest.ts b/src/app/datasources/rest/auth.rest.ts
index 1792920..e7a593c 100644
--- a/src/app/datasources/rest/auth.rest.ts
+++ b/src/app/datasources/rest/auth.rest.ts
@@ -13,9 +13,15 @@
   };
 }
 
+export interface IXosUser {
+  id: number;
+  email: string;
+}
+
 export interface IXosAuthService {
   login(data: IAuthRequestData): Promise<any>;
   logout(): Promise<any>;
+  getUser(): IXosUser;
 }
 export class AuthService {
 
@@ -44,7 +50,7 @@
 
   public logout(): Promise<any> {
     const d = this.$q.defer();
-    this.$http.post(`${AppConfig.apiEndpoint}/utility/login/`, {
+    this.$http.post(`${AppConfig.apiEndpoint}/utility/logout/`, {
       xoscsrftoken: this.$cookies.get('xoscsrftoken'),
       xossessionid: this.$cookies.get('xossessionid')
     })
@@ -59,4 +65,8 @@
       });
     return d.promise;
   }
+
+  public getUser(): IXosUser {
+    return JSON.parse(this.$cookies.get('xosuser'));
+  }
 }
diff --git a/src/app/images/brand/cord-logo.png b/src/app/images/brand/cord-logo.png
new file mode 100644
index 0000000..ff0fdf5
--- /dev/null
+++ b/src/app/images/brand/cord-logo.png
Binary files differ
diff --git a/src/app/images/brand/opencloud-logo.png b/src/app/images/brand/opencloud-logo.png
new file mode 100644
index 0000000..a55f86a
--- /dev/null
+++ b/src/app/images/brand/opencloud-logo.png
Binary files differ
diff --git a/src/app/template/directives/directives.ts b/src/app/template/directives/directives.ts
index ef6b628..c2d96cd 100644
--- a/src/app/template/directives/directives.ts
+++ b/src/app/template/directives/directives.ts
@@ -34,7 +34,6 @@
     restrict: 'EA',
     template: '<div class="left-nav-toggle"><a href ng-click="minimalize()"><i class="stroke-hamburgermenu"></i> </a>',
     controller: function ($scope, $element) {
-      console.log('mimalize');
       $scope.minimalize = function () {
         $("body").toggleClass("nav-toggle");
       }
diff --git a/src/app/views/crud/crud.html b/src/app/views/crud/crud.html
index 118a6b7..52e9a51 100644
--- a/src/app/views/crud/crud.html
+++ b/src/app/views/crud/crud.html
@@ -8,7 +8,7 @@
                         <a class="btn btn-default" ng-if="!vm.list" href="{{vm.baseUrl}}">Back</a>
                     </div>
                     <div class="header-icon">
-                        <i class="pe page-header-icon pe-7s-plugin"></i>
+                        <i class="pe page-header-icon pe-7s-note2"></i>
                     </div>
                     <div class="header-title">
                         <h3>{{vm.title}}</h3>
@@ -27,9 +27,11 @@
                         <h4>Related Items: </h4>
                     </div>
                     <div class="col-lg-8 text-right">
-                        <a ng-repeat="r in vm.related" href="#/core/{{r.toLowerCase()}}s/" class="btn btn-default">
-                            {{r}}
-                        </a>
+                        <div class="btn-group">
+                            <a ng-repeat="r in vm.related" href="#/core/{{r.toLowerCase()}}s/" class="btn btn-default">
+                                {{r}}
+                            </a>
+                        </div>
                     </div>
                     <hr>
                 </div>
diff --git a/src/index.scss b/src/index.scss
index a1a3f77..4cc14b8 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -1,3 +1,8 @@
+html, body.blank {
+  height: 100%;
+  min-height: 100%;
+}
+
 .content > div {
   opacity: 1 !important;
 }
\ No newline at end of file
diff --git a/src/interceptors.ts b/src/interceptors.ts
index 7707b0b..57f79f2 100644
--- a/src/interceptors.ts
+++ b/src/interceptors.ts
@@ -33,7 +33,7 @@
       if (!$cookies.get('xoscsrftoken') || !$cookies.get('xossessionid')) {
         return req;
       }
-      req.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
+      // req.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
       req.headers['x-csrftoken'] = $cookies.get('xoscsrftoken');
       req.headers['x-sessionid'] = $cookies.get('xossessionid');
       return req;
@@ -44,7 +44,11 @@
 export function NoHyperlinksInterceptor() {
   return {
     request: (req) => {
-      if (req.url.indexOf('.html') === -1 && req.url.indexOf('login') !== -1) {
+      if (
+        req.url.indexOf('.html') === -1
+        // && req.url.indexOf('login') === -1
+        // && req.url.indexOf('logout') === -1
+      ) {
         // NOTE this may fail if there are already query params
         req.url += '?no_hyperlinks=1';
       }