Added possiblity to extend the dashboard programmatically
Change-Id: Ibf2c2f7e6d51e6f5a661021f3f9f4b15c9cbefa1
diff --git a/src/app/core/index.ts b/src/app/core/index.ts
index e6f740e..4b89ac8 100644
--- a/src/app/core/index.ts
+++ b/src/app/core/index.ts
@@ -18,6 +18,7 @@
import {ModelSetup} from './services/helpers/model-setup.helpers';
import {xosSidePanel} from './side-panel/side-panel';
import {XosSidePanel} from './side-panel/side-panel.service';
+import {XosComponentInjector} from './services/helpers/component-injector.helpers';
export const xosCore = 'xosCore';
@@ -35,6 +36,7 @@
.service('ConfigHelpers', ConfigHelpers)
.service('ModelSetup', ModelSetup)
.service('XosSidePanel', XosSidePanel)
+ .service('XosComponentInjector', XosComponentInjector)
.directive('xosLinkWrapper', xosLinkWrapper)
.component('xosHeader', xosHeader)
.component('xosFooter', xosFooter)
diff --git a/src/app/core/nav/nav.html b/src/app/core/nav/nav.html
index 402d2fa..ce495da 100644
--- a/src/app/core/nav/nav.html
+++ b/src/app/core/nav/nav.html
@@ -44,7 +44,8 @@
<a ng-click="vm.logout()" class="btn btn-accent btn-block btn-logout">Logout</a>
</div>
</div>
- <!--<a ng-click="vm.togglePanel()" class="btn btn-success">Open XSP</a>-->
+ <a ng-click="vm.togglePanel()" class="btn btn-success">Open XSP</a>
+ <a ng-click="vm.addToDashboard()" class="btn btn-success">Add to home</a>
</li>
</ul>
</nav>
diff --git a/src/app/core/nav/nav.spec.ts b/src/app/core/nav/nav.spec.ts
index f443d91..5101ba8 100644
--- a/src/app/core/nav/nav.spec.ts
+++ b/src/app/core/nav/nav.spec.ts
@@ -32,7 +32,8 @@
.service('NavigationService', NavigationService)
.value('AuthService', AuthMock)
.value('StyleConfig', {})
- .value('XosSidePanel', {});
+ .value('XosSidePanel', {})
+ .value('XosComponentInjector', {});
angular.mock.module('xosNav');
});
diff --git a/src/app/core/nav/nav.ts b/src/app/core/nav/nav.ts
index ec2d8b2..08ad48a 100644
--- a/src/app/core/nav/nav.ts
+++ b/src/app/core/nav/nav.ts
@@ -3,9 +3,10 @@
import {IXosAuthService} from '../../datasources/rest/auth.rest';
import {IXosStyleConfig} from '../../../index';
import {IXosSidePanelService} from '../side-panel/side-panel.service';
+import {IXosComponentInjectorService} from '../services/helpers/component-injector.helpers';
class NavCtrl {
- static $inject = ['$scope', '$state', 'NavigationService', 'AuthService', 'StyleConfig', 'XosSidePanel'];
+ static $inject = ['$scope', '$state', 'NavigationService', 'AuthService', 'StyleConfig', 'XosSidePanel', 'XosComponentInjector'];
public routes: IXosNavigationRoute[];
public navSelected: string;
public appName: string;
@@ -17,7 +18,8 @@
private navigationService: IXosNavigationService,
private authService: IXosAuthService,
private StyleConfig: IXosStyleConfig,
- private XosSidePanel: IXosSidePanelService
+ private XosSidePanel: IXosSidePanelService,
+ private XosComponentInjector: IXosComponentInjectorService
) {
// NOTE we'll need to have:
// - Base routes (defined from configuration based on BRAND)
@@ -62,6 +64,9 @@
togglePanel() {
this.XosSidePanel.injectComponent('xosAlert', {config: {type: 'danger'}, show: true}, 'Sample message');
}
+ addToDashboard() {
+ this.XosComponentInjector.injectComponent('#dashboard-component-container', 'xosAlert', {config: {type: 'danger'}, show: true}, 'Sample message', false);
+ }
logout() {
this.authService.logout()
diff --git a/src/app/core/services/helpers/component-injector.helpers.spec.ts b/src/app/core/services/helpers/component-injector.helpers.spec.ts
new file mode 100644
index 0000000..0ba501f
--- /dev/null
+++ b/src/app/core/services/helpers/component-injector.helpers.spec.ts
@@ -0,0 +1,52 @@
+import * as angular from 'angular';
+import 'angular-mocks';
+import 'angular-ui-router';
+import * as $ from 'jquery';
+import {XosComponentInjector, IXosComponentInjectorService} from './component-injector.helpers';
+
+let service: IXosComponentInjectorService;
+let element, scope: angular.IRootScopeService, compile: ng.ICompileService;
+
+describe('The XosComponentInjector service', () => {
+ beforeEach(() => {
+ angular
+ .module('test', [])
+ .component('extension', {
+ template: 'extended'
+ })
+ .component('target', {
+ template: `<div id="target"></div>`
+ })
+ .service('XosComponentInjector', XosComponentInjector);
+
+ angular.mock.module('test');
+ });
+
+ beforeEach(angular.mock.inject((
+ XosComponentInjector: IXosComponentInjectorService,
+ ) => {
+ service = XosComponentInjector;
+ }));
+
+ beforeEach(angular.mock.inject(($rootScope: ng.IRootScopeService, $compile: ng.ICompileService) => {
+ scope = $rootScope;
+ compile = $compile;
+ element = $compile('<target></target>')($rootScope);
+ $rootScope.$digest();
+ }));
+
+ it('should have an InjectComponent method', () => {
+ expect(service.injectComponent).toBeDefined();
+ });
+
+ it('should have an removeInjectedComponents method', () => {
+ expect(service.removeInjectedComponents).toBeDefined();
+ });
+
+ it('should add a component to the target container', () => {
+ service.injectComponent($('#target', element), 'extension');
+ scope.$apply();
+ const extension = $('extension', element);
+ expect(extension.text()).toBe('extended');
+ });
+});
diff --git a/src/app/core/services/helpers/component-injector.helpers.ts b/src/app/core/services/helpers/component-injector.helpers.ts
new file mode 100644
index 0000000..8fd7a50
--- /dev/null
+++ b/src/app/core/services/helpers/component-injector.helpers.ts
@@ -0,0 +1,61 @@
+import * as $ from 'jquery';
+import * as _ from 'lodash';
+
+export interface IXosComponentInjectorService {
+ injectComponent(target: string | JQuery, componentName: string, attributes?: any, transclude?: string, clean?: boolean): void;
+ removeInjectedComponents(target: string | JQuery): void;
+}
+
+export class XosComponentInjector implements IXosComponentInjectorService {
+ static $inject = ['$rootScope', '$compile'];
+
+ constructor (
+ private $rootScope: ng.IRootScopeService,
+ private $compile: ng.ICompileService
+ ) {
+ }
+
+ public injectComponent(target: string | JQuery, componentName: string, attributes?: any, transclude?: string, clean?: boolean) {
+ let targetEl;
+ if (angular.isString(target)) {
+ targetEl = $(target);
+ }
+ else {
+ targetEl = target;
+ }
+
+ const componentTagName = this.camelToSnakeCase(componentName);
+ let scope = this.$rootScope.$new();
+ let attr: string = '';
+
+ if (clean) {
+ this.removeInjectedComponents(target);
+ }
+
+ if (angular.isDefined(attributes) && angular.isObject(attributes)) {
+ attr = this.stringifyAttributes(attributes);
+ scope = angular.merge(scope, attributes);
+ }
+
+ const componentTag = `<${componentTagName} ${attr}>${transclude || ''}</${componentTagName}>`;
+ const element = this.$compile(componentTag)(scope);
+
+ targetEl.append(element);
+ }
+
+ public removeInjectedComponents(target: string | JQuery) {
+ const targetEl = $(target);
+ targetEl.html('');
+ }
+
+ private stringifyAttributes(attributes: any): string {
+ return _.reduce(Object.keys(attributes), (string: string, a: string) => {
+ string += `${a}="${a}"`;
+ return string;
+ }, '');
+ }
+
+ private camelToSnakeCase(name: string): string {
+ return name.split(/(?=[A-Z])/).map(w => w.toLowerCase()).join('-');
+ };
+}
diff --git a/src/app/core/side-panel/side-panel.service.ts b/src/app/core/side-panel/side-panel.service.ts
index 06dfef9..a7471f5 100644
--- a/src/app/core/side-panel/side-panel.service.ts
+++ b/src/app/core/side-panel/side-panel.service.ts
@@ -1,5 +1,5 @@
import * as $ from 'jquery';
-import * as _ from 'lodash';
+import {IXosComponentInjectorService} from '../services/helpers/component-injector.helpers';
export interface IXosSidePanelService {
open(): void;
@@ -8,14 +8,15 @@
}
export class XosSidePanel implements IXosSidePanelService {
- static $inject = ['$rootScope', '$compile'];
+ static $inject = ['$rootScope', '$compile', 'XosComponentInjector'];
public sidePanelElName = 'xos-side-panel';
public sidePanelElClass = '.xos-side-panel';
public sidePanelEl: JQuery;
constructor (
private $rootScope: ng.IRootScopeService,
- private $compile: ng.ICompileService
+ private $compile: ng.ICompileService,
+ private XosComponentInjector: IXosComponentInjectorService
) {
this.sidePanelEl = $(`${this.sidePanelElName} > ${this.sidePanelElClass}`);
}
@@ -29,36 +30,7 @@
};
public injectComponent(componentName: string, attributes?: any, transclude?: string) {
- const componentTagName = this.camelToSnakeCase(componentName);
- let scope = this.$rootScope.$new();
- let attr: string = '';
-
- // NOTE add a flag to keep the loaded compoenents?
- this.removeInjectedComponents();
-
- if (angular.isDefined(attributes) && angular.isObject(attributes)) {
- attr = this.stringifyAttributes(attributes);
- scope = angular.merge(scope, attributes);
- }
-
- const componentTag = `<${componentTagName} ${attr}>${transclude || ''}</${componentTagName}>`;
- const element = this.$compile(componentTag)(scope);
- this.sidePanelEl.find('#side-panel-container').append(element);
+ this.XosComponentInjector.injectComponent('#side-panel-container', componentName, attributes, transclude, true);
this.open();
}
-
- public removeInjectedComponents() {
- this.sidePanelEl.find('#side-panel-container').html('');
- }
-
- private stringifyAttributes(attributes: any): string {
- return _.reduce(Object.keys(attributes), (string: string, a: string) => {
- string += `${a}="${a}"`;
- return string;
- }, '');
- }
-
- private camelToSnakeCase(name: string): string {
- return name.split(/(?=[A-Z])/).map(w => w.toLowerCase()).join('-');
- };
}
diff --git a/src/app/views/dashboard/dashboard.html b/src/app/views/dashboard/dashboard.html
index de4c358..f42c842 100644
--- a/src/app/views/dashboard/dashboard.html
+++ b/src/app/views/dashboard/dashboard.html
@@ -1,6 +1,7 @@
<section class="content">
<div class="container-fluid">
<!--<h1>Dashboard</h1>-->
+ <div class="row" id="dashboard-component-container"></div>
<div class="row">
<div class="col-xs-4">
<div class="panel panel-filled">
@@ -9,7 +10,11 @@
{{vm.nodes}}
<!--<span class="slight"><i class="fa fa-play fa-rotate-270 text-warning"> </i> +20%</span>-->
</h2>
- <h4>Nodes</h4>
+ <h4>
+ <a ui-sref="xos.core.nodes">
+ Nodes
+ </a>
+ </h4>
<!--<div class="small">% New Sessions</div>-->
<!--<div class="slight m-t-sm"><i class="fa fa-clock-o"> </i> Updated: <span class="c-white">10:22pm</span></div>-->
</div>
@@ -22,7 +27,11 @@
<h2 class="m-b-none">
{{vm.slices}}
</h2>
- <h4>Slices</h4>
+ <h4>
+ <a ui-sref="xos.core.slices">
+ Slices
+ </a>
+ </h4>
</div>
</div>
</div>
@@ -33,7 +42,11 @@
<h2 class="m-b-none">
{{vm.instances}}
</h2>
- <h4>Instances</h4>
+ <h4>
+ <a ui-sref="xos.core.instances">
+ Instances
+ </a>
+ </h4>
</div>
</div>
</div>