[CORD-814] Building nodes and links for coarse tenancy graph
Change-Id: I85769dc4c8d7f7714fa4b59f052d0073e7b32ec5
diff --git a/src/app/core/services/helpers/debounce.helper.spec.ts b/src/app/core/services/helpers/debounce.helper.spec.ts
index 1c47dbd..e04b11e 100644
--- a/src/app/core/services/helpers/debounce.helper.spec.ts
+++ b/src/app/core/services/helpers/debounce.helper.spec.ts
@@ -22,7 +22,7 @@
it('should call a function only after it has not been called for 500ms', (done) => {
const spy = jasmine.createSpy('fn');
- const efficientSpy = service.debounce(spy, 500, false);
+ const efficientSpy = service.debounce(spy, 500, this, false);
/* tslint:disable */
efficientSpy();
efficientSpy();
diff --git a/src/app/core/services/helpers/debounce.helper.ts b/src/app/core/services/helpers/debounce.helper.ts
index 3d4011f..0534106 100644
--- a/src/app/core/services/helpers/debounce.helper.ts
+++ b/src/app/core/services/helpers/debounce.helper.ts
@@ -1,5 +1,5 @@
export interface IXosDebouncer {
- debounce(func: any, wait: number, immediate?: boolean): any;
+ debounce(func: any, wait: number, context: any, immediate?: boolean): any;
}
export class XosDebouncer implements IXosDebouncer {
@@ -14,11 +14,9 @@
// wait for 'wait' ms without actions to call the function
// if 'immediate' call it immediatly then wait for 'wait'
// NOTE that we cannot use $timeout service to debounce functions as it trigger infiniteDigest Exception
- public debounce(func: any, wait: number, immediate?: boolean) {
+ public debounce(func: any, wait: number, context: any, immediate?: boolean) {
let timeout;
- const self = this;
return function() {
- const context = self;
const args = arguments;
const later = function() {
timeout = null;
diff --git a/src/app/datasources/stores/model.store.ts b/src/app/datasources/stores/model.store.ts
index ab2f3d2..60d2473 100644
--- a/src/app/datasources/stores/model.store.ts
+++ b/src/app/datasources/stores/model.store.ts
@@ -23,7 +23,7 @@
private XosDebouncer: IXosDebouncer
) {
this._collections = {};
- this.efficientNext = this.XosDebouncer.debounce(this.next, 500, false);
+ this.efficientNext = this.XosDebouncer.debounce(this.next, 500, this, false);
}
public query(modelName: string, apiUrl: string): Observable<any> {
diff --git a/src/app/service-graph/components/coarse/coarse.component.html b/src/app/service-graph/components/coarse/coarse.component.html
new file mode 100644
index 0000000..75ef18b
--- /dev/null
+++ b/src/app/service-graph/components/coarse/coarse.component.html
@@ -0,0 +1,3 @@
+<h1>Coarse Tenancy Graph</h1>
+
+<pre>{{vm.graph | json}}</pre>
\ No newline at end of file
diff --git a/src/app/service-graph/components/coarse/coarse.component.ts b/src/app/service-graph/components/coarse/coarse.component.ts
new file mode 100644
index 0000000..b64e806
--- /dev/null
+++ b/src/app/service-graph/components/coarse/coarse.component.ts
@@ -0,0 +1,25 @@
+import {IXosServiceGraphStore} from '../../services/graph.store';
+import {IXosServiceGraph} from '../../interfaces';
+class XosCoarseTenancyGraphCtrl {
+
+ static $inject = ['$log', 'XosServiceGraphStore'];
+
+ public graph: IXosServiceGraph;
+
+ constructor (
+ private $log: ng.ILogService,
+ private XosServiceGraphStore: IXosServiceGraphStore
+ ) {
+
+ this.XosServiceGraphStore.getCoarse()
+ .subscribe((res) => {
+ this.graph = res;
+ });
+ }
+}
+
+export const XosCoarseTenancyGraph: angular.IComponentOptions = {
+ template: require('./coarse.component.html'),
+ controllerAs: 'vm',
+ controller: XosCoarseTenancyGraphCtrl,
+};
diff --git a/src/app/service-graph/index.ts b/src/app/service-graph/index.ts
index 5c861fd..ab9207b 100644
--- a/src/app/service-graph/index.ts
+++ b/src/app/service-graph/index.ts
@@ -1,11 +1,13 @@
import {xosDataSources} from '../datasources/index';
import {XosServiceGraphStore} from './services/graph.store';
import {xosCore} from '../core/index';
+import {XosCoarseTenancyGraph} from './components/coarse/coarse.component';
export const xosServiceGraph = 'xosServiceGraph';
angular
.module(xosServiceGraph, [xosDataSources, xosCore])
.service('XosServiceGraphStore', XosServiceGraphStore)
- .run(($log: ng.ILogService, XosServiceGraphStore) => {
+ .component('xosCoarseTenancyGraph', XosCoarseTenancyGraph)
+ .run(($log: ng.ILogService) => {
$log.info(`[${xosServiceGraph}] Module Setup`);
});
diff --git a/src/app/service-graph/interfaces.ts b/src/app/service-graph/interfaces.ts
index b55c441..ab80c79 100644
--- a/src/app/service-graph/interfaces.ts
+++ b/src/app/service-graph/interfaces.ts
@@ -30,6 +30,11 @@
subscribed_tenants_ids: number[];
}
+export interface IXosCoarseGraphData {
+ services: IXosServiceModel[];
+ tenants: IXosTenantModel[];
+}
+
export interface IXosServiceGraphNodeBadge {
type: 'info'|'success'|'warning'|'danger';
text: string;
@@ -37,18 +42,20 @@
export interface IXosServiceGraphNode {
id: number;
- x: number;
- y: number;
- px: number;
- py: number;
label: string;
- badge: IXosServiceGraphNodeBadge;
+ x?: number;
+ y?: number;
+ px?: number;
+ py?: number;
+ badge?: IXosServiceGraphNodeBadge;
+ model: IXosServiceModel;
}
export interface IXosServiceGraphLink {
id: number;
source: number;
target: number;
+ model: IXosTenantModel;
}
export interface IXosServiceGraph {
diff --git a/src/app/service-graph/services/graph.store.ts b/src/app/service-graph/services/graph.store.ts
index e892b99..f9d4d15 100644
--- a/src/app/service-graph/services/graph.store.ts
+++ b/src/app/service-graph/services/graph.store.ts
@@ -1,9 +1,14 @@
+import * as _ from 'lodash';
import {Observable, BehaviorSubject} from 'rxjs';
import {IXosModelStoreService} from '../../datasources/stores/model.store';
-import {IXosServiceGraph, IXosServiceModel, IXosTenantModel} from '../interfaces';
+import {
+ IXosServiceGraph, IXosServiceModel, IXosTenantModel, IXosCoarseGraphData,
+ IXosServiceGraphNode, IXosServiceGraphLink
+} from '../interfaces';
import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
export interface IXosServiceGraphStore {
get(): Observable<IXosServiceGraph>;
+ getCoarse(): Observable<IXosServiceGraph>;
}
export class XosServiceGraphStore implements IXosServiceGraphStore {
@@ -12,7 +17,16 @@
'XosModelStore',
'XosDebouncer'
];
- private d3Graph = new BehaviorSubject({});
+
+ // graph data store
+ private graphData: BehaviorSubject<IXosCoarseGraphData> = new BehaviorSubject({
+ services: [],
+ tenants: []
+ });
+
+ // reprentations of the graph as D3 requires
+ private d3CoarseGraph = new BehaviorSubject({});
+ private d3FineGrainedGraph = new BehaviorSubject({});
// storing locally reference to the data model
private services;
@@ -31,12 +45,15 @@
private XosDebouncer: IXosDebouncer
) {
+ this.$log.info(`[XosServiceGraphStore] Setup`);
+
// we want to have a quiet period of 500ms from the last event before doing anything
- this.handleData = this.XosDebouncer.debounce(this._handleData, 500, false);
+ this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);
this.ServiceObservable = this.XosModelStore.query('Service', '/core/services');
- this.TenantObservable = this.XosModelStore.query('Service', '/core/tenants');
+ this.TenantObservable = this.XosModelStore.query('Tenant', '/core/tenants');
+ // observe models and populate graphData
this.ServiceObservable
.subscribe(
(res) => {
@@ -47,7 +64,7 @@
}
);
- this.ServiceObservable
+ this.TenantObservable
.subscribe(
(res) => {
this.combineData(res, 'tenants');
@@ -56,10 +73,30 @@
this.$log.error(err);
}
);
+
+ // observe graphData and build Coarse or FineGrained graphs (based on who's subscribed)
+ this.graphData
+ .subscribe(
+ (res: IXosCoarseGraphData) => {
+ if (this.d3CoarseGraph.observers.length > 0) {
+ this.graphDataToCoarseGraph(res);
+ }
+ if (this.d3FineGrainedGraph.observers.length > 0) {
+ // TODO graphDataToFineGrainedGraph
+ }
+ },
+ (err) => {
+ this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
+ }
+ );
}
public get() {
- return this.d3Graph.asObservable();
+ return this.d3FineGrainedGraph.asObservable();
+ }
+
+ public getCoarse() {
+ return this.d3CoarseGraph.asObservable();
}
private combineData(data: any, type: 'services'|'tenants') {
@@ -75,7 +112,40 @@
}
private _handleData(services: IXosServiceModel[], tenants: IXosTenantModel[]) {
- this.$log.log(`XosServiceGraphStore`, services, tenants);
+ this.graphData.next({
+ services: this.services,
+ tenants: this.tenants
+ });
+ }
+
+ private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
+
+ const links: IXosServiceGraphLink[] = _.chain(data.tenants)
+ .filter((t: IXosTenantModel) => t.kind === 'coarse')
+ .map((t: IXosTenantModel) => {
+ return {
+ id: t.id,
+ source: t.provider_service_id,
+ target: t.subscriber_service_id,
+ model: t
+ };
+ })
+ .value();
+
+ // NOTE show all services anyway or find only the node that have links pointing to it
+ const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
+ return {
+ id: s.id,
+ label: s.name,
+ model: s
+ };
+ });
+
+ // TODO call next on this.d3CoarseGraph
+ this.d3CoarseGraph.next({
+ nodes: nodes,
+ links: links
+ });
}
}
diff --git a/src/app/views/dashboard/dashboard.html b/src/app/views/dashboard/dashboard.html
index db87d74..91481ad 100644
--- a/src/app/views/dashboard/dashboard.html
+++ b/src/app/views/dashboard/dashboard.html
@@ -1,4 +1,9 @@
<!--<h1>Dashboard</h1>-->
+ <div class="row">
+ <div class="col-xs-12">
+ <xos-coarse-tenancy-graph></xos-coarse-tenancy-graph>
+ </div>
+ </div>
<div class="row">
<div class="col-xs-12" id="dashboard-component-container"></div>
</div>