blob: f7a70e570270a019354e5f5631815eafbe9b781e [file] [log] [blame]
Matteo Scandolo8a64fa42016-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 Scandolo06f45d62016-01-21 15:38:06 -080012 controller: function($element, $window, d3, serviceTopologyConfig, ServiceRelation, Slice, Instances){
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080013
Matteo Scandolo6e8a75a2016-01-22 09:33:26 -080014 this.instances = [];
15 this.slices = [];
16
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080017 // count the mas depth of an object
18 const depthOf = (obj) => {
19 var depth = 0;
20 if (obj.children) {
21 obj.children.forEach(function (d) {
22 var tmpDepth = depthOf(d);
23 if (tmpDepth > depth) {
24 depth = tmpDepth
25 }
26 })
27 }
28 return 1 + depth
29 };
30
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080031 const width = $window.innerWidth - serviceTopologyConfig.widthMargin;
32 const height = $window.innerHeight - serviceTopologyConfig.heightMargin;
33
34 const tree = d3.layout.tree()
35 .size([height, width]);
36
37 const diagonal = d3.svg.diagonal()
38 .projection(d => [d.y, d.x]);
39
40 const svg = d3.select($element[0])
41 .append('svg')
42 .style('width', `${$window.innerWidth}px`)
43 .style('height', `${$window.innerHeight}px`)
44 .append('g')
45 .attr("transform", "translate(" + serviceTopologyConfig.widthMargin+ "," + serviceTopologyConfig.heightMargin + ")");;
46
Matteo Scandolof16b3792016-01-21 14:23:28 -080047 //const resizeCanvas = () => {
48 // var targetSize = svg.node().getBoundingClientRect();
49 //
50 // d3.select(self.frameElement)
51 // .attr('width', `${targetSize.width}px`)
52 // .attr('height', `${targetSize.height}px`)
53 //};
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080054 //d3.select(window)
55 // .on('load', () => {
56 // resizeCanvas();
57 // });
58 //d3.select(window)
59 // .on('resize', () => {
60 // resizeCanvas();
61 // update(root);
62 // });
Matteo Scandolof16b3792016-01-21 14:23:28 -080063 var root;
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080064 var i = 0;
65 var duration = 750;
66
Matteo Scandolof16b3792016-01-21 14:23:28 -080067 const draw = (tree) => {
68 root = tree;
69 root.x0 = $window.innerHeight / 2;
70 root.y0 = 0;
71
72 update(root);
73 };
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080074
75 function update(source) {
76
77 const maxDepth = depthOf(source);
78
79 // Compute the new tree layout.
80 var nodes = tree.nodes(root).reverse(),
81 links = tree.links(nodes);
82
83 // Normalize for fixed-depth.
84 nodes.forEach(function(d) {
Matteo Scandolo3501ccb2016-01-21 16:02:57 -080085 // position the child node horizontally
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080086 d.y = d.depth * (($window.innerWidth - (serviceTopologyConfig.widthMargin * 2)) / maxDepth);
87 console.log(d.x);
88 });
89
90 // Update the nodes…
91 var node = svg.selectAll('g.node')
92 .data(nodes, function(d) { return d.id || (d.id = ++i); });
93
94 // Enter any new nodes at the parent's previous position.
95 var nodeEnter = node.enter().append('g')
96 .attr('class', 'node')
97 .attr('transform', function(d) {
98 // this is the starting position
99 return 'translate(' + source.y0 + ',' + source.x0 + ')';
Matteo Scandolo3501ccb2016-01-21 16:02:57 -0800100 });
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800101
102 nodeEnter.append('circle')
103 .attr('r', 1e-6)
Matteo Scandolo3501ccb2016-01-21 16:02:57 -0800104 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; })
105 .on('click', click);
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800106
107 nodeEnter.append('text')
108 .attr('x', function(d) { return d.children || d._children ? -13 : 13; })
Matteo Scandolo06f45d62016-01-21 15:38:06 -0800109 .attr('transform', function(d) {
110 if((d.children || d._children) && d.parent || d._parent){
111 return 'rotate(30)';
112 }
113 return;
114 })
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800115 .attr('dy', '.35em')
116 .attr('text-anchor', function(d) { return d.children || d._children ? 'end' : 'start'; })
117 .text(function(d) { return d.name; })
118 .style('fill-opacity', 1e-6);
119
120 // Transition nodes to their new position.
121 var nodeUpdate = node.transition()
122 .duration(duration)
123 .attr('transform', function(d) {
124 return 'translate(' + d.y + ',' + d.x + ')';
125 });
126
127 nodeUpdate.select('circle')
128 .attr('r', 10)
129 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
130
131 nodeUpdate.select('text')
132 .style('fill-opacity', 1);
133
134 // Transition exiting nodes to the parent's new position.
135 var nodeExit = node.exit().transition()
136 .duration(duration)
137 .attr('transform', function(d) { return 'translate(' + source.y + ',' + source.x + ')'; })
138 .remove();
139
140 nodeExit.select('circle')
141 .attr('r', 1e-6);
142
143 nodeExit.select('text')
144 .style('fill-opacity', 1e-6);
145
146 // Update the links…
147 var link = svg.selectAll('path.link')
148 .data(links, function(d) { return d.target.id; });
149
150 // Enter any new links at the parent's previous position.
151 link.enter().insert('path', 'g')
152 .attr('class', 'link')
153 .attr('d', function(d) {
154 var o = {x: source.x0, y: source.y0};
155 return diagonal({source: o, target: o});
156 });
157
158 // Transition links to their new position.
159 link.transition()
160 .duration(duration)
161 .attr('d', diagonal);
162
163 // Transition exiting nodes to the parent's new position.
164 link.exit().transition()
165 .duration(duration)
166 .attr('d', function(d) {
167 var o = {x: source.x, y: source.y};
168 return diagonal({source: o, target: o});
169 })
170 .remove();
171
172 // Stash the old positions for transition.
173 nodes.forEach(function(d) {
174 d.x0 = d.x;
175 d.y0 = d.y;
176 });
177 }
Matteo Scandolof16b3792016-01-21 14:23:28 -0800178
Matteo Scandolo3501ccb2016-01-21 16:02:57 -0800179 var _this = this;
180 const click = function(d) {
181
Matteo Scandolo6e8a75a2016-01-22 09:33:26 -0800182 // empty panel
183 _this.slices = [];
184 _this.instances = [];
185
186 var nodes = d3.selectAll('circle')
187 .transition()
188 .duration(duration)
189 .attr('r', 10);
190
191 d3.selectAll('rect.slice-detail')
192 .remove();
193
194 d3.selectAll('text.slice-name')
195 .remove();
196
197 var selectedNode = d3.select(this);
198
199 selectedNode
200 .transition()
201 .duration(duration)
202 .attr('r', 30);
Matteo Scandolo3501ccb2016-01-21 16:02:57 -0800203
204 _this.selectedService = {
Matteo Scandolo06f45d62016-01-21 15:38:06 -0800205 id: d.id,
206 name: d.name
207 };
Matteo Scandolo6e8a75a2016-01-22 09:33:26 -0800208
Matteo Scandolo06f45d62016-01-21 15:38:06 -0800209 Slice.query({service: d.id}).$promise
210 .then(slices => {
Matteo Scandolo3501ccb2016-01-21 16:02:57 -0800211 _this.slices = slices;
Matteo Scandolo6e8a75a2016-01-22 09:33:26 -0800212
213 if(slices.length > 0){
214 const parentNode = d3.select(this.parentNode);
215
216 parentNode
217 .append('rect')
218 .style('opacity', 0)
219 .attr({
220 width: 150,
221 height: 50,
222 y: 35,
223 x: -75,
224 class: 'slice-detail'
225 })
226 .transition()
227 .duration(duration)
228 .style('opacity', 1);
229
230 parentNode
231 .append('text')
232 .style('opacity', 0)
233 .attr({
234 y: 65,
235 x: -60,
236 class: 'slice-name'
237 })
238 .text(() => {
239 if(slices[0]){
240 console.log(slices[0].humanReadableName);
241 return slices[0].humanReadableName;
242 }
243
244 return '';
245 })
246 .transition()
247 .duration(duration)
248 .style('opacity', 1);
249 }
Matteo Scandolo06f45d62016-01-21 15:38:06 -0800250 })
251 };
252
Matteo Scandolof16b3792016-01-21 14:23:28 -0800253 ServiceRelation.get()
254 .then((tree) => {
Matteo Scandolof16b3792016-01-21 14:23:28 -0800255 draw(tree);
256 });
Matteo Scandolo06f45d62016-01-21 15:38:06 -0800257
258 this.getInstances = (slice) => {
259 Instances.query({slice: slice.id}).$promise
260 .then((instances) => {
261 this.selectedSlice = slice;
262 this.instances = instances;
263 })
264 };
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800265 }
266 }
267 });
268
269}());