ali stopped
diff --git a/views/ngXosLib/gulpfile.js b/views/ngXosLib/gulpfile.js
index e514d7a..e030ad9 100644
--- a/views/ngXosLib/gulpfile.js
+++ b/views/ngXosLib/gulpfile.js
@@ -2,6 +2,7 @@
 
 var gulp = require('gulp');
 var wrench = require('wrench');
+var path = require('path');
 
 var options = {
   ngXosVendor: '../../xos/core/xoslib/static/js/vendor/', //save here the minfied vendor file, this is automatically loaded in the django page
@@ -11,9 +12,9 @@
   docs: './docs'
 };
 
-wrench.readdirSyncRecursive('./gulp')
+wrench.readdirSyncRecursive(path.join(__dirname, './gulp'))
 .map(function(file) {
-  require('./gulp/' + file)(options);
+  require(path.join(__dirname, './gulp/' + file))(options);
 });
 
 gulp.task('default', function () {
diff --git a/views/ngXosLib/xosHelpers/src/services/notification.service.js b/views/ngXosLib/xosHelpers/src/services/notification.service.js
index 7c4154b..e190451 100644
--- a/views/ngXosLib/xosHelpers/src/services/notification.service.js
+++ b/views/ngXosLib/xosHelpers/src/services/notification.service.js
@@ -1,7 +1,6 @@
 (function() {
   'use strict';
 
-
   angular
   .module('xos.helpers')
   .factory('Notification', function(){
diff --git a/views/ngXosViews/synchronizerNotifier/src/js/main.js b/views/ngXosViews/synchronizerNotifier/src/js/main.js
index 1d7de32..54ef0a6 100644
--- a/views/ngXosViews/synchronizerNotifier/src/js/main.js
+++ b/views/ngXosViews/synchronizerNotifier/src/js/main.js
@@ -6,29 +6,6 @@
   'ui.router',
   'xos.helpers'
 ])
-.config(function($provide) {
-  $provide.decorator('$rootScope', function($delegate) {
-    var Scope = $delegate.constructor;
-    // var origBroadcast = Scope.prototype.$broadcast;
-    // var origEmit = Scope.prototype.$emit;
-    var origOn = Scope.prototype.$on;
-
-    // Scope.prototype.$broadcast = function() {
-    //   // console.log("$broadcast was called on $scope " + $scope.$id + " with arguments:", arguments);
-    //   return origBroadcast.apply(this, arguments);
-    // };
-    // Scope.prototype.$emit = function() {
-    //   // console.log("$emit was called on $scope " + $scope.$id + " with arguments:", arguments);
-    //   return origEmit.apply(this, arguments);
-    // };
-
-    Scope.prototype.$on = function(){
-      // console.log('$on', arguments, arguments[1].toString());
-      return origOn.apply(this, arguments);
-    }
-    return $delegate;
-  });
-})
 .service('Diag', function($rootScope, $http, $q, $interval){
 
   let isRunning = false;
@@ -50,6 +27,7 @@
     diags.forEach(d => {
       let status = JSON.parse(d.backend_register);
       status.last_run = new Date(status.last_run * 1000);
+      status.last_duration = status.last_duration * 1000;
       status.last_synchronizer_start = new Date(status.last_synchronizer_start * 1000);
       status.last_syncrecord_start = status.last_syncrecord_start ? new Date(status.last_syncrecord_start * 1000) : null;
       $rootScope.$broadcast(`diag`, {
@@ -77,25 +55,26 @@
 
   this.getSyncStatus = (status) => {
 
-    let gap = 5 * 60 * 1000; /* ms */
-    // let gap = 2;
-    if(status.last_run > status.last_synchronizer_start){
-      // the synchronizer has finished
-      return true;
-    }
-    else {
+    // let gap = 5 * 60 * 1000; /* ms */
+    let gap = 1 * 60 * 1000;
+    // if(status.last_run > status.last_synchronizer_start){
+    //   // the synchronizer has finished
+    //   return true;
+    // }
+    // else {
       // the synchronizer is running
-      if(!status.last_syncrecord_start){
-        // but no step have been completed
-        return false;
-      }
-      else if (((new Date()) - status.last_syncrecord_start) > gap){
+      // if(status.last_syncrecord_start){
+      //   // but no step have been completed
+      //   return false;
+      // }
+      // else
+      if (((new Date()) - status.last_syncrecord_start) > gap){
         return false;
       }
       else{
         return true;
       }
-    }
+    // }
   }
 
   $interval(() => {
@@ -105,10 +84,7 @@
         this.sendEvents(diags);
       });
     }
-  }, 25000);
-})
-.run(function($log){
-  $log.info('Listening for Syncronizers Events!');
+  }, 10000);
 })
 .directive('syncStatus', function() {
   return {
@@ -117,18 +93,41 @@
     bindToController: true,
     controllerAs: 'vm',
     templateUrl: 'templates/sync-status.tpl.html',
-    controller: function($log, $rootScope, Diag){
+    controller: function($log, $rootScope, Diag, xosNotification){
       Diag.start();
       this.showNotificationPanel = true;
       this.synchronizers = {};
 
+      const notified = {};
+
+      // xosNotification.notify('test', {icon: 'http://localhost:8888/static/cord-logo.png', body: 'Diag'});
+
       this.showNoSync = true;
 
       $rootScope.$on('diag', (e, d) => {
-        if(d.name === 'vcpe'){
-          $log.info('Received event: ', d.info.last_run, d.info.last_synchronizer_start);
+        // console.log(d.name);
+        if(d.name === 'global'){
+          $log.info('Received event: ', d.info.last_syncrecord_start);
         }
         this.synchronizers[d.name] = d;
+
+        if(!d.status){
+          
+          if(!notified[d.name]){
+            console.log('sent notify');
+            xosNotification.notify('CORD Synchronizer Error', {
+              icon: 'http://localhost:8888/static/cord-logo.png',
+              body: `[DEBUG] The ${d.name} synchronizer has stopped.`
+            });
+          }
+
+          notified[d.name] = true;
+        }
+        else {
+          notified[d.name] = false;
+        }
+
+        // hide list if empty
         this.showNoSync = false;
         if(Object.keys(this.synchronizers).length === 0){
           this.showNoSync = true;
diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index e1cfb38..3652f92 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1397,6 +1397,161 @@
  *
  * 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.name = 'input-name';
+            this.field = {label: 'My Object Value:', type: 'object'};
+            this.model = {
+              name: 'Jhon',
+              age: '25',
+              email: 'jhon@thewall.ru',
+              active: true
+            };
+          });
+        </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>
+    */
+  .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              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\'"\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            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && !vm.isEmptyObject(vm.ngModel)"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div 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>\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) {
+        // console.log('Field: ', this.name, this.field, this.ngModel);
+        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 (!$attrs.ngModel) {
+          throw new Error('[xosField] Please provide an ng-model');
+        }
+
+        this.getType = XosFormHelpers._getFieldFormat;
+        this.formatLabel = LabelFormatter.format;
+
+        this.isEmptyObject = function (o) {
+          return Object.keys(o).length === 0;
+        };
+      }]
+    };
+  }]);
+})();
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
  * Created by teone on 4/15/16.
  */
 
@@ -1534,6 +1689,203 @@
 (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
+    };
+  }
+})();
+'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 (typeof value === 'string' || 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 = Object.keys(modelField).length > 0 ? modelField : customField; //if no model field are provided, check custom
+      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 (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;
+      }, {});
+    };
+  }]);
+})();
+'use strict';
+
+(function () {
+  'use strict';
+
   config.$inject = ["$httpProvider", "$interpolateProvider", "$resourceProvider"];
   angular.module('bugSnag', []).factory('$exceptionHandler', function () {
     return function (exception, cause) {
@@ -2115,6 +2467,66 @@
 (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