[CORD-1117] XOS GUI Various fix

Change-Id: I4237a5e23509e9173c958d76aa929a70583ba1e6
diff --git a/src/app/core/loader/loader.spec.ts b/src/app/core/loader/loader.spec.ts
new file mode 100644
index 0000000..1bcff9c
--- /dev/null
+++ b/src/app/core/loader/loader.spec.ts
@@ -0,0 +1,115 @@
+import * as angular from 'angular';
+import 'angular-mocks';
+import {xosLoader} from './loader';
+
+let loaded = true;
+
+const MockConfig = {
+  lastVisitedUrl: '/test'
+};
+
+const MockDiscover = {
+  areModelsLoaded: () => loaded,
+  discover: null
+};
+
+const MockOnboarder = {
+  onboard: null
+};
+
+describe('The XosLoader component', () => {
+  beforeEach(() => {
+    angular
+      .module('loader', [])
+      .value('XosConfig', MockConfig)
+      .value('XosModelDiscoverer', MockDiscover)
+      .value('XosOnboarder', MockOnboarder)
+      .component('xosLoader', xosLoader);
+    angular.mock.module('loader');
+  });
+
+  let scope, element, isolatedScope, rootScope, compile, timeout, location;
+  const compileElement = () => {
+
+    if (!scope) {
+      scope = rootScope.$new();
+    }
+
+    element = angular.element('<xos-loader></xos-loader>');
+    compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  };
+
+  beforeEach(inject(function ($q: ng.IQService, $compile: ng.ICompileService, $rootScope: ng.IScope, $timeout: ng.ITimeoutService, $location: ng.ILocationService) {
+    compile = $compile;
+    rootScope = $rootScope;
+    timeout = $timeout;
+    location = $location;
+    spyOn(location, 'path');
+
+    MockDiscover.discover = jasmine.createSpy('discover')
+      .and.callFake(() => {
+        const d = $q.defer();
+        d.resolve(true);
+        return d.promise;
+      });
+
+    MockOnboarder.onboard = jasmine.createSpy('onboard')
+      .and.callFake(() => {
+        const d = $q.defer();
+        d.resolve();
+        return d.promise;
+      });
+  }));
+
+  describe('when models are already loaded', () => {
+
+    beforeEach(() => {
+      compileElement();
+      spyOn(isolatedScope, 'moveOnTo');
+      isolatedScope.run();
+      timeout.flush();
+    });
+
+    it('should redirect to the last visited page', (done) => {
+      window.setTimeout(() => {
+        expect(isolatedScope.moveOnTo).toHaveBeenCalledWith('/test');
+        expect(location.path).toHaveBeenCalledWith('/test');
+        done();
+      }, 600);
+    });
+  });
+
+  describe('when the last visited page is "loader"', () => {
+
+    beforeEach(() => {
+      MockConfig.lastVisitedUrl = '/loader';
+      compileElement();
+      spyOn(isolatedScope, 'moveOnTo');
+      isolatedScope.run();
+    });
+
+    it('should redirect to the "dashboard" page', (done) => {
+      window.setTimeout(() => {
+        expect(isolatedScope.moveOnTo).toHaveBeenCalledWith('/loader');
+        expect(location.path).toHaveBeenCalledWith('/dashboard');
+        done();
+      }, 600);
+    });
+  });
+
+  describe('when models are not loaded', () => {
+
+    beforeEach(() => {
+      loaded = false;
+      compileElement();
+      spyOn(isolatedScope, 'moveOnTo');
+    });
+
+    it('should call XosModelDiscoverer.discover', () => {
+      expect(MockDiscover.discover).toHaveBeenCalled();
+    });
+  });
+
+});
diff --git a/src/app/core/loader/loader.ts b/src/app/core/loader/loader.ts
new file mode 100644
index 0000000..07a9875
--- /dev/null
+++ b/src/app/core/loader/loader.ts
@@ -0,0 +1,83 @@
+import {IXosModelDiscovererService} from '../../datasources/helpers/model-discoverer.service';
+import {IXosOnboarder} from '../../extender/services/onboard.service';
+class LoaderCtrl {
+  static $inject = [
+    '$log',
+    '$rootScope',
+    '$location',
+    '$timeout',
+    'XosConfig',
+    'XosModelDiscoverer',
+    `XosOnboarder`
+  ];
+
+  public aaaaa = 'ciao';
+
+  constructor (
+    private $log: ng.ILogService,
+    private $rootScope: ng.IScope,
+    private $location: ng.ILocationService,
+    private $timeout: ng.ITimeoutService,
+    private XosConfig: any,
+    private XosModelDiscoverer: IXosModelDiscovererService,
+    private XosOnboarder: IXosOnboarder
+  ) {
+
+    this.run();
+  }
+
+  public run() {
+    if (this.XosModelDiscoverer.areModelsLoaded()) {
+      this.moveOnTo(this.XosConfig.lastVisitedUrl);
+    }
+    else {
+      this.XosModelDiscoverer.discover()
+      // NOTE loading XOS Models
+        .then((res) => {
+          if (res) {
+            this.$log.info('[XosLoader] All models loaded');
+          }
+          else {
+            this.$log.info('[XosLoader] Failed to load some models, moving on.');
+          }
+          return this.XosOnboarder.onboard();
+        })
+        // NOTE loading GUI Extensions
+        .then(() => {
+          this.moveOnTo(this.XosConfig.lastVisitedUrl);
+        })
+        .finally(() => {
+          // NOTE it is in a timeout as the searchService is loaded after that
+          // we navigate to another page
+          this.$timeout(() => {
+            this.$rootScope.$emit('xos.core.modelSetup');
+          }, 500);
+        });
+    }
+  }
+
+  public moveOnTo(url: string) {
+    this.$log.info(`[XosLoader] Redirecting to: ${url}`);
+    switch (url) {
+      case '':
+      case '/':
+      case '/loader':
+      case '/login':
+        this.$location.path('/dashboard');
+        break;
+      default:
+        this.$timeout(() => {
+          this.$location.path(url);
+        }, 500);
+        break;
+    }
+  }
+}
+
+export const xosLoader: angular.IComponentOptions = {
+  template: `
+    <div class="loader"></div>
+  `,
+  controllerAs: 'vm',
+  controller: LoaderCtrl
+};