blob: 82061942beef6298512b125cfc5902ab933275c3 [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 Scandolof16b3792016-01-21 14:23:28 -080012 controller: function($element, $window, d3, serviceTopologyConfig, ServiceRelation){
Matteo Scandolo8a64fa42016-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 Scandolof16b3792016-01-21 14:23:28 -080028 ServiceRelation.get()
29 .then(res => {
30 //console.log(res);
31 });
32
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080033 const treeData = [
34 {
35 'name': 'Top Level',
36 'parent': 'null',
37 'children': [
38 {
39 'name': 'Level 2: A',
40 'parent': 'Top Level',
41 'children': [
42 {
43 'name': 'Son of A',
44 'parent': 'Level 2: A'
45 },
46 {
47 'name': 'Daughter of A',
48 'parent': 'Level 2: A'
49 }
50 ]
51 },
52 {
53 'name': 'Level 2: B',
54 'parent': 'Top Level'
55 }
56 ]
57 }
58 ];
59
60 const width = $window.innerWidth - serviceTopologyConfig.widthMargin;
61 const height = $window.innerHeight - serviceTopologyConfig.heightMargin;
62
63 const tree = d3.layout.tree()
64 .size([height, width]);
65
66 const diagonal = d3.svg.diagonal()
67 .projection(d => [d.y, d.x]);
68
69 const svg = d3.select($element[0])
70 .append('svg')
71 .style('width', `${$window.innerWidth}px`)
72 .style('height', `${$window.innerHeight}px`)
73 .append('g')
74 .attr("transform", "translate(" + serviceTopologyConfig.widthMargin+ "," + serviceTopologyConfig.heightMargin + ")");;
75
Matteo Scandolof16b3792016-01-21 14:23:28 -080076 //const resizeCanvas = () => {
77 // var targetSize = svg.node().getBoundingClientRect();
78 //
79 // d3.select(self.frameElement)
80 // .attr('width', `${targetSize.width}px`)
81 // .attr('height', `${targetSize.height}px`)
82 //};
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080083 //d3.select(window)
84 // .on('load', () => {
85 // resizeCanvas();
86 // });
87 //d3.select(window)
88 // .on('resize', () => {
89 // resizeCanvas();
90 // update(root);
91 // });
Matteo Scandolof16b3792016-01-21 14:23:28 -080092 var root;
Matteo Scandolo8a64fa42016-01-21 11:21:03 -080093 var i = 0;
94 var duration = 750;
95
Matteo Scandolof16b3792016-01-21 14:23:28 -080096 const draw = (tree) => {
97 root = tree;
98 root.x0 = $window.innerHeight / 2;
99 root.y0 = 0;
100
101 update(root);
102 };
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800103
104 function update(source) {
105
106 const maxDepth = depthOf(source);
107
108 // Compute the new tree layout.
109 var nodes = tree.nodes(root).reverse(),
110 links = tree.links(nodes);
111
112 // Normalize for fixed-depth.
113 nodes.forEach(function(d) {
114 console.log(d);
115 // 180 should be based on window.width and max node depth
116
117 d.y = d.depth * (($window.innerWidth - (serviceTopologyConfig.widthMargin * 2)) / maxDepth);
118 console.log(d.x);
119 });
120
121 // Update the nodes…
122 var node = svg.selectAll('g.node')
123 .data(nodes, function(d) { return d.id || (d.id = ++i); });
124
125 // Enter any new nodes at the parent's previous position.
126 var nodeEnter = node.enter().append('g')
127 .attr('class', 'node')
128 .attr('transform', function(d) {
129 // this is the starting position
130 return 'translate(' + source.y0 + ',' + source.x0 + ')';
131 });
132 //.on('click', click);
133
134 nodeEnter.append('circle')
135 .attr('r', 1e-6)
136 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
137
138 nodeEnter.append('text')
139 .attr('x', function(d) { return d.children || d._children ? -13 : 13; })
140 .attr('dy', '.35em')
141 .attr('text-anchor', function(d) { return d.children || d._children ? 'end' : 'start'; })
142 .text(function(d) { return d.name; })
143 .style('fill-opacity', 1e-6);
144
145 // Transition nodes to their new position.
146 var nodeUpdate = node.transition()
147 .duration(duration)
148 .attr('transform', function(d) {
149 return 'translate(' + d.y + ',' + d.x + ')';
150 });
151
152 nodeUpdate.select('circle')
153 .attr('r', 10)
154 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
155
156 nodeUpdate.select('text')
157 .style('fill-opacity', 1);
158
159 // Transition exiting nodes to the parent's new position.
160 var nodeExit = node.exit().transition()
161 .duration(duration)
162 .attr('transform', function(d) { return 'translate(' + source.y + ',' + source.x + ')'; })
163 .remove();
164
165 nodeExit.select('circle')
166 .attr('r', 1e-6);
167
168 nodeExit.select('text')
169 .style('fill-opacity', 1e-6);
170
171 // Update the links…
172 var link = svg.selectAll('path.link')
173 .data(links, function(d) { return d.target.id; });
174
175 // Enter any new links at the parent's previous position.
176 link.enter().insert('path', 'g')
177 .attr('class', 'link')
178 .attr('d', function(d) {
179 var o = {x: source.x0, y: source.y0};
180 return diagonal({source: o, target: o});
181 });
182
183 // Transition links to their new position.
184 link.transition()
185 .duration(duration)
186 .attr('d', diagonal);
187
188 // Transition exiting nodes to the parent's new position.
189 link.exit().transition()
190 .duration(duration)
191 .attr('d', function(d) {
192 var o = {x: source.x, y: source.y};
193 return diagonal({source: o, target: o});
194 })
195 .remove();
196
197 // Stash the old positions for transition.
198 nodes.forEach(function(d) {
199 d.x0 = d.x;
200 d.y0 = d.y;
201 });
202 }
Matteo Scandolof16b3792016-01-21 14:23:28 -0800203
204 ServiceRelation.get()
205 .then((tree) => {
206 console.log(tree);
207 draw(tree);
208 });
209 //draw(treeData[0]);
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800210 }
211 }
212 });
213
214}());