blob: d0e86b3574c02eddf3ece1b8da75042d352d671e [file] [log] [blame]
Matteo Scandolobe9b13d2016-01-21 11:21:03 -08001(function () {
2 'use strict';
3
4 angular.module('xos.serviceTopology')
5 .directive('serviceCanvas', function(){
6 return {
7 restrict: 'E',
8 scope: {},
9 bindToController: true,
10 controllerAs: 'vm',
11 templateUrl: 'templates/topology_canvas.tpl.html',
Matteo Scandolo68236262016-01-21 15:38:06 -080012 controller: function($element, $window, d3, serviceTopologyConfig, ServiceRelation, Slice, Instances){
Matteo Scandolobe9b13d2016-01-21 11:21:03 -080013
14 // count the mas depth of an object
15 const depthOf = (obj) => {
16 var depth = 0;
17 if (obj.children) {
18 obj.children.forEach(function (d) {
19 var tmpDepth = depthOf(d);
20 if (tmpDepth > depth) {
21 depth = tmpDepth
22 }
23 })
24 }
25 return 1 + depth
26 };
27
Matteo Scandolobe9b13d2016-01-21 11:21:03 -080028 const width = $window.innerWidth - serviceTopologyConfig.widthMargin;
29 const height = $window.innerHeight - serviceTopologyConfig.heightMargin;
30
31 const tree = d3.layout.tree()
32 .size([height, width]);
33
34 const diagonal = d3.svg.diagonal()
35 .projection(d => [d.y, d.x]);
36
37 const svg = d3.select($element[0])
38 .append('svg')
39 .style('width', `${$window.innerWidth}px`)
40 .style('height', `${$window.innerHeight}px`)
41 .append('g')
42 .attr("transform", "translate(" + serviceTopologyConfig.widthMargin+ "," + serviceTopologyConfig.heightMargin + ")");;
43
Matteo Scandolo85aad312016-01-21 14:23:28 -080044 //const resizeCanvas = () => {
45 // var targetSize = svg.node().getBoundingClientRect();
46 //
47 // d3.select(self.frameElement)
48 // .attr('width', `${targetSize.width}px`)
49 // .attr('height', `${targetSize.height}px`)
50 //};
Matteo Scandolobe9b13d2016-01-21 11:21:03 -080051 //d3.select(window)
52 // .on('load', () => {
53 // resizeCanvas();
54 // });
55 //d3.select(window)
56 // .on('resize', () => {
57 // resizeCanvas();
58 // update(root);
59 // });
Matteo Scandolo85aad312016-01-21 14:23:28 -080060 var root;
Matteo Scandolobe9b13d2016-01-21 11:21:03 -080061 var i = 0;
62 var duration = 750;
63
Matteo Scandolo85aad312016-01-21 14:23:28 -080064 const draw = (tree) => {
65 root = tree;
66 root.x0 = $window.innerHeight / 2;
67 root.y0 = 0;
68
69 update(root);
70 };
Matteo Scandolobe9b13d2016-01-21 11:21:03 -080071
72 function update(source) {
73
74 const maxDepth = depthOf(source);
75
76 // Compute the new tree layout.
77 var nodes = tree.nodes(root).reverse(),
78 links = tree.links(nodes);
79
80 // Normalize for fixed-depth.
81 nodes.forEach(function(d) {
82 console.log(d);
83 // 180 should be based on window.width and max node depth
84
85 d.y = d.depth * (($window.innerWidth - (serviceTopologyConfig.widthMargin * 2)) / maxDepth);
86 console.log(d.x);
87 });
88
89 // Update the nodes…
90 var node = svg.selectAll('g.node')
91 .data(nodes, function(d) { return d.id || (d.id = ++i); });
92
93 // Enter any new nodes at the parent's previous position.
94 var nodeEnter = node.enter().append('g')
95 .attr('class', 'node')
96 .attr('transform', function(d) {
97 // this is the starting position
98 return 'translate(' + source.y0 + ',' + source.x0 + ')';
Matteo Scandolo68236262016-01-21 15:38:06 -080099 })
100 .on('click', click);
Matteo Scandolobe9b13d2016-01-21 11:21:03 -0800101
102 nodeEnter.append('circle')
103 .attr('r', 1e-6)
104 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
105
106 nodeEnter.append('text')
107 .attr('x', function(d) { return d.children || d._children ? -13 : 13; })
Matteo Scandolo68236262016-01-21 15:38:06 -0800108 .attr('transform', function(d) {
109 if((d.children || d._children) && d.parent || d._parent){
110 return 'rotate(30)';
111 }
112 return;
113 })
Matteo Scandolobe9b13d2016-01-21 11:21:03 -0800114 .attr('dy', '.35em')
115 .attr('text-anchor', function(d) { return d.children || d._children ? 'end' : 'start'; })
116 .text(function(d) { return d.name; })
117 .style('fill-opacity', 1e-6);
118
119 // Transition nodes to their new position.
120 var nodeUpdate = node.transition()
121 .duration(duration)
122 .attr('transform', function(d) {
123 return 'translate(' + d.y + ',' + d.x + ')';
124 });
125
126 nodeUpdate.select('circle')
127 .attr('r', 10)
128 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
129
130 nodeUpdate.select('text')
131 .style('fill-opacity', 1);
132
133 // Transition exiting nodes to the parent's new position.
134 var nodeExit = node.exit().transition()
135 .duration(duration)
136 .attr('transform', function(d) { return 'translate(' + source.y + ',' + source.x + ')'; })
137 .remove();
138
139 nodeExit.select('circle')
140 .attr('r', 1e-6);
141
142 nodeExit.select('text')
143 .style('fill-opacity', 1e-6);
144
145 // Update the links…
146 var link = svg.selectAll('path.link')
147 .data(links, function(d) { return d.target.id; });
148
149 // Enter any new links at the parent's previous position.
150 link.enter().insert('path', 'g')
151 .attr('class', 'link')
152 .attr('d', function(d) {
153 var o = {x: source.x0, y: source.y0};
154 return diagonal({source: o, target: o});
155 });
156
157 // Transition links to their new position.
158 link.transition()
159 .duration(duration)
160 .attr('d', diagonal);
161
162 // Transition exiting nodes to the parent's new position.
163 link.exit().transition()
164 .duration(duration)
165 .attr('d', function(d) {
166 var o = {x: source.x, y: source.y};
167 return diagonal({source: o, target: o});
168 })
169 .remove();
170
171 // Stash the old positions for transition.
172 nodes.forEach(function(d) {
173 d.x0 = d.x;
174 d.y0 = d.y;
175 });
176 }
Matteo Scandolo85aad312016-01-21 14:23:28 -0800177
Matteo Scandolo68236262016-01-21 15:38:06 -0800178 const click = (d) => {
179 console.log(d);
180 this.selectedService = {
181 id: d.id,
182 name: d.name
183 };
184 Slice.query({service: d.id}).$promise
185 .then(slices => {
186 this.instances = null;
187 this.slices = slices;
188 })
189 };
190
Matteo Scandolo85aad312016-01-21 14:23:28 -0800191 ServiceRelation.get()
192 .then((tree) => {
193 console.log(tree);
194 draw(tree);
195 });
Matteo Scandolo68236262016-01-21 15:38:06 -0800196
197 this.getInstances = (slice) => {
198 Instances.query({slice: slice.id}).$promise
199 .then((instances) => {
200 this.selectedSlice = slice;
201 this.instances = instances;
202 })
203 };
Matteo Scandolobe9b13d2016-01-21 11:21:03 -0800204 }
205 }
206 });
207
208}());