CORD-772 Extending the GUI with external apps
Change-Id: Ie13d438716054260e03ff54ac752d9f072fb9d76
diff --git a/src/app/core/services/helpers/component-injector.helpers.ts b/src/app/core/services/helpers/component-injector.helpers.ts
index 35c73a0..e70e257 100644
--- a/src/app/core/services/helpers/component-injector.helpers.ts
+++ b/src/app/core/services/helpers/component-injector.helpers.ts
@@ -46,6 +46,9 @@
});
}
+ // FIXME
+ // component are correctly injected but not persisted,
+ // if I change route they go away
public injectComponent(target: string | JQuery, componentName: string, attributes?: any, transclude?: string, clean?: boolean) {
let targetEl;
if (angular.isString(target)) {
diff --git a/src/app/datasources/stores/synchronizer.store.ts b/src/app/datasources/stores/synchronizer.store.ts
index 33a0c39..aa25cc0 100644
--- a/src/app/datasources/stores/synchronizer.store.ts
+++ b/src/app/datasources/stores/synchronizer.store.ts
@@ -15,6 +15,9 @@
) {
this.webSocket.list()
.filter((e: IWSEvent) => {
+ if (!e.msg || !e.msg.changed_fields) {
+ return false;
+ }
return e.msg.changed_fields.indexOf('backend_status') > -1;
})
.subscribe(
diff --git a/src/app/extender/index.ts b/src/app/extender/index.ts
new file mode 100644
index 0000000..622491a
--- /dev/null
+++ b/src/app/extender/index.ts
@@ -0,0 +1,21 @@
+import {xosDataSources} from '../datasources/index';
+export const xosExtender = 'xosExtender';
+
+import 'angular-ui-bootstrap';
+import 'angular-animate';
+import 'angular-toastr';
+import 'oclazyload';
+import {XosOnboarder, IXosOnboarder} from './services/onboard.service';
+
+
+(function () {
+ angular.module(xosExtender, [
+ 'oc.lazyLoad',
+ xosDataSources
+ ])
+ .service('XosOnboarder', XosOnboarder)
+ .run(function ($log: ng.ILogService, XosOnboarder: IXosOnboarder) {
+ $log.info('[XosOnboarder] Setup');
+ });
+})();
+
diff --git a/src/app/extender/services/onboard.service.spec.ts b/src/app/extender/services/onboard.service.spec.ts
new file mode 100644
index 0000000..f9373c9
--- /dev/null
+++ b/src/app/extender/services/onboard.service.spec.ts
@@ -0,0 +1,69 @@
+import * as angular from 'angular';
+import 'angular-mocks';
+import 'angular-resource';
+import {Subject} from 'rxjs';
+import {XosOnboarder, IXosOnboarder} from './onboard.service';
+import {IWSEventService} from '../../datasources/websocket/global';
+
+let service, $ocLazyLoad;
+
+const subject = new Subject();
+
+const MockWs: IWSEventService = {
+ list() {
+ return subject.asObservable();
+ }
+};
+
+const MockPromise = {
+ then: (cb) => {
+ cb('done');
+ return MockPromise;
+ },
+ catch: (cb) => {
+ cb('err');
+ return MockPromise;
+ }
+};
+
+const MockLoad = {
+ load: () => {
+ return MockPromise;
+ }
+};
+
+describe('The XosOnboarder service', () => {
+
+ beforeEach(() => {
+
+ angular
+ .module('XosOnboarder', [])
+ .value('WebSocket', MockWs)
+ .value('$ocLazyLoad', MockLoad)
+ .service('XosOnboarder', XosOnboarder);
+
+ angular.mock.module('XosOnboarder');
+ });
+
+ beforeEach(angular.mock.inject((
+ XosOnboarder: IXosOnboarder,
+ _$ocLazyLoad_: any
+ ) => {
+ $ocLazyLoad = _$ocLazyLoad_;
+ spyOn($ocLazyLoad, 'load').and.callThrough();
+ service = XosOnboarder;
+ }));
+
+ describe('when receive an event', () => {
+ it('should use $ocLazyLoad to add modules to the app', () => {
+ subject.next({
+ msg: {
+ app: 'sample',
+ files: ['vendor.js', 'app.js']
+ }
+ });
+ expect($ocLazyLoad.load).toHaveBeenCalledWith('vendor.js');
+ expect($ocLazyLoad.load).toHaveBeenCalledWith('app.js');
+ });
+ });
+});
diff --git a/src/app/extender/services/onboard.service.ts b/src/app/extender/services/onboard.service.ts
new file mode 100644
index 0000000..70d830c
--- /dev/null
+++ b/src/app/extender/services/onboard.service.ts
@@ -0,0 +1,56 @@
+import {IWSEventService} from '../../datasources/websocket/global';
+
+export interface IXosOnboarder {
+
+}
+
+export class XosOnboarder implements IXosOnboarder {
+ static $inject = ['$timeout', '$log', '$q', 'WebSocket', '$ocLazyLoad'];
+
+ constructor(
+ private $timeout: ng.ITimeoutService,
+ private $log: ng.ILogService,
+ private $q: ng.IQService,
+ private webSocket: IWSEventService,
+ private $ocLazyLoad: any // TODO add definition
+ ) {
+ this.$log.info('[XosOnboarder] Setup');
+ this.webSocket.list()
+ .filter((e) => {
+ this.$log.log(e);
+ // TODO define event format
+ return e.msg['files'].length > 0;
+ })
+ .subscribe(
+ (event) => {
+ this.loadFile(event.msg['files'])
+ .then((res) => {
+ this.$log.info(`[XosOnboarder] All files loaded for app: ${event.msg['app']}`);
+ });
+ }
+ );
+ }
+
+ // NOTE files needs to be loaded in order, so async loop!
+ private loadFile(files: string[], d?: ng.IDeferred<any>): ng.IPromise<string[]> {
+ if (!angular.isDefined(d)) {
+ d = this.$q.defer();
+ }
+ const file = files.shift();
+ this.$log.info(`[XosOnboarder] Loading file: ${file}`);
+ this.$ocLazyLoad.load(file)
+ .then((res) => {
+ this.$log.info(`[XosOnboarder] Loaded file: `, file);
+ if (files.length > 0) {
+ return this.loadFile(files, d);
+ }
+ return d.resolve(file);
+ })
+ .catch((err) => {
+ this.$log.error(`[XosOnboarder] Failed to load file: `, err);
+ d.reject(err);
+ });
+
+ return d.promise;
+ }
+}