blob: bfe6c582dd1ad43eef128294a053939a3034c361 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import {IXosResourceService} from '../../datasources/rest/model.rest';
import {IXosSgNode} from '../interfaces';
import {IXosConfirm} from '../../core/confirm/confirm.service';
export interface IXosNodePositioner {
positionNodes(svg: {width: number, height: number}, nodes: any[]): ng.IPromise<IXosSgNode[]>;
}
export class XosNodePositioner implements IXosNodePositioner {
static $inject = [
'$log',
'$q',
'ModelRest',
'XosConfirm'
];
constructor (
private $log: ng.ILogService,
private $q: ng.IQService,
private ModelRest: IXosResourceService,
private XosConfirm: IXosConfirm
) {
this.$log.info('[XosNodePositioner] Setup');
}
public positionNodes(svg: {width: number, height: number}, nodes: IXosSgNode[]): ng.IPromise<IXosSgNode[]> {
const d = this.$q.defer();
this.getConstraints()
.then(constraints => {
const hStep = this.getHorizontalStep(svg.width, constraints);
const positionConstraints = _.reduce(constraints, (all: any, horizontalConstraint: string | string[], i: number) => {
// NOTE it's a single element, leave it in the middle
if (angular.isString(horizontalConstraint)) {
all[horizontalConstraint] = {
x: (i + 1) * hStep,
y: svg.height / 2,
fixed: true
};
}
else {
const verticalConstraints = horizontalConstraint;
const vStep = this.getVerticalStep(svg.height, verticalConstraints);
_.forEach(verticalConstraints, (verticalConstraint: string, v: number) => {
if (angular.isString(verticalConstraint)) {
all[verticalConstraint] = {
x: (i + 1) * hStep,
y: (v + 1) * vStep,
fixed: true
};
}
});
}
return all;
}, {});
// find the nodes that don't have a position defined and put them at the bottom
const allServiceNodes = _.reduce(nodes, (all: string[], n: IXosSgNode) => {
if (n.type === 'service') {
all.push(n.data.name);
}
return all;
}, []);
const positionedNodes = Object.keys(positionConstraints);
const unpositionedNodes = _.difference(allServiceNodes, positionedNodes);
_.forEach(unpositionedNodes, (node: string, i: number) => {
const hStep = this.getHorizontalStep(svg.width, unpositionedNodes);
positionConstraints[node] = {
x: (i + 1) * hStep,
y: svg.height - 50,
fixed: true
};
});
d.resolve(_.map(nodes, n => {
return angular.merge(n, positionConstraints[n.data.name]);
}));
})
.catch(e => {
this.$log.error(`[XosNodePositioner] Error retrieving constraints`, e);
});
return d.promise;
}
private getConstraints(): ng.IPromise<any[]> {
const d = this.$q.defer();
this.ModelRest.getResource('/core/servicegraphconstraints').query().$promise
.then(res => {
d.resolve(JSON.parse(res[0].constraints));
})
.catch(e => {
this.XosConfirm.open({
header: 'Error in graph constraints config',
text: `
There was an error in the settings you provided as graph constraints.
Please check the declaration of the <code>"Graph Constraints"</code> model. <br/>
The error was: <br/><br/>
<code>${e}</code>
<br/><br/>
Please fix it to see the graph.`,
actions: []
});
d.reject(e);
});
return d.promise;
}
private getHorizontalStep(svgWidth: number, constraints: any[]) {
return svgWidth / (constraints.length + 1);
}
private getVerticalStep(svgHeight: number, verticalConstraints: string[]) {
// NOTE verticalConstraints represent the vertical part (the nested array)
return svgHeight / (verticalConstraints.length + 1);
}
}