Added mCord apps
diff --git a/views/ngXosViews/mcordTopology/src/js/main.js b/views/ngXosViews/mcordTopology/src/js/main.js
new file mode 100644
index 0000000..bf57f1d
--- /dev/null
+++ b/views/ngXosViews/mcordTopology/src/js/main.js
@@ -0,0 +1,296 @@
+'use strict';
+
+angular.module('xos.mcordTopology', [
+  'ngResource',
+  'ngCookies',
+  'ngLodash',
+  'ui.router',
+  'xos.helpers'
+])
+.config(($stateProvider) => {
+  $stateProvider
+  .state('topology', {
+    url: '/',
+    template: '<m-cord-topology></m-cord-topology>'
+  });
+})
+.config(function($httpProvider){
+  $httpProvider.interceptors.push('NoHyperlinks');
+})
+.directive('mCordTopology', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    template: '',
+    controller: function($element, $interval, XosApi, lodash, TopologyElements, NodeDrawer){
+
+      const el = $element[0];
+
+      let nodes = [];
+      let links = [];
+
+      const filterBBU = (instances) => {
+        return lodash.filter(instances, i => i.name.indexOf('BBU') >= 0);
+      };
+
+      const filterOthers = (instances) => {
+        return lodash.filter(instances, i => {
+          return (i.name.indexOf('MME') >= 0)
+          || (i.name.indexOf('SGW') >= 0)
+          || (i.name.indexOf('PGW') >= 0)
+        });
+      };
+
+      // retrieving instances list
+      const getData = () => {
+
+        nodes = TopologyElements.nodes;
+        links = TopologyElements.links;
+
+        XosApi.Instance_List_GET()
+        .then((instances) => {
+          addBbuNodes(filterBBU(instances));
+          addOtherNodes(filterOthers(instances));
+
+          draw(svg, nodes, links);
+        })
+        .catch((e) => {
+          throw new Error(e);
+        });
+      };
+
+      const force = d3.layout.force();
+
+      // create svg elements
+      const svg = d3.select(el)
+        .append('svg')
+        .style('width', `${el.clientWidth}px`)
+        .style('height', `${el.clientHeight}px`);
+
+      const linkContainer = svg.append('g')
+        .attr({
+          class: 'link-container'
+        });
+
+      const nodeContainer = svg.append('g')
+        .attr({
+          class: 'node-container'
+        });
+
+      // replace human readable ids with d3 ids
+      // NOTE now ids are not manatined on update...
+      const buildLinks = (links, nodes) => {
+        return links.map((l) => {
+
+
+          let source = lodash.findIndex(nodes, {id: l.source});
+          let target = lodash.findIndex(nodes, {id: l.target});
+          // console.log(`link-${source}-${target}`, source, target);
+          return {
+            source: source,
+            target: target,
+            value: 1,
+            id: `link-${source}-${target}`,
+            type: l.source.indexOf('fabric') >= 0 ? 'big':'small'
+          };
+
+        });
+      };
+
+      // find fabric nodes and center horizontally
+      const positionFabricNodes = (nodes) => {
+        return lodash.map(nodes, n => {
+          if(n.type !== 'fabric'){
+            return n;
+          }
+
+          n.x = n.x * hStep;
+          n.y = n.y * vStep;
+
+          return n;
+        });
+      };
+
+      const addBbuNodes = (instances) => {
+
+        // calculate bbu hStep
+        let bbuHStep = ((el.clientWidth / 2) / (instances.length + 1));
+
+        // create nodes
+        let bbuNodes = instances.map((n, i) => {
+          return {
+            type: 'bbu',
+            name: n.name,
+            id: `bbu-${n.id}`,
+            fixed: true,
+            y: vStep * 3,
+            x: bbuHStep * (i + 1)
+          };
+        });
+
+        // create links
+        let bbuLinks = bbuNodes.map(n => {
+          return {
+            source: n.id,
+            target: 'fabric2'
+          };
+        });
+
+        // fake RRU nodes and links
+        instances.forEach((n, i) => {
+          bbuNodes.push({
+            type: 'rru',
+            name: 'rru',
+            id: `rru-${n.id}`,
+            fixed: true,
+            y: vStep * 4,
+            x: bbuHStep * (i + 1)
+          });
+
+          bbuLinks.push({
+            source: `rru-${n.id}`,
+            target: `bbu-${n.id}`
+          });
+        })
+
+        nodes = nodes.concat(bbuNodes);
+
+
+        links = links.concat(bbuLinks);
+      };
+
+      // add MME, PGW, SGW nodes
+      const addOtherNodes = (instances) => {
+        let hStep = ((el.clientWidth / 2) / (instances.length + 1));
+
+        // create nodes
+        let otherNodes = instances.map((n, i) => {
+          return {
+            type: n.name.substring(0, 3),
+            name: n.name,
+            id: `${n.name.substring(0, 3)}-${n.id}`,
+            fixed: true,
+            y: vStep * 3,
+            x: (el.clientWidth / 2) + (hStep * (i + 1))
+          };
+        });
+
+        // create links
+        let otherLinks = otherNodes.map(n => {
+          return {
+            source: n.id,
+            target: 'fabric4'
+          };
+        });
+
+
+        nodes = nodes.concat(otherNodes);
+        links = links.concat(otherLinks);
+      }
+
+      let hStep, vStep;
+
+      hStep = el.clientWidth / 3;
+      vStep = el.clientHeight / 5;
+
+      const draw = (svg, nodes, links) => {
+
+        hStep = el.clientWidth / 3;
+        vStep = el.clientHeight / 5;
+
+        links = buildLinks(links, nodes);
+
+        nodes = positionFabricNodes(nodes);
+
+
+        // start force layout
+        force
+          .nodes(nodes)
+          .links(links)
+          .size([el.clientWidth, el.clientHeight])
+          .charge(-20)
+          .chargeDistance(200)
+          .linkDistance(80)
+          .linkStrength(0.1)
+          .start();
+
+
+        const linkContainer = d3.select('.link-container');
+        const nodeContainer = d3.select('.node-container');
+
+        NodeDrawer.drawFabricBox(nodeContainer, hStep, vStep);
+
+        // draw links
+        var link = linkContainer.selectAll('.link')
+          .data(links, d => d.id);
+        
+        link.enter().append('line')
+          .attr({
+            // class: 'link',
+            id: d => d.id,
+            opacity: 0,
+            class: d => `link ${d.type}`
+          })
+          .transition()
+          .duration(1000)
+          // .delay((d, i) => 50 * i)
+          .attr({
+            opacity: 1
+          });
+
+        link.exit()
+        .remove();
+
+        //draw nodes
+        var node = nodeContainer.selectAll('.node')
+          .data(nodes, d => {
+            return d.id
+          });
+        
+        // append a group for any new node
+        var enter = node.enter()
+          .append('g', d => d.interfaceCfgIdentifier)
+          .attr({
+            class: d => `${d.type} node`,
+            transform: d => `translate(${d.x}, ${d.y})`
+          });
+
+        // draw nodes
+        NodeDrawer.drawBbus(enter.filter('.bbu'))
+        NodeDrawer.drawRrus(enter.filter('.rru'))
+        NodeDrawer.drawFabric(enter.filter('.fabric'))
+        NodeDrawer.drawOthers(enter.filter(d => {
+          return (
+            d.type  === 'MME' ||
+            d.type === 'SGW' ||
+            d.type === 'PGW'
+          )
+        }));
+
+        // remove nodes
+        var exit = node.exit();
+
+        NodeDrawer.removeElements(exit);
+
+        force.on('tick', function() {
+          link
+            .attr('x1', d => d.source.x )
+            .attr('y1', d => d.source.y )
+            .attr('x2', d => d.target.x )
+            .attr('y2', d => d.target.y );
+
+          node.attr('transform', (d) => `translate(${d.x},${d.y})`);
+        });
+      };
+      
+      $interval(() => {
+        getData();
+      }, 5000);
+      getData();
+
+      
+    }
+  };
+});
\ No newline at end of file