[CORD-1044] Migrating vTR Dashboard to the new GUI using gui-extensions

Change-Id: I33847766b790ffba2b9a9e9cfab9a7060734ce91
diff --git a/xos/gui/src/app/components/vtr/vtr-dashboard.html b/xos/gui/src/app/components/vtr/vtr-dashboard.html
new file mode 100644
index 0000000..f089f4e
--- /dev/null
+++ b/xos/gui/src/app/components/vtr/vtr-dashboard.html
@@ -0,0 +1,109 @@
+<pre>{{vm.subscribers | json}}</pre>
+<div class="row">
+  <div class="col-xs-12">
+    <h1>vTR Dashboard</h1>
+    <p>Use this page to run test against your subscriber</p>
+  </div>
+</div>
+<form ng-submit="vm.runTest()">
+  <div class="row">
+    <div class="col-xs-12">
+      <label>Target:</label>
+    </div>
+    <div class="col-xs-12">
+      <select class="form-control" ng-model="vm.truckroll.target_id" ng-options="s.id as s.name for s in vm.subscribers"></select>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-xs-12">
+      <label>Scope:</label>
+    </div>
+    <div class="col-xs-6">
+      <a 
+      ng-click="vm.truckroll.scope = 'container'"
+      ng-class="{'btn-default': vm.truckroll.scope !== 'container', 'btn-primary': vm.truckroll.scope === 'container'}"
+      class="btn btn-block"
+      >Container</a>
+    </div>
+    <div class="col-xs-6">
+      <a 
+      ng-click="vm.truckroll.scope = 'vm'"
+      ng-class="{'btn-default': vm.truckroll.scope !== 'vm', 'btn-primary': vm.truckroll.scope === 'vm'}"
+      class="btn btn-block"
+      >VM</a>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-xs-12">
+      <label>Test:</label>
+    </div>
+    <div class="col-xs-4">
+      <a 
+      ng-click="vm.truckroll.test = 'ping'"
+      ng-class="{'btn-default': vm.truckroll.test !== 'ping', 'btn-primary': vm.truckroll.test === 'ping'}"
+      class="btn btn-block">Ping</a>
+    </div>
+    <div class="col-xs-4">
+      <a 
+      ng-click="vm.truckroll.test = 'traceroute'"
+      ng-class="{'btn-default': vm.truckroll.test !== 'traceroute', 'btn-primary': vm.truckroll.test === 'traceroute'}"
+      class="btn btn-block">Traceroute</a>
+    </div>
+    <div class="col-xs-4">
+      <a 
+      ng-click="vm.truckroll.test = 'tcpdump'"
+      ng-class="{'btn-default': vm.truckroll.test !== 'tcpdump', 'btn-primary': vm.truckroll.test === 'tcpdump'}"
+      class="btn btn-block">Tcp Dump</a>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-xs-12">
+      <label>Argument:</label>
+    </div>
+    <div class="col-xs-12">
+      <input type="text" class="form-control" ng-model="vm.truckroll.argument" required />
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-xs-12" ng-show="!vm.loader">
+      <button class="btn btn-success btn-block">Run test</button>
+    </div>
+  </div>
+</form>
+<div class="row">
+  <div class="col-xs-12 animate-vertical" ng-show="vm.loader">
+    <div class="loader"></div>
+  </div>
+</div>
+<div class="row" ng-hide="!vm.truckroll.result_code">
+  <div class="col-xs-12">
+    <label>Result Code</label>
+  </div>
+  <div class="col-xs-12">
+    <pre>{{vm.truckroll.result_code}}</pre>
+  </div>
+</div>
+<div class="row" ng-hide="!vm.truckroll.result">
+  <div class="col-xs-12">
+    <label>Result:</label>
+  </div>
+  <div class="col-xs-12">
+    <pre>{{vm.truckroll.result}}</pre>
+  </div>
+</div>
+<div class="row" ng-hide="!vm.truckroll.backend_status">
+  <div class="col-xs-12">
+    <label>Backend Status</label>
+  </div>
+  <div class="col-xs-12">
+    <pre>{{vm.truckroll.backend_status}}</pre>
+  </div>
+</div>
+
+<div class="row" ng-show="vm.error">
+  <div class="col-xs-12">
+    <div class="alert alert-danger">
+      {{vm.error}}
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/xos/gui/src/app/components/vtr/vtr-dashboard.scss b/xos/gui/src/app/components/vtr/vtr-dashboard.scss
new file mode 100644
index 0000000..2ead2bf
--- /dev/null
+++ b/xos/gui/src/app/components/vtr/vtr-dashboard.scss
@@ -0,0 +1,5 @@
+xos-vtr-dashboard-component {
+  .row + .row {
+    margin-top: 20px;
+  }
+}
\ No newline at end of file
diff --git a/xos/gui/src/app/components/vtr/vtr-dashboard.ts b/xos/gui/src/app/components/vtr/vtr-dashboard.ts
new file mode 100644
index 0000000..3db80d1
--- /dev/null
+++ b/xos/gui/src/app/components/vtr/vtr-dashboard.ts
@@ -0,0 +1,97 @@
+import './vtr-dashboard.scss';
+import * as _ from 'lodash';
+import {subscribeOn} from 'rxjs/operator/subscribeOn';
+
+class VtrDashboardComponent {
+  static $inject = [
+    '$timeout',
+    'XosModelStore',
+    'XosVtrTruckroll'
+   ];
+
+  public subscribers = [];
+  public truckroll: any;
+  public loader: boolean;
+  public error: string;
+  private Truckroll;
+
+  constructor(
+    private $timeout: ng.ITimeoutService,
+    private XosModelStore: any,
+    private XosVtrTruckroll: any
+  ) {
+
+    this.Truckroll = this.XosVtrTruckroll.getResource();
+
+    // load subscribers
+    this.XosModelStore.query('Subscribers')
+      .subscribe(
+        res => {
+          this.subscribers = res;
+        }
+      );
+  }
+
+  public runTest() {
+
+    // clean previous tests
+    delete this.truckroll.id;
+    delete this.truckroll.result;
+    delete this.truckroll.is_synced;
+    delete this.truckroll.result_code;
+    delete this.truckroll.backend_status;
+    delete this.error;
+
+    this.truckroll.target_type_id = this.getSubscriberContentTypeId(this.truckroll.target_id);
+
+    const test = new this.Truckroll(this.truckroll);
+    this.loader = true;
+    test.$save()
+    .then((res) => {
+      this.waitForTest(res.id);
+    });
+  };
+
+  private getSubscriberContentTypeId(subscriberId: number) {
+    return _.find(this.subscribers, {id: subscriberId}).self_content_type_id;
+  }
+
+  private waitForTest(id: number) {
+
+        this.Truckroll.get({id: id}).$promise
+        .then((testResult, status) => {
+          // this is becasue error returning a string in an array
+          if (testResult[0] && testResult[0].length === 1) {
+            this.loader = false;
+            this.error = 'An error occurred, please try again later';
+            return;
+          }
+
+          // if error
+          // or
+          // if is synced
+          if (
+              testResult.backend_status.indexOf('2') >= 0 ||
+              (testResult.result_code && testResult.result_code.indexOf('2') >= 0) ||
+              testResult.is_synced
+            ) {
+            this.truckroll = angular.copy(testResult);
+            this.loader = false;
+            this.Truckroll.delete({id: id});
+          }
+          // else keep polling
+          else {
+            this.$timeout(() => {
+              this.waitForTest(id);
+            }, 2000);
+          }
+        });
+      };
+
+}
+
+export const xosVtrDashboardComponent: angular.IComponentOptions = {
+  template: require('./vtr-dashboard.html'),
+  controllerAs: 'vm',
+  controller: VtrDashboardComponent
+};
diff --git a/xos/gui/src/app/services/truckroll.resource.ts b/xos/gui/src/app/services/truckroll.resource.ts
new file mode 100644
index 0000000..1791021
--- /dev/null
+++ b/xos/gui/src/app/services/truckroll.resource.ts
@@ -0,0 +1,20 @@
+export class XosVtrTruckroll {
+
+  static $inject = [
+    '$resource',
+    'AppConfig'
+  ];
+
+  constructor(
+    private $resource: ng.resource.IResourceService,
+    private AppConfig: any
+  ) {
+
+  }
+
+  public getResource() {
+    return this.$resource(`${this.AppConfig.apiEndpoint}/vtr/vtrtenants/:id/`, { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }
+}
diff --git a/xos/gui/src/index.html b/xos/gui/src/index.html
new file mode 100644
index 0000000..33dcbd3
--- /dev/null
+++ b/xos/gui/src/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en" ng-app="xos-vtr-gui-extension">
+<head>
+  <meta charset="UTF-8">
+  <title>Document</title>
+  <link href="http://192.168.46.100/spa/loader.css" rel="stylesheet">
+  <link href="http://192.168.46.100/spa/app.css" rel="stylesheet">
+</head>
+<body>
+  <div ui-view></div>
+  <script src="http://192.168.46.100/spa/vendor.js"></script>
+  <script src="http://192.168.46.100/spa/app.js"></script>
+  <script src="http://192.168.46.100/spa/loader.js"></script>
+  <script src="http://192.168.46.100/spa/app.config.js"></script>
+  <script src="http://192.168.46.100/spa/style.config.js"></script>
+</body>
+</html>
diff --git a/xos/gui/src/index.ts b/xos/gui/src/index.ts
new file mode 100644
index 0000000..03d248c
--- /dev/null
+++ b/xos/gui/src/index.ts
@@ -0,0 +1,31 @@
+/// <reference path="../typings/index.d.ts" />
+import * as angular from 'angular';
+
+import 'angular-ui-router';
+import 'angular-resource';
+import 'angular-cookies';
+import routesConfig from './routes';
+import {xosVtrDashboardComponent} from './app/components/vtr/vtr-dashboard';
+import {XosVtrTruckroll} from './app/services/truckroll.resource';
+
+angular.module('xos-vtr-gui-extension', [
+    'ui.router',
+    'app'
+  ])
+  .config(routesConfig)
+  .service('XosVtrTruckroll', XosVtrTruckroll)
+  .component('xosVtrDashboardComponent', xosVtrDashboardComponent)
+  .run(function($log: ng.ILogService, XosNavigationService: any) {
+    $log.info('[xos-vtr-gui-extension] App is running');
+
+    XosNavigationService.add({
+      label: 'vTR',
+      state: 'xos.vtr',
+    });
+
+    XosNavigationService.add({
+      label: 'Dashboard',
+      state: 'xos.vtr.dashboard',
+      parent: 'xos.vtr'
+    });
+  });
diff --git a/xos/gui/src/routes.ts b/xos/gui/src/routes.ts
new file mode 100644
index 0000000..84abd47
--- /dev/null
+++ b/xos/gui/src/routes.ts
@@ -0,0 +1,16 @@
+export default routesConfig;
+
+function routesConfig($stateProvider: angular.ui.IStateProvider, $locationProvider: angular.ILocationProvider) {
+  $locationProvider.html5Mode(false).hashPrefix('');
+
+  $stateProvider
+  .state('xos.vtr', {
+      abstract: true,
+      template: '<div ui-view></div>'
+    })
+    .state('xos.vtr.dashboard', {
+      url: 'vtr/dashboard',
+      parent: 'xos.vtr',
+      component: 'xosVtrDashboardComponent'
+    });
+}