[CORD-1043] Registering reducers on the graph
Change-Id: I5804025f25733b5b5da1fd95725db3467a65abef
diff --git a/conf/karma-auto.conf.js b/conf/karma-auto.conf.js
index e66de9c..a5ea084 100644
--- a/conf/karma-auto.conf.js
+++ b/conf/karma-auto.conf.js
@@ -12,7 +12,7 @@
},
browsers: [
'PhantomJS',
- 'Chrome'
+ // 'Chrome'
],
frameworks: [
'jasmine',
diff --git a/src/app/service-graph/components/coarse/coarse.component.ts b/src/app/service-graph/components/coarse/coarse.component.ts
index d610aa6..4e681d7 100644
--- a/src/app/service-graph/components/coarse/coarse.component.ts
+++ b/src/app/service-graph/components/coarse/coarse.component.ts
@@ -6,13 +6,15 @@
import {XosServiceGraphConfig as config} from '../../graph.config';
import {IXosDebouncer} from '../../../core/services/helpers/debounce.helper';
import {Subscription} from 'rxjs';
+import {IXosGraphHelpers} from '../../services/d3-helpers/graph.helpers';
class XosCoarseTenancyGraphCtrl {
static $inject = [
'$log',
'XosServiceGraphStore',
- 'XosDebouncer'
+ 'XosDebouncer',
+ 'XosGraphHelpers'
];
public graph: IXosServiceGraph;
@@ -29,7 +31,8 @@
constructor (
private $log: ng.ILogService,
private XosServiceGraphStore: IXosServiceGraphStore,
- private XosDebouncer: IXosDebouncer
+ private XosDebouncer: IXosDebouncer,
+ private XosGraphHelpers: IXosGraphHelpers
) {
}
@@ -141,10 +144,6 @@
.start();
}
- private getSiblingTextBBox(contex: any /* D3 this */) {
- return d3.select(contex.parentNode).select('text').node().getBBox();
- }
-
private renderNodes(nodes: IXosServiceGraphNode[]) {
const self = this;
const node = this.nodeGroup
@@ -155,7 +154,7 @@
const entering = node.enter()
.append('g')
.attr({
- class: 'node',
+ class: n => `node ${this.XosGraphHelpers.parseElemClasses(n.d3Class)}`,
transform: `translate(${svgDim.width / 2}, ${svgDim.heigth / 2})`
})
.call(this.forceLayout.drag)
@@ -184,7 +183,7 @@
// resize node > rect as contained text
existing.each(function() {
- const textBBox = self.getSiblingTextBBox(this);
+ const textBBox = self.XosGraphHelpers.getSiblingTextBBox(this);
const rect = d3.select(this);
rect.attr({
width: textBBox.width + config.node.padding,
@@ -201,15 +200,12 @@
.data(links, l => l.id);
const entering = link.enter();
- // NOTE do we need to have groups?
- // .append('g')
- // .attr({
- // class: 'link',
- // });
+
+ // TODO read classes from graph links
entering.append('line')
.attr({
- class: 'link',
+ class: l => `link ${this.XosGraphHelpers.parseElemClasses(l.d3Class)}`,
'marker-start': 'url(#arrow)'
});
}
diff --git a/src/app/service-graph/components/fine-grained/fine-grained.component.ts b/src/app/service-graph/components/fine-grained/fine-grained.component.ts
index 522e06f..c7efd1c 100644
--- a/src/app/service-graph/components/fine-grained/fine-grained.component.ts
+++ b/src/app/service-graph/components/fine-grained/fine-grained.component.ts
@@ -8,6 +8,7 @@
import {IXosServiceGraph, IXosServiceGraphLink, IXosServiceGraphNode} from '../../interfaces';
import {IXosModelDiscovererService} from '../../../datasources/helpers/model-discoverer.service';
import {IXosSidePanelService} from '../../../core/side-panel/side-panel.service';
+import {IXosGraphHelpers} from '../../services/d3-helpers/graph.helpers';
class XosFineGrainedTenancyGraphCtrl {
static $inject = [
@@ -15,7 +16,8 @@
'XosServiceGraphStore',
'XosDebouncer',
'XosModelDiscoverer',
- 'XosSidePanel'
+ 'XosSidePanel',
+ 'XosGraphHelpers'
];
public graph: IXosServiceGraph;
@@ -35,7 +37,8 @@
private XosServiceGraphStore: IXosServiceGraphStore,
private XosDebouncer: IXosDebouncer,
private XosModelDiscoverer: IXosModelDiscovererService,
- private XosSidePanel: IXosSidePanelService
+ private XosSidePanel: IXosSidePanelService,
+ private XosGraphHelpers: IXosGraphHelpers
) {
this.handleSvg();
this.loadDefs();
@@ -158,10 +161,6 @@
.start();
}
- private getSiblingTextBBox(contex: any /* D3 this */) {
- return d3.select(contex.parentNode).select('text').node().getBBox();
- }
-
private renderServiceNodes(nodes: any) {
const self = this;
@@ -182,7 +181,7 @@
// resize node > rect as contained text
existing.each(function() {
- const textBBox = self.getSiblingTextBBox(this);
+ const textBBox = self.XosGraphHelpers.getSiblingTextBBox(this);
const rect = d3.select(this);
rect.attr({
width: textBBox.width + config.node.padding,
@@ -237,7 +236,7 @@
// resize node > rect as contained text
existing.each(function() {
- const textBBox = self.getSiblingTextBBox(this);
+ const textBBox = self.XosGraphHelpers.getSiblingTextBBox(this);
const useElem = d3.select(this);
const w = textBBox.width + config.node.padding * 2;
const h = w;
@@ -266,7 +265,7 @@
// resize node > rect as contained text
existing.each(function() {
- const textBBox = self.getSiblingTextBBox(this);
+ const textBBox = self.XosGraphHelpers.getSiblingTextBBox(this);
const rect = d3.select(this);
rect.attr({
width: textBBox.width + config.node.padding,
@@ -289,7 +288,7 @@
const entering = node.enter()
.append('g')
.attr({
- class: n => `node ${n.type}`,
+ class: n => `node ${n.type} ${this.XosGraphHelpers.parseElemClasses(n.d3Class)}`,
transform: (n, i) => `translate(${hStep * i}, ${vStep * i})`
})
.call(this.forceLayout.drag)
@@ -335,7 +334,7 @@
entering.append('line')
.attr({
- class: 'link',
+ class: n => `link ${this.XosGraphHelpers.parseElemClasses(n.d3Class)}`,
'marker-start': 'url(#arrow)'
});
}
diff --git a/src/app/service-graph/index.ts b/src/app/service-graph/index.ts
index 70b255e..00cf9e8 100644
--- a/src/app/service-graph/index.ts
+++ b/src/app/service-graph/index.ts
@@ -3,11 +3,15 @@
import {xosCore} from '../core/index';
import {XosCoarseTenancyGraph} from './components/coarse/coarse.component';
import {XosFineGrainedTenancyGraph} from './components/fine-grained/fine-grained.component';
+import {XosServiceGraphExtender, IXosServiceGraphExtender} from './services/graph.extender';
+import {XosGraphHelpers} from './services/d3-helpers/graph.helpers';
export const xosServiceGraph = 'xosServiceGraph';
angular
.module(xosServiceGraph, [xosDataSources, xosCore])
.service('XosServiceGraphStore', XosServiceGraphStore)
+ .service('XosServiceGraphExtender', XosServiceGraphExtender)
+ .service('XosGraphHelpers', XosGraphHelpers)
.component('xosCoarseTenancyGraph', XosCoarseTenancyGraph)
.component('xosFineGrainedTenancyGraph', XosFineGrainedTenancyGraph)
.config(($stateProvider) => {
@@ -17,6 +21,6 @@
component: 'xosFineGrainedTenancyGraph',
});
})
- .run(($log: ng.ILogService) => {
+ .run(($log: ng.ILogService, XosServiceGraphExtender: IXosServiceGraphExtender) => {
$log.info(`[${xosServiceGraph}] Module Setup`);
});
diff --git a/src/app/service-graph/interfaces.ts b/src/app/service-graph/interfaces.ts
index e08bc78..3dba9d3 100644
--- a/src/app/service-graph/interfaces.ts
+++ b/src/app/service-graph/interfaces.ts
@@ -1,13 +1,19 @@
+interface Id3Element {
+ d3Class?: string;
+ d3Id?: string;
+}
+
export interface IXosServiceModel {
id: number;
d3Id?: string;
backend_status: string;
kind: string;
name: string;
+ class_names: string;
service_specific_attributes: string; // this is json stringified
}
-export interface IXosTenantModel {
+export interface IXosTenantModel extends Id3Element {
id: number;
d3Id?: string;
backend_status: string;
@@ -48,19 +54,20 @@
text: string;
}
-export interface IXosServiceGraphNode {
+export interface IXosServiceGraphNode extends Id3Element {
id: number | string;
label: string;
x?: number;
y?: number;
px?: number;
py?: number;
- badge?: IXosServiceGraphNodeBadge;
+ fixed?: boolean;
+ badge?: IXosServiceGraphNodeBadge; // TODO implement badges
model: IXosServiceModel;
type: 'service' | 'tenant' | 'network' | 'subscriber';
}
-export interface IXosServiceGraphLink {
+export interface IXosServiceGraphLink extends Id3Element {
id: number | string;
source: number;
target: number;
diff --git a/src/app/service-graph/services/README.md b/src/app/service-graph/services/README.md
new file mode 100644
index 0000000..7058021
--- /dev/null
+++ b/src/app/service-graph/services/README.md
@@ -0,0 +1,37 @@
+# Service Graph extender example
+
+```
+XosServiceGraphExtender.register('coarse', 'test', (graph: IXosServiceGraph) => {
+ graph.nodes = graph.nodes.map(n => {
+ // do my changes
+ n.label = `reduced_${n.label}`;
+ return n;
+ });
+
+ graph.links = graph.links.map(l => {
+ // do my changes
+ return l;
+ });
+ return graph;
+});
+```
+
+Note that if you add classes you'll need to provide CSS for that
+
+## What can you change:
+
+### Nodes:
+
+You can change any of the property that are present in the `node` element, plus:
+
+property | type | effect
+-------- | ---- | -----:
+d3Class | space separated string |the class names get prefixed with `ext-`
+x | number | horizontal position
+y | number | vertical position
+
+### Links:
+
+property | type | effect
+-------- | ---- | -----:
+d3Class | space separated string |the class names get prefixed with `ext-`
diff --git a/src/app/service-graph/services/d3-helpers/graph.helpers.ts b/src/app/service-graph/services/d3-helpers/graph.helpers.ts
new file mode 100644
index 0000000..4bf4cb8
--- /dev/null
+++ b/src/app/service-graph/services/d3-helpers/graph.helpers.ts
@@ -0,0 +1,25 @@
+import * as d3 from 'd3';
+
+export interface Id3BBox {
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+}
+
+export interface IXosGraphHelpers {
+ parseElemClasses (classes: string): string;
+ getSiblingTextBBox(contex: any /* D3 this */): Id3BBox;
+}
+
+export class XosGraphHelpers implements IXosGraphHelpers {
+ public parseElemClasses (classes: string): string {
+ return classes ? classes.split(' ')
+ .map(c => `ext-${c}`)
+ .join(' ') : '';
+ }
+
+ public getSiblingTextBBox(contex: any): Id3BBox {
+ return d3.select(contex.parentNode).select('text').node().getBBox();
+ }
+}
diff --git a/src/app/service-graph/services/graph.extender.spec.ts b/src/app/service-graph/services/graph.extender.spec.ts
new file mode 100644
index 0000000..28ab96e
--- /dev/null
+++ b/src/app/service-graph/services/graph.extender.spec.ts
@@ -0,0 +1,47 @@
+import * as angular from 'angular';
+import 'angular-mocks';
+import 'angular-ui-router';
+import {IXosServiceGraphExtender, XosServiceGraphExtender} from './graph.extender';
+
+let service: IXosServiceGraphExtender, registerSpy;
+
+const reducer = (graph) => {
+ return graph;
+};
+
+describe('The XosServiceGraphExtender service', () => {
+
+ beforeEach(() => {
+ angular.module('xosServiceGraphExtender', [])
+ .service('XosServiceGraphExtender', XosServiceGraphExtender);
+
+ angular.mock.module('xosServiceGraphExtender');
+ });
+
+ beforeEach(angular.mock.inject((
+ XosServiceGraphExtender: IXosServiceGraphExtender,
+ ) => {
+ service = XosServiceGraphExtender;
+
+ registerSpy = spyOn(service, 'register').and.callThrough();
+ }));
+
+ it('should register a reducer for the coarse service graph', () => {
+ service.register('coarse', 'testCoarse', reducer);
+ expect(registerSpy).toHaveBeenCalled();
+ const coarseReducers = service.getCoarse();
+ expect(coarseReducers).toHaveLength(1);
+ expect(coarseReducers[0].name).toEqual('testCoarse');
+ expect(typeof coarseReducers[0].reducer).toEqual('function');
+ });
+
+ it('should register a reducer for the fine-grained service graph', () => {
+ service.register('finegrained', 'testFinegrained', reducer);
+ expect(registerSpy).toHaveBeenCalled();
+ const coarseReducers = service.getFinegrained();
+ expect(coarseReducers).toHaveLength(1);
+ expect(coarseReducers[0].name).toEqual('testFinegrained');
+ expect(typeof coarseReducers[0].reducer).toEqual('function');
+ });
+
+});
diff --git a/src/app/service-graph/services/graph.extender.ts b/src/app/service-graph/services/graph.extender.ts
new file mode 100644
index 0000000..ba9218f
--- /dev/null
+++ b/src/app/service-graph/services/graph.extender.ts
@@ -0,0 +1,57 @@
+import {IXosServiceGraph} from '../interfaces';
+
+export interface IXosServiceGraphReducers {
+ coarse: IXosServiceGraphReducer[];
+ finegrained: IXosServiceGraphReducer[];
+}
+
+export interface IXosServiceGraphReducer {
+ name: string;
+ reducer: IXosServiceGraphReducerFn;
+}
+
+export interface IXosServiceGraphReducerFn {
+ (graph: IXosServiceGraph): IXosServiceGraph;
+}
+
+export interface IXosServiceGraphExtender {
+ register(type: 'coarse' | 'finegrained', name: string, reducer: IXosServiceGraphReducerFn): boolean;
+ getCoarse(): IXosServiceGraphReducer[];
+ getFinegrained(): IXosServiceGraphReducer[];
+}
+
+export class XosServiceGraphExtender implements IXosServiceGraphExtender {
+
+ static $inject = ['$log'];
+
+ private reducers: IXosServiceGraphReducers = {
+ coarse: [],
+ finegrained: []
+ };
+
+ constructor (
+ private $log: ng.ILogService
+ ) {
+ }
+
+ public getCoarse(): IXosServiceGraphReducer[] {
+ return this.reducers.coarse;
+ }
+
+ public getFinegrained(): IXosServiceGraphReducer[] {
+ return this.reducers.finegrained;
+ }
+
+ // NOTE
+ // as now extender support:
+ // - nodes property: x, y, d3Class (applied to the group element)
+ // - links propery: d3Class (applied to the line element, there's no group for now)
+ public register(type: 'coarse' | 'finegrained', name: string, reducer: IXosServiceGraphReducerFn): boolean {
+ this.$log.debug(`[XosServiceGraphExtender] Registering ${name} reducer in ${type} list`);
+ this.reducers[type].push({
+ name,
+ reducer
+ });
+ return false;
+ }
+}
diff --git a/src/app/service-graph/services/graph.store.spec.ts b/src/app/service-graph/services/graph.store.spec.ts
new file mode 100644
index 0000000..9073d58
--- /dev/null
+++ b/src/app/service-graph/services/graph.store.spec.ts
@@ -0,0 +1,138 @@
+import * as angular from 'angular';
+import 'angular-mocks';
+import 'angular-ui-router';
+import {IXosServiceGraphStore, XosServiceGraphStore} from './graph.store';
+import {Subject} from 'rxjs';
+import {XosDebouncer} from '../../core/services/helpers/debounce.helper';
+import {IXosServiceGraph} from '../interfaces';
+import {XosServiceGraphExtender, IXosServiceGraphExtender} from './graph.extender';
+
+let service: IXosServiceGraphStore, extender: IXosServiceGraphExtender;
+
+const subjects = {
+ service: new Subject<any>(),
+ tenant: new Subject<any>(),
+ subscriber: new Subject<any>(),
+ network: new Subject<any>(),
+};
+
+// COARSE data
+const coarseServices = [
+ {
+ id: 1,
+ name: 'Service A',
+ class_names: 'Service,PlCoreBase'
+ },
+ {
+ id: 2,
+ name: 'Service B',
+ class_names: 'Service,PlCoreBase'
+ }
+];
+
+const coarseTenants = [
+ {
+ id: 1,
+ provider_service_id: 2,
+ subscriber_service_id: 1,
+ kind: 'coarse',
+ class_names: 'Tenant,PlCoreBase'
+ }
+];
+
+const mockModelStore = {
+ query: (modelName: string) => {
+ return subjects[modelName.toLowerCase()].asObservable();
+ }
+};
+
+describe('The XosServiceGraphStore service', () => {
+
+ beforeEach(() => {
+ angular.module('xosServiceGraphStore', [])
+ .service('XosServiceGraphStore', XosServiceGraphStore)
+ .value('XosModelStore', mockModelStore)
+ .service('XosServiceGraphExtender', XosServiceGraphExtender)
+ .service('XosDebouncer', XosDebouncer);
+
+ angular.mock.module('xosServiceGraphStore');
+ });
+
+ beforeEach(angular.mock.inject((
+ XosServiceGraphStore: IXosServiceGraphStore,
+ XosServiceGraphExtender: IXosServiceGraphExtender
+ ) => {
+ service = XosServiceGraphStore;
+ extender = XosServiceGraphExtender;
+ }));
+
+ describe('when subscribing for the COARSE service graph', () => {
+ beforeEach((done) => {
+ subjects.service.next(coarseServices);
+ subjects.tenant.next(coarseTenants);
+ setTimeout(done, 500);
+ });
+
+ it('should return an observer for the Coarse Service Graph', (done) => {
+ service.getCoarse()
+ .subscribe(
+ (res: IXosServiceGraph) => {
+ expect(res.nodes.length).toBe(2);
+ expect(res.nodes[0].d3Class).toBeUndefined();
+ expect(res.links.length).toBe(1);
+ expect(res.links[0].d3Class).toBeUndefined();
+ done();
+ },
+ (err) => {
+ done(err);
+ }
+ );
+ });
+
+ describe('when a reducer is register', () => {
+
+ beforeEach((done) => {
+ extender.register('coarse', 'test', (graph: IXosServiceGraph) => {
+ graph.nodes = graph.nodes.map(n => {
+ n.d3Class = `testNode`;
+ return n;
+ });
+
+ graph.links = graph.links.map(n => {
+ n.d3Class = `testLink`;
+ return n;
+ });
+
+ return graph;
+ });
+
+ // triggering another next cycle to apply the reducer
+ subjects.service.next(coarseServices);
+ subjects.tenant.next(coarseTenants);
+ setTimeout(done, 500);
+ });
+
+ it('should transform the result', (done) => {
+ service.getCoarse()
+ .subscribe(
+ (res: IXosServiceGraph) => {
+ expect(res.nodes.length).toBe(2);
+ expect(res.nodes[0].d3Class).toEqual('testNode');
+ expect(res.links.length).toBe(1);
+ expect(res.links[0].d3Class).toEqual('testLink');
+ done();
+ },
+ (err) => {
+ done(err);
+ }
+ );
+ });
+ });
+ });
+
+ describe('when subscribing for the Fine-grained service graph', () => {
+ xit('should have a test', () => {
+ expect(true).toBeTruthy();
+ });
+ });
+});
diff --git a/src/app/service-graph/services/graph.store.ts b/src/app/service-graph/services/graph.store.ts
index 1bb5d4c..54bc083 100644
--- a/src/app/service-graph/services/graph.store.ts
+++ b/src/app/service-graph/services/graph.store.ts
@@ -6,6 +6,7 @@
IXosServiceGraphNode, IXosServiceGraphLink, IXosFineGrainedGraphData
} from '../interfaces';
import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
+import {IXosServiceGraphExtender, IXosServiceGraphReducer} from './graph.extender';
export interface IXosServiceGraphStore {
get(): Observable<IXosServiceGraph>;
getCoarse(): Observable<IXosServiceGraph>;
@@ -15,7 +16,8 @@
static $inject = [
'$log',
'XosModelStore',
- 'XosDebouncer'
+ 'XosDebouncer',
+ 'XosServiceGraphExtender'
];
// graph data store
@@ -48,7 +50,8 @@
constructor (
private $log: ng.ILogService,
private XosModelStore: IXosModelStoreService,
- private XosDebouncer: IXosDebouncer
+ private XosDebouncer: IXosDebouncer,
+ private XosServiceGraphExtender: IXosServiceGraphExtender
) {
this.$log.info(`[XosServiceGraphStore] Setup`);
@@ -199,92 +202,112 @@
private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
- const links: IXosServiceGraphLink[] = _.chain(data.tenants)
- .filter((t: IXosTenantModel) => t.kind === 'coarse')
- .map((t: IXosTenantModel) => {
+ try {
+ const links: IXosServiceGraphLink[] = _.chain(data.tenants)
+ .filter((t: IXosTenantModel) => t.kind === 'coarse')
+ .map((t: IXosTenantModel) => {
+ return {
+ id: t.id,
+ source: this.getNodeIndexById(t.provider_service_id, data.services),
+ target: this.getNodeIndexById(t.subscriber_service_id, data.services),
+ model: t
+ };
+ })
+ .value();
+
+ const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
return {
- id: t.id,
- source: this.getNodeIndexById(t.provider_service_id, data.services),
- target: this.getNodeIndexById(t.subscriber_service_id, data.services),
- model: t
+ id: s.id,
+ label: s.name,
+ model: s
};
- })
- .value();
+ });
- const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
- return {
- id: s.id,
- label: s.name,
- model: s
+ let graph: IXosServiceGraph = {
+ nodes,
+ links
};
- });
- this.d3CoarseGraph.next({
- nodes: nodes,
- links: links
- });
+ _.forEach(this.XosServiceGraphExtender.getCoarse(), (r: IXosServiceGraphReducer) => {
+ graph = r.reducer(graph);
+ });
+
+ this.d3CoarseGraph.next(graph);
+ } catch (e) {
+ this.d3CoarseGraph.error(e);
+ }
}
private graphDataToFineGrainedGraph(data: IXosFineGrainedGraphData) {
- data = this.removeUnwantedFineGrainedData(data);
+ try {
+ data = this.removeUnwantedFineGrainedData(data);
- let nodes = _.reduce(Object.keys(data), (list: any[], k: string) => {
- return list.concat(data[k]);
- }, []);
+ let nodes = _.reduce(Object.keys(data), (list: any[], k: string) => {
+ return list.concat(data[k]);
+ }, []);
- nodes = _.chain(nodes)
- .map(n => {
- n.d3Id = this.d3Id(this.getNodeType(n), n.id);
- return n;
- })
- .map(n => {
- let node: IXosServiceGraphNode = {
- id: n.d3Id,
- label: this.getNodeLabel(n),
- model: n,
- type: this.getNodeType(n)
+ nodes = _.chain(nodes)
+ .map(n => {
+ n.d3Id = this.d3Id(this.getNodeType(n), n.id);
+ return n;
+ })
+ .map(n => {
+ let node: IXosServiceGraphNode = {
+ id: n.d3Id,
+ label: this.getNodeLabel(n),
+ model: n,
+ type: this.getNodeType(n)
+ };
+ return node;
+ })
+ .value();
+
+ const links = _.reduce(data.tenants, (links: IXosServiceGraphLink[], tenant: IXosTenantModel) => {
+ const sourceId = this.getSourceId(tenant);
+ const targetId = this.getTargetId(tenant);
+
+ if (!angular.isDefined(targetId)) {
+ // if the tenant is not pointing to anything, don't draw links
+ return links;
+ }
+
+ const tenantToProvider = {
+ id: `${sourceId}_${tenant.d3Id}`,
+ source: this.getNodeIndexById(sourceId, nodes),
+ target: this.getNodeIndexById(tenant.d3Id, nodes),
+ model: tenant
};
- return node;
- })
- .value();
- const links = _.reduce(data.tenants, (links: IXosServiceGraphLink[], tenant: IXosTenantModel) => {
- const sourceId = this.getSourceId(tenant);
- const targetId = this.getTargetId(tenant);
+ const tenantToSubscriber = {
+ id: `${tenant.d3Id}_${targetId}`,
+ source: this.getNodeIndexById(tenant.d3Id, nodes),
+ target: this.getNodeIndexById(targetId, nodes),
+ model: tenant
+ };
- if (!angular.isDefined(targetId)) {
- // if the tenant is not pointing to anything, don't draw links
+ links.push(tenantToProvider);
+ links.push(tenantToSubscriber);
return links;
+ }, []);
+
+ if (nodes.length === 0 || links.length === 0) {
+ return;
}
- const tenantToProvider = {
- id: `${sourceId}_${tenant.d3Id}`,
- source: this.getNodeIndexById(sourceId, nodes),
- target: this.getNodeIndexById(tenant.d3Id, nodes),
- model: tenant
+ let graph: IXosServiceGraph = {
+ nodes,
+ links
};
- const tenantToSubscriber = {
- id: `${tenant.d3Id}_${targetId}`,
- source: this.getNodeIndexById(tenant.d3Id, nodes),
- target: this.getNodeIndexById(targetId, nodes),
- model: tenant
- };
+ _.forEach(this.XosServiceGraphExtender.getFinegrained(), (r: IXosServiceGraphReducer) => {
+ graph = r.reducer(graph);
+ });
- links.push(tenantToProvider);
- links.push(tenantToSubscriber);
- return links;
- }, []);
-
- if (nodes.length === 0 || links.length === 0) {
- return;
+ this.d3FineGrainedGraph.next(graph);
+ } catch (e) {
+ this.d3FineGrainedGraph.error(e);
}
-
- this.d3FineGrainedGraph.next({
- nodes: nodes,
- links: links
- });
}
}