Drawing logic layer shapes
diff --git a/views/ngXosViews/diagnostic/src/css/serviceTopology.css b/views/ngXosViews/diagnostic/src/css/serviceTopology.css
index d9b219d..634b6ed 100644
--- a/views/ngXosViews/diagnostic/src/css/serviceTopology.css
+++ b/views/ngXosViews/diagnostic/src/css/serviceTopology.css
@@ -4,6 +4,14 @@
     height: 50%;
 }
 
+diagnostic .subscriber-select{
+    max-width: 200px;
+    position: absolute;
+    top: 20px;
+    right: 20px;
+    z-index: 1;
+}
+
 .half-height + .half-height {
     border-top: 1px solid black;
 }
@@ -24,6 +32,12 @@
     stroke-width: 1px;
 }
 
+logic-topology .network .cloud {
+    fill: #fff;
+    stroke: green;
+    stroke-width: 1px;   
+}
+
 /* LEGEND */
 
 .legend {
@@ -49,7 +63,9 @@
 }
 
 .node.subscriber circle,
-.node.internet circle {
+.node.subscriber rect,
+.node.router circle,
+.node.router rect {
     stroke: #05ffcb;
 }
 
diff --git a/views/ngXosViews/diagnostic/src/index.html b/views/ngXosViews/diagnostic/src/index.html
index d9bfc1e..afe559c 100644
--- a/views/ngXosViews/diagnostic/src/index.html
+++ b/views/ngXosViews/diagnostic/src/index.html
@@ -36,6 +36,7 @@
 <script src="/.tmp/serviceTopologyHelper.js"></script>
 <script src="/.tmp/serviceTopology.js"></script>
 <script src="/.tmp/rest_services.js"></script>
+<script src="/.tmp/nodeDrawer.js"></script>
 <script src="/.tmp/logicTopologyHelper.js"></script>
 <script src="/.tmp/logicTopology.js"></script>
 <script src="/.tmp/diagnostic.js"></script>
diff --git a/views/ngXosViews/diagnostic/src/js/config.js b/views/ngXosViews/diagnostic/src/js/config.js
index 91ea0c2..7308995 100644
--- a/views/ngXosViews/diagnostic/src/js/config.js
+++ b/views/ngXosViews/diagnostic/src/js/config.js
@@ -8,6 +8,7 @@
     duration: 750,
     circle: {
       radius: 10,
+      r: 10,
       selectedRadius: 15
     },
     square: {
@@ -15,6 +16,12 @@
       height: 20,
       x: -10,
       y: -10
+    },
+    rack: {
+      width: 50,
+      height: 50,
+      x: -25,
+      y: -25
     }
   })
 
diff --git a/views/ngXosViews/diagnostic/src/js/logicTopologyHelper.js b/views/ngXosViews/diagnostic/src/js/logicTopologyHelper.js
index 56d1f56..d33de36 100644
--- a/views/ngXosViews/diagnostic/src/js/logicTopologyHelper.js
+++ b/views/ngXosViews/diagnostic/src/js/logicTopologyHelper.js
@@ -2,104 +2,7 @@
   'use strict';
 
   angular.module('xos.serviceTopology')
-  .service('LogicTopologyHelper', function($window, $log, lodash, serviceTopologyConfig){
-
-    var hStep, vStep;
-
-    const createDevice = (container, device, xPos, yPos, target) => {
-
-      const deviceGroup = container.append('g')
-      .attr({
-        class: 'device',
-        transform: `translate(${xPos}, ${yPos})`
-      });
-
-      const deviceEl = deviceGroup.append('circle')
-      .attr({
-        r: serviceTopologyConfig.circle.radius
-      });
-
-      deviceGroup.append('text')
-      .attr({
-        x: - serviceTopologyConfig.circle.radius - 3,
-        dy: '.35em',
-        'text-anchor': 'end'
-      })
-      .text(device.name)
-
-      const [deviceX, deviceY] = d3.transform(deviceEl.attr('transform')).translate;
-      const [deviceGroupX, deviceGroupY] = d3.transform(deviceGroup.attr('transform')).translate;
-      let [targetX, targetY] = d3.transform(target.attr('transform')).translate;
-
-      targetX = targetX - deviceGroupX;
-      targetY = targetY - deviceGroupY;
-
-      console.log('Device: ' + deviceX, deviceY);
-      console.log('Subscriber: ' + targetX, targetY);
-
-      var diagonal = d3.svg.diagonal()
-      .source({x: deviceX, y: deviceY})
-      .target({x: targetX, y: targetY})
-      // .projection(d => {
-      //   return [d.y, d.x];
-      // });
-
-      deviceGroup
-        .append('path')
-        .attr('class', 'device-link')
-        .attr('d', diagonal);
-    }
-
-    const createSubscriber = (container, subscriber, xPos, yPos) => {
-
-      const subscriberGroup = container.append('g')
-      .attr({
-        class: 'subscriber',
-        transform: `translate(${xPos * 2}, ${yPos})`
-      });
-
-      subscriberGroup.append('circle')
-      .attr({
-        r: serviceTopologyConfig.circle.radius
-      });
-
-      subscriberGroup.append('text')
-      .attr({
-        x: serviceTopologyConfig.circle.radius + 3,
-        dy: '.35em',
-        'text-anchor': 'start'
-      })
-      .text(subscriber.humanReadableName)
-
-      // TODO
-      // starting from the subscriber position, we should center
-      // the device goup based on his own height
-      // const deviceContainer = container.append('g')
-      // .attr({
-      //   class: 'devices-container',
-      //   transform: `translate(${xPos}, ${yPos -(vStep / 2)})`
-      // });
-
-      angular.forEach(subscriber.devices, (device, j) => {
-        createDevice(container, device, xPos, ((vStep / subscriber.devices.length) * j) + (yPos - vStep / 2), subscriberGroup);
-      });
-    }
-
-    this.handleSubscribers = (svg, subscribers) => {
-
-      // HACKY
-      hStep = angular.element(svg[0])[0].clientWidth / 7;
-      vStep = angular.element(svg[0])[0].clientHeight / (subscribers.length + 1);
-
-      const container = svg.append('g')
-      .attr({
-        class: 'subscribers-container'
-      });
-
-      lodash.forEach(subscribers, (subscriber, i) => {
-        createSubscriber(container, subscriber, hStep, vStep * (i + 1));
-      })
-    }
+  .service('LogicTopologyHelper', function($window, $log, lodash, serviceTopologyConfig, NodeDrawer){
 
     var diagonal, nodes, links, i = 0, svgWidth, svgHeight, layout;
 
@@ -127,6 +30,10 @@
       ]
     };
 
+    /**
+    * from a nested data structure,
+    * create nodes and links for a D3 Tree Layout
+    */
     const computeLayout = (data) => {
       let nodes = layout.nodes(data);
 
@@ -138,41 +45,35 @@
       });
 
       let links = layout.links(nodes);
-      console.log(nodes.length, links.length);
+
       return [nodes, links];
     };
 
+    /**
+    * Draw the containing group for any node or update the existing one
+    */
     const drawNodes = (svg, nodes) => {
       // Update the nodes…
       var node = svg.selectAll('g.node')
-      .data(nodes, d => {return d.id || (d.id = `tree-${i++}`)});
+      .data(nodes, d => {
+        if(!angular.isString(d.d3Id)){
+          d.d3Id = `tree-${++i}`;
+        }
+        return d.d3Id;
+      });
 
-      // Enter any new nodes at the parent's previous position.
+      // Enter any new nodes
       var nodeEnter = node.enter().append('g')
       .attr({
         class: d => `node ${d.type}`,
         transform: `translate(${svgWidth / 2}, ${svgHeight / 2})`
       });
 
-      nodeEnter.append('circle')
-        .attr('r', 10)
-        .style('fill', d => d._children ? 'lightsteelblue' : '#fff');
-
-      nodeEnter.append('text')
-        .attr({
-          x: d => d.children ? serviceTopologyConfig.circle.selectedRadius + 3 : -serviceTopologyConfig.circle.selectedRadius - 3,
-          dy: '.35em',
-          transform: d => {
-            if (d.children && d.parent){
-              if(d.parent.x < d.x){
-                return 'rotate(-30)';
-              }
-              return 'rotate(30)';
-            }
-          },
-          'text-anchor': d => d.children ? 'start' : 'end'
-        })
-        .text(d => d.name);
+      NodeDrawer.addNetworks(nodeEnter.filter('.network'));
+      NodeDrawer.addRack(nodeEnter.filter('.rack'));
+      NodeDrawer.addPhisical(nodeEnter.filter('.router'));
+      NodeDrawer.addPhisical(nodeEnter.filter('.subscriber'));
+      NodeDrawer.addDevice(nodeEnter.filter('.device'));
 
       // Transition nodes to their new position.
       var nodeUpdate = node.transition()
@@ -184,6 +85,9 @@
       // TODO handle node remove
     };
 
+    /**
+    * Handle links in the tree layout
+    */
     const drawLinks = (svg, links) => {
 
       diagonal = d3.svg.diagonal()
@@ -192,7 +96,7 @@
       // Update the links…
       var link = svg.selectAll('path.link')
         .data(links, d => {
-          return d.target.id
+          return d.target.d3Id
         });
 
       // Enter any new links at the parent's previous position.
@@ -209,6 +113,9 @@
         .attr('d', diagonal);
     };
 
+    /**
+    * Calculate the svg size and setup tree layout
+    */
     this.drawTree = (svg) => {
       
 
@@ -229,10 +136,11 @@
       
     };
 
+    /**
+    * Add Subscribers to the tree
+    */
     this.addSubscribers = (svg, subscribers) => {
 
-      console.log(subscribers);
-
       subscribers.map((subscriber) => {
         subscriber.children = subscriber.devices;
       });
@@ -240,8 +148,6 @@
       // add subscriber to data tree
       baseData.children[0].children[0].children[0].children = subscribers;
 
-      console.log(baseData);
-
       [nodes, links] = computeLayout(baseData);
 
       drawNodes(svg, nodes);
diff --git a/views/ngXosViews/diagnostic/src/js/nodeDrawer.js b/views/ngXosViews/diagnostic/src/js/nodeDrawer.js
new file mode 100644
index 0000000..82349ea
--- /dev/null
+++ b/views/ngXosViews/diagnostic/src/js/nodeDrawer.js
@@ -0,0 +1,62 @@
+(function () {
+  'use strict';
+
+  const shapes = {
+    cloud: ' M 79.72 49.60 C 86.00 37.29 98.57 29.01 111.96 26.42 C 124.27 24.11 137.53 26.15 148.18 32.90 C 158.08 38.78 165.39 48.87 167.65 60.20 C 176.20 57.90 185.14 56.01 194.00 57.73 C 206.08 59.59 217.92 66.01 224.37 76.66 C 227.51 81.54 228.85 87.33 229.23 93.06 C 237.59 93.33 246.22 95.10 253.04 100.19 C 256.69 103.13 259.87 107.67 258.91 112.59 C 257.95 118.43 252.78 122.38 247.78 124.82 C 235.27 130.43 220.23 130.09 207.98 123.93 C 199.33 127.88 189.76 129.43 180.30 128.57 C 173.70 139.92 161.70 147.65 148.86 149.93 C 133.10 153.26 116.06 148.15 104.42 137.08 C 92.98 143.04 78.96 143.87 66.97 139.04 C 57.75 135.41 49.70 128.00 46.60 118.43 C 43.87 109.95 45.81 100.29 51.30 93.32 C 57.38 85.18 67.10 80.44 76.99 78.89 C 74.38 69.20 74.87 58.52 79.72 49.60 Z'
+  }
+
+  angular.module('xos.serviceTopology')
+  .service('NodeDrawer', function(serviceTopologyConfig){
+    this.addNetworks = (nodes) => {
+      nodes.append('path')
+      .attr({
+        d: shapes.cloud,
+        transform: 'translate(-63, -52), scale(0.5)',
+        class: 'cloud'
+      });
+
+      nodes.append('text')
+      .attr({
+        'text-anchor': 'middle'
+      })
+      .text(d => d.name)
+    }
+
+    this.addRack = (nodes) => {
+      nodes.append('rect')
+      .attr(serviceTopologyConfig.rack);
+
+      nodes.append('text')
+      .attr({
+        'text-anchor': 'middle',
+        y: serviceTopologyConfig.rack.y - 10
+      })
+      .text(d => d.name)
+    }
+
+    this.addPhisical = (nodes) => {
+      nodes.append('rect')
+      .attr(serviceTopologyConfig.square);
+
+      nodes.append('text')
+      .attr({
+        'text-anchor': 'middle',
+        y: serviceTopologyConfig.square.y - 10
+      })
+      .text(d => d.name);
+    }
+
+    this.addDevice = (nodes) => {
+      nodes.append('circle')
+      .attr(serviceTopologyConfig.circle);
+
+      nodes.append('text')
+      .attr({
+        'text-anchor': 'end',
+        x: - serviceTopologyConfig.circle.r - 10,
+        y: serviceTopologyConfig.circle.r / 2
+      })
+      .text(d => d.name); 
+    }
+  });
+})();
diff --git a/views/ngXosViews/diagnostic/src/js/rest_services.js b/views/ngXosViews/diagnostic/src/js/rest_services.js
index be523da..2673bfc 100644
--- a/views/ngXosViews/diagnostic/src/js/rest_services.js
+++ b/views/ngXosViews/diagnostic/src/js/rest_services.js
@@ -38,9 +38,16 @@
             .then((list) => {
               res.data.map((subscriber, i) => {
                 subscriber.devices = list[i];
+                subscriber.type = 'subscriber';
+
+                subscriber.devices.map(d => d.type = 'device')
+
                 return subscriber;
               });
 
+              // faking to have 2 subscriber
+              res.data.push(angular.copy(res.data[0]));
+
               deferred.resolve(res.data);
             })
 
@@ -134,8 +141,8 @@
       // if it is the last element append internet
       if(tree.children.length === 0){
         tree.children.push({
-          name: 'Internet',
-          type: 'internet',
+          name: 'Router',
+          type: 'router',
           children: []
         });
       }
diff --git a/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js b/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
index f3cb2d2..045a393 100644
--- a/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
+++ b/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
@@ -124,7 +124,7 @@
         });
 
       const subscriberNodes = nodeEnter.filter('.subscriber');
-      const internetNodes = nodeEnter.filter('.internet');
+      const internetNodes = nodeEnter.filter('.router');
       const serviceNodes = nodeEnter.filter('.service');
       const instanceNodes = nodeEnter.filter('.instance');
       const sliceNodes = nodeEnter.filter('.slice');
diff --git a/views/ngXosViews/diagnostic/src/templates/diagnostic.tpl.html b/views/ngXosViews/diagnostic/src/templates/diagnostic.tpl.html
index 5b8ce78..6754702 100644
--- a/views/ngXosViews/diagnostic/src/templates/diagnostic.tpl.html
+++ b/views/ngXosViews/diagnostic/src/templates/diagnostic.tpl.html
@@ -3,14 +3,12 @@
     <service-topology service-chain="vm.serviceChain"></service-topology>
   </div>
   <div class="half-height">
-    <div class="row col-sm-offset-9 col-sm-3">
-      <div class="panel panel-primary">
-        <div class="panel-heading">Select a subscriber:</div>
-        <div class="panel-body">
-          <select class="form-control" ng-options="s as s.name for s in vm.subscribers" ng-model="vm.selectedSubscriber">
-            <option value="">Select a subscriber...</option>
-          </select>
-        </div>
+    <div class="panel panel-primary subscriber-select">
+      <div class="panel-heading">Select a subscriber:</div>
+      <div class="panel-body">
+        <select class="form-control" ng-options="s as s.name for s in vm.subscribers" ng-model="vm.selectedSubscriber">
+          <option value="">Select a subscriber...</option>
+        </select>
       </div>
     </div>
     <logic-topology ng-if="vm.subscribers" subscribers="vm.subscribers" selected="vm.selectedSubscriber"></logic-topology>