Changes to user-prefs to add better tests

Change-Id: Ic86928304c20a4c5fca781517e7eff91c1a28bd4
diff --git a/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js b/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js
index 7a00cc7..464184b 100644
--- a/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js
+++ b/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js
@@ -48,8 +48,6 @@
         expect(service.setSynchronizerNotificationStatus).toBeDefined();
         expect(service.setUserDetailsCookie).toBeDefined();
         expect(service.getUserDetailsCookie).toBeDefined();
-        expect(service.setDataUser).toBeDefined()
-
       });
 
       describe('the getAll method', () => {
@@ -94,15 +92,6 @@
           });
         });
 
-        describe('the getUserDetailsCookie method', () => {
-          it('should return current user id', (done) => {
-            service.getUserDetailsCookie().$promise.then((res) => {
-              expect(res.userId).toEqual(syncNotification.userData.userId);
-              done();
-            });
-            rootScope.$apply();
-          });
-        });
         describe('the setSynchronizerNotificationStatus', () => {
           
           it('should throw an error if called without synchronizer name', () => {
@@ -128,32 +117,60 @@
           });
         });
       });
+
       describe('the userdetails status', () => {
-        let syncNotification;
-        beforeEach(() => {
-          syncNotification = {
-            synchronizers: {
-              notification: {
-                first: true,
-                second: false
-              }
-            }
-          }
-          cookies.xosUserPrefs = JSON.stringify(syncNotification);
-        });
+        let userdata, meMock;
         const userData = {
-          userId: 1
+          current_user_id: 2
         };
         beforeEach(inject(($q,Me) => {
+          userdata = {
+            userData: {
+              current_user_id:1
+            }
+          }
+          cookies.xosUserPrefs = JSON.stringify(userdata);
           deffered= $q.defer();
-          spyOn(Me, 'get').and.callFake(function(){
-            return {$promise: deffered.promise};
+          meMock = Me;
+          spyOn(meMock, 'get').and.callFake(function(){
+            return deffered.promise;
           });
         }));
-        describe('the getUserDetailsCookie method', () => {
-          it('should return current user id', (done) => {
+        describe('Get user data method' , ()=>{
+          it('it should return the stored data', (done) => {
+            service.getUserDetailsCookie().$promise.then((data) => {
+              expect(data).toEqual(userdata.userData);
+              done();
+            });
+            rootScope.$apply();
+          });
+
+          it('Should call the Api to return the data', (done) => {
+            cookies.xosUserPrefs = JSON.stringify();
             service.getUserDetailsCookie().$promise.then((res) => {
               expect(res.userId).toEqual(userData.userId);
+              expect(meMock.get).toHaveBeenCalled();
+              done();
+            });
+            deffered.resolve(userData);
+            rootScope.$apply();
+          });
+
+        });
+        describe('Set user data method' , ()=>{
+          it('it should save the provided data' , (done) => {
+            service.setUserDetailsCookie(userData).$promise.then(data => {
+              expect(data).toEqual(userData);
+              expect(cookieMock.put).toHaveBeenCalledWith('xosUserPrefs',  '{"userData":{"current_user_id":2}}');
+              done();
+            });
+            rootScope.$apply();
+          });
+          it('Should call the Api to save the data',(done)=>{
+            service.setUserDetailsCookie().$promise.then(data => {
+              expect(meMock.get).toHaveBeenCalled();
+              expect(data).toEqual(userData);
+              expect(cookieMock.put).toHaveBeenCalledWith('xosUserPrefs',  '{"userData":{"current_user_id":2}}');
               done();
             });
             deffered.resolve(userData);
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
index bb8a810..5e59c7c 100644
--- a/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
@@ -84,7 +84,7 @@
       var defer = $q.defer();

       let localPref  = this.getAll();

       if(!localPref.userData){

-        this.setUserDetailsCookie(localPref).$promise.then((data)=>{

+        this.setUserDetailsCookie().$promise.then((data)=>{

           defer.resolve(data);

         });

       }

@@ -96,21 +96,6 @@
 

     /**

     * @ngdoc method

-    * @name xos.helpers.XosUserPrefs#setDataUser

-    * @methodOf xos.helpers.XosUserPrefs

-    * @description

-    * Return all the user details from the endpoint (api/utility/me)

-    * @returns {object} The user details

-    **/

-

-    this.setDataUser = ()=>{

-      //var deff = $q.defer();

-      return Me.get().$promise;

-

-    };

-

-    /**

-    * @ngdoc method

     * @name xos.helpers.XosUserPrefs#setUserDetailsCookie

     * @methodOf xos.helpers.XosUserPrefs

     * @description

@@ -118,20 +103,25 @@
     * @param {object} details stored in cookie

     * @param {objects} returns the user details as a promise

     **/

-    this.setUserDetailsCookie = (localPref = localPref)=> {

+    this.setUserDetailsCookie = (userData = null)=> {

 

       var defer = $q.defer();

-      this.setDataUser().then((user)=>{

-        this.model = user;

-        defer.resolve(this.model);

-      }).then(() => {

-        localPref.userData = this.model.data;

-        this.setAll(localPref);

-      })

-      .catch ((e) => {

-        defer.reject(e);

-        throw new Error(e);

-      });

+      let cookies = this.getAll();

+      if (!userData){

+        Me.get().then((user)=> {

+          cookies.userData = user;

+          this.setAll(cookies);

+          defer.resolve(user);

+        })

+        .catch ((e) => {

+          defer.reject(e);

+        });

+      }

+      else {

+        cookies.userData = userData;

+        this.setAll(cookies);

+        defer.resolve(userData);

+      }

       return {$promise: defer.promise};

     }

 

diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 33a02db..3184e0e 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1,2 +1,3063 @@
-"use strict";function _toConsumableArray(e){if(Array.isArray(e)){for(var n=0,o=Array(e.length);n<e.length;n++)o[n]=e[n];return o}return Array.from(e)}!function(){angular.module("xos.uiComponents",["chart.js","RecursionHelper"])}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").directive("xosSmartTable",function(){return{restrict:"E",scope:{config:"="},template:'\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","LabelFormatter","_","XosFormHelpers",function(e,n,o,t){var i=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){i.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(i.data,function(n){return n.id===e.id}),i.responseMsg=i.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){i.responseErr=n.data.detail||"Error while deleting "+i.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){i.detailedItem=e}}],classes:"table table-striped table-bordered table-responsive",filter:"field",order:!0,pagination:{pageSize:10}},this.formConfig={exclude:this.config.hiddenFields,fields:{},formName:this.config.resource+"Form",actions:[{label:"Save",icon:"ok",cb:function(e){var n=void 0,o=!0;e.id?(n=e.$update(),o=!1):n=e.$save(),n.then(function(n){o&&i.data.push(angular.copy(n)),delete i.detailedItem,i.responseMsg=i.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){i.responseErr=n.data.detail||"Error while saving "+i.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete i.detailedItem},this.createItem=function(){i.detailedItem=new i.Resource},this.Resource=e.get(this.config.resource);var r=function(){i.Resource.query().$promise.then(function(e){if(!e[0])return void(i.data=e);var r=e[0],a=Object.keys(r);o.remove(a,function(e){return"id"===e||"validators"===e}),angular.isArray(i.config.hiddenFields)&&(a=o.difference(a,i.config.hiddenFields));var s=a.map(function(e){return n.format(e)});a.forEach(function(e,n){var o={label:s[n],prop:e};angular.isString(r[e])&&"undefined"!=typeof r[e]&&(o.type=_typeof(r[e])),i.tableConfig.columns.push(o)}),a.forEach(function(e,o){i.formConfig.fields[e]={label:n.format(s[o]).replace(":",""),type:t._getFieldFormat(r[e])}}),i.data=e})};r()}]}})}(),function(){angular.module("xos.uiComponents").directive("xosSmartPie",function(){return{restrict:"E",scope:{config:"="},template:'\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","$interval","$scope","$timeout","_",function(e,n,o,t,i){var r=this;if(!this.config.resource&&!this.config.data)throw new Error("[xosSmartPie] Please provide a resource or an array of data in the configuration");var a=function(e){return i.groupBy(e,r.config.groupBy)},s=function(e){return i.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},l=function(e){return angular.isFunction(r.config.labelFormatter)?r.config.labelFormatter(Object.keys(e)):Object.keys(e)},c=function(e){var n=a(e);r.data=s(n),r.labels=l(n)};this.config.resource?!function(){r.Resource=e.get(r.config.resource);var o=function(){r.Resource.query().$promise.then(function(e){e[0]&&c(e)})};o(),r.config.poll&&n(function(){o()},1e3*r.config.poll)}():o.$watch(function(){return r.config.data},function(e){e&&c(r.config.data)},!0),o.$on("create",function(e,n){console.log("create: "+n.id)}),o.$on("destroy",function(e,n){console.log("destroy: "+n.id)})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosValidation",function(){return{restrict:"E",scope:{field:"=",form:"="},template:'\n        <div ng-cloak>\n          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),function(){angular.module("xos.uiComponents").directive("xosTable",function(){return{restrict:"E",scope:{data:"=",config:"="},template:'\n          <div ng-show="vm.data.length > 0 && vm.loader == false">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\' && col.type !== \'array\' && col.type !== \'object\' && col.type !== \'custom\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" xos-link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n          <div ng-show="vm.loader == true">\n            <div class="loader"></div>\n          </div>\n        ',bindToController:!0,controllerAs:"vm",controller:["_","$scope","Comparator",function(e,n,o){var t=this;if(this.comparator=o,this.loader=!0,n.$watch(function(){return t.data},function(e){angular.isDefined(e)&&(t.loader=!1)}),!this.config)throw new Error('[xosTable] Please provide a configuration via the "config" attribute');if(!this.config.columns)throw new Error("[xosTable] Please provide a columns list in the configuration");this.config.order&&angular.isObject(this.config.order)&&(this.reverse=this.config.order.reverse||!1,this.orderBy=this.config.order.field||"id");var i=e.filter(this.config.columns,{type:"custom"});angular.isArray(i)&&i.length>0&&e.forEach(i,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided a custom field type, a formatter function should provided too.")});var r=e.filter(this.config.columns,{type:"icon"});angular.isArray(r)&&r.length>0&&e.forEach(r,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided an icon field type, a formatter function should provided too.")});var a=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(a)&&a.length>0&&e.forEach(a,function(e){if(!angular.isFunction(e.link))throw new Error("[xosTable] The link property should be a function.")}),this.columns=this.config.columns,this.classes=this.config.classes||"table table-striped table-bordered",this.config.actions,this.config.pagination&&(this.currentPage=0,this.goToPage=function(e){t.currentPage=e})}]}}).filter("arrayToList",function(){return function(e){return angular.isArray(e)?e.join(", "):e}}).directive("xosLinkWrapper",function(){return{restrict:"A",transclude:!0,template:'\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '}})}(),function(){angular.module("xos.uiComponents").directive("xosPagination",function(){return{restrict:"E",scope:{pageSize:"=",totalElements:"=",change:"="},template:'\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope",function(e){var n=this;this.currentPage=0,this.goToPage=function(e){e<0||e===n.pages||(n.currentPage=e,n.change(e))},this.createPages=function(e){for(var n=[],o=0;o<e;o++)n.push(o);return n},e.$watch(function(){return n.totalElements},function(){n.totalElements&&(n.pages=Math.ceil(n.totalElements/n.pageSize),n.pageList=n.createPages(n.pages))})}]}}).filter("pagination",function(){return function(e,n){return e&&angular.isArray(e)?(n=parseInt(n,10),e.slice(n)):e}})}(),function(){angular.module("xos.uiComponents").directive("xosForm",function(){return{restrict:"E",scope:{config:"=",ngModel:"="},template:'\n        <form name="vm.{{vm.config.formName || \'form\'}}" novalidate>\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation field="vm[vm.config.formName || \'form\'][name]" form = "vm[vm.config.formName || \'form\']"></xos-validation>\n            <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n          <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>\n\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel, vm[vm.config.formName || \'form\'])"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </form>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope","$log","_","XosFormHelpers",function(e,n,o,t){var i=this;if(!this.config)throw new Error('[xosForm] Please provide a configuration via the "config" attribute');if(!this.config.actions)throw new Error("[xosForm] Please provide an action list in the configuration");this.config.feedback||(this.config.feedback={show:!1,message:"Form submitted successfully !!!",type:"success"}),this.excludedField=["id","validators","created","updated","deleted","backend_status"],this.config&&this.config.exclude&&(this.excludedField=this.excludedField.concat(this.config.exclude)),this.formField=[],e.$watch(function(){return i.config},function(){if(i.ngModel){var e=o.difference(Object.keys(i.ngModel),i.excludedField),n=t.parseModelField(e);i.formField=t.buildFormStructure(n,i.config.fields,i.ngModel)}},!0),e.$watch(function(){return i.ngModel},function(e){if(i.formField={},e){var n=o.difference(Object.keys(e),i.excludedField),r=t.parseModelField(n);i.formField=t.buildFormStructure(r,i.config.fields,e)}})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosField",["RecursionHelper",function(e){return{restrict:"E",scope:{name:"=",field:"=",ngModel:"="},template:'\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              xos-custom-validator custom-validator="vm.field.validators.custom || null"\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\' && vm.field.type !== \'select\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n              <select class="form-control" ng-if ="vm.field.type === \'select\'"\n                name = "{{vm.name}}"\n                ng-options="item.id as item.label for item in vm.field.options"\n                ng-model="vm.ngModel"\n                ng-required="vm.field.validators.required || false">\n                </select>\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <a href="#"\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </a>\n              <a href="#"\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </a>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n                <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">\n                  <xos-field\n                    name="k"\n                    field="{\n                      label: v.label || vm.formatLabel(k),\n                      type: v.type,\n                      validators: v.validators\n                    }"\n                    ng-model="vm.ngModel[k]">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',bindToController:!0,controllerAs:"vm",compile:function(n){return e.compile(n)},controller:["$attrs","XosFormHelpers","LabelFormatter",function(e,n,o){if(!this.name)throw new Error("[xosField] Please provide a field name");if(!this.field)throw new Error("[xosField] Please provide a field definition");if(!this.field.type)throw new Error("[xosField] Please provide a type in the field definition");if(!e.ngModel)throw new Error("[xosField] Please provide an ng-model");this.getType=n._getFieldFormat,this.formatLabel=o.format,this.isEmptyObject=function(e){return!e||0===Object.keys(e).length}}]}}]).directive("xosCustomValidator",function(){return{restrict:"A",scope:{fn:"=customValidator"},require:"ngModel",link:function(e,n,o,t){function i(n){var o=e.fn(n);return angular.isArray(o)?t.$setValidity.apply(t,_toConsumableArray(o)):t.$setValidity("customValidation",o),n}angular.isFunction(e.fn)&&t.$parsers.push(i)}}})}(),function(){angular.module("xos.uiComponents").directive("xosAlert",function(){return{restrict:"E",scope:{config:"=",show:"=?"},template:'\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:["$timeout",function(e){var n=this;if(!this.config)throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');this.show=this.show!==!1,this.dismiss=function(){n.show=!1},this.config.autoHide&&!function(){var o=e(function(){n.dismiss(),e.cancel(o)},n.config.autoHide)}()}]}})}(),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},t=function(t){return t=e(t),t=n(t),t=o(t).replace(/\s\s+/g," ")+":",t.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:t}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").service("XosFormHelpers",["_","LabelFormatter",function(e,n){var o=this;this._isEmail=function(e){var n=/(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;return n.test(e)},this._getFieldFormat=function(n){return angular.isArray(n)?"array":e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":o._isEmail(n)?"email":angular.isString(n)||null===n?"text":"undefined"==typeof n?"undefined":_typeof(n)},this.buildFormStructure=function(t,i,r){return t=angular.extend(t,i),i=i||{},e.reduce(Object.keys(t),function(e,t){return e[t]={label:i[t]&&i[t].label?i[t].label+":":n.format(t),type:i[t]&&i[t].type?i[t].type:o._getFieldFormat(r[t]),validators:i[t]&&i[t].validators?i[t].validators:{},hint:i[t]&&i[t].hint?i[t].hint:""},i[t]&&i[t].options&&(e[t].options=i[t].options),i[t]&&i[t].properties&&(e[t].properties=i[t].properties),"date"===e[t].type&&(r[t]=new Date(r[t])),"number"===e[t].type&&(r[t]=parseInt(r[t],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[n]={},e},{})}}])}(),function(){function e(){return function(e,n){if(angular.isUndefined(e))return!1;if(null===e||null===n)return e===n;if(angular.isObject(n)||angular.isObject(e))return angular.equals(n,e);if(_.isBoolean(e)||_.isBoolean(n))return 0!==e&&1!==e||(e=!!e),angular.equals(n,e);if(!angular.isString(e)||!angular.isString(n)){if(!angular.isDefined(e.toString)||!angular.isDefined(n.toString))return e===n;e=e.toString(),n=n.toString()}return e=e.toLowerCase()+"",n=n.toLowerCase()+"",e.indexOf(n)!==-1}}angular.module("xos.uiComponents").factory("Comparator",e)}(),function(){function e(e,n,o){e.interceptors.push("SetCSRFToken"),n.startSymbol("{$"),n.endSymbol("$}"),o.defaults.stripTrailingSlashes=!1}e.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],angular.module("xos.helpers",["ngCookies","ngResource","ngAnimate","xos.uiComponents"]).config(e).factory("_",["$window",function(e){return e._}])}(),function(){angular.module("xos.helpers").service("vSG-Collection",["$resource",function(e){return e("/api/service/vsg/")}])}(),function(){angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(e){return e("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Login",["$resource",function(e){return e("/api/utility/login/")}]).service("Logout",["$resource",function(e){return e("/api/utility/logout/")}])}(),function(){angular.module("xos.helpers").service("Users",["$resource",function(e){return e("/api/core/users/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Truckroll",["$resource",function(e){return e("/api/tenant/truckroll/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Tenants",["$resource",function(e){return e("/api/core/tenants/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Subscribers",["$resource",function(e){return e("/api/tenant/cord/subscriber/:id/",{id:"@id"},{update:{method:"PUT"},"View-a-Subscriber-Features-Detail":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/"},"Read-Subscriber-uplink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Update-Subscriber-uplink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Read-Subscriber-downlink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Update-Subscriber-downlink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Read-Subscriber-cdn":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Update-Subscriber-cdn":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Read-Subscriber-uverse":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Update-Subscriber-uverse":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Read-Subscriber-status":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"},"Update-Subscriber-status":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"}})}])}(),function(){angular.module("xos.helpers").service("SlicesPlus",["$http","$q",function(e,n){this.query=function(o){var t=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){t.resolve(e.data)})["catch"](function(e){t.reject(e.data)}),{$promise:t.promise}},this.get=function(o,t){var i=n.defer();return e.get("/api/utility/slicesplus/"+o,{params:t}).then(function(e){i.resolve(e.data)})["catch"](function(e){i.reject(e.data)}),{$promise:i.promise}}}])}(),function(){angular.module("xos.helpers").service("Slices",["$resource",function(e){return e("/api/core/slices/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Sites",["$resource",function(e){return e("/api/core/sites/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Services",["$resource",function(e){return e("/api/core/services/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(e){return e("/api/service/onos/")}])}(),function(){angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(e){return e("/api/tenant/onos/app/")}])}(),function(){angular.module("xos.helpers").service("Nodes",["$resource",function(e){return e("/api/core/nodes/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Networkstemplates",["$resource",function(e){return e("/api/core/networktemplates/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Networks",["$resource",function(e){return e("/api/core/networks/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Me",["$q","$http",function(e,n){this.get=function(){var o=e.defer();return n.get("/api/utility/me/").then(function(e){o.resolve(e)})["catch"](function(e){o.reject(e)}),o.promise}}])}(),function(){angular.module("xos.helpers").service("Instances",["$resource",function(e){return e("/api/core/instances/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Images",["$resource",function(e){return e("/api/core/images/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Flavors",["$resource",function(e){return e("/api/core/flavors/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Example-Services-Collection",["$resource",function(e){return e("/api/service/exampleservice/")}])}(),function(){angular.module("xos.helpers").service("Deployments",["$resource",function(e){return e("/api/core/deployments/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("XosUserPrefs",["$cookies","Me","$q",function(e,n,o){var t=this,i=e.get("xosUserPrefs")?angular.fromJson(e.get("xosUserPrefs")):{};this.getAll=function(){return i=e.get("xosUserPrefs")?angular.fromJson(e.get("xosUserPrefs")):{}},this.setAll=function(n){e.put("xosUserPrefs",angular.toJson(n))},this.getSynchronizerNotificationStatus=function(){var e=!(arguments.length<=0||void 0===arguments[0])&&arguments[0];return e?t.getAll().synchronizers.notification[e]:t.getAll().synchronizers.notification},this.getUserDetailsCookie=function(){var e=o.defer(),n=t.getAll();return n.userData?e.resolve(n.userData):t.setUserDetailsCookie(n).$promise.then(function(n){e.resolve(n)}),{$promise:e.promise}},this.setDataUser=function(){return n.get().$promise},this.setUserDetailsCookie=function(){var e=arguments.length<=0||void 0===arguments[0]?e:arguments[0],n=o.defer();return t.setDataUser().then(function(e){t.model=e,n.resolve(t.model)}).then(function(){e.userData=t.model.data,t.setAll(e)})["catch"](function(e){throw n.reject(e),new Error(e)}),{$promise:n.promise}},this.setSynchronizerNotificationStatus=function(){var e=!(arguments.length<=0||void 0===arguments[0])&&arguments[0],n=arguments[1];if(!e)throw new Error("[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.");var o=t.getAll();o.synchronizers||(o.synchronizers={notification:{}}),o.synchronizers.notification[e]=n,t.setAll(o)}}])}(),function(){angular.module("xos.helpers").service("GraphService",["$q","Tenants","Services",function(e,n,o){
-var t=this;this.loadCoarseData=function(){var t=void 0,i=e.defer();return o.query().$promise.then(function(e){return t=e,n.query({kind:"coarse"}).$promise}).then(function(e){i.resolve({tenants:e,services:t})}),i.promise},this.getCoarseGraph=function(){return t.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),function(){angular.module("xos.helpers").factory("Notification",function(){return window.Notification}).service("xosNotification",["$q","$log","Notification",function(e,n,o){var t=this;this.checkPermission=function(){var n=e.defer();return o.requestPermission().then(function(e){"granted"===e?n.resolve(e):n.reject(e)}),n.promise},this.sendNotification=function(e,t){var i=new o(e,t);i.onerror=function(e){n.error(e)}},this.notify=function(e,i){"Notification"in window?"granted"!==o.permission?t.checkPermission().then(function(){return t.sendNotification(e,i)}):"granted"===o.permission&&t.sendNotification(e,i):n.info("This browser does not support desktop notification")}}])}(),function(){function e(){return{request:function(e){return e.url.indexOf(".html")===-1&&(e.url+="?no_hyperlinks=1"),e}}}angular.module("xos.helpers").factory("NoHyperlinks",e)}(),angular.module("xos.helpers").config(["$provide",function(e){e.decorator("$log",["$delegate",function(e){var n=function(){return window.location.href.indexOf("debug=true")>=0},o=e.log,t=e.info,i=e.warn,r=e.debug,a=function(o){return function(){if(n()){var t=[].slice.call(arguments),i=new Date;return t[0]="["+i.getHours()+":"+i.getMinutes()+":"+i.getSeconds()+"] "+t[0],!angular.isFunction(e.reset)||e.debug.logs instanceof Array||e.reset(),o.apply(null,t)}}};return e.info=a(t),e.log=a(o),e.warn=a(i),e.debug=a(r),e}])}]),function(){function e(e){return{request:function(n){return"GET"!==n.method&&(n.headers["X-CSRFToken"]=e.get("xoscsrftoken")),n}}}e.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",e)}();
\ No newline at end of file
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc overview
+  * @name xos.uiComponents
+  * @description
+  * A collection of UI components useful for Dashboard development.
+  * Currently available components are:
+  * - [xosAlert](/#/module/xos.uiComponents.directive:xosAlert)
+  * - [xosForm](/#/module/xos.uiComponents.directive:xosForm)
+  * - [xosPagination](/#/module/xos.uiComponents.directive:xosPagination)
+  * - [xosSmartTable](/#/module/xos.uiComponents.directive:xosSmartTable)
+  * - [xosTable](/#/module/xos.uiComponents.directive:xosTable)
+  * - [xosValidation](/#/module/xos.uiComponents.directive:xosValidation)
+  **/
+
+  angular.module('xos.uiComponents', ['chart.js', 'RecursionHelper']);
+})();
+//# sourceMappingURL=../maps/ui_components/ui-components.module.js.map
+
+'use strict';
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+  * @ngdoc directive
+  * @name xos.uiComponents.directive:xosSmartTable
+  * @link xos.uiComponents.directive:xosTable xosTable
+  * @link xos.uiComponents.directive:xosForm xosForm
+  * @restrict E
+  * @description The xos-table directive
+  * @param {Object} config The configuration for the component,
+  * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
+  * and an array of fields that shouldn't be printed.
+  * ```
+  * {
+      resource: 'Users',
+      hiddenFields: []
+    }
+  * ```
+  * @scope
+  * @example
+   <example module="sampleSmartTable">
+    <file name="index.html">
+      <div ng-controller="SampleCtrl as vm">
+        <xos-smart-table config="vm.config"></xos-smart-table>
+      </div>
+    </file>
+    <file name="script.js">
+      angular.module('sampleSmartTable', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+      // This is only for documentation purpose
+      .run(function($httpBackend, _){
+        let datas = [{id: 1, name: 'Jhon', surname: 'Doe'}];
+        let count = 1;
+         let paramsUrl = new RegExp(/\/test\/(.+)/);
+         $httpBackend.whenDELETE(paramsUrl, undefined, ['id']).respond((method, url, data, headers, params) => {
+          data = angular.fromJson(data);
+          let id = url.match(paramsUrl)[1];
+          _.remove(datas, (d) => {
+            return d.id === parseInt(id);
+          })
+          return [204];
+        });
+         $httpBackend.whenGET('/test').respond(200, datas)
+        $httpBackend.whenPOST('/test').respond((method, url, data) => {
+          data = angular.fromJson(data);
+          data.id = ++count;
+          datas.push(data);
+          return [201, data, {}];
+        });
+      })
+      .factory('_', function($window){
+        return $window._;
+      })
+      .service('SampleResource', function($resource){
+        return $resource('/test/:id', {id: '@id'});
+      })
+      // End of documentation purpose, example start
+      .controller('SampleCtrl', function(){
+        this.config = {
+          resource: 'SampleResource'
+        };
+      });
+    </file>
+  </example>
+  */
+
+  .directive('xosSmartTable', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        config: '='
+      },
+      template: '\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["$injector", "LabelFormatter", "_", "XosFormHelpers", function controller($injector, LabelFormatter, _, XosFormHelpers) {
+        var _this = this;
+
+        // TODO
+        // - Validate the config (what if resource does not exist?)
+
+        // NOTE
+        // Corner case
+        // - if response is empty, how can we generate a form ?
+
+        this.responseMsg = false;
+        this.responseErr = false;
+
+        this.tableConfig = {
+          columns: [],
+          actions: [{
+            label: 'delete',
+            icon: 'remove',
+            cb: function cb(item) {
+              _this.Resource.delete({ id: item.id }).$promise.then(function () {
+                _.remove(_this.data, function (d) {
+                  return d.id === item.id;
+                });
+                _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully deleted';
+              }).catch(function (err) {
+                _this.responseErr = err.data.detail || 'Error while deleting ' + _this.config.resource + ' with id ' + item.id;
+              });
+            },
+            color: 'red'
+          }, {
+            label: 'details',
+            icon: 'search',
+            cb: function cb(item) {
+              _this.detailedItem = item;
+            }
+          }],
+          classes: 'table table-striped table-bordered table-responsive',
+          filter: 'field',
+          order: true,
+          pagination: {
+            pageSize: 10
+          }
+        };
+
+        this.formConfig = {
+          exclude: this.config.hiddenFields,
+          fields: {},
+          formName: this.config.resource + 'Form',
+          actions: [{
+            label: 'Save',
+            icon: 'ok',
+            cb: function cb(item) {
+              var p = void 0;
+              var isNew = true;
+
+              if (item.id) {
+                p = item.$update();
+                isNew = false;
+              } else {
+                p = item.$save();
+              }
+
+              p.then(function (res) {
+                if (isNew) {
+                  _this.data.push(angular.copy(res));
+                }
+                delete _this.detailedItem;
+                _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully saved';
+              }).catch(function (err) {
+                _this.responseErr = err.data.detail || 'Error while saving ' + _this.config.resource + ' with id ' + item.id;
+              });
+            },
+            class: 'success'
+          }]
+        };
+
+        this.cleanForm = function () {
+          delete _this.detailedItem;
+        };
+
+        this.createItem = function () {
+          _this.detailedItem = new _this.Resource();
+        };
+
+        this.Resource = $injector.get(this.config.resource);
+
+        var getData = function getData() {
+          _this.Resource.query().$promise.then(function (res) {
+
+            if (!res[0]) {
+              _this.data = res;
+              return;
+            }
+
+            var item = res[0];
+            var props = Object.keys(item);
+
+            _.remove(props, function (p) {
+              return p === 'id' || p === 'validators';
+            });
+
+            // TODO move out cb,  non sense triggering a lot of times
+            if (angular.isArray(_this.config.hiddenFields)) {
+              props = _.difference(props, _this.config.hiddenFields);
+            }
+
+            var labels = props.map(function (p) {
+              return LabelFormatter.format(p);
+            });
+
+            props.forEach(function (p, i) {
+              var fieldConfig = {
+                label: labels[i],
+                prop: p
+              };
+
+              if (angular.isString(item[p]) && typeof item[p] !== 'undefined') {
+                fieldConfig.type = _typeof(item[p]);
+              }
+
+              _this.tableConfig.columns.push(fieldConfig);
+            });
+
+            // build form structure
+            // TODO move in a pure function for testing purposes
+            props.forEach(function (p, i) {
+              _this.formConfig.fields[p] = {
+                label: LabelFormatter.format(labels[i]).replace(':', ''),
+                type: XosFormHelpers._getFieldFormat(item[p])
+              };
+            });
+
+            _this.data = res;
+          });
+        };
+
+        getData();
+      }]
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartTable/smartTable.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosSmartPie
+    * @restrict E
+    * @description The xos-table directive
+    * @param {Object} config The configuration for the component,
+    * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
+    * and a field name that is used to group the data.
+    * ```
+    * {
+        resource: 'Users',
+        groupBy: 'fieldName',
+        classes: 'my-custom-class',
+        labelFormatter: (labels) => {
+          // here you can format your label,
+          // you should return an array with the same order
+          return labels;
+        }
+      }
+    * ```
+    * @scope
+    * @example
+    
+    Displaying Local data
+     <example module="sampleSmartPieLocal">
+      <file name="index.html">
+        <div ng-controller="SampleCtrlLocal as vm">
+          <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
+        </div>
+      </file>
+      <file name="script.js">
+        angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
+        .factory('_', function($window){
+          return $window._;
+        })
+        .controller('SampleCtrlLocal', function($timeout){
+          
+          this.datas = [
+            {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
+            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
+            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
+          ];
+           this.configLocal = {
+            data: [],
+            groupBy: 'category',
+            classes: 'local',
+            labelFormatter: (labels) => {
+              return labels.map(l => l === '1' ? 'North' : 'Dragon');
+            }
+          };
+          
+          $timeout(() => {
+            // this need to be triggered in this way just because of ngDoc,
+            // otherwise you can assign data directly in the config
+            this.configLocal.data = this.datas;
+          }, 1)
+        });
+      </file>
+    </example>
+     Fetching data from API
+     <example module="sampleSmartPieResource">
+      <file name="index.html">
+        <div ng-controller="SampleCtrl as vm">
+          <xos-smart-pie config="vm.config"></xos-smart-pie>
+        </div>
+      </file>
+      <file name="script.js">
+        angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+        .controller('SampleCtrl', function(){
+          this.config = {
+            resource: 'SampleResource',
+            groupBy: 'category',
+            classes: 'resource',
+            labelFormatter: (labels) => {
+              return labels.map(l => l === '1' ? 'North' : 'Dragon');
+            }
+          };
+        });
+      </file>
+      <file name="backendPoll.js">
+        angular.module('sampleSmartPieResource')
+        .run(function($httpBackend, _){
+          let datas = [
+            {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
+          ];
+           $httpBackend.whenGET('/test').respond(200, datas)
+        })
+        .factory('_', function($window){
+          return $window._;
+        })
+        .service('SampleResource', function($resource){
+          return $resource('/test/:id', {id: '@id'});
+        })
+      </file>
+    </example>
+     Polling data from API
+     <example module="sampleSmartPiePoll">
+      <file name="index.html">
+        <div ng-controller="SampleCtrl as vm">
+          <xos-smart-pie config="vm.config"></xos-smart-pie>
+        </div>
+      </file>
+      <file name="script.js">
+        angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+        .controller('SampleCtrl', function(){
+          this.config = {
+            resource: 'SampleResource',
+            groupBy: 'category',
+            poll: 2,
+            labelFormatter: (labels) => {
+              return labels.map(l => l === '1' ? 'Active' : 'Banned');
+            }
+          };
+        });
+      </file>
+      <file name="backend.js">
+        angular.module('sampleSmartPiePoll')
+        .run(function($httpBackend, _){
+          let mock = [
+            [
+              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
+              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
+            ],
+             [
+              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
+              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
+            ],
+             [
+              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
+              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
+            ]
+          ];
+          $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
+            return [200, mock[Math.round(Math.random() * 3)]];
+          });
+        })
+        .factory('_', function($window){
+          return $window._;
+        })
+        .service('SampleResource', function($resource){
+          return $resource('/test/:id', {id: '@id'});
+        })
+      </file>
+    </example>
+    */
+  .directive('xosSmartPie', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        config: '='
+      },
+      template: '\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["$injector", "$interval", "$scope", "$timeout", "_", function controller($injector, $interval, $scope, $timeout, _) {
+        var _this = this;
+
+        if (!this.config.resource && !this.config.data) {
+          throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
+        }
+
+        var groupData = function groupData(data) {
+          return _.groupBy(data, _this.config.groupBy);
+        };
+        var formatData = function formatData(data) {
+          return _.reduce(Object.keys(data), function (list, group) {
+            return list.concat(data[group].length);
+          }, []);
+        };
+        var formatLabels = function formatLabels(data) {
+          return angular.isFunction(_this.config.labelFormatter) ? _this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
+        };
+
+        var prepareData = function prepareData(data) {
+          // group data
+          var grouped = groupData(data);
+          _this.data = formatData(grouped);
+          // create labels
+          _this.labels = formatLabels(grouped);
+        };
+
+        if (this.config.resource) {
+          (function () {
+
+            _this.Resource = $injector.get(_this.config.resource);
+            var getData = function getData() {
+              _this.Resource.query().$promise.then(function (res) {
+
+                if (!res[0]) {
+                  return;
+                }
+
+                prepareData(res);
+              });
+            };
+
+            getData();
+
+            if (_this.config.poll) {
+              $interval(function () {
+                getData();
+              }, _this.config.poll * 1000);
+            }
+          })();
+        } else {
+          $scope.$watch(function () {
+            return _this.config.data;
+          }, function (data) {
+            if (data) {
+              prepareData(_this.config.data);
+            }
+          }, true);
+        }
+
+        $scope.$on('create', function (event, chart) {
+          console.log('create: ' + chart.id);
+        });
+
+        $scope.$on('destroy', function (event, chart) {
+          console.log('destroy: ' + chart.id);
+        });
+      }]
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartPie/smartPie.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosValidation
+    * @restrict E
+    * @description The xos-validation directive
+    * @param {Object} errors The error object
+    * @element ANY
+    * @scope
+  * @example
+  <example module="sampleValidation">
+    <file name="index.html">
+      <div ng-controller="SampleCtrl as vm">
+        <div class="row">
+          <div class="col-xs-12">
+            <label>Set an error type:</label>
+          </div>
+          <div class="col-xs-2">
+            <a class="btn"
+              ng-click="vm.field.$error.required = !vm.field.$error.required"
+              ng-class="{'btn-default': !vm.field.$error.required, 'btn-success': vm.field.$error.required}">
+              Required
+            </a>
+          </div>
+          <div class="col-xs-2">
+            <a class="btn"
+              ng-click="vm.field.$error.email = !vm.field.$error.email"
+              ng-class="{'btn-default': !vm.field.$error.email, 'btn-success': vm.field.$error.email}">
+              Email
+            </a>
+          </div>
+          <div class="col-xs-2">
+            <a class="btn"
+              ng-click="vm.field.$error.minlength = !vm.field.$error.minlength"
+              ng-class="{'btn-default': !vm.field.$error.minlength, 'btn-success': vm.field.$error.minlength}">
+              Min Length
+            </a>
+          </div>
+          <div class="col-xs-2">
+            <a class="btn"
+              ng-click="vm.field.$error.maxlength = !vm.field.$error.maxlength"
+              ng-class="{'btn-default': !vm.field.$error.maxlength, 'btn-success': vm.field.$error.maxlength}">
+              Max Length
+            </a>
+          </div>
+        </div>
+        <xos-validation field ="vm.field" form = "vm.form"></xos-validation>
+      </div>
+    </file>
+    <file name="script.js">
+      angular.module('sampleValidation', ['xos.uiComponents'])
+      .controller('SampleCtrl', function(){
+        this.field = {
+          $error: {}
+        };
+        this.form= {
+        $submitted:true
+        }
+      });
+    </file>
+  </example>
+    */
+
+  .directive('xosValidation', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        field: '=',
+        form: '='
+      },
+      template: '\n        <div ng-cloak>\n          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',
+      transclude: true,
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: function controller() {
+        this.config = {
+          type: 'danger'
+        };
+      }
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/validation/validation.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+  * @ngdoc directive
+  * @name xos.uiComponents.directive:xosTable
+  * @restrict E
+  * @description The xos-table directive
+  * @param {Object} config The configuration for the component.
+  * ```
+  * {
+  *   columns: [
+  *     {
+  *       label: 'Human readable name',
+  *       prop: 'Property to read in the model object',
+  *       type: 'boolean'| 'array'| 'object'| 'custom'| 'date' | 'icon' // see examples for more details
+          formatter: fn(), // receive the whole item if tipe is custom and return a string
+          link: fn() // receive the whole item and return an url
+  *     }
+  *   ],
+  *   classes: 'table table-striped table-bordered',
+  *   actions: [ // if defined add an action column
+        {
+          label: 'delete',
+          icon: 'remove', // refers to bootstraps glyphicon
+          cb: (user) => { // receive the model
+            console.log(user);
+          },
+          color: 'red'
+        }
+      ],
+      filter: 'field', // can be by `field` or `fulltext`
+      order: true | {field: 'property name', reverse: true | false} // whether to show ordering arrows, or a configuration for a default ordering
+  * }
+  * ```
+  * @param {Array} data The data that should be rendered
+  * @element ANY
+  * @scope
+  * @example
+   # Basic usage
+  <example module="sampleTable1">
+  <file name="index.html">
+    <div ng-controller="SampleCtrl1 as vm">
+      <xos-table data="vm.data" config="vm.config"></xos-table>
+    </div>
+  </file>
+  <file name="script.js">
+    angular.module('sampleTable1', ['xos.uiComponents'])
+    .factory('_', function($window){
+      return $window._;
+    })
+    .controller('SampleCtrl1', function(){
+      this.config = {
+        columns: [
+          {
+            label: 'First Name', // column title
+            prop: 'name' // property to read in the data array
+          },
+          {
+            label: 'Last Name',
+            prop: 'lastname'
+          }
+        ]
+      };
+       this.data = [
+        {
+          name: 'John',
+          lastname: 'Doe'
+        },
+        {
+          name: 'Gili',
+          lastname: 'Fereydoun'
+        }
+      ]
+    });
+  </file>
+  </example>
+   # Filtering
+  <example module="sampleTable2" animations="true">
+  <file name="index.html">
+    <div ng-controller="SampleCtrl2 as vm">
+      <xos-table data="vm.data" config="vm.config"></xos-table>
+    </div>
+  </file>
+  <file name="script.js">
+    angular.module('sampleTable2', ['xos.uiComponents', 'ngAnimate'])
+    .factory('_', function($window){
+      return $window._;
+    })
+    .controller('SampleCtrl2', function(){
+      this.config = {
+        columns: [
+          {
+            label: 'First Name', // column title
+            prop: 'name' // property to read in the data array
+          },
+          {
+            label: 'Last Name',
+            prop: 'lastname'
+          }
+        ],
+        classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
+        actions: [ // if defined add an action column
+          {
+            label: 'delete', // label
+            icon: 'remove', // icons, refers to bootstraps glyphicon
+            cb: (user) => { // callback, get feeded with the full object
+              console.log(user);
+            },
+            color: 'red' // icon color
+          }
+        ],
+        filter: 'field', // can be by `field` or `fulltext`
+        order: true
+      };
+       this.data = [
+        {
+          name: 'John',
+          lastname: 'Doe'
+        },
+        {
+          name: 'Gili',
+          lastname: 'Fereydoun'
+        }
+      ]
+    });
+  </file>
+  </example>
+   # Pagination
+  <example module="sampleTable3">
+  <file name="index.html">
+    <div ng-controller="SampleCtrl3 as vm">
+      <xos-table data="vm.data" config="vm.config"></xos-table>
+    </div>
+  </file>
+  <file name="script.js">
+    angular.module('sampleTable3', ['xos.uiComponents'])
+    .factory('_', function($window){
+      return $window._;
+    })
+    .controller('SampleCtrl3', function(){
+      this.config = {
+        columns: [
+          {
+            label: 'First Name', // column title
+            prop: 'name' // property to read in the data array
+          },
+          {
+            label: 'Last Name',
+            prop: 'lastname'
+          }
+        ],
+        pagination: {
+          pageSize: 2
+        }
+      };
+       this.data = [
+        {
+          name: 'John',
+          lastname: 'Doe'
+        },
+        {
+          name: 'Gili',
+          lastname: 'Fereydoun'
+        },
+        {
+          name: 'Lucky',
+          lastname: 'Clarkson'
+        },
+        {
+          name: 'Tate',
+          lastname: 'Spalding'
+        }
+      ]
+    });
+  </file>
+  </example>
+   # Field formatter
+  <example module="sampleTable4">
+  <file name="index.html">
+    <div ng-controller="SampleCtrl as vm">
+      <xos-table data="vm.data" config="vm.config"></xos-table>
+    </div>
+  </file>
+  <file name="script.js">
+    angular.module('sampleTable4', ['xos.uiComponents'])
+    .factory('_', function($window){
+      return $window._;
+    })
+    .controller('SampleCtrl', function(){
+      this.config = {
+        columns: [
+          {
+            label: 'First Name',
+            prop: 'name',
+            link: item => `https://www.google.it/#q=${item.name}`
+          },
+          {
+            label: 'Enabled',
+            prop: 'enabled',
+            type: 'boolean'
+          },
+          {
+            label: 'Services',
+            prop: 'services',
+            type: 'array'
+          },
+          {
+            label: 'Details',
+            prop: 'details',
+            type: 'object'
+          },
+          {
+            label: 'Created',
+            prop: 'created',
+            type: 'date'
+          },
+          {
+            label: 'Icon',
+            type: 'icon',
+            formatter: item => item.icon //note that this refer to [Bootstrap Glyphicon](http://getbootstrap.com/components/#glyphicons)
+          }
+        ]
+      };
+       this.data = [
+        {
+          name: 'John',
+          enabled: true,
+          services: ['Cdn', 'IpTv'],
+          details: {
+            c_tag: '243',
+            s_tag: '444'
+          },
+          created: new Date('December 17, 1995 03:24:00'),
+          icon: 'music'
+        },
+        {
+          name: 'Gili',
+          enabled: false,
+          services: ['Cdn', 'IpTv', 'Cache'],
+          details: {
+            c_tag: '675',
+            s_tag: '893'
+          },
+          created: new Date(),
+          icon: 'camera'
+        }
+      ]
+    });
+  </file>
+  </example>
+  # Custom formatter
+  <example module="sampleTable5">
+  <file name="index.html">
+    <div ng-controller="SampleCtrl as vm">
+      <xos-table data="vm.data" config="vm.config"></xos-table>
+    </div>
+  </file>
+  <file name="script.js">
+    angular.module('sampleTable5', ['xos.uiComponents'])
+    .factory('_', function($window){
+      return $window._;
+    })
+    .controller('SampleCtrl', function(){
+      this.config = {
+        columns: [
+          {
+            label: 'Username',
+            prop: 'username'
+          },
+          {
+            label: 'Features',
+            type: 'custom',
+            formatter: (val) => {
+              
+              let cdnEnabled = val.features.cdn ? 'enabled' : 'disabled';
+              return `
+                Cdn is ${cdnEnabled},
+                uplink speed is ${val.features.uplink_speed}
+                and downlink speed is ${val.features.downlink_speed}
+              `;
+            }
+          }
+        ]
+      };
+       this.data = [
+        {
+          username: 'John',
+          features: {
+            "cdn": false,
+            "uplink_speed": 1000000000,
+            "downlink_speed": 1000000000,
+            "uverse": true,
+            "status": "enabled"
+          }
+        },
+        {
+          username: 'Gili',
+          features: {
+            "cdn": true,
+            "uplink_speed": 3000000000,
+            "downlink_speed": 2000000000,
+            "uverse": true,
+            "status": "enabled"
+          }
+        }
+      ]
+    });
+  </file>
+  </example>
+  **/
+
+  .directive('xosTable', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        data: '=',
+        config: '='
+      },
+      template: '\n          <div ng-show="vm.data.length > 0 && vm.loader == false">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\' && col.type !== \'array\' && col.type !== \'object\' && col.type !== \'custom\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" xos-link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n          <div ng-show="vm.loader == true">\n            <div class="loader"></div>\n          </div>\n        ',
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["_", "$scope", "Comparator", function controller(_, $scope, Comparator) {
+        var _this = this;
+
+        this.comparator = Comparator;
+
+        this.loader = true;
+
+        $scope.$watch(function () {
+          return _this.data;
+        }, function (data) {
+          if (angular.isDefined(data)) {
+            _this.loader = false;
+          }
+        });
+
+        if (!this.config) {
+          throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
+        }
+
+        if (!this.config.columns) {
+          throw new Error('[xosTable] Please provide a columns list in the configuration');
+        }
+
+        // handle default ordering
+        if (this.config.order && angular.isObject(this.config.order)) {
+          this.reverse = this.config.order.reverse || false;
+          this.orderBy = this.config.order.field || 'id';
+        }
+
+        // if columns with type 'custom' are provided
+        // check that a custom formatte3 is provided too
+        var customCols = _.filter(this.config.columns, { type: 'custom' });
+        if (angular.isArray(customCols) && customCols.length > 0) {
+          _.forEach(customCols, function (col) {
+            if (!col.formatter || !angular.isFunction(col.formatter)) {
+              throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
+            }
+          });
+        }
+
+        // if columns with type 'icon' are provided
+        // check that a custom formatte3 is provided too
+        var iconCols = _.filter(this.config.columns, { type: 'icon' });
+        if (angular.isArray(iconCols) && iconCols.length > 0) {
+          _.forEach(iconCols, function (col) {
+            if (!col.formatter || !angular.isFunction(col.formatter)) {
+              throw new Error('[xosTable] You have provided an icon field type, a formatter function should provided too.');
+            }
+          });
+        }
+
+        // if a link property is passed,
+        // it should be a function
+        var linkedColumns = _.filter(this.config.columns, function (col) {
+          return angular.isDefined(col.link);
+        });
+        if (angular.isArray(linkedColumns) && linkedColumns.length > 0) {
+          _.forEach(linkedColumns, function (col) {
+            if (!angular.isFunction(col.link)) {
+              throw new Error('[xosTable] The link property should be a function.');
+            }
+          });
+        }
+
+        this.columns = this.config.columns;
+        this.classes = this.config.classes || 'table table-striped table-bordered';
+
+        if (this.config.actions) {
+          // TODO validate action format
+        }
+        if (this.config.pagination) {
+          this.currentPage = 0;
+          this.goToPage = function (n) {
+            _this.currentPage = n;
+          };
+        }
+      }]
+    };
+  })
+  // TODO move in separate files
+  // TODO test
+  .filter('arrayToList', function () {
+    return function (input) {
+      if (!angular.isArray(input)) {
+        return input;
+      }
+      return input.join(', ');
+    };
+  })
+  // TODO test
+  .directive('xosLinkWrapper', function () {
+    return {
+      restrict: 'A',
+      transclude: true,
+      template: '\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/table/table.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosPagination
+    * @restrict E
+    * @description The xos-table directive
+    * @param {Number} pageSize Number of elements per page
+    * @param {Number} totalElements Number of total elements in the collection
+    * @param {Function} change The callback to be triggered on page change.
+    * * @element ANY
+    * @scope
+    * @example
+  <example module="samplePagination">
+    <file name="index.html">
+      <div ng-controller="SampleCtrl1 as vm">
+        <xos-pagination
+          page-size="vm.pageSize"
+          total-elements="vm.totalElements"
+          change="vm.change">
+        </xos-pagination>
+      </div>
+    </file>
+    <file name="script.js">
+      angular.module('samplePagination', ['xos.uiComponents'])
+      .controller('SampleCtrl1', function(){
+        this.pageSize = 10;
+        this.totalElements = 35;
+        this.change = (pageNumber) => {
+          console.log(pageNumber);
+        }
+      });
+    </file>
+  </example>
+  **/
+
+  .directive('xosPagination', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        pageSize: '=',
+        totalElements: '=',
+        change: '='
+      },
+      template: '\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["$scope", function controller($scope) {
+        var _this = this;
+
+        this.currentPage = 0;
+
+        this.goToPage = function (n) {
+          if (n < 0 || n === _this.pages) {
+            return;
+          }
+          _this.currentPage = n;
+          _this.change(n);
+        };
+
+        this.createPages = function (pages) {
+          var arr = [];
+          for (var i = 0; i < pages; i++) {
+            arr.push(i);
+          }
+          return arr;
+        };
+
+        // watch for data changes
+        $scope.$watch(function () {
+          return _this.totalElements;
+        }, function () {
+          if (_this.totalElements) {
+            _this.pages = Math.ceil(_this.totalElements / _this.pageSize);
+            _this.pageList = _this.createPages(_this.pages);
+          }
+        });
+      }]
+    };
+  }).filter('pagination', function () {
+    return function (input, start) {
+      if (!input || !angular.isArray(input)) {
+        return input;
+      }
+      start = parseInt(start, 10);
+      return input.slice(start);
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/pagination/pagination.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/18/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosForm
+    * @restrict E
+    * @description The xos-form directive.
+    * This components have two usage, given a model it is able to autogenerate a form or it can be configured to create a custom form.
+    * @param {Object} config The configuration object
+    * ```
+    * {
+    *   exclude: ['id', 'validators', 'created', 'updated', 'deleted'], //field to be skipped in the form, the provide values are concatenated
+    *   actions: [ // define the form buttons with related callback
+    *     {
+            label: 'save',
+            icon: 'ok', // refers to bootstraps glyphicon
+            cb: (user) => { // receive the model
+              console.log(user);
+            },
+            class: 'success'
+          }
+    *   ],
+    *   feedback: {
+          show: false,
+          message: 'Form submitted successfully !!!',
+          type: 'success'  //refers to bootstrap class
+        },
+    *   fields: {
+    *     field_name: {
+    *       label: 'Field Label',
+    *       type: 'string' // options are: [date, boolean, number, email, string, select],
+    *       validators: {
+    *         minlength: number,
+              maxlength: number,
+              required: boolean,
+              min: number,
+              max: number,
+              custom: (value) => {
+                // do your validation here and return true | false
+                // alternatively you can return an array [errorName, true|false]
+              }
+    *       }
+    *     }
+    *   }
+    * }
+    * ```
+    * @element ANY
+    * @scope
+    * @requires xos.uiComponents.directive:xosField
+    * @requires xos.uiComponents.XosFormHelpers
+    * @requires xos.helpers._
+    * @example
+    
+    Autogenerated form
+   <example module="sampleForm">
+    <file name="script.js">
+      angular.module('sampleForm', ['xos.uiComponents'])
+      .factory('_', function($window){
+        return $window._;
+      })
+      .controller('SampleCtrl', function(){
+        this.model = {
+          first_name: 'Jhon',
+          last_name: 'Doe',
+          email: 'jhon.doe@sample.com',
+          active: true,
+          birthDate: '2015-02-17T22:06:38.059000Z'
+        }
+        this.config = {
+          exclude: ['password', 'last_login'],
+          formName: 'sampleForm',
+          actions: [
+            {
+              label: 'Save',
+              icon: 'ok', // refers to bootstraps glyphicon
+              cb: (user) => { // receive the model
+                console.log(user);
+              },
+              class: 'success'
+            }
+          ]
+        };
+      });
+    </file>
+    <file name="index.html">
+      <div ng-controller="SampleCtrl as vm">
+        <xos-form ng-model="vm.model" config="vm.config"></xos-form>
+      </div>
+    </file>
+  </example>
+   Configuration defined form
+   <example module="sampleForm1">
+    <file name="script.js">
+      angular.module('sampleForm1', ['xos.uiComponents','ngResource', 'ngMockE2E'])
+      .factory('_', function($window){
+        return $window._;
+      })
+      .controller('SampleCtrl1', function(SampleResource){
+          this.model = {
+        };
+         this.config = {
+          exclude: ['password', 'last_login'],
+          formName: 'sampleForm1',
+          feedback: {
+            show: false,
+            message: 'Form submitted successfully !!!',
+            type: 'success'
+          },
+          actions: [
+            {
+              label: 'Save',
+              icon: 'ok', // refers to bootstraps glyphicon
+              cb: (user) => { // receive the model
+                console.log(user);
+                this.config.feedback.show = true;
+                this.config.feedback.type='success';
+              },
+              class: 'success'
+            }
+          ],
+          fields: {
+            first_name: {
+              type: 'string',
+              validators: {
+                required: true
+              }
+            },
+            last_name: {
+              label: 'Surname',
+              type: 'string',
+              validators: {
+                required: true,
+                minlength: 10
+              }
+            },
+            age: {
+              type: 'number',
+              validators: {
+                required: true,
+                min: 21
+              }
+            },
+             site: {
+            label: 'Site',
+            type: 'select',
+            validators: { required: true},
+            hint: 'The Site this Slice belongs to',
+            options: []
+            },
+         }
+        };
+        SampleResource.query().$promise
+          .then((users) => {
+          //this.users_site = users;
+        //console.log(users);
+          this.optionVal = users;
+          this.config.fields['site'].options = this.optionVal;
+        //= this.optionVal;
+       })
+      .catch((e) => {
+        throw new Error(e);
+      });
+       });
+    </file>
+   <file name="backend.js">
+     angular.module('sampleForm1')
+     .run(function($httpBackend, _){
+        let datas = [{id: 1, label: 'site1'},{id: 4, label: 'site4'},{id: 3, label: 'site3'}];
+        let paramsUrl = new RegExp(/\/test\/(.+)/);
+        $httpBackend.whenGET('/test').respond(200, datas)
+      })
+      .service('SampleResource', function($resource){
+        return $resource('/test/:id', {id: '@id'});
+      });
+     </file>
+    <file name="index.html">
+      <div ng-controller="SampleCtrl1 as vm">
+        <xos-form ng-model="vm.model" config="vm.config"></xos-form>
+      </div>
+    </file>
+  </example>
+   **/
+
+  .directive('xosForm', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        config: '=',
+        ngModel: '='
+      },
+      template: '\n        <form name="vm.{{vm.config.formName || \'form\'}}" novalidate>\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation field="vm[vm.config.formName || \'form\'][name]" form = "vm[vm.config.formName || \'form\']"></xos-validation>\n            <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n          <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>\n\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel, vm[vm.config.formName || \'form\'])"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </form>\n      ',
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["$scope", "$log", "_", "XosFormHelpers", function controller($scope, $log, _, XosFormHelpers) {
+        var _this = this;
+
+        if (!this.config) {
+          throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
+        }
+
+        if (!this.config.actions) {
+          throw new Error('[xosForm] Please provide an action list in the configuration');
+        }
+
+        if (!this.config.feedback) {
+          this.config.feedback = {
+            show: false,
+            message: 'Form submitted successfully !!!',
+            type: 'success'
+          };
+        }
+
+        this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
+        if (this.config && this.config.exclude) {
+          this.excludedField = this.excludedField.concat(this.config.exclude);
+        }
+
+        this.formField = [];
+
+        $scope.$watch(function () {
+          return _this.config;
+        }, function () {
+          if (!_this.ngModel) {
+            return;
+          }
+          var diff = _.difference(Object.keys(_this.ngModel), _this.excludedField);
+          var modelField = XosFormHelpers.parseModelField(diff);
+          _this.formField = XosFormHelpers.buildFormStructure(modelField, _this.config.fields, _this.ngModel);
+        }, true);
+
+        $scope.$watch(function () {
+          return _this.ngModel;
+        }, function (model) {
+          // empty from old stuff
+          _this.formField = {};
+          if (!model) {
+            return;
+          }
+          var diff = _.difference(Object.keys(model), _this.excludedField);
+          var modelField = XosFormHelpers.parseModelField(diff);
+          _this.formField = XosFormHelpers.buildFormStructure(modelField, _this.config.fields, model);
+        });
+      }]
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/form/form.component.js.map
+
+'use strict';
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 5/25/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosField
+    * @restrict E
+    * @description The xos-field directive.
+    * This component decide, give a field wich kind of input it need to print.
+    * @param {string} name The field name
+    * @param {object} field The field configuration:
+    * ```
+    * {
+    *   label: 'Label',
+    *   type: 'number', //typeof field
+    *   validators: {} // see xosForm for more details
+    * }
+    * ```
+    * @param {mixed} ngModel The field value
+    *
+    * @example
+    
+    # Basic Example
+    
+      <example module="sampleField1">
+        <file name="script.js">
+          angular.module('sampleField1', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.name = 'input-name';
+            this.field = {label: 'My String Value:', type: 'string'};
+            this.model = 'my string';
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <xos-field ng-model="vm.model" name="vm.name" field="vm.field"></xos-field>
+          </div>
+        </file>
+      </example>
+      
+      # Possible Values
+       <example module="sampleField2">
+        <file name="script.js">
+          angular.module('sampleField2', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.field1 = {
+              name: 'number-field',
+              field: {label: 'My Number Value:', type: 'number'},
+              model: 2
+            };
+             this.field2 = {
+              name: 'date-field',
+              field: {label: 'My Date Value:', type: 'date'},
+              model: new Date()
+            };
+             this.field3 = {
+              name: 'boolean-field',
+              field: {label: 'My Boolean Value:', type: 'boolean'},
+              model: true
+            };
+             this.field4 = {
+              name: 'email-field',
+              field: {label: 'My Email Value:', type: 'email'},
+              model: 'sample@domain.us'
+            };
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <xos-field ng-model="vm.field1.model" name="vm.field1.name" field="vm.field1.field"></xos-field>
+            <xos-field ng-model="vm.field2.model" name="vm.field2.name" field="vm.field2.field"></xos-field>
+            <xos-field ng-model="vm.field3.model" name="vm.field3.name" field="vm.field3.field"></xos-field>
+            <xos-field ng-model="vm.field4.model" name="vm.field4.name" field="vm.field4.field"></xos-field>
+          </div>
+        </file>
+      </example>
+       # This element is recursive
+       <example module="sampleField3">
+        <file name="script.js">
+          angular.module('sampleField3', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.name1 = 'input-name';
+            this.field1 = {label: 'My Object Field:', type: 'object'};
+            this.model1 = {
+              name: 'Jhon',
+              age: '25',
+              email: 'jhon@thewall.ru',
+              active: true
+            };
+             this.name2 = 'another-name';
+            this.field2 = {
+              label: 'Empty Object Field',
+              type: 'object',
+              properties: {
+                foo: {
+                  label: 'FooLabel:',
+                  type: 'string',
+                  validators: {
+                    required: true
+                  }
+                },
+                bar: {
+                  type: 'number'
+                }
+              }
+            }
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <h4>Autogenerated object field</h4>
+            <xos-field ng-model="vm.model1" name="vm.name1" field="vm.field1"></xos-field>
+             <h4>Configured object field</h4>
+            <xos-field ng-model="vm.model2" name="vm.name2" field="vm.field2"></xos-field>
+          </div>
+        </file>
+      </example>
+    */
+  .directive('xosField', ["RecursionHelper", function (RecursionHelper) {
+    return {
+      restrict: 'E',
+      scope: {
+        name: '=',
+        field: '=',
+        ngModel: '='
+      },
+      template: '\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              xos-custom-validator custom-validator="vm.field.validators.custom || null"\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\' && vm.field.type !== \'select\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n              <select class="form-control" ng-if ="vm.field.type === \'select\'"\n                name = "{{vm.name}}"\n                ng-options="item.id as item.label for item in vm.field.options"\n                ng-model="vm.ngModel"\n                ng-required="vm.field.validators.required || false">\n                </select>\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <a href="#"\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </a>\n              <a href="#"\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </a>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n                <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">\n                  <xos-field\n                    name="k"\n                    field="{\n                      label: v.label || vm.formatLabel(k),\n                      type: v.type,\n                      validators: v.validators\n                    }"\n                    ng-model="vm.ngModel[k]">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',
+      bindToController: true,
+      controllerAs: 'vm',
+      // the compile cicle is needed to support recursion
+      compile: function compile(element) {
+        return RecursionHelper.compile(element);
+      },
+      controller: ["$attrs", "XosFormHelpers", "LabelFormatter", function controller($attrs, XosFormHelpers, LabelFormatter) {
+
+        if (!this.name) {
+          throw new Error('[xosField] Please provide a field name');
+        }
+        if (!this.field) {
+          throw new Error('[xosField] Please provide a field definition');
+        }
+        if (!this.field.type) {
+          throw new Error('[xosField] Please provide a type in the field definition');
+        }
+        if (!$attrs.ngModel) {
+          throw new Error('[xosField] Please provide an ng-model');
+        }
+        this.getType = XosFormHelpers._getFieldFormat;
+        this.formatLabel = LabelFormatter.format;
+
+        this.isEmptyObject = function (o) {
+          return o ? Object.keys(o).length === 0 : true;
+        };
+      }]
+    };
+  }])
+
+  /**
+   * @ngdoc directive
+   * @name xos.uiComponents.directive:xosCustomValidator
+   * @restrict A
+   * @description The xosCustomValidator directive.
+   * This component apply a custom validation function
+   * @param {function} customValidator The function that execute the validation.
+   *
+   * You should do your validation here and return true | false,
+   * or alternatively you can return an array [errorName, true|false]
+   */
+  .directive('xosCustomValidator', function () {
+    return {
+      restrict: 'A',
+      scope: {
+        fn: '=customValidator'
+      },
+      require: 'ngModel',
+      link: function link(scope, element, attr, ctrl) {
+        if (!angular.isFunction(scope.fn)) {
+          return;
+        }
+
+        function customValidatorWrapper(ngModelValue) {
+          var valid = scope.fn(ngModelValue);
+          if (angular.isArray(valid)) {
+            // ES6 spread rocks over fn.apply()
+            ctrl.$setValidity.apply(ctrl, _toConsumableArray(valid));
+          } else {
+            ctrl.$setValidity('customValidation', valid);
+          }
+          return ngModelValue;
+        }
+
+        ctrl.$parsers.push(customValidatorWrapper);
+      }
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/field/field.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+  'use strict';
+
+  angular.module('xos.uiComponents')
+
+  /**
+    * @ngdoc directive
+    * @name xos.uiComponents.directive:xosAlert
+    * @restrict E
+    * @description The xos-alert directive
+    * @param {Object} config The configuration object
+    * ```
+    * {
+    *   type: 'danger', //info, success, warning
+    *   closeBtn: true, //default false
+    *   autoHide: 3000 //delay to automatically hide the alert
+    * }
+    * ```
+    * @param {Boolean=} show Binding to show and hide the alert, default to true
+    * @element ANY
+    * @scope
+    * @example
+  <example module="sampleAlert1">
+    <file name="index.html">
+      <div ng-controller="SampleCtrl1 as vm">
+        <xos-alert config="vm.config1">
+          A sample alert message
+        </xos-alert>
+        <xos-alert config="vm.config2">
+          A sample alert message (with close button)
+        </xos-alert>
+        <xos-alert config="vm.config3">
+          A sample info message
+        </xos-alert>
+        <xos-alert config="vm.config4">
+          A sample success message
+        </xos-alert>
+        <xos-alert config="vm.config5">
+          A sample warning message
+        </xos-alert>
+      </div>
+    </file>
+    <file name="script.js">
+      angular.module('sampleAlert1', ['xos.uiComponents'])
+      .controller('SampleCtrl1', function(){
+        this.config1 = {
+          type: 'danger'
+        };
+         this.config2 = {
+          type: 'danger',
+          closeBtn: true
+        };
+         this.config3 = {
+          type: 'info'
+        };
+         this.config4 = {
+          type: 'success'
+        };
+         this.config5 = {
+          type: 'warning'
+        };
+      });
+    </file>
+  </example>
+   <example module="sampleAlert2" animations="true">
+    <file name="index.html">
+      <div ng-controller="SampleCtrl as vm" class="row">
+        <div class="col-sm-4">
+          <a class="btn btn-default btn-block" ng-show="!vm.show" ng-click="vm.show = true">Show Alert</a>
+          <a class="btn btn-default btn-block" ng-show="vm.show" ng-click="vm.show = false">Hide Alert</a>
+        </div>
+        <div class="col-sm-8">
+          <xos-alert config="vm.config1" show="vm.show">
+            A sample alert message, not displayed by default.
+          </xos-alert>
+        </div>
+      </div>
+    </file>
+    <file name="script.js">
+      angular.module('sampleAlert2', ['xos.uiComponents', 'ngAnimate'])
+      .controller('SampleCtrl', function(){
+        this.config1 = {
+          type: 'success'
+        };
+         this.show = false;
+      });
+    </file>
+  </example>
+  **/
+
+  .directive('xosAlert', function () {
+    return {
+      restrict: 'E',
+      scope: {
+        config: '=',
+        show: '=?'
+      },
+      template: '\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',
+      transclude: true,
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: ["$timeout", function controller($timeout) {
+        var _this = this;
+
+        if (!this.config) {
+          throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
+        }
+
+        // default the value to true
+        this.show = this.show !== false;
+
+        this.dismiss = function () {
+          _this.show = false;
+        };
+
+        if (this.config.autoHide) {
+          (function () {
+            var to = $timeout(function () {
+              _this.dismiss();
+              $timeout.cancel(to);
+            }, _this.config.autoHide);
+          })();
+        }
+      }]
+    };
+  });
+})();
+//# sourceMappingURL=../../../maps/ui_components/dumbComponents/alert/alert.component.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc service
+  * @name xos.uiComponents.LabelFormatter
+  * @description This factory define a set of helper function to format label started from an object property
+  **/
+
+  angular.module('xos.uiComponents').factory('LabelFormatter', labelFormatter);
+
+  function labelFormatter() {
+
+    var _formatByUnderscore = function _formatByUnderscore(string) {
+      return string.split('_').join(' ').trim();
+    };
+
+    var _formatByUppercase = function _formatByUppercase(string) {
+      return string.split(/(?=[A-Z])/).map(function (w) {
+        return w.toLowerCase();
+      }).join(' ');
+    };
+
+    var _capitalize = function _capitalize(string) {
+      return string.slice(0, 1).toUpperCase() + string.slice(1);
+    };
+
+    var format = function format(string) {
+      string = _formatByUnderscore(string);
+      string = _formatByUppercase(string);
+
+      string = _capitalize(string).replace(/\s\s+/g, ' ') + ':';
+      return string.replace('::', ':');
+    };
+
+    return {
+      // test export
+      _formatByUnderscore: _formatByUnderscore,
+      _formatByUppercase: _formatByUppercase,
+      _capitalize: _capitalize,
+      // export to use
+      format: format
+    };
+  }
+})();
+//# sourceMappingURL=../../../maps/services/helpers/ui/label_formatter.service.js.map
+
+'use strict';
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+(function () {
+
+  angular.module('xos.uiComponents')
+
+  /**
+  * @ngdoc service
+  * @name xos.uiComponents.XosFormHelpers
+  * @requires xos.uiComponents.LabelFormatter
+  * @requires xos.helpers._
+  **/
+
+  .service('XosFormHelpers', ["_", "LabelFormatter", function (_, LabelFormatter) {
+    var _this = this;
+
+    /**
+    * @ngdoc method
+    * @name xos.uiComponents.XosFormHelpers#_isEmail
+    * @methodOf xos.uiComponents.XosFormHelpers
+    * @description
+    * Return true if the string is an email address
+    * @param {string} text The string to be evaluated
+    * @returns {boolean} If the string match an email format
+    **/
+
+    this._isEmail = function (text) {
+      var re = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
+      return re.test(text);
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.uiComponents.XosFormHelpers#_getFieldFormat
+    * @methodOf xos.uiComponents.XosFormHelpers
+    * @description
+    * Return the type of the input
+    * @param {mixed} value The data to be evaluated
+    * @returns {string} The type of the input
+    **/
+
+    this._getFieldFormat = function (value) {
+
+      if (angular.isArray(value)) {
+        return 'array';
+      }
+
+      // check if is date
+      if (_.isDate(value) || !Number.isNaN(Date.parse(value)) && new Date(value).getTime() > 631180800000) {
+        return 'date';
+      }
+
+      // check if is boolean
+      // isNaN(false) = false, false is a number (0), true is a number (1)
+      if (typeof value === 'boolean') {
+        return 'boolean';
+      }
+
+      // check if a string is an email
+      if (_this._isEmail(value)) {
+        return 'email';
+      }
+
+      // if null return string
+      if (angular.isString(value) || value === null) {
+        return 'text';
+      }
+
+      return typeof value === 'undefined' ? 'undefined' : _typeof(value);
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.uiComponents.XosFormHelpers#buildFormStructure
+    * @methodOf xos.uiComponents.XosFormHelpers
+    * @description
+    * Return the type of the input
+    * @param {object} modelField An object containing one property for each field of the model
+    * @param {object} customField An object containing one property for each field custom field
+    * @param {object} model The actual model on wich build the form structure (it is used to determine the type of the input)
+    * @returns {object} An object describing the form structure in the form of:
+    * ```
+    * {
+    *   'field-name': {
+    *     label: 'Label',
+    *     type: 'number', //typeof field
+    *     validators: {}, // see xosForm for more details
+    *     hint: 'A Custom hint for the field'
+    *   }
+    * }
+    * ```
+    **/
+
+    this.buildFormStructure = function (modelField, customField, model) {
+
+      modelField = angular.extend(modelField, customField);
+      customField = customField || {};
+
+      return _.reduce(Object.keys(modelField), function (form, f) {
+
+        form[f] = {
+          label: customField[f] && customField[f].label ? customField[f].label + ':' : LabelFormatter.format(f),
+          type: customField[f] && customField[f].type ? customField[f].type : _this._getFieldFormat(model[f]),
+          validators: customField[f] && customField[f].validators ? customField[f].validators : {},
+          hint: customField[f] && customField[f].hint ? customField[f].hint : ''
+        };
+
+        if (customField[f] && customField[f].options) {
+          form[f].options = customField[f].options;
+        }
+        if (customField[f] && customField[f].properties) {
+          form[f].properties = customField[f].properties;
+        }
+        if (form[f].type === 'date') {
+          model[f] = new Date(model[f]);
+        }
+
+        if (form[f].type === 'number') {
+          model[f] = parseInt(model[f], 10);
+        }
+
+        return form;
+      }, {});
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.uiComponents.XosFormHelpers#parseModelField
+    * @methodOf xos.uiComponents.XosFormHelpers
+    * @description
+    * Helpers for buildFormStructure, convert a list of model properties in an object used to build the form structure, eg:
+    * ```
+    * // input:
+    * ['id', 'name'm 'mail']
+    *
+    * // output
+    * {
+    *   id: {},
+    *   name: {},
+    *   mail: {}
+    * }
+    * ```
+    * @param {array} fields An array of fields representing the model properties
+    * @returns {object} An object containing one property for each field of the model
+    **/
+
+    this.parseModelField = function (fields) {
+      return _.reduce(fields, function (form, f) {
+        form[f] = {};
+        return form;
+      }, {});
+    };
+  }]);
+})();
+//# sourceMappingURL=../../../maps/services/helpers/ui/form.helpers.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+   * @ngdoc service
+   * @name xos.uiComponents.Comparator
+   * @description
+   * This factory define a function that replace the native angular.filter comparator.
+   *
+   * It is done to allow the comparation between (0|1) values with booleans.
+   * >Note that this factory return a single function, not an object.
+   *
+   * The tipical usage of this factory is inside an `ng-repeat`
+   * @example
+   * <example module="comparator">
+   *   <file name="index.html">
+   *     <div ng-controller="sample as vm">
+   *       <div class="row">
+   *         <div class="col-xs-6">
+   *           <label>Filter by name:</label>
+   *           <input class="form-control" type="text" ng-model="vm.query.name"/>
+   *         </div>
+   *         <div class="col-xs-6">
+   *           <label>Filter by status:</label>
+   *           <select
+   *            ng-model="vm.query.status"
+   *            ng-options="i for i in [true, false]">
+   *           </select>
+   *         </div>
+   *       </div>
+   *       <div ng-repeat="item in vm.data | filter:vm.query:vm.comparator">
+   *         <div class="row">
+   *           <div class="col-xs-6">{{item.name}}</div>
+   *           <div class="col-xs-6">{{item.status}}</div>
+   *         </div>
+   *       </div>
+   *     </div>
+   *   </file>
+   *   <file name="script.js">
+   *     angular.module('comparator', ['xos.uiComponents'])
+   *     .controller('sample', function(Comparator){
+   *       this.comparator = Comparator;
+   *       this.data = [
+   *         {name: 'Jhon', status: 1},
+   *         {name: 'Jack', status: 0},
+   *         {name: 'Mike', status: 1},
+   *         {name: 'Scott', status: 0}
+   *       ];
+   *     });
+   *   </file>
+   * </example>
+   **/
+
+  angular.module('xos.uiComponents').factory('Comparator', comparator);
+
+  function comparator() {
+
+    return function (actual, expected) {
+
+      if (angular.isUndefined(actual)) {
+        // No substring matching against `undefined`
+        return false;
+      }
+      if (actual === null || expected === null) {
+        // No substring matching against `null`; only match against `null`
+        return actual === expected;
+      }
+      if (angular.isObject(expected) || angular.isObject(actual)) {
+        return angular.equals(expected, actual);
+      }
+
+      if (_.isBoolean(actual) || _.isBoolean(expected)) {
+        if (actual === 0 || actual === 1) {
+          actual = !!actual;
+        }
+        return angular.equals(expected, actual);
+      }
+
+      if (!angular.isString(actual) || !angular.isString(expected)) {
+        if (angular.isDefined(actual.toString) && angular.isDefined(expected.toString)) {
+          actual = actual.toString();
+          expected = expected.toString();
+        } else {
+          return actual === expected;
+        }
+      }
+
+      actual = actual.toLowerCase() + '';
+      expected = expected.toLowerCase() + '';
+      return actual.indexOf(expected) !== -1;
+    };
+  }
+})();
+//# sourceMappingURL=../../../maps/services/helpers/ui/comparator.service.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc overview
+  * @name xos.helpers
+  * @description this is the module that group all the helpers service and components for XOS
+  **/
+
+  config.$inject = ["$httpProvider", "$interpolateProvider", "$resourceProvider"];
+  angular.module('xos.helpers', ['ngCookies', 'ngResource', 'ngAnimate', 'xos.uiComponents']).config(config)
+
+  /**
+  * @ngdoc service
+  * @name xos.helpers._
+  * @description Wrap [lodash](https://lodash.com/docs) in an Angular Service
+  **/
+
+  .factory('_', ["$window", function ($window) {
+    return $window._;
+  }]);
+
+  function config($httpProvider, $interpolateProvider, $resourceProvider) {
+    $httpProvider.interceptors.push('SetCSRFToken');
+
+    $interpolateProvider.startSymbol('{$');
+    $interpolateProvider.endSymbol('$}');
+
+    // NOTE http://www.masnun.com/2013/09/18/django-rest-framework-angularjs-resource-trailing-slash-problem.html
+    $resourceProvider.defaults.stripTrailingSlashes = false;
+  }
+})();
+//# sourceMappingURL=maps/xosHelpers.module.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.vSG-Collection
+  * @description Angular resource to fetch /api/service/vsg/
+  **/
+  .service('vSG-Collection', ["$resource", function ($resource) {
+    return $resource('/api/service/vsg/');
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/vSG.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.vOLT-Collection
+  * @description Angular resource to fetch /api/tenant/cord/volt/:volt_id/
+  **/
+  .service('vOLT-Collection', ["$resource", function ($resource) {
+    return $resource('/api/tenant/cord/volt/:volt_id/', { volt_id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/vOLT.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Login
+  * @description Angular resource to fetch /api/utility/login/
+  **/
+  .service('Login', ["$resource", function ($resource) {
+    return $resource('/api/utility/login/');
+  }])
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Logout
+  * @description Angular resource to fetch /api/utility/logout/
+  **/
+  .service('Logout', ["$resource", function ($resource) {
+    return $resource('/api/utility/logout/');
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Utility.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Users
+  * @description Angular resource to fetch /api/core/users/:id/
+  **/
+  .service('Users', ["$resource", function ($resource) {
+    return $resource('/api/core/users/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Users.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Truckroll
+  * @description Angular resource to fetch /api/tenant/truckroll/:id/
+  **/
+  .service('Truckroll', ["$resource", function ($resource) {
+    return $resource('/api/tenant/truckroll/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Truckroll.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Tenant
+  * @description Angular resource to fetch /api/core/tenant/:id/
+  **/
+  .service('Tenants', ["$resource", function ($resource) {
+    return $resource('/api/core/tenants/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Tenant.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Subscribers
+  * @description Angular resource to fetch Subscribers
+  **/
+  .service('Subscribers', ["$resource", function ($resource) {
+    return $resource('/api/tenant/cord/subscriber/:id/', { id: '@id' }, {
+      update: { method: 'PUT' },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#View-a-Subscriber-Features-Detail
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * View-a-Subscriber-Features-Detail
+      **/
+      'View-a-Subscriber-Features-Detail': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Read-Subscriber-uplink_speed
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Read-Subscriber-uplink_speed
+      **/
+      'Read-Subscriber-uplink_speed': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Update-Subscriber-uplink_speed
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Update-Subscriber-uplink_speed
+      **/
+      'Update-Subscriber-uplink_speed': {
+        method: 'PUT',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Read-Subscriber-downlink_speed
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Read-Subscriber-downlink_speed
+      **/
+      'Read-Subscriber-downlink_speed': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Update-Subscriber-downlink_speed
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Update-Subscriber-downlink_speed
+      **/
+      'Update-Subscriber-downlink_speed': {
+        method: 'PUT',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Read-Subscriber-cdn
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Read-Subscriber-cdn
+      **/
+      'Read-Subscriber-cdn': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/cdn/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Update-Subscriber-cdn
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Update-Subscriber-cdn
+      **/
+      'Update-Subscriber-cdn': {
+        method: 'PUT',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/cdn/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Read-Subscriber-uverse
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Read-Subscriber-uverse
+      **/
+      'Read-Subscriber-uverse': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/uverse/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Update-Subscriber-uverse
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Update-Subscriber-uverse
+      **/
+      'Update-Subscriber-uverse': {
+        method: 'PUT',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/uverse/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Read-Subscriber-status
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Read-Subscriber-status
+      **/
+      'Read-Subscriber-status': {
+        method: 'GET',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/status/'
+      },
+      /**
+      * @ngdoc method
+      * @name xos.helpers.Subscribers#Update-Subscriber-status
+      * @methodOf xos.helpers.Subscribers
+      * @description
+      * Update-Subscriber-status
+      **/
+      'Update-Subscriber-status': {
+        method: 'PUT',
+        isArray: false,
+        url: '/api/tenant/cord/subscriber/:id/features/status/'
+      }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Subscribers.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.SlicesPlus
+  * @description Angular resource to fetch /api/utility/slicesplus/
+  * This is a read-only API and only the `query` method is currently supported.
+  **/
+  .service('SlicesPlus', ["$http", "$q", function ($http, $q) {
+    this.query = function (params) {
+      var deferred = $q.defer();
+
+      $http.get('/api/utility/slicesplus/', { params: params }).then(function (res) {
+        deferred.resolve(res.data);
+      }).catch(function (res) {
+        deferred.reject(res.data);
+      });
+
+      return { $promise: deferred.promise };
+    };
+
+    this.get = function (id, params) {
+      var deferred = $q.defer();
+
+      $http.get('/api/utility/slicesplus/' + id, { params: params }).then(function (res) {
+        deferred.resolve(res.data);
+      }).catch(function (res) {
+        deferred.reject(res.data);
+      });
+      return { $promise: deferred.promise };
+    };
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Slices_plus.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Slices
+  * @description Angular resource to fetch /api/core/slices/:id/
+  **/
+  .service('Slices', ["$resource", function ($resource) {
+    return $resource('/api/core/slices/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Slices.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Sites
+  * @description Angular resource to fetch /api/core/sites/:id/
+  **/
+  .service('Sites', ["$resource", function ($resource) {
+    return $resource('/api/core/sites/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Sites.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Services
+  * @description Angular resource to fetch /api/core/services/:id/
+  **/
+  .service('Services', ["$resource", function ($resource) {
+    return $resource('/api/core/services/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Services.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.ONOS-Services-Collection
+  * @description Angular resource to fetch /api/service/onos/
+  **/
+  .service('ONOS-Services-Collection', ["$resource", function ($resource) {
+    return $resource('/api/service/onos/');
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/ONOS-Services.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.ONOS-App-Collection
+  * @description Angular resource to fetch /api/tenant/onos/app/
+  **/
+  .service('ONOS-App-Collection', ["$resource", function ($resource) {
+    return $resource('/api/tenant/onos/app/');
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/ONOS-Apps.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Nodes
+  * @description Angular resource to fetch /api/core/nodes/:id/
+  **/
+  .service('Nodes', ["$resource", function ($resource) {
+    return $resource('/api/core/nodes/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Nodes.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Networkstemplates
+  * @description Angular resource to fetch /api/core/networktemplates/:id/
+  **/
+  .service('Networkstemplates', ["$resource", function ($resource) {
+    return $resource('/api/core/networktemplates/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Networkstemplates.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Networks
+  * @description Angular resource to fetch /api/core/networks/:id/
+  **/
+  .service('Networks', ["$resource", function ($resource) {
+    return $resource('/api/core/networks/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Networks.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**

+  * @ngdoc service

+  * @name xos.helpers.Me

+  * @description Http read-only api to fetch /api/utility/me/

+  **/
+  .service('Me', ["$q", "$http", function ($q, $http) {
+
+    this.get = function () {
+      var deferred = $q.defer();
+
+      $http.get('/api/utility/me/').then(function (res) {
+        deferred.resolve(res);
+      }).catch(function (e) {
+        deferred.reject(e);
+      });
+      return deferred.promise;
+    };
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Me.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Instances
+  * @description Angular resource to fetch /api/core/instances/:id/
+  **/
+  .service('Instances', ["$resource", function ($resource) {
+    return $resource('/api/core/instances/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Instances.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Images
+  * @description Angular resource to fetch /api/core/images/
+  **/
+  .service('Images', ["$resource", function ($resource) {
+    return $resource('/api/core/images/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Images.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Flavors
+  * @description Angular resource to fetch /api/core/flavors/:id/
+  **/
+  .service('Flavors', ["$resource", function ($resource) {
+    return $resource('/api/core/flavors/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Flavors.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Example-Services-Collection
+  * @description Angular resource to fetch /api/service/exampleservice/
+  **/
+  .service('Example-Services-Collection', ["$resource", function ($resource) {
+    return $resource('/api/service/exampleservice/');
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Example.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Deployments
+  * @description Angular resource to fetch /api/core/deployments/:id/
+  **/
+  .service('Deployments', ["$resource", function ($resource) {
+    return $resource('/api/core/deployments/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/rest/Deployments.js.map
+
+'use strict';
+
+(function () {
+
+  angular.module('xos.helpers')
+
+  /**

+  * @ngdoc service

+  * @name xos.helpers.XosUserPrefs

+  * @description

+  * This service is used to store the user preferences in cookies, so that they survive to page changes.

+  * The structure of the user preference is:

+  * ```

+  * {

+  *   synchronizers: {

+  *     notification: {

+  *       'volt': boolean,

+  *       'openstack': boolean,

+  *       ...

+  *     }

+  *   }

+  *   userData: {

+  *     current_user_site_id: Number,

+  *     current_user_site_user_names: Array[1],

+  *     ...

+  *     }

+  * }

+  * ```

+  **/
+
+  .service('XosUserPrefs', ["$cookies", "Me", "$q", function ($cookies, Me, $q) {
+    var _this = this;
+
+    var userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#getAll

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Return all the user preferences stored in cookies

+    * @returns {object} The user preferences

+    **/
+    this.getAll = function () {
+      userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
+      return userPrefs;
+    };
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#setAll

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Override all user preferences

+    * @param {object} prefs The user preferences

+    **/
+    this.setAll = function (prefs) {
+      $cookies.put('xosUserPrefs', angular.toJson(prefs));
+    };
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#getSynchronizerNotificationStatus

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Return the synchronizer notification status, if name is not provided return the status for all synchronizers

+    * @param {string=} prefs The synchronizer name

+    * @returns {object | string} The synchronizer status

+    **/
+    this.getSynchronizerNotificationStatus = function () {
+      var name = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
+
+      if (name) {
+        return _this.getAll().synchronizers.notification[name];
+      }
+      return _this.getAll().synchronizers.notification;
+    };
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#getUserDetailsCookie

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Return all the user details stored in cookies or call the service

+    * @returns {object} The user details

+    **/
+    this.getUserDetailsCookie = function () {
+      var defer = $q.defer();
+      var localPref = _this.getAll();
+      if (!localPref.userData) {
+        _this.setUserDetailsCookie().$promise.then(function (data) {
+          defer.resolve(data);
+        });
+      } else {
+        defer.resolve(localPref.userData);
+      }
+      return { $promise: defer.promise };
+    };
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#setUserDetailsCookie

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Save the user details in the cookie

+    * @param {object} details stored in cookie

+    * @param {objects} returns the user details as a promise

+    **/
+    this.setUserDetailsCookie = function () {
+      var userData = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
+
+
+      var defer = $q.defer();
+      var cookies = _this.getAll();
+      if (!userData) {
+        Me.get().then(function (user) {
+          cookies.userData = user;
+          _this.setAll(cookies);
+          defer.resolve(user);
+        }).catch(function (e) {
+          defer.reject(e);
+        });
+      } else {
+        cookies.userData = userData;
+        _this.setAll(cookies);
+        defer.resolve(userData);
+      }
+      return { $promise: defer.promise };
+    };
+
+    /**

+    * @ngdoc method

+    * @name xos.helpers.XosUserPrefs#setSynchronizerNotificationStatus

+    * @methodOf xos.helpers.XosUserPrefs

+    * @description

+    * Update the notification status for a single synchronizer

+    * @param {string} name The synchronizer name

+    * @param {boolean} value The notification status (true means that it has been sent)

+    **/
+
+    this.setSynchronizerNotificationStatus = function () {
+      var name = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
+      var value = arguments[1];
+
+      if (!name) {
+        throw new Error('[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.');
+      }
+
+      var cookies = _this.getAll();
+
+      if (!cookies.synchronizers) {
+        cookies.synchronizers = {
+          notification: {}
+        };
+      }
+      cookies.synchronizers.notification[name] = value;
+      _this.setAll(cookies);
+    };
+  }]);
+})();
+//# sourceMappingURL=../../maps/services/helpers/user-prefs.service.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc service
+  * @name xos.helpers.ServiceGraph
+  * @description This factory define a set of helper function to query the service tenancy graph
+  **/
+
+  angular.module('xos.helpers').service('GraphService', ["$q", "Tenants", "Services", function ($q, Tenants, Services) {
+    var _this = this;
+
+    this.loadCoarseData = function () {
+
+      var services = void 0;
+
+      var deferred = $q.defer();
+
+      Services.query().$promise.then(function (res) {
+        services = res;
+        return Tenants.query({ kind: 'coarse' }).$promise;
+      }).then(function (tenants) {
+        deferred.resolve({
+          tenants: tenants,
+          services: services
+        });
+      });
+
+      return deferred.promise;
+    };
+
+    this.getCoarseGraph = function () {
+      _this.loadCoarseData().then(function (res) {
+        console.log(res);
+      });
+      return 'ciao';
+    };
+  }]);
+})();
+//# sourceMappingURL=../maps/services/service_graph.service.js.map
+
+'use strict';
+
+/* eslint-disable  angular/ng_window_service*/
+(function () {
+  'use strict';
+
+  angular.module('xos.helpers').factory('Notification', function () {
+    return window.Notification;
+  })
+  /**
+  * @ngdoc service
+  * @name xos.helpers.xosNotification
+  * @description This factory define a set of helper function to trigger desktop notification
+  **/
+  .service('xosNotification', ["$q", "$log", "Notification", function ($q, $log, Notification) {
+    var _this = this;
+
+    this.checkPermission = function () {
+      var deferred = $q.defer();
+      Notification.requestPermission().then(function (permission) {
+        if (permission === 'granted') {
+          deferred.resolve(permission);
+        } else {
+          deferred.reject(permission);
+        }
+      });
+      return deferred.promise;
+    };
+
+    this.sendNotification = function (title, options) {
+      var notification = new Notification(title, options);
+      notification.onerror = function (err) {
+        $log.error(err);
+      };
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.xosNotification#notify
+    * @methodOf xos.helpers.xosNotification
+    * @description
+    * This method will check for user permission and if granted will send a browser notification.
+    * @param {string} title The notification title
+    * @param {object} options The notification options: `{icon: 'url', body: 'Notification body'}`
+    **/
+
+    this.notify = function (title, options) {
+      if (!('Notification' in window)) {
+        $log.info('This browser does not support desktop notification');
+      } else if (Notification.permission !== 'granted') {
+        _this.checkPermission().then(function () {
+          return _this.sendNotification(title, options);
+        });
+      } else if (Notification.permission === 'granted') {
+        _this.sendNotification(title, options);
+      }
+    };
+  }]);
+})();
+//# sourceMappingURL=../maps/services/notification.service.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc service
+  * @name xos.helpers.NoHyperlinks
+  * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will add ?no_hyperlinks=1 to your api request, that is required by django
+  **/
+
+  angular.module('xos.helpers').factory('NoHyperlinks', noHyperlinks);
+
+  function noHyperlinks() {
+    return {
+      request: function request(_request) {
+        if (_request.url.indexOf('.html') === -1) {
+          _request.url += '?no_hyperlinks=1';
+        }
+        return _request;
+      }
+    };
+  }
+})();
+//# sourceMappingURL=../maps/services/noHyperlinks.interceptor.js.map
+
+'use strict';
+
+// TODO write tests for log
+
+/* eslint-disable  angular/ng_window_service*/
+
+angular.module('xos.helpers').config(['$provide', function ($provide) {
+  // Use the `decorator` solution to substitute or attach behaviors to
+  // original service instance; @see angular-mocks for more examples....
+
+  $provide.decorator('$log', ['$delegate', function ($delegate) {
+
+    var isLogEnabled = function isLogEnabled() {
+      return window.location.href.indexOf('debug=true') >= 0;
+    };
+    // Save the original $log.debug()
+    var logFn = $delegate.log;
+    var infoFn = $delegate.info;
+    var warnFn = $delegate.warn;
+    //let errorFn = $delegate.error;
+    var debugFn = $delegate.debug;
+
+    // create the replacement function
+    var replacement = function replacement(fn) {
+      return function () {
+        //console.log(`Is Log Enabled: ${isLogEnabled()}`)
+        if (!isLogEnabled()) {
+          // console.log('logging is disabled');
+          return;
+        }
+
+        var args = [].slice.call(arguments);
+        var now = new Date();
+
+        // Prepend timestamp
+        args[0] = '[' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + '] ' + args[0];
+
+        // HACK awfull fix for angular mock implementation whithin jasmine test failing issue
+        if (angular.isFunction($delegate.reset) && !($delegate.debug.logs instanceof Array)) {
+          // if we are within the mock and did not reset yet, we call it to avoid issue
+          // console.log('mock log impl fix to avoid logs array not existing...');
+          $delegate.reset();
+        }
+
+        // Call the original with the output prepended with formatted timestamp
+
+        return fn.apply(null, args);
+      };
+    };
+
+    $delegate.info = replacement(infoFn);
+    $delegate.log = replacement(logFn);
+    $delegate.warn = replacement(warnFn);
+    //$delegate.error = replacement(errorFn); // note this will prevent errors to be printed
+    $delegate.debug = replacement(debugFn);
+
+    return $delegate;
+  }]);
+}]);
+//# sourceMappingURL=../maps/services/log.decorator.js.map
+
+'use strict';
+
+(function () {
+  'use strict';
+
+  /**
+  * @ngdoc service
+  * @name xos.helpers.SetCSRFToken
+  * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will the CSRF-Token to your request headers
+  **/
+
+  setCSRFToken.$inject = ["$cookies"];
+  angular.module('xos.helpers').factory('SetCSRFToken', setCSRFToken);
+
+  function setCSRFToken($cookies) {
+    return {
+      request: function request(_request) {
+        if (_request.method !== 'GET') {
+          _request.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
+        }
+        return _request;
+      }
+    };
+  }
+})();
+//# sourceMappingURL=../maps/services/csrfToken.interceptor.js.map