1 define(['next-ui'], function() {
3 var NextTopology = function (NextTopologyService){
13 template: '<div id="graph-container" class="col-md-12"></div>',
14 link: function(scope) {
15 var saveTopoInterval = null;
20 * Colors used for topology objects
21 * @type {nx.data.Dictionary}
23 scope.topoColors = new nx.data.Dictionary({
24 'operational': '#0f9d58',
25 'configured': '#464646',
26 'operational-mixed': '#C4AF00',
29 'forwarding-box': '#0386d2',
34 * init next topology graph
36 scope.init = function (successCbk) {
37 // register "font" icon
38 nx.graphic.Icons.registerFontIcon('devicedown', 'FontAwesome', "\uf057", 20);
40 var circle = "<defs xmlns='http://www.w3.org/2000/svg'><marker id='circle' viewBox='-3 -3 6 6' markerWidth='6' markerHeight='6' orient='auto'> <circle r='3' fill='#68BD6B'></circle></marker></defs>";
42 var app = new nx.ui.Application();
44 document.getElementById('graph-container').innerHTML = '';
45 app.container(document.getElementById('graph-container'));
47 scope.topo = NextTopologyService.getNxTopClass(scope.topoColors);
48 scope.setTopoEvents();
49 scope.topo.stage().addDefString(circle);
54 // TODO: remove when come to decision about depiction of node status
55 //createNodeStatusLayer();
60 // App events - if app is resized
61 app.on('resize', function(){
62 scope.topo.adaptToContainer();
66 scope.topo.attach(app);
76 scope.setTopoEvents = function () {
77 // Fired when the app is ready and displayed
78 scope.topo.on('ready', function (sender, event) {
79 scope.topo.data(scope.topologyData);
82 if ( scope.dictionaries ){
83 var data = NextTopologyService.readTopologyDataFromLS();
84 NextTopologyService.setTopologyDataFromLS(data, scope.topo, scope.dictionaries.nodes);
87 // clear interval after reload data
88 if ( saveTopoInterval ) {
89 clearInterval(saveTopoInterval);
92 // set interval for saving topo nodes position
93 saveTopoInterval = window.setInterval(function(){NextTopologyService.saveTopologyDataToLS(scope.topo);}, 5000);
96 // Fired when topology is generated
97 scope.topo.on('topologyGenerated', function(sender, event) {
99 // use custom events for the topology
100 // TODO: remove when come to decision about depiction of node status
101 //sender.attachLayer("status", "NodeStatus");
102 sender.registerScene('ce', 'CustomEvents');
103 sender.activateScene('ce');
104 scope.topo.tooltipManager().showNodeTooltip(false);
109 * Watching topology data
111 scope.$watch('topologyData', function(){
112 //console.log('scope.topologyData', scope.topologyData);
114 //if( scope.topologyData.nodes.length ) { //&& initialized === false
115 scope.init(scope.cbkFunctions.topologyGenerated);
120 * Extend base nx node class function
122 function extendNodeClass(){
123 nx.define('ExtendedNode', nx.graphic.Topology.Node, {
124 view: function(view){
127 "name": "deviceDownBadge",
128 "type": "nx.graphic.Group",
131 "name": "deviceDownBadgeBg",
132 "type": "nx.graphic.Rect",
134 "class": "device-down-bg",
140 "name": "deviceDownBadgeText",
141 "type": "nx.graphic.Icon",
144 "iconType": "devicedown",
156 // inherit properties/parent's data
157 init: function(args){
158 this.inherited(args);
159 var stageScale = this.topology().stageScale();
160 this.view('label').setStyle('font-size', 14 * stageScale);
162 // inherit parent's model
163 'setModel': function(model) {
164 this.inherited(model);
167 this._drawDeviceDownBadge(this.model());
170 "_drawDeviceDownBadge": function(model){
172 var badge, badgeBg, badgeText,
173 icon, iconSize, iconScale,
174 bound, boundMax, badgeTransform,
175 badgeVisibility = model.get("status") === "configured";
178 badge = this.view("deviceDownBadge");
179 badgeBg = this.view("deviceDownBadgeBg");
180 badgeText = this.view("deviceDownBadgeText");
182 // view of device icon
183 icon = this.view('icon');
184 iconSize = icon.size();
185 iconScale = icon.scale();
187 // define position of the badge
189 x: iconSize.width * iconScale / -2.5,
190 y: iconSize.height * iconScale / 3
193 // make badge visible
194 badgeText.set("visible", badgeVisibility);
196 // get bounds and apply them for white background
197 bound = badge.getBound();
198 boundMax = Math.max(bound.width - 6, 1);
201 visible: badgeVisibility
204 // set position of the badge
205 badgeBg.setTransform(badgeTransform.x, badgeTransform.y);
206 badgeText.setTransform(badgeTransform.x, badgeTransform.y);
209 "_showDownBadge": function(){
210 this.view("deviceDownBadgeBg").set("visible", true);
211 this.view("deviceDownBadgeText").set("visible", true);
213 "_hideDownBadge": function(){
214 this.view("deviceDownBadgeBg").set("visible", false);
215 this.view("deviceDownBadgeText").set("visible", false);
222 * Extend base nx link class function
224 function extendLinkClass () {
225 nx.define('ExtendedLink', nx.graphic.Topology.Link, {
226 view: function(view){
229 type: 'nx.graphic.Group',
233 type: 'nx.graphic.Rect',
235 'class': 'link-set-circle',
241 type: 'nx.graphic.Text',
243 'class': 'link-set-text',
254 this.view("badge").setTransform(null, null, a);
255 var b = (this._width || 1) * a;
256 this.view("line").dom().setStyle("stroke-width", b);
257 this.view("path").dom().setStyle("stroke-width", b);
258 this._stageScale = a;
264 // inherit properties/parent's data
265 init: function(args){
266 this.inherited(args);
267 this.topology().fit();
269 // inherit parent's model
270 'setModel': function(model) {
271 this.inherited(model);
272 //if(model._data.linksIntegrity){
273 // this.view('statusIcon').set('src', 'assets/images/attention.png');
276 // when topology's updated
281 // ECMP badge settings
282 var badge = this.view('badge');
283 var badgeText = this.view('badgeText');
284 var badgeBg = this.view('badgeBg');
285 var statusIcon = this.view('statusIcon');
286 var status = this.model()._data.status;
287 ECMP, not needed here
288 if( this.model()._data.gLinks.length > 2 ) {
290 text: status.operational + '/' + status.configured,
293 var bound = badge.getBound();
294 var boundMax = Math.max(bound.width - 6, 1);
295 badgeBg.sets({width: boundMax, visible: true});
296 badgeBg.setTransform(boundMax / -2);
297 var centerPoint = this.centerPoint();
298 badge.setTransform(centerPoint.x, centerPoint.y);
300 // record source & target 'node-id's
301 var sourceNode = this.model().source()._data;
302 this.model()._data.sourceName = this.model().source()._data.label;
303 this.model()._data.targetName = this.model().target()._data.label;
305 this.view("badge").visible(true);
306 this.view("badgeBg").visible(true);
307 this.view("badgeText").visible(true);
309 //set correct link color
310 this.set('color',this.getColor());
313 this.setProviderStyleLine();
314 this.set('color', this.getColor());
316 // generate the color for a link
317 getColor: function(){
318 // get color depend on status
319 var color = this.model()._data.type === 'chain' ? '#3366ff' : '#009900';
320 // make it available outside next
321 this.model()._data.linkColor = color;
325 setProviderStyleLine: function() {
326 var _offset = this.getOffset();
327 var offset = new nx.geometry.Vector(0, _offset);
328 var stageScale = this.stageScale();
329 var line = this.reverse() ? this.line().negate() : this.line();
330 var lineEl = this.view('line');
331 var newLine = line.translate(offset).pad(25 * stageScale, 17 * stageScale);
338 lineEl.setStyle('marker-start', 'url(#circle)');
345 * Extended class for tooltip nx component
347 function extendedTooltip(){
348 nx.define('ExtendedTooltip', nx.ui.Component, {
353 view: NextTopologyService.getTooltipContent()
359 * Define custom events for topology componets
361 function defineCustomEvents(){
362 nx.define('CustomEvents', nx.graphic.Topology.DefaultScene, {
364 clickNode: function(sender, node){
365 if ( scope.cbkFunctions.clickNode ) {
366 scope.cbkFunctions.clickNode(node);
369 clickLink: function(sender, link){
370 if ( scope.cbkFunctions.clickLink ) {
371 scope.cbkFunctions.clickLink(link);
379 // TODO: remove when come to decision about depiction of node status
381 // * Creating new node status layer - circles representing device status - up, down
383 //function createNodeStatusLayer(){
384 // nx.define("NodeStatus", nx.graphic.Topology.Layer, {
385 // nx.define("NodeStatus", nx.graphic.Topology.Layer, {
387 // draw: function() {
388 // var topo = this.topology();
389 // topo.eachNode(function(node) {
390 // var nodeStatus = node._model._data.status === 'operational' ? node._model._data.status : 'down',
391 // //type = node._model._data.type,
392 // dot = new nx.graphic.Circle({
398 // dot.set("fill", topoColors.getItem(nodeStatus));
411 NextTopology.$inject=['NextTopologyService'];