Drawing slices, expanding and collapsing slices
Drawing forms
Added keybindings

Change-Id: Ic1f06eef20a6e1e7c0f1fea51752fe738f86d600
diff --git a/views/ngXosViews/mcord-slicing/.bowerrc b/views/ngXosViews/mcord-slicing/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/.eslintrc b/views/ngXosViews/mcord-slicing/.eslintrc
new file mode 100644
index 0000000..c852748
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/.eslintrc
@@ -0,0 +1,42 @@
+{
+    "ecmaFeatures": {
+        "blockBindings": true,
+        "forOf": true,
+        "destructuring": true,
+        "arrowFunctions": true,
+        "templateStrings": true
+    },
+    "env": { 
+        "browser": true,
+        "node": true,
+        "es6": true
+    },
+    "plugins": [
+        //"angular"
+    ],
+    "rules": {
+        "quotes": [2, "single"],
+        "camelcase": [1, {"properties": "always"}],
+        "no-underscore-dangle": 1,
+        "eqeqeq": [2, "smart"],
+        "no-alert": 1,
+        "key-spacing": [1, { "beforeColon": false, "afterColon": true }],
+        "indent": [2, 2],
+        "no-irregular-whitespace": 1,
+        "eol-last": 0,
+        "max-nested-callbacks": [2, 4],
+        "comma-spacing": [1, {"before": false, "after": true}],
+        "no-trailing-spaces": [1, { skipBlankLines: true }],
+        "no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
+        "new-cap": 0,
+
+        //"angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
+        //"angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
+        //"angular/ng_service_name": [2, '/^[A-Z].*Service$/'],
+        //"angular/ng_directive_name": [2, '/^[a-z]+[[A-Z].*]*$/'],
+        //"angular/ng_di": [0, "function or array"]
+    },
+    "globals" :{
+        "angular": true
+    } 
+}
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/.gitignore b/views/ngXosViews/mcord-slicing/.gitignore
new file mode 100644
index 0000000..567aee4
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/.gitignore
@@ -0,0 +1,6 @@
+dist/
+src/vendor
+.tmp
+node_modules
+npm-debug.log
+dist/
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/bower.json b/views/ngXosViews/mcord-slicing/bower.json
new file mode 100644
index 0000000..8f0a0c9
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/bower.json
@@ -0,0 +1,41 @@
+{
+  "name": "xos-mcord-slicing",
+  "version": "0.0.0",
+  "authors": [
+    "Matteo Scandolo <matteo.scandolo@gmail.com>"
+  ],
+  "description": "The mcord-slicing view",
+  "license": "Apache-2.0",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "static/js/vendor/",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "graphlib": "~2.1.1"
+  },
+  "devDependencies": {
+    "jquery": "2.1.4",
+    "angular-mocks": "1.5.8",
+    "angular": "1.5.8",
+    "angular-ui-router": "0.2.15",
+    "angular-cookies": "1.5.8",
+    "angular-animate": "1.5.8",
+    "angular-resource": "1.5.8",
+    "lodash": "~4.11.1",
+    "bootstrap-css": "3.3.6",
+    "angular-chart.js": "~0.10.2",
+    "d3": "~3.5.17",
+    "angular-recursion": "~1.0.5",
+    "ng-xos-lib": "opencord/ng-xos-lib#9422c38b214229fa6afdf0eea7862ccb6ff53dd7"
+  },
+  "resolutions": {
+    "angular": "1.5.8",
+    "angular-cookies": "~1.5.8",
+    "angular-animate": "~1.5.8",
+    "angular-resource": "~1.5.8"
+  }
+}
diff --git a/views/ngXosViews/mcord-slicing/gulp/build.js b/views/ngXosViews/mcord-slicing/gulp/build.js
new file mode 100644
index 0000000..48938c8
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/gulp/build.js
@@ -0,0 +1,227 @@
+'use strict';
+
+// BUILD
+//
+// The only purpose of this gulpfile is to build a XOS view and copy the correct files into
+// .html => dashboards
+// .js (minified and concat) => static/js
+//
+// The template are parsed and added to js with angular $templateCache
+
+var gulp = require('gulp');
+var ngAnnotate = require('gulp-ng-annotate');
+var uglify = require('gulp-uglify');
+var templateCache = require('gulp-angular-templatecache');
+var runSequence = require('run-sequence');
+var concat = require('gulp-concat-util');
+var del = require('del');
+var wiredep = require('wiredep');
+var angularFilesort = require('gulp-angular-filesort');
+var _ = require('lodash');
+var eslint = require('gulp-eslint');
+var inject = require('gulp-inject');
+var rename = require('gulp-rename');
+var replace = require('gulp-replace');
+var postcss = require('gulp-postcss');
+var autoprefixer = require('autoprefixer');
+var mqpacker = require('css-mqpacker');
+var csswring = require('csswring');
+var yaml = require('js-yaml');
+var colors = require('colors/safe');
+var fs =  require('fs');
+
+const TEMPLATE_FOOTER = `
+angular.module('xos.mcord-slicing')
+.run(['$location', function(a){
+  a.path('/');
+}])
+`
+
+module.exports = function(options){
+  
+  // delete previous builded file
+  gulp.task('clean', function(){
+    return del(
+      [
+        options.dashboards + 'xosMcord-slicing.html',
+        options.static + 'css/xosMcord-slicing.css',
+        options.static + 'images/mcord-slicing-icon.png',
+        options.static + 'images/mcord-slicing-icon-active.png'
+      ],
+      {force: true}
+    );
+  });
+
+  // minify css
+  gulp.task('css', function () {
+    var processors = [
+      autoprefixer({browsers: ['last 1 version']}),
+      mqpacker,
+      csswring
+    ];
+
+    gulp.src([
+      `${options.css}**/*.css`,
+      `!${options.css}dev.css`
+    ])
+    .pipe(postcss(processors))
+    .pipe(gulp.dest(options.tmp + '/css/'));
+  });
+
+  // copy css in correct folder
+  gulp.task('copyCss', ['wait'], function(){
+    return gulp.src([`${options.tmp}/css/*.css`])
+    .pipe(concat('xosMcord-slicing.css'))
+    .pipe(gulp.dest(options.static + 'css/'))
+  });
+
+  // copy images in correct folder
+  gulp.task('copyImages', ['wait'], function(){
+    return gulp.src([`${options.icon}/mcord-slicing-icon.png`, `${options.icon}/mcord-slicing-icon-active.png`])
+    .pipe(gulp.dest(options.static + 'images/'))
+  });
+
+  // compile and minify scripts
+  gulp.task('scripts', function() {
+    return gulp.src([
+      options.tmp + '**/*.js'
+    ])
+    .pipe(ngAnnotate())
+    .pipe(angularFilesort())
+    .pipe(concat('xosMcord-slicing.js'))
+    .pipe(concat.header('//Autogenerated, do not edit!!!\n'))
+    .pipe(concat.footer(TEMPLATE_FOOTER))
+    .pipe(uglify())
+    .pipe(gulp.dest(options.static + 'js/'));
+  });
+
+  // set templates in cache
+  gulp.task('templates', function(){
+    return gulp.src('./src/templates/*.html')
+      .pipe(templateCache({
+        module: 'xos.mcord-slicing',
+        root: 'templates/'
+      }))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // copy html index to Django Folder
+  gulp.task('copyHtml', function(){
+    return gulp.src(options.src + 'index.html')
+      // remove dev dependencies from html
+      .pipe(replace(/<!-- bower:css -->(\n^<link.*)*\n<!-- endbower -->/gmi, ''))
+      .pipe(replace(/<!-- bower:js -->(\n^<script.*)*\n<!-- endbower -->/gmi, ''))
+      // injecting minified files
+      .pipe(
+        inject(
+          gulp.src([
+            options.static + 'vendor/xosMcord-slicingVendor.js',
+            options.static + 'js/xosMcord-slicing.js',
+            options.static + 'css/xosMcord-slicing.css'
+          ]),
+          {ignorePath: '/../../../xos/core/xoslib'}
+        )
+      )
+      .pipe(rename('xosMcord-slicing.html'))
+      .pipe(gulp.dest(options.dashboards));
+  });
+
+  // minify vendor js files
+  gulp.task('wiredep', function(){
+    var bowerDeps = wiredep().js;
+    if(!bowerDeps){
+      return;
+    }
+
+    // remove angular (it's already loaded)
+    _.remove(bowerDeps, function(dep){
+      return dep.indexOf('angular/angular.js') !== -1;
+    });
+
+    return gulp.src(bowerDeps)
+      .pipe(concat('xosMcord-slicingVendor.js'))
+      .pipe(uglify())
+      .pipe(gulp.dest(options.static + 'vendor/'));
+  });
+
+  gulp.task('lint', function () {
+    return gulp.src(['src/js/**/*.js'])
+      .pipe(eslint())
+      .pipe(eslint.format())
+      .pipe(eslint.failAfterError());
+  });
+
+  gulp.task('wait', function (cb) {
+    // setTimeout could be any async task
+    setTimeout(function () {
+      cb();
+    }, 1000);
+  });
+
+  gulp.task('tosca', function (cb) {
+
+    // TOSCA to register the dashboard in the system
+    const dashboardJson = {};
+    dashboardJson['Mcord-slicing'] = {
+      type: 'tosca.nodes.DashboardView',
+      properties: {
+        url: 'template:xosMcord-slicing'
+      }
+    };
+
+    // check for custom icons
+    if(
+      fs.existsSync(`${options.icon}/mcord-slicing-icon.png`) &&
+      fs.existsSync(`${options.icon}/mcord-slicing-icon-active.png`)
+    ){
+      dashboardJson['Mcord-slicing'].properties.custom_icon = true;
+    }
+
+    const dashboardTosca = yaml.dump(dashboardJson).replace(/'/gmi, '');
+
+    // TOSCA to add the dashboard to the user
+    const userDashboardJson = {};
+    userDashboardJson['mcord-slicing_dashboard'] = {
+      node: 'Mcord-slicing',
+      relationship: 'tosca.relationships.UsesDashboard'
+    };
+    const userJson = {
+      'padmin@vicci.org': {
+        type: 'tosca.nodes.User',
+        properties: {
+          'no-create': true,
+          'no-delete': true
+        },
+        requirements: [userDashboardJson]
+      }
+    };
+    const userTosca = yaml.dump(userJson).replace(/'/gmi, '');
+
+
+    // the output is in a timeout so that it get printed after the gulp logs
+    setTimeout(function () {
+      console.log(colors.cyan('\n\n# You can use this recipe to load the dashboard in the system:'));
+      console.log(colors.yellow(dashboardTosca));
+      console.log(colors.cyan('# And this recipe to activate the dashboard for a user:'));
+      console.log(colors.yellow(userTosca));
+    }, 1000);
+    cb();
+  });
+
+  gulp.task('build', function() {
+    runSequence(
+      'clean',
+      'sass',
+      'templates',
+      'babel',
+      'scripts',
+      'wiredep',
+      'css',
+      'copyCss',
+      'copyImages',
+      'copyHtml',
+      'cleanTmp',
+      'tosca'
+    );
+  });
+};
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/gulp/server.js b/views/ngXosViews/mcord-slicing/gulp/server.js
new file mode 100644
index 0000000..7ff49c6
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/gulp/server.js
@@ -0,0 +1,176 @@
+'use strict';
+
+var gulp = require('gulp');
+var browserSync = require('browser-sync').create();
+var inject = require('gulp-inject');
+var runSequence = require('run-sequence');
+var angularFilesort = require('gulp-angular-filesort');
+var babel = require('gulp-babel');
+var wiredep = require('wiredep').stream;
+var httpProxy = require('http-proxy');
+var del = require('del');
+var sass = require('gulp-sass');
+var fs = require('fs');
+var path = require('path');
+
+const environment = process.env.NODE_ENV;
+
+if(!fs.existsSync(path.join(__dirname, `../../../env/${environment || 'default'}.js`))){
+  if(!environment){
+    throw new Error('You should define a default.js config in /views/env folder.');
+  }
+  else{
+    throw new Error(`Since you are loading a custom environment, you should define a ${environment}.js config in /views/env folder.`);
+  }
+}
+
+var conf = require(path.join(__dirname, `../../../env/${environment || 'default'}.js`));
+
+var proxy = httpProxy.createProxyServer({
+  target: conf.host
+});
+
+
+proxy.on('error', function(error, req, res) {
+  res.writeHead(500, {
+    'Content-Type': 'text/plain'
+  });
+
+  console.error('[Proxy]', error);
+});
+
+proxy.on('proxyRes', function (proxyRes, req, res) {
+  // console.log(JSON.stringify(res, true, 2));
+  // console.log(Object.keys(res), res.output);
+  // console.log(JSON.stringify(proxyRes, true, 2));
+  // console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
+});
+
+module.exports = function(options){
+
+  gulp.task('browser', function() {
+    browserSync.init({
+      startPath: '#/',
+      snippetOptions: {
+        rule: {
+          match: /<!-- browserSync -->/i
+        }
+      },
+      server: {
+        baseDir: options.src,
+        routes: {
+          '/xos/core/static': options.static + '../../static/'
+        },
+        middleware: function(req, res, next){
+          if(
+            req.url.indexOf('/api/') !== -1
+          ){
+            if(conf.xoscsrftoken && conf.xossessionid){
+              req.headers.cookie = `xoscsrftoken=${conf.xoscsrftoken}; xossessionid=${conf.xossessionid}`;
+              req.headers['x-csrftoken'] = conf.xoscsrftoken;
+            }
+            proxy.web(req, res);
+          }
+          else{
+            next();
+          }
+        }
+      }
+    });
+
+    gulp.watch(options.src + 'js/**/*.js', ['js-watch']);
+    gulp.watch(options.src + 'vendor/**/*.js', ['bower'], function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.src + '**/*.html', function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.css + '**/*.css', function(){
+      browserSync.reload();
+    });
+    gulp.watch(`${options.sass}/**/*.scss`, ['sass'], function(){
+      browserSync.reload();
+    });
+
+    gulp.watch([
+      options.helpers + 'ngXosHelpers.js',
+      options.static + '../../static/xosNgLib.css'
+    ], function(){
+      browserSync.reload();
+    });
+  });
+
+  // compile sass
+  gulp.task('sass', function () {
+    return gulp.src(`${options.sass}/**/*.scss`)
+      .pipe(sass().on('error', sass.logError))
+      .pipe(gulp.dest(options.css));
+  });
+
+  // transpile js with sourceMaps
+  gulp.task('babel', function(){
+    return gulp.src(options.scripts + '**/*.js')
+      .pipe(babel({sourceMaps: true}))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // inject scripts
+  gulp.task('injectScript', ['cleanTmp', 'babel'], function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.tmp + '**/*.js',
+            options.helpers + 'ngXosHelpers.min.js'
+          ])
+          .pipe(angularFilesort()),
+          {
+            ignorePath: [options.src, '/../../ngXosLib']
+          }
+        )
+      )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject CSS
+  gulp.task('injectCss', function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.src + 'css/*.css',
+            options.static + '../../static/xosNgLib.css'
+          ]),
+          {
+            ignorePath: [options.src]
+          }
+          )
+        )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject bower dependencies with wiredep
+  gulp.task('bower', function () {
+    return gulp.src(options.src + 'index.html')
+    .pipe(wiredep({devDependencies: true}))
+    .pipe(gulp.dest(options.src));
+  });
+
+  gulp.task('js-watch', ['injectScript'], function(){
+    browserSync.reload();
+  });
+
+  gulp.task('cleanTmp', function(){
+    return del([options.tmp + '**/*']);
+  });
+
+  gulp.task('serve', function() {
+    runSequence(
+      'sass',
+      'bower',
+      'injectScript',
+      'injectCss',
+      ['browser']
+    );
+  });
+};
diff --git a/views/ngXosViews/mcord-slicing/gulpfile.js b/views/ngXosViews/mcord-slicing/gulpfile.js
new file mode 100644
index 0000000..c825df8
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/gulpfile.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var gulp = require('gulp');
+var wrench = require('wrench');
+
+var options = {
+  src: 'src/',
+  css: 'src/css/',
+  icon: 'src/icons',
+  sass: 'src/sass/',
+  scripts: 'src/js/',
+  tmp: 'src/.tmp',
+  dist: 'dist/',
+  api: '../../ngXosLib/api/',
+  helpers: './src/vendor/ng-xos-lib/dist/',
+  static: '../../../xos/core/xoslib/static/', // this is the django static folder
+  dashboards: '../../../xos/core/xoslib/dashboards/' // this is the django html folder
+};
+
+wrench.readdirSyncRecursive('./gulp')
+.map(function(file) {
+  require('./gulp/' + file)(options);
+});
+
+gulp.task('default', function () {
+  gulp.start('build');
+});
diff --git a/views/ngXosViews/mcord-slicing/karma.conf.js b/views/ngXosViews/mcord-slicing/karma.conf.js
new file mode 100644
index 0000000..e5abf39
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/karma.conf.js
@@ -0,0 +1,90 @@
+// Karma configuration
+// Generated on Tue Oct 06 2015 09:27:10 GMT+0000 (UTC)
+
+/* eslint indent: [2,2], quotes: [2, "single"]*/
+
+/*eslint-disable*/
+var wiredep = require('wiredep');
+var path = require('path');
+
+var bowerComponents = wiredep( {devDependencies: true} )[ 'js' ].map(function( file ){
+  return path.relative(process.cwd(), file);
+});
+
+module.exports = function(config) {
+/*eslint-enable*/
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['jasmine'],
+
+
+    // list of files / patterns to load in the browser
+    files: bowerComponents.concat([
+      './src/vendor/ng-xos-lib/dist/ngXosVendor.min.js',
+      './src/vendor/ng-xos-lib/dist/ngXosHelpers.min.js',
+      'src/js/main.js',
+      'src/js/**/*.js',
+      'spec/**/*.mock.js',
+      'spec/**/*.test.js',
+      'src/**/*.html'
+    ]),
+
+
+    // list of files to exclude
+    exclude: [
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+      'src/js/**/*.js': ['babel'],
+      'spec/**/*.test.js': ['babel'],
+      'spec/**/*.mock.js': ['babel'],
+      'src/**/*.html': ['ng-html2js']
+    },
+
+    ngHtml2JsPreprocessor: {
+      stripPrefix: 'src/', //strip the src path from template url (http://stackoverflow.com/questions/22869668/karma-unexpected-request-when-testing-angular-directive-even-with-ng-html2js)
+      moduleName: 'templates' // define the template module name
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['mocha'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false
+  });
+};
diff --git a/views/ngXosViews/mcord-slicing/mock-cfg.json b/views/ngXosViews/mcord-slicing/mock-cfg.json
new file mode 100644
index 0000000..9361822
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/mock-cfg.json
@@ -0,0 +1,19 @@
+{
+  "endpoints": [
+    {
+      "url": "topology",
+      "base": "api/service/mcord_slicing_ui/",
+      "methods": ["GET"]
+    },
+    {
+      "url": "slicing/nodes",
+      "base": "api/service/mcord_slicing_ui/topology/",
+      "methods": ["POST"]
+    },
+    {
+      "url": "slicing/links",
+      "base": "api/service/mcord_slicing_ui/topology/",
+      "methods": ["POST"]
+    }
+  ]
+}
diff --git a/views/ngXosViews/mcord-slicing/mocks/topology.json b/views/ngXosViews/mcord-slicing/mocks/topology.json
new file mode 100644
index 0000000..48137bb
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/mocks/topology.json
@@ -0,0 +1,91 @@
+{
+    "nodes": [
+        {"id": 1, "name": "vRouter", "type": "upstream", "model_id": 1, "plane": "data"},
+
+
+
+
+
+        {"id": 21, "name": "ran-ru-1", "type": "ran-ru", "model_id": 1, "plane": "data"},
+        {"id": 22, "name": "ran-cu-1", "type": "ran-cu", "model_id": 1, "plane": "data"},
+        {"id": 23, "name": "sgw-1", "type": "sgw", "model_id": 1, "plane": "data"},
+        {"id": 24, "name": "pgw-1", "type": "pgw", "model_id": 1, "plane": "data"},
+
+        {"id": 25, "name": "ran-ru-1", "type": "ran-ru", "model_id": 1, "plane": "control", "model": {"DlSchedType": "RR", "DlAllocRBRate": 30, "UlSchedType": "RR", "UlAllocRBRate": 30}},
+        {"id": 26, "name": "ran-cu-1", "type": "ran-cu", "model_id": 1, "plane": "control", "model": {"AdmissionControl": 0,"HandHover": 10}},
+        {"id": 27, "name": "sgw-1", "type": "sgw", "model_id": 1, "plane": "control"},
+        {"id": 28, "name": "pgw-1", "type": "pgw", "model_id": 1, "plane": "control", "model": {"brand": "Quortus"}},
+        {"id": 29, "name": "mme-1", "type": "mme", "model_id": 1, "plane": "control"},
+
+        {"id": 210, "name": "profile-1", "type": "profile", "model_id": 1, "plane": "data", "model": {"start": "2016-01-01T08:00:00.000Z", "end": "2016-12-01T08:00:00.000Z"}},
+        {"id": 220, "name": "profile-2", "type": "profile", "model_id": 1, "plane": "data", "model": {"start": "2016-01-01T08:00:00.000Z", "end": "2016-12-01T08:00:00.000Z"}},
+
+        {"id": 211, "name": "ue-1", "type": "ue", "model_id": 1, "plane": "data", "model": {"id": 123}},
+        {"id": 212, "name": "ue-2", "type": "ue", "model_id": 1, "plane": "data", "model": {"id": 456}},
+        {"id": 221, "name": "ue-3", "type": "ue", "model_id": 1, "plane": "data", "model": {"id": 789}},
+
+
+
+
+        {"id": 31, "name": "ran-ru-2", "type": "ran-ru", "model_id": 1, "plane": "data"},
+        {"id": 32, "name": "ran-cu-2", "type": "ran-cu", "model_id": 1, "plane": "data"},
+        {"id": 33, "name": "sgw-2", "type": "sgw", "model_id": 1, "plane": "data"},
+        {"id": 34, "name": "pgw-2", "type": "pgw", "model_id": 1, "plane": "data"},
+
+        {"id": 35, "name": "ran-ru-2", "type": "ran-ru", "model_id": 1, "plane": "control", "model": {"DlSchedType": "RR", "DlAllocRBRate": 30, "UlSchedType": "RR", "UlAllocRBRate": 30}},
+        {"id": 36, "name": "ran-cu-2", "type": "ran-cu", "model_id": 1, "plane": "control", "model": {"AdmissionControl": 1,"HandHover": 10}},
+        {"id": 37, "name": "sgw-2", "type": "sgw", "model_id": 1, "plane": "control"},
+        {"id": 38, "name": "pgw-2", "type": "pgw", "model_id": 1, "plane": "control", "model": {"brand": "Radysis"}},
+        {"id": 39, "name": "mme-2", "type": "mme", "model_id": 1, "plane": "control"},
+
+        {"id": 310, "name": "profile-3", "type": "profile", "model_id": 1, "plane": "data", "model": {"start": "2016-01-01T08:00:00.000Z", "end": "2016-12-01T08:00:00.000Z"}},
+
+        {"id": 311, "name": "ue-4", "type": "ue", "model_id": 1, "plane": "data", "model": {"id": 321}},
+        {"id": 312, "name": "ue-5", "type": "ue", "model_id": 1, "plane": "data", "model": {"id": 654}}
+    ],
+    "links": [
+        {"id": 1, "source": 24, "target": 1, "plane": "data"},
+
+        {"id": 2, "source": 21, "target": 22, "plane": "data"},
+        {"id": 3, "source": 22, "target": 23, "plane": "data"},
+        {"id": 4, "source": 23, "target": 24, "plane": "data"},
+
+        {"id": 5, "source": 21, "target": 25, "plane": "control"},
+        {"id": 6, "source": 22, "target": 26, "plane": "control"},
+        {"id": 7, "source": 23, "target": 27, "plane": "control"},
+        {"id": 8, "source": 24, "target": 28, "plane": "control"},
+        {"id": 9, "source": 25, "target": 26, "plane": "control"},
+        {"id": 10, "source": 26, "target": 29, "plane": "control"},
+        {"id": 11, "source": 27, "target": 28, "plane": "control"},
+        {"id": 12, "source": 27, "target": 29, "plane": "control"},
+
+        {"id": 13, "source": 210, "target": 21, "plane": "data"},
+        {"id": 14, "source": 220, "target": 21, "plane": "data"},
+
+        {"id": 15, "source": 211, "target": 210, "plane": "data"},
+        {"id": 16, "source": 212, "target": 210, "plane": "data"},
+        {"id": 17, "source": 221, "target": 220, "plane": "data"},
+
+
+
+        {"id": 18, "source": 34, "target": 1, "plane": "data"},
+
+        {"id": 19, "source": 31, "target": 32, "plane": "data"},
+        {"id": 20, "source": 32, "target": 33, "plane": "data"},
+        {"id": 21, "source": 33, "target": 34, "plane": "data"},
+
+        {"id": 22, "source": 31, "target": 35, "plane": "control"},
+        {"id": 23, "source": 32, "target": 36, "plane": "control"},
+        {"id": 24, "source": 33, "target": 37, "plane": "control"},
+        {"id": 25, "source": 34, "target": 38, "plane": "control"},
+        {"id": 26, "source": 35, "target": 36, "plane": "control"},
+        {"id": 27, "source": 36, "target": 39, "plane": "control"},
+        {"id": 28, "source": 37, "target": 38, "plane": "control"},
+        {"id": 29, "source": 37, "target": 39, "plane": "control"},
+
+        {"id": 30, "source": 310, "target": 31, "plane": "data"},
+
+        {"id": 31, "source": 311, "target": 310, "plane": "data"},
+        {"id": 32, "source": 312, "target": 310, "plane": "data"}
+    ]
+}
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/package.json b/views/ngXosViews/mcord-slicing/package.json
new file mode 100644
index 0000000..fcea3a3
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/package.json
@@ -0,0 +1,67 @@
+{
+  "name": "xos-mcord-slicing",
+  "version": "1.0.0",
+  "description": "Angular Application for XOS, created with generator-xos",
+  "scripts": {
+    "prestart": "npm install && bower install",
+    "start": "gulp serve",
+    "tosca": "gulp tosca",
+    "prebuild": "npm install && bower install",
+    "build": "gulp",
+    "test": "karma start",
+    "test:ci": "karma start --single-run",
+    "lint": "eslint src/js/",
+    "mock": "easy-mocker -c mock-cfg.json -d mocks/"
+  },
+  "keywords": [
+    "XOS",
+    "Angular",
+    "XOSlib"
+  ],
+  "author": "Matteo Scandolo",
+  "license": "Apache-2.0",
+  "dependencies": {},
+  "devDependencies": {
+    "autoprefixer": "^6.3.3",
+    "browser-sync": "^2.9.11",
+    "colors": "^1.1.2",
+    "css-mqpacker": "^4.0.0",
+    "csswring": "^4.2.1",
+    "del": "^2.0.2",
+    "easy-mocker": "^1.3.1",
+    "eslint": "^1.8.0",
+    "eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
+    "gulp": "^3.9.0",
+    "gulp-angular-filesort": "^1.1.1",
+    "gulp-angular-templatecache": "^1.8.0",
+    "gulp-babel": "^5.3.0",
+    "gulp-concat": "^2.6.0",
+    "gulp-concat-util": "^0.5.5",
+    "gulp-eslint": "^1.0.0",
+    "gulp-inject": "^3.0.0",
+    "gulp-minify-html": "^1.0.4",
+    "gulp-ng-annotate": "^1.1.0",
+    "gulp-postcss": "^6.0.1",
+    "gulp-rename": "^1.2.2",
+    "gulp-replace": "^0.5.4",
+    "gulp-sass": "^2.2.0",
+    "gulp-uglify": "^1.4.2",
+    "http-proxy": "^1.12.0",
+    "ink-docstrap": "^0.5.2",
+    "jasmine-core": "~2.3.4",
+    "js-yaml": "^3.6.1",
+    "karma": "^0.13.14",
+    "karma-babel-preprocessor": "~5.2.2",
+    "karma-coverage": "^0.5.3",
+    "karma-jasmine": "~0.3.6",
+    "karma-mocha-reporter": "~1.1.1",
+    "karma-ng-html2js-preprocessor": "^0.2.0",
+    "karma-phantomjs-launcher": "~0.2.1",
+    "lodash": "^3.10.1",
+    "phantomjs": "^1.9.19",
+    "proxy-middleware": "^0.15.0",
+    "run-sequence": "^1.1.4",
+    "wiredep": "^3.0.0-beta",
+    "wrench": "^1.5.8"
+  }
+}
diff --git a/views/ngXosViews/mcord-slicing/spec/sample.test.js b/views/ngXosViews/mcord-slicing/spec/sample.test.js
new file mode 100644
index 0000000..9976190
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/spec/sample.test.js
@@ -0,0 +1,35 @@
+'use strict';
+
+describe('The MCORD Slicing Topology', () => {
+  
+  var scope, element, isolatedScope, httpBackend;
+
+  beforeEach(module('xos.mcord-slicing'));
+  beforeEach(module('templates'));
+
+  beforeEach(inject(function($httpBackend, $compile, $rootScope){
+
+    httpBackend = $httpBackend;
+    // Setting up mock request
+    $httpBackend.expectGET('api/service/mcord_slicing_ui/topology/?no_hyperlinks=1').respond([
+      {
+        email: 'matteo.scandolo@gmail.com',
+        firstname: 'Matteo',
+        lastname: 'Scandolo'
+      }
+    ]);
+
+    scope = $rootScope.$new();
+    element = angular.element('<slicing-topo></slicing-topo>');
+    $compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }));
+
+  xit('should create 1 svg', () => {
+    httpBackend.flush();
+    let svg = $(element).find('svg');
+    expect(svg.length).toBe(1);
+  });
+
+});
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/css/dev.css b/views/ngXosViews/mcord-slicing/src/css/dev.css
new file mode 100644
index 0000000..c8ed540
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/css/dev.css
@@ -0,0 +1,5 @@
+/*#xosMcord-slicing{
+  position: absolute;
+  top: 100px;
+  left: 200px;
+}*/
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/css/main.css b/views/ngXosViews/mcord-slicing/src/css/main.css
new file mode 100644
index 0000000..f35a9c9
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/css/main.css
@@ -0,0 +1,69 @@
+#xosMcord-slicing,
+#xosMcord-slicing > [ui-view],
+slicing-topo {
+  width: 100%;
+  height: 100%; }
+
+slicing-topo {
+  display: block; }
+
+#xosMcord-slicing .node {
+  stroke: #337ab7;
+  fill: white; }
+
+#xosMcord-slicing .node,
+#xosMcord-slicing .node + text {
+  cursor: pointer; }
+
+#xosMcord-slicing text {
+  pointer-events: none;
+  -webkit-user-select: none;
+  /* Chrome all / Safari all */
+  -moz-user-select: none;
+  /* Firefox all */
+  -ms-user-select: none;
+  /* IE 10+ */
+  user-select: none; }
+
+#xosMcord-slicing .node.control {
+  stroke-dasharray: 5;
+  stroke: #d9534f; }
+
+#xosMcord-slicing .node.button {
+  stroke: #5bc0de;
+  fill: #daf1f8; }
+
+#xosMcord-slicing .node.selected {
+  stroke-width: 5px;
+  stroke-dasharray: 5; }
+
+#xosMcord-slicing .link {
+  stroke: #286090;
+  stroke-width: 2px;
+  cursor: pointer; }
+
+#xosMcord-slicing .link.control {
+  stroke-dasharray: 5;
+  stroke: #d9534f; }
+
+#xosMcord-slicing .link.selected {
+  stroke-width: 5px;
+  stroke-dasharray: 5; }
+
+#xosMcord-slicing .dragline {
+  stroke-dasharray: 5;
+  stroke: #286090;
+  stroke-width: 2px; }
+
+#xosMcord-slicing .dragline.hidden {
+  stroke-width: 0; }
+
+#xosMcord-slicing div.element-form {
+  position: absolute;
+  border: 1px solid #5bc0de;
+  padding: 10px;
+  background: #fff; }
+
+#xosMcord-slicing .form-line {
+  stroke: #31b0d5;
+  stroke-width: 1px; }
diff --git a/views/ngXosViews/mcord-slicing/src/icons/README.md b/views/ngXosViews/mcord-slicing/src/icons/README.md
new file mode 100644
index 0000000..0d5a787
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/icons/README.md
@@ -0,0 +1,18 @@
+# Set icon for custom dashboard 
+
+## Path to add images : <dashboard-name>/src/icons
+
+### Add two images with name in following format 
+    <dashboard-name>-icon.png
+    <dashboard-name>-icon-active.png
+
+Examples: 
+    If your dashboard name is `slice`
+    then you will add the images with the name as
+        `slice-icon.png`
+        `slice-icon-active.png`
+        
+        
+        
+        
+Note: If you don't add the custom images, then dashboard will use the default images stored at `/xos/core/xoslib/static/images`
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/index.html b/views/ngXosViews/mcord-slicing/src/index.html
new file mode 100644
index 0000000..78bed2d
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/index.html
@@ -0,0 +1,41 @@
+<!-- browserSync -->
+<!-- bower:css -->
+<link rel="stylesheet" href="vendor/bootstrap-css/css/bootstrap.min.css" />
+<link rel="stylesheet" href="vendor/angular-chart.js/dist/angular-chart.css" />
+<!-- endbower -->
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/css/dev.css">
+<link rel="stylesheet" href="/css/main.css">
+<link rel="stylesheet" href="/../../../xos/core/static/xosNgLib.css">
+<!-- endinject -->
+
+<div ng-app="xos.mcord-slicing" id="xosMcord-slicing" class="container-fluid">
+  <div ui-view></div>
+</div>
+
+<!-- bower:js -->
+<script src="vendor/lodash/lodash.js"></script>
+<script src="vendor/graphlib/dist/graphlib.core.js"></script>
+<script src="vendor/jquery/dist/jquery.js"></script>
+<script src="vendor/angular/angular.js"></script>
+<script src="vendor/angular-mocks/angular-mocks.js"></script>
+<script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
+<script src="vendor/angular-cookies/angular-cookies.js"></script>
+<script src="vendor/angular-animate/angular-animate.js"></script>
+<script src="vendor/angular-resource/angular-resource.js"></script>
+<script src="vendor/bootstrap-css/js/bootstrap.min.js"></script>
+<script src="vendor/Chart.js/Chart.js"></script>
+<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
+<script src="vendor/d3/d3.js"></script>
+<script src="vendor/angular-recursion/angular-recursion.js"></script>
+<script src="vendor/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js"></script>
+<!-- endbower -->
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/vendor/ng-xos-lib/dist/ngXosHelpers.min.js"></script>
+<script src="/.tmp/main.js"></script>
+<script src="/.tmp/slicing-topo.directive.js"></script>
+<script src="/.tmp/graph.service.js"></script>
+<script src="/.tmp/form.service.js"></script>
+<!-- endinject -->
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/js/aa b/views/ngXosViews/mcord-slicing/src/js/aa
new file mode 100644
index 0000000..0d4d9ae
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/js/aa
@@ -0,0 +1 @@
+that was the approach since it is completely independent from CORD or XOS, but if you prefere we can follow the same release scheme of CORD and from master pull the latest
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/js/form.service.js b/views/ngXosViews/mcord-slicing/src/js/form.service.js
new file mode 100644
index 0000000..e18ab10
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/js/form.service.js
@@ -0,0 +1,178 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 9/29/16.
+ */
+
+(function () {
+  'use strict';
+  angular.module('xos.mcord-slicing')
+  .service('FormHandler', function(LabelFormatter, XosFormHelpers){
+    const self = this;
+    const t = d3.transition()
+      .duration(500);
+
+    // draw a form nearby the node
+    this.drawForm = (node, linkGroup, formGroup) => {
+
+      // create an svg to draw a line from the node to the form
+      const line = linkGroup
+        .append('line')
+        .attr({
+          class: 'form-line',
+          id: `form-line-${node.type}-${node.id}`,
+          x1: node.x + 10,
+          y1: node.y,
+          x2: node.x + 10,
+          y2: node.y + 40,
+          opacity: 0,
+        });
+
+      line.transition(t)
+        .attr({
+          opacity: 1
+        });
+
+      // form container
+      const form = formGroup
+        .append('div')
+        .attr({
+          class: 'element-form',
+          id: `form-${node.type}-${node.id}`,
+        })
+        .style({
+          opacity: 0
+        });
+
+      const formEl = form
+        .append('form');
+
+      // cicle trough props (to be defined from rest)
+      this.addFormfields(node, formEl);
+
+      const buttonRow = formEl
+        .append('div')
+        .attr({
+          class: 'row'
+        });
+
+      buttonRow
+        .append('div')
+        .attr({
+          class: 'col-xs-6'
+        })
+        .append('a')
+        .attr({
+          class: 'btn btn-danger',
+          'data-parent-node-type': node.type,
+          'data-parent-node-id': node.id
+        })
+        .text('Close')
+        .on('click', function(){
+          self.removeForm(
+            d3.select(this).attr('data-parent-node-type'),
+            d3.select(this).attr('data-parent-node-id'),
+            linkGroup,
+            formGroup
+          );
+        });
+
+      buttonRow
+        .append('div')
+        .attr({
+          class: 'col-xs-6'
+        })
+        .append('button')
+        .attr({
+          type: 'button',
+          class: 'btn btn-success'
+        })
+        .text('Save')
+        .on('click', function(){
+          $(`#form-${node.type}-${node.id} input`).each(function(){
+            let input = $(this); // This is the jquery object of the input, do what you will
+            let val = input.val();
+            let name = input.attr('name');
+            console.log(name, val);
+          });
+        });
+
+      form.transition(t)
+        .style({
+          opacity: 1,
+          top: `${node.y + 95}px`,
+          left: `${node.x}px`
+        });
+    };
+
+    this.removeForm = (nodeType, nodeId, linkGroup, formGroup) => {
+      this.removeFormByParentNode({type: nodeType, id: nodeId}, linkGroup, formGroup);
+    };
+
+    // remove a form starting form his parent node
+    this.removeFormByParentNode = (node, linkGroup, formGroup) => {
+      // remove form
+      formGroup.selectAll(`#form-${node.type}-${node.id}`)
+        .transition(t)
+        .style({
+          opacity: 0
+        })
+        .remove();
+      // remove link
+      linkGroup.selectAll(`#form-line-${node.type}-${node.id}`)
+        .transition(t)
+        .attr({
+          opacity: 0
+        })
+        .remove();
+    };
+
+    this.getFieldValue = (val, fieldType) => {
+      if(fieldType === 'date'){
+        val = new Date(val);
+        val = `${val.getFullYear()}-${('0' + val.getMonth() + 1).slice(-2)}-${('0' + val.getDate()).slice(-2)}`
+      }
+      return val || '';
+    };
+
+    this.addFormField = (fieldName, fieldValue, formEl) => {
+      let fieldType = XosFormHelpers._getFieldFormat(fieldValue);
+      formEl
+        .append('div')
+        .attr({
+          class: 'row'
+        })
+        .append('div')
+        .attr({
+          class: 'col-xs-12'
+        })
+        .append('label')
+        .text(fieldName ? LabelFormatter.format(fieldName ) : 'test')
+        .append('input')
+        .attr({
+          type: fieldType,
+          name: fieldName,
+          value: this.getFieldValue(fieldValue, fieldType),
+          class: 'form-control'
+        });
+    };
+
+    this.addFormfields = (node, formEl) => {
+
+      this.addFormField('name', node.name, formEl);
+      // tmp check
+      if(!node.model){
+        return this.addFormField(null, null, formEl);
+      }
+
+      // create a list of fields to be printed
+      const fields = Object.keys(node.model);
+      _.forEach(fields, f => {
+        this.addFormField(f, node.model[f], formEl);
+      });
+    };
+  });
+})();
+
diff --git a/views/ngXosViews/mcord-slicing/src/js/graph.service.js b/views/ngXosViews/mcord-slicing/src/js/graph.service.js
new file mode 100644
index 0000000..223be9f
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/js/graph.service.js
@@ -0,0 +1,291 @@
+(function () {
+  'use strict';
+
+  angular.module('xos.mcord-slicing')
+  .service('SliceGraph', function(_, NodePositioner){
+    const g = new graphlib.Graph();
+
+    /**
+    * @ngdoc method
+    * @name xos.mcord-slicing.SliceGraph#buildGraph
+    * @methodOf xos.mcord-slicing.SliceGraph
+    * @description
+    * buildGraph
+    * @param {object} data An object in the for of {nodes: [], links: []} describing the graph
+    * @returns {null}
+    **/
+    this.buildGraph = (data) => {
+      _.forEach(data.nodes, n => g.setNode(n.id, n));
+      _.forEach(data.links, n => g.setEdge(n.source, n.target, n));
+    };
+
+    this.getLinks = () => {
+      return g.edges().map(e => {
+        return {
+          source: g.node(e.v),
+          target: g.node(e.w),
+          data: g.edge(e)
+        }
+      });
+    }
+
+    this.getGraph = () => g;
+
+    // find the successor of a node
+    this.getNodeSuccessors = (node) => {
+      return _.map(g.successors(node.id), n => {
+        return g.node(n);
+      })
+    };
+
+    this.getNodePredecessors = (node) => {
+      return _.map(g.predecessors(node.id), n => {
+        return g.node(n);
+      });
+    };
+
+    // get data plane successors of a node
+    this.getNodeDataPlaneSuccessors = (node) => {
+      return _.filter(this.getNodeSuccessors(node), n => {
+        return n.plane === 'data';
+      });
+    };
+
+    // find the end of the graph toward upstream
+    this.getUpstreamSinks = (el) => {
+      const sinks =  _.reduce(g.sinks(), (sinks, node, i) => {
+        let n = g.node(node);
+        if(n.type === 'upstream'){
+          sinks.push(n);
+        }
+        return sinks;
+      }, []);
+
+      return _.map(sinks, (s, i) => {
+        s.position = {
+          top: 0,
+          bottom: el.clientHeight,
+          total: sinks.length,
+          index: i + 1
+        };
+        return s;
+      })
+    };
+
+    this.positionGraph = (el) => {
+      // get root node
+      let nodes = this.getUpstreamSinks(el);
+
+      // find children, recursively
+      let children = [];
+      _.forEach(nodes, (n, i) => {
+        children = children.concat(this.findPredecessor(n));
+      });
+      nodes = nodes.concat(children);
+
+      // calculate the position for all nodes
+      nodes = _.map(nodes, r => {
+        return NodePositioner.getDataPlaneNodePos(r, el);
+      });
+
+      return nodes;
+    };
+
+    // this iterate on all the nodes, and add position information
+    this.findPredecessor = (node) => {
+      let preds = g.predecessors(node.id);
+
+      // saving predecessor information
+      preds = preds.map((p, i) => {
+        p = g.node(p);
+        const parentAvailableSpace = (node.position.bottom - node.position.top) / node.position.total;
+        const parentY = NodePositioner.getVpos(node);
+        p.position = {
+          top: parentY - (parentAvailableSpace / 2),
+          bottom: (parentY + (parentAvailableSpace / 2)),
+          total: preds.length,
+          index: i + 1
+        };
+        return p;
+      });
+
+      //recurse
+      const predsChild = _.reduce(preds, (list, p) => {
+        return list.concat(this.findPredecessor(p));
+      }, []);
+
+      return preds.concat(predsChild);
+    };
+
+    this.getGraphLinks = (nodes) => {
+      const links = [];
+      _.forEach(nodes, n => {
+        const edges = g.inEdges(n.id);
+        _.forEach(edges, e => {
+          links.push({
+            source: g.node(e.v),
+            target: g.node(e.w),
+            data: g.edge(e)
+          });
+        });
+      });
+      return links;
+    };
+
+    this.getDataPlaneForSlice = (ranRu, sliceId) => {
+      // hardcoded, likely to be improved
+      const ranCu = g.node(g.successors(ranRu.id)[0]);
+      const sgw = g.node(g.successors(ranCu.id)[0]);
+      const pgw = g.node(g.successors(sgw.id)[0]);
+
+      // augmenting nodes with sliceId
+      ranRu.sliceId = sliceId;
+      ranCu.sliceId = sliceId;
+      sgw.sliceId = sliceId;
+      pgw.sliceId = sliceId;
+      return [ranRu, ranCu, sgw, pgw];
+    };
+
+    this.getControlPlaneForSlice = (dataPlane, sliceId) => {
+      return _.reduce(dataPlane, (cp_nodes, dp_node) => {
+        // NOTE: looks that all the time the cplane version of the node is successors number 1, we may need to check
+        let cp_node = g.node(g.successors(dp_node.id)[1]);
+
+        // position relative to their data-plane node
+        cp_node = NodePositioner.getControlPlaneNodePos(cp_node, dp_node);
+        cp_node.sliceId = sliceId;
+        // hardcoded
+        // if control plane node is a sgw, there is an MME attached
+        if(cp_node.type === 'sgw'){
+          let mme = g.node(g.successors(cp_node.id)[1]);
+          // position relative to their data-plane node
+          mme = NodePositioner.getControlPlaneNodePos(mme, cp_node);
+          mme.sliceId = sliceId;
+          cp_nodes.push(mme);
+        }
+
+        return cp_nodes.concat(cp_node);
+      }, []);
+    };
+
+    this.activeSlices = [];
+    // this.usedSlicesId = [];
+    this.getSliceDetail= (node) => {
+      if(node.sliceId && this.activeSlices.indexOf(node.sliceId) > -1){
+        // the slice is already active, return an empty set
+        return [[], []];
+      }
+
+      // let sliceId;
+      // if (node.sliceId){
+      //   sliceId = node.sliceId;
+      // }
+      // else{
+        const sliceId = _.min(this.activeSlices) ? _.min(this.activeSlices) + 1 : 1;
+      // }
+      this.activeSlices.push(sliceId);
+      // this.usedSlicesId.push(sliceId);
+
+      // getting the beginning of the slice
+      const ranRu = (function getRanRu(n) {
+        if(n.type === 'ran-ru'){
+          return n;
+        }
+        // we assume that in the slice node have only one predecessor
+        const pred = g.predecessors(n.id);
+        return getRanRu(g.node(pred[0]));
+      })(node);
+
+      // get data plane nodes for this slice (need them to get the corresponding control plane)
+      const dp_nodes = this.getDataPlaneForSlice(ranRu, sliceId);
+      // get control plane nodes for this slice
+      const cp_nodes = this.getControlPlaneForSlice(dp_nodes, sliceId);
+
+      const links = this.getGraphLinks(cp_nodes);
+
+      // add a close button
+      let closeButton = {
+        name: 'Close',
+        id: `close-button-${sliceId}`,
+        type: 'button',
+        sliceId: sliceId
+      };
+      closeButton = NodePositioner.getControlPlaneNodePos(closeButton, cp_nodes[3]);
+      cp_nodes.push(closeButton);
+
+      return [cp_nodes, links];
+    };
+
+    this.removeActiveSlice = sliceId => {
+      // nodes are remove from the d3 nodes identified by id
+      this.activeSlices.splice(this.activeSlices.indexOf(sliceId), 1);
+    };
+
+  })
+  .service('NodePositioner', function(_, sliceElOrder){
+
+    let el;
+
+    this.storeEl = (_el) => {
+      el = _el;
+    };
+
+    this.getHpos = (node, el) => {
+      let elPos = sliceElOrder.indexOf(node.type) + 1;
+
+      // hardcoded
+      if(node.type === 'mme'){
+        elPos = sliceElOrder.indexOf('sgw') + 1
+      }
+      if(node.type === 'button'){
+        elPos = sliceElOrder.indexOf('pgw') + 1
+      }
+      let x = (el.clientWidth / (sliceElOrder.length + 1)) * elPos;
+      return x;
+    };
+
+    this.getVpos = (node) => {
+      // calculate the available space to distribute items
+      const availableSpace = node.position.bottom - node.position.top;
+
+      // calculate the distance between each item
+      const step = availableSpace / (node.position.total + 1);
+
+      // vertical position
+      const y = (step * node.position.index) + node.position.top;
+      return y;
+    };
+
+    // for nodes that are part of the data plane
+    this.getDataPlaneNodePos = (node) => {
+      const x = this.getHpos(node, el);
+      const y = this.getVpos(node);
+      node.x = x;
+      node.y = y;
+      node.transform = `translate(${x}, ${y})`;
+      node.fixed = true;
+      return node;
+    };
+
+    // control element nodes are positioned relatively to their corresponding data plane node
+    this.getControlPlaneNodePos = (cp_node, dp_node) => {
+      const x = this.getHpos(cp_node, el);
+      const y = dp_node.y - 75;
+      cp_node.x = x;
+      cp_node.y = y;
+      cp_node.transform = `translate(${x}, ${y})`;
+      cp_node.fixed = true;
+      return cp_node;
+    };
+
+  })
+  .value('sliceElOrder', [
+    'ue',
+    'profile',
+    'ran-ru',
+    'ran-cu',
+    'sgw',
+    'pgw',
+    'upstream'
+  ]);
+})();
diff --git a/views/ngXosViews/mcord-slicing/src/js/main.js b/views/ngXosViews/mcord-slicing/src/js/main.js
new file mode 100644
index 0000000..fbd9039
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/js/main.js
@@ -0,0 +1,93 @@
+'use strict';
+
+angular.module('xos.mcord-slicing', [
+  'ngResource',
+  'ngCookies',
+  'ui.router',
+  'xos.helpers'
+])
+.config(($stateProvider) => {
+  $stateProvider
+  .state('slicing-topo', {
+    url: '/',
+    template: '<slicing-topo></slicing-topo>'
+  })
+  .state('node-links', {
+    url: '/data',
+    template: '<node-links></node-links>'
+  });
+})
+.config(function($httpProvider){
+  $httpProvider.interceptors.push('NoHyperlinks');
+})
+.service('McordSlicingTopo', function($http, $q){
+  this.query = () => {
+    const d = $q.defer();
+
+    $http.get('api/service/mcord_slicing_ui/topology/')
+    .then((res) => {
+      let data;
+      if (res.data.hasOwnProperty('nodes')){
+        data = res.data;
+      }
+      else {
+        // INVESTIGATE why proxy change resposne
+        data = {
+          nodes: res.data[0],
+          links: res.data[1]
+        };
+      }
+      d.resolve(data);
+    })
+    .catch((e) => {
+      d.reject(e);
+    });
+
+    return {$promise: d.promise};
+  };
+})
+.directive('nodeLinks', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/node-links.tpl.html',
+    controller: function(McordSlicingTopo){
+
+      this.tableConfig = {
+        columns: [
+          {
+            label: 'Id',
+            prop: 'id'
+          },
+          {
+            label: 'Name',
+            prop: 'name'
+          },
+          {
+            label: 'Type',
+            prop: 'type'
+          },
+          {
+            label: 'Plane',
+            prop: 'plane'
+          },
+          {
+            label: 'Model Id',
+            prop: 'model_id'
+          }
+        ]
+      };
+      
+      // retrieving user list
+      McordSlicingTopo.query().$promise
+      .then((users) => {
+        this.users = users.nodes;
+      })
+      .catch((e) => {
+        throw new Error(e);
+      });
+    }
+  };
+});
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/js/slicing-topo.directive.js b/views/ngXosViews/mcord-slicing/src/js/slicing-topo.directive.js
new file mode 100644
index 0000000..b91c8f4
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/js/slicing-topo.directive.js
@@ -0,0 +1,502 @@
+(function () {
+  'use strict';
+
+  angular.module('xos.mcord-slicing')
+  .directive('slicingTopo', function(){
+    return {
+      restrict: 'E',
+      scope: {},
+      bindToController: true,
+      controllerAs: 'vm',
+      templateUrl: 'templates/slicing-topo.tpl.html',
+      controller: function($element, SliceGraph, McordSlicingTopo, _, NodePositioner, FormHandler){
+
+        let svg;
+        let nodes, links;
+        let nodeGroup, linkGroup, formGroup;
+        let dragLine, dragStartNode, dragEndNode, selectedLink;
+        let selectedNode, nodeSiblings;
+
+        var t = d3.transition()
+          .duration(500);
+
+        this.activeSlices = [];
+
+        const resetDragInfo = () => {
+          // reset drag nodes
+          dragStartNode = null;
+          dragEndNode = null;
+
+          // hide dragLine
+          dragLine
+            .classed('hidden', true);
+        };
+
+        McordSlicingTopo.query().$promise
+        .then((topology) => {
+          NodePositioner.storeEl($element[0]);
+          handleSvg($element[0]);
+          SliceGraph.buildGraph(topology);
+          _nodes = SliceGraph.positionGraph($element[0]);
+          _links = SliceGraph.getGraphLinks(_nodes);
+          drawGraph();
+        })
+        .catch((e) => {
+          throw new Error(e);
+        });
+
+        const handleSvg = (el) => {
+          this.el = el;
+          d3.select(el).select('svg').remove();
+
+          svg = d3.select(el)
+          .append('svg')
+          .style('width', `${el.clientWidth}px`)
+          .style('height', `${el.clientHeight}px`);
+
+          linkGroup = svg.append('g')
+            .attr({
+              class: 'link-group'
+            });
+
+          nodeGroup = svg.append('g')
+            .attr({
+              class: 'node-group'
+            });
+
+          formGroup = d3.select(el)
+            .append('div')
+            .attr({
+              class: 'form-container'
+            });
+
+          // line displayed when dragging nodes
+          dragLine = svg.append('svg:path')
+            .attr('class', 'dragline hidden')
+            .attr('d', 'M0,0L0,0');
+        };
+
+        const tick = () => {
+          svg.selectAll('.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);
+        };
+
+        // prepare the data to show all slices
+        let _nodes = [];
+        let _links = [];
+
+        // attach slice details
+        const attachSliceDetails = n => {
+          let [newNodes, newLinks] = SliceGraph.getSliceDetail(n);
+          _nodes = _nodes.concat(newNodes);
+          _links = _links.concat(newLinks);
+          drawGraph();
+        };
+
+        // remove slice detail
+        const removeSliceDetails = sliceId => {
+
+          SliceGraph.removeActiveSlice(sliceId);
+
+          // if the selected node is part of the slice I'm closing
+          // deselect the node
+          if(selectedNode && selectedNode.sliceId === sliceId){
+            selectedNode = null;
+            nodeSiblings = null;
+          }
+
+          // remove control plane nodes related to this slice
+          _nodes = _.filter(_nodes, n => {
+            if(n.sliceId === sliceId && (n.plane === 'control' || n.type === 'button')){
+              // if I remove the node check that there is no form attached
+              FormHandler.removeFormByParentNode(n, linkGroup, formGroup);
+              return false;
+            }
+            return true;
+          });
+
+          // remove sliceId from data plane element
+          _nodes = _.map(_nodes, n => {
+            if(n.sliceId === sliceId){
+              delete n.sliceId;
+            }
+            return n;
+          });
+
+          // remove control plane links related to this slice
+          _links = _.filter(_links, l => {
+            if(_.findIndex(_nodes, {id: l.data.source}) === -1){
+              return false;
+            }
+            if(_.findIndex(_nodes, {id: l.data.target}) === -1){
+              return false;
+            }
+            return true;
+          });
+          drawGraph();
+        };
+
+        const deleteLink = linkId => {
+          // TODO
+          // [ ] delete from graphlib
+          // [ ] delete from backend
+          console.log(_links);
+          _.remove(_links, (l) => {
+            return l.data.id === linkId;
+          });
+          console.log(_links);
+          drawGraph();
+        };
+
+        const expandNode = (n) => {
+          console.log('exp', n);
+          resetDragInfo();
+          const sliceComponents = ['ran-ru', 'ran-cu', 'pgw', 'sgw'];
+          if(sliceComponents.indexOf(n.type) > -1 && n.plane === 'data' && !n.sliceId){
+            attachSliceDetails(n);
+          }
+          else if (n.type === 'button'){
+            removeSliceDetails(n.sliceId);
+          }
+          else if (!n.formAttached && n.model){
+            n.formAttached = true;
+            FormHandler.drawForm(n, linkGroup, formGroup);
+          }
+          else if (n.formAttached){
+            n.formAttached = false;
+            FormHandler.removeFormByParentNode(n, linkGroup, formGroup);
+          }
+        };
+
+        const selectNextNode = () => {
+          if(!selectedNode){
+            selectedNode = _nodes[0];
+            selectedNode.selected = true;
+          }
+          else {
+            // TODO if no sliceId check only data plane successors
+            nodeSiblings = SliceGraph.getNodeSuccessors(selectedNode);
+
+            if(nodeSiblings.length === 0){
+              return;
+            };
+            // reset current selected node
+            selectedNode.selected = false;
+            // find next node
+            let nextNodeId = _.findIndex(_nodes, {id: nodeSiblings[0].id});
+            selectedNode = _nodes[nextNodeId];
+            selectedNode.selected = true;
+
+            // NOTE I need to update sibling with successor of the parent
+            // to enable vertical navigation
+            let parents = SliceGraph.getNodeSuccessors(selectedNode);
+            if(parents.lenght > 0){
+              nodeSiblings = SliceGraph.getNodePredecessors(parents[0]);
+            }
+            else {
+              nodeSiblings = null;
+            }
+          }
+          drawGraph();
+        };
+
+        const selectPrevNode = () => {
+          if(!selectedNode){
+            selectedNode = _nodes[0];
+            selectedNode.selected = true;
+          }
+          else {
+            nodeSiblings = SliceGraph.getNodePredecessors(selectedNode);
+
+            if(nodeSiblings.length === 0){
+              return;
+            };
+            // reset current selected node
+            selectedNode.selected = false;
+            // find next node
+            let prev = _.findIndex(_nodes, {id: nodeSiblings[0].id});
+
+            if(prev < 0){
+              prev = _nodes.length - 1;
+            }
+            selectedNode = _nodes[prev];
+            selectedNode.selected = true;
+          }
+          drawGraph();
+        };
+
+        const sortByY = (a, b) => {
+          if (a.y < b.y)
+            return 1;
+          if (a.y > b.y)
+            return -1;
+          return 0;
+        };
+
+        const getSameTypeNodes = (selectedNode) => {
+          return _.filter(_nodes, n => {
+            if(selectedNode.type === 'pgw' && n.type === 'button'){
+              return true;
+            }
+            if(selectedNode.type === 'button' && n.type === 'pgw'){
+              return true;
+            }
+            if (selectedNode.type === 'sgw' && n.type === 'mme'){
+              return true;
+            }
+            if (selectedNode.type === 'mme' && n.type === 'sgw'){
+              return true;
+            }
+            return n.type === selectedNode.type;
+          }).sort(sortByY);
+        };
+
+        const selectNextSibling = () => {
+          if(!selectedNode){
+            selectedNode = _nodes[0];
+            selectedNode.selected = true;
+          }
+          else {
+            // reset current selected node
+            selectedNode.selected = false;
+
+            // find next node
+            let sameTypeNodes = getSameTypeNodes(selectedNode);
+
+            let nextSiblingId = _.findIndex(sameTypeNodes, {id: selectedNode.id}) + 1;
+            if(nextSiblingId === sameTypeNodes.length){
+              nextSiblingId = 0;
+            }
+            let nextNodeId = _.findIndex(_nodes, {id: sameTypeNodes[nextSiblingId].id});
+            selectedNode = _nodes[nextNodeId];
+            selectedNode.selected = true;
+          }
+          drawGraph();
+        };
+
+        const selectPrevSibling = () => {
+          if(!selectedNode){
+            selectedNode = _nodes[0];
+            selectedNode.selected = true;
+          }
+          else {
+            // reset current selected node
+            selectedNode.selected = false;
+
+            // find next node
+            let sameTypeNodes = getSameTypeNodes(selectedNode);
+
+            let nextSiblingId = _.findIndex(sameTypeNodes, {id: selectedNode.id}) - 1;
+            if(nextSiblingId < 0){
+              nextSiblingId = sameTypeNodes.length - 1;
+            }
+            let nextNodeId = _.findIndex(_nodes, {id: sameTypeNodes[nextSiblingId].id});
+            selectedNode = _nodes[nextNodeId];
+            selectedNode.selected = true;
+          }
+          drawGraph();
+        };
+
+        const drawGraph = () => {
+
+          // svg.selectAll('.node-container').remove();
+          // svg.selectAll('.link-container').remove();
+
+          var force = d3.layout.force()
+            .nodes(_nodes)
+            .links(_links)
+            .charge(-1060)
+            .gravity(0.1)
+            .linkDistance(200)
+            .size([this.el.clientWidth, this.el.clientHeight])
+            .on('tick', tick)
+            .start();
+
+          links = linkGroup.selectAll('.link-container')
+            .data(_links, d => d.data.id)
+            .enter()
+            .insert('g')
+            .attr({
+              class: 'link-container',
+              opacity: 0
+            });
+
+          links
+            .transition(t)
+            .attr({
+              opacity: 1
+            });
+
+          links.insert('line')
+            .attr('class', d => `link ${d.data.plane}`)
+            .on('click', function(link ){
+              selectedLink = link;
+
+              // deselect all other links
+              d3.selectAll('.link').classed('selected', false);
+
+              d3.select(this).classed('selected', true);
+            });
+
+          nodes = nodeGroup.selectAll('.node')
+            .data(_nodes, d => d.id)
+            .attr({
+              class: d => `node ${d.plane} ${d.type} ${d.selected ? 'selected': ''}`,
+            });
+
+          nodes
+            .enter()
+            .append('g')
+            .attr({
+              class: 'node-container',
+              transform: d => d.transform,
+              opacity: 0
+            });
+
+          nodes.transition(t)
+            .attr({
+              opacity: 1
+            });
+
+          nodes.append('rect')
+            .attr({
+              class: d => `node ${d.plane} ${d.type} ${d.selected ? 'selected': ''}`,
+              width: 100,
+              height: 50,
+              x: -50,
+              y: -25
+            });
+
+          nodes.append('text')
+            .attr({
+              'text-anchor': 'middle',
+              'alignment-baseline': 'middle'
+            })
+            // .text(d => `${d.id} ${d.name}`);
+            .text(d => `${d.name}`);
+
+          nodes.on('click', (n) => {
+            expandNode(n);
+          });
+
+          nodes
+            .on('mousedown', (n) => {
+              // save a reference to dragStart
+              dragStartNode = n;
+
+              dragLine
+                .classed('hidden', false)
+                .attr('d', 'M' + dragStartNode.x + ',' + dragStartNode.y + 'L' + dragStartNode.x + ',' + dragStartNode.y);
+            })
+            .on('mouseover', (n) => {
+              if(dragStartNode){
+                dragEndNode = n;
+              }
+            });
+
+          svg
+            .on('mousemove', function(){
+              if(!dragStartNode){
+                return;
+              }
+              dragLine.attr('d', 'M' + dragStartNode.x + ',' + dragStartNode.y + 'L' + d3.mouse(this)[0] + ',' + d3.mouse(this)[1]);
+            })
+            .on('mouseup', () => {
+              if(!dragStartNode || !dragEndNode){
+                resetDragInfo();
+                return;
+              }
+
+              // TODO
+              // [X] check that I can connect the two nodes
+              // [X] check link direction
+              // [ ] save the new link in the BE
+
+              // check that I can connect the 2 nodes
+              const successorType = SliceGraph.getNodeDataPlaneSuccessors(dragStartNode)[0].type;
+              if(dragEndNode.type !== successorType){
+                resetDragInfo();
+                return;
+              }
+
+              // create the link
+              _links.push({
+                source: dragStartNode,
+                target: dragEndNode,
+                data: {
+                  id: `${dragStartNode.id}.${dragEndNode.id}`,
+                  source: dragStartNode.id,
+                  target: dragEndNode.id
+                }
+              });
+
+              // update the graph
+              // TODO recalculate graph positions
+              drawGraph();
+
+              resetDragInfo();
+            });
+
+          // remove exiting nodes
+          svg.selectAll('.node-container')
+            .data(_nodes, d => d.id)
+            .exit()
+            .transition(t)
+            .attr({
+              opacity: 0
+            })
+            .remove();
+
+          // remove exiting links
+          svg.selectAll('.link-container')
+            .data(_links, d => d.data.id)
+            .exit()
+            .transition(t)
+            .attr({
+              opacity: 0
+            })
+            .remove();
+        };
+
+        d3.select('body')
+          .on('keydown', function(){
+            // console.log(d3.event.code);
+            if(d3.event.code === 'Backspace' && selectedLink){
+              // delete link
+              deleteLink(selectedLink.data.id);
+            }
+            if(d3.event.code === 'Enter' && selectedNode){
+              d3.event.preventDefault();
+              expandNode(selectedNode);
+            }
+            if(d3.event.code === 'Escape' && selectedNode){
+              selectedNode.selected = false;
+              selectedNode = null;
+              nodeSiblings = null;
+              drawGraph();
+            }
+            if(d3.event.code === 'ArrowRight'){
+              d3.event.preventDefault();
+              selectNextNode();
+            }
+            if(d3.event.code === 'ArrowLeft'){
+              d3.event.preventDefault();
+              selectPrevNode();
+            }
+            if(d3.event.code === 'ArrowUp'){
+              d3.event.preventDefault();
+              selectNextSibling();
+            }
+            if(d3.event.code === 'ArrowDown'){
+              d3.event.preventDefault();
+              selectPrevSibling();
+            }
+
+          });
+      }
+    }
+  });
+})();
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/sass/main.scss b/views/ngXosViews/mcord-slicing/src/sass/main.scss
new file mode 100644
index 0000000..7224300
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/sass/main.scss
@@ -0,0 +1,88 @@
+@import '../../../../style/sass/lib/_variables.scss';
+
+#xosMcord-slicing,
+#xosMcord-slicing > [ui-view],
+slicing-topo {
+  width: 100%;
+  height: 100%;
+}
+
+slicing-topo {
+  display: block;
+}
+
+#xosMcord-slicing {
+  .node {
+    stroke: $brand-primary;
+    fill: white;
+  }
+
+  .node,
+  .node + text {
+    cursor: pointer;
+  }
+
+  text {
+    pointer-events: none;
+    -webkit-user-select: none;  /* Chrome all / Safari all */
+    -moz-user-select: none;     /* Firefox all */
+    -ms-user-select: none;      /* IE 10+ */
+    user-select: none;
+  }
+
+  .node.control {
+    stroke-dasharray: 5;
+    stroke: $brand-danger;
+  }
+
+  .node.button {
+    //stroke-dasharray: 5;
+    stroke: $brand-info;
+    fill: lighten($brand-info, 30)
+  }
+
+  .node.selected{
+    stroke-width: 5px;
+    stroke-dasharray: 5;
+  }
+
+  .link {
+    stroke: darken($brand-primary, 10);
+    stroke-width: 2px;
+    cursor: pointer;
+  }
+
+  .link.control {
+    stroke-dasharray: 5;
+    stroke: $brand-danger;
+  }
+
+  .link.selected {
+    stroke-width: 5px;
+    stroke-dasharray: 5;
+  }
+
+  // drag line
+  .dragline {
+    stroke-dasharray: 5;
+    stroke: darken($brand-primary, 10);
+    stroke-width: 2px;
+  }
+
+  .dragline.hidden {
+    stroke-width: 0;
+  }
+
+  // form styling
+  div.element-form {
+    position: absolute;
+    border: 1px solid $brand-info;
+    padding: 10px;
+    background: #fff;
+  }
+
+  .form-line {
+    stroke: darken($brand-info, 10);
+    stroke-width: 1px;
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/templates/node-links.tpl.html b/views/ngXosViews/mcord-slicing/src/templates/node-links.tpl.html
new file mode 100644
index 0000000..e15da33
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/templates/node-links.tpl.html
@@ -0,0 +1,6 @@
+<div class="row">
+  <div class="col-sm-12">
+    <xos-table config="vm.tableConfig" data="vm.users"></xos-table>
+  </div>
+  <div class="col-sm-12"></div>
+</div>
\ No newline at end of file
diff --git a/views/ngXosViews/mcord-slicing/src/templates/slicing-topo.tpl.html b/views/ngXosViews/mcord-slicing/src/templates/slicing-topo.tpl.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/views/ngXosViews/mcord-slicing/src/templates/slicing-topo.tpl.html