<commit_before>/****************************
Copyright (c) 2013 Canadensys
Explorer Map
****************************/
/*global EXPLORER, $, window, document, console, jQuery, CartoDBLayer, google, _ */

EXPLORER.map = (function() {

  'use strict';

  var _private = {

    map: {},
    marker: {},
    cartodb_gmapsv3: {},
    drawing_manager: {},
    drawing_overlay: {},
    drawing_types: ["geoellipse", "georectangle", "geopolygon"],
    filter: {},

    init: function() {
      this.addBoundsMethod();
      this.cartoDBsetBounds();
      this.cartoDBgenerateTile();
      EXPLORER.backbone.bindToFilterList('add',this.onAddFilter,this);
      EXPLORER.backbone.bindToFilterList('remove',this.removeFilterListener,this);
    },

    // Adapted from http://tutorialspots.com/google-maps-javascript-api-v3-method-polygon-getbounds-515.html
    addBoundsMethod: function() {
      if (!google.maps.Polygon.prototype.getBounds) {
        google.maps.Polygon.prototype.getBounds = function(){
          var bounds = new google.maps.LatLngBounds();
          this.getPath().forEach(function(element,index){ bounds.extend(element); });
          return bounds;
        };
      }
    },

    cartoDBsetBounds: function() {
      CartoDBLayer.prototype.setBounds = function() { return; };
    },

    onAddFilter: function(filter) {
      var self = this, fieldName = filter.get('searchableFieldName'), valueList, coords, data, overlay_type;

      if($.inArray(fieldName, this.drawing_types) !== -1 && $.isEmptyObject(this.drawing_overlay)) {
        self.filter = filter;
        valueList = filter.get('valueList');

        switch (fieldName) {
          case this.drawing_types[0]:
            overlay_type = 'circle';
            coords = valueList[0].split(",");
            data = { coords : [coords[0],coords[1]], radius : parseInt(valueList[1], 10) };
          break;

          case this.drawing_types[1]:
            overlay_type = 'rectangle';
            coords = $.map(valueList.reverse(), function(n) { return n.split(","); });
            data = { coords : [ [coords[0], coords[1]], [coords[2], coords[3]] ] };
          break;

          case this.drawing_types[2]:
            overlay_type = 'polygon';
            coords = $.map(valueList, function(n) { return [ n.split(",") ]; });
            data = { coords : coords };
          break;
        }

        this.addDrawingOverlay({ type : fieldName, data : data });
        this.addDrawingOverlayListeners(overlay_type);
      }
    },

    removeFilterListener: function(filter) {
      if($.inArray(filter.get('searchableFieldName'), this.drawing_types) !== -1) {
        this.removeDrawingOverlay();
        this.filter = {};
      }
    },

    setBounds: function(filterList) {
      var self = this, spatial_filter = false, bounds;

      $.each(this.drawing_types, function(k, v) {
        if(filterList.where({ searchableFieldName : v }).length > 0) {
          spatial_filter = true;
          return;
        }
      });

      if(filterList.length > 0 && !spatial_filter) {
        $.ajax({
          method:'GET',
          url: EXPLORER.settings.baseUrl + EXPLORER.settings.wsPath + 'mapinfo?q='+encodeURIComponent(this.cartodb_gmapsv3.options.query || ''),
          dataType: 'json',
          success: function(result) {
            if(result.extentMin[1]*result.extentMax[1] > 0 &&
            self.getDistanceAtEquator(result.extentMin[1], result.extentMax[1]) < 6000) { //set bounds if distance at equator is < 6k km
              bounds = new google.maps.LatLngBounds();
              bounds.extend(new google.maps.LatLng(result.extentMin[0], result.extentMin[1]));
              bounds.extend(new google.maps.LatLng(result.extentMax[0], result.extentMax[1]));
              self.map.fitBounds(bounds);
            } else {
              self.map.setZoom(2);
              self.map.setCenter(new google.maps.LatLng(35, -15));
            }
          }
        });
      }
    },

    radians: function(x) {
      return x * Math.PI / 180;
    },

    //Adapted from http://stackoverflow.com/a/1502821
    getDistanceAtEquator: function(lng1, lng2) {
      var R = 6378.137, // Earth’s mean radius in km
          dLong = this.radians(lng2 - lng1),
          a = Math.sin(dLong / 2) * Math.sin(dLong / 2),
          c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
      return R * c;
    },

    cartoDBgenerateTile: function() {
      CartoDBLayer.prototype._generateTileJson = function() {
        var core_url = this._generateUrl("tiler"),
            base_url = core_url + '/database/dataportal/table/' + this.options.table_name + '/{z}/{x}/{y}',
            tile_url = base_url + '.png',
            grid_url = base_url + '.grid.json',
            query, style, interactivity;

        // SQL?
        if (this.options.query) {
          query = 'sql=' + encodeURIComponent(this.options.query.replace(/\{\{table_name\}\}/g,this.options.table_name));
          tile_url = this._addUrlData(tile_url, query);
          grid_url = this._addUrlData(grid_url, query);
        }

        // STYLE?
        if (this.options.tile_style) {
          style = 'style=' + encodeURIComponent(this.options.tile_style.replace(/\{\{table_name\}\}/g,this.options.table_name));
          tile_url = this._addUrlData(tile_url, style);
          grid_url = this._addUrlData(grid_url, style);
        }

        // INTERACTIVITY?
        if (this.options.interactivity) {
          interactivity = 'interactivity=' + encodeURIComponent(this.options.interactivity.replace(/ /g,''));
          tile_url = this._addUrlData(tile_url, interactivity);
          grid_url = this._addUrlData(grid_url, interactivity);
        }

        // Build up the tileJSON
        return {
          blankImage: '../img/blank_tile.png',
          tilejson: '1.0.0',
          scheme: 'xyz',
          name: this.options.table_name,
          tiles: [tile_url],
          grids: [grid_url],
          tiles_base: tile_url,
          grids_base: grid_url,
          opacity: this.options.opacity,
          formatter: function(options, data) {
            return data;
          }
        };
      };
    },

    setupMap: function(obj) {

      _.defaults(obj, {
        mapCanvasId : "map_canvas",
        tilerDomain : "tiles.example.com",
        tilerProtocol : "http",
        tilerPort : 80,
        mapQuery : "",
        mapCenter : [0,0],
        mapZoom : 3
      });

      this.map = new google.maps.Map($('#' + obj.mapCanvasId)[0], {
        center: new google.maps.LatLng(obj.mapCenter[0],obj.mapCenter[1]),
        defaults: {
          editable: true,
          strokeColor: '#0B0B09',
          fillColor: '#E7E7E7',
          fillOpacity: 0.4
        },
        zoom: obj.mapZoom,
        mapTypeId: google.maps.MapTypeId.TERRAIN,
        mapTypeControl: true
      });

      this.marker = new google.maps.Marker({
        position: null,
        map: this.map
      });

      this.addDrawingManager();
      this.addDrawingListeners();

      this.cartodb_gmapsv3 = new CartoDBLayer({
        map: this.map,
        marker: this.marker,
        table_name: 'occurrence',
        interactivity: 'auto_id',
        query: obj.mapQuery,
        map_style: false,
        infowindow: true,
        auto_bound: true,
        featureClick: this.onMapClick,
        tiler_domain: obj.tilerDomain,
        tiler_port: parseInt(obj.tilerPort,10),
        tiler_protocol: obj.tilerProtocol,
        featureOver: function() {
          this.map.setOptions({draggableCursor: 'pointer'});
        },
        featureOut: function() {
          this.map.setOptions({draggableCursor: 'default'});
        }
      });
    },

    onMapClick: function(e, latlng, pos, data) {
      var url = EXPLORER.settings.baseUrl + '/' + EXPLORER.settings.locale + '/' + EXPLORER.i18n.getLanguageResource('url.occurrence-preview') + '/' + data.auto_id;
      this.marker.setPosition(latlng);
      $.get(url,'context=map')
        .success(function(htmlFragment){
          EXPLORER.preview.replacePreviewContent(htmlFragment);
          EXPLORER.preview.show();
        })
         .error(function(jqXHR, textStatus, errorThrown){
           console.log(textStatus+':'+errorThrown);
        });
    },

    addDrawingManager: function() {
      this.drawing_manager = new google.maps.drawing.DrawingManager({
        drawingControl: true,
        drawingControlOptions: {
          position: google.maps.ControlPosition.TOP_CENTER,
          drawingModes: [
            google.maps.drawing.OverlayType.CIRCLE,
            google.maps.drawing.OverlayType.RECTANGLE,
            google.maps.drawing.OverlayType.POLYGON
          ]
        },
        circleOptions: this.map.defaults,
        rectangleOptions: this.map.defaults,
        polygonOptions: this.map.defaults
      });

      this.drawing_manager.setMap(this.map);
    },

    addDrawingListeners: function() {
      var self = this;

      google.maps.event.addListener(this.drawing_manager, 'drawingmode_changed', function() {
        if(self.drawing_manager.drawingMode) {
          self.removeDrawingOverlay();
          self.removeSpatialFilter();
          self.cartodb_gmapsv3.setInteraction(false);
        }
      });

      google.maps.event.addListener(this.drawing_manager, "overlaycomplete", function(e) {
        self.drawing_manager.setOptions({ drawingMode: null });
        self.drawing_overlay = e.overlay;
        self.filter = self.addFilter(e.type);
        self.addDrawingOverlayListeners(e.type);
        self.cartodb_gmapsv3.setInteraction(true);
      });
    },

    addDrawingOverlayListeners: function(type) {
      var self = this;

      switch(type) {
        case 'circle':
          $.each(["center", "bounds"], function(k, v) {
            google.maps.event.addListener(self.drawing_overlay, v +"_changed", function() {
              EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.circleParameters() });
            });
          });
        break;

        case 'rectangle':
          google.maps.event.addListener(self.drawing_overlay, 'bounds_changed', function() {
            EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.rectangleParameters() });
          });
        break;

        case 'polygon':
          $.each(["insert", "remove", "set"], function(k, v) {
            google.maps.event.addListener(self.drawing_overlay.getPath(), v +"_at", function() {
              EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.polygonParameters() });
            });
          });
        break;
      }
    },

    circleParameters: function() {
      var o = this.drawing_overlay;
      return [o.getCenter().lat()+','+o.getCenter().lng(),o.getRadius()];
    },

    rectangleParameters: function() {
      var o = this.drawing_overlay;
      return [o.getBounds().getNorthEast().lat() + ',' + o.getBounds().getNorthEast().lng(),
        o.getBounds().getSouthWest().lat() + ',' + o.getBounds().getSouthWest().lng()];
    },

    polygonParameters: function() {
      var o = this.drawing_overlay,
          searchValue = $.map(o.getPath().getArray(), function(n) { return [n.lat() + ',' + n.lng()]; });
      searchValue.push(searchValue[0]);
      return searchValue;
    },

    addDrawingOverlay: function(json) {
      var coord, center, options, circle, bbox, bounds, rectangle, paths, vertices, polygon;

      switch(json.type) {
        case this.drawing_types[0]:
          coord = json.data.coords;
          center = new google.maps.LatLng(coord[0], coord[1]);
          options = $.extend({ center : center, radius : json.data.radius }, this.map.defaults);
          circle = new google.maps.Circle(options);

          circle.setMap(this.map);
          this.map.fitBounds(circle.getBounds());
          this.drawing_overlay = circle;
        break;

        case this.drawing_types[1]:
          //bbox is an array of vertices eg [[lat0,lng0], [lat1,lng1]] expressed as [SW, NE]
          bbox = json.data.coords;
          bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(bbox[0][0], bbox[0][1]),
            new google.maps.LatLng(bbox[1][0], bbox[1][1])
          );
          options = $.extend({ bounds : bounds }, this.map.defaults);
          rectangle = new google.maps.Rectangle(options);

          rectangle.setMap(this.map);
          this.map.fitBounds(rectangle.getBounds());
          this.drawing_overlay = rectangle;
        break;

        case this.drawing_types[2]:
          //vertices is an array of arrays where last member is identical to first eg [[lat0,lng0], [lat1,lng1], [lat0,lng0]]
          vertices = json.data.coords;
          paths = $.map(vertices, function(n) { return new google.maps.LatLng(n[0], n[1]); });
          options = $.extend({ paths: paths }, this.map.defaults);
          polygon = new google.maps.Polygon(options);

          polygon.setMap(this.map);
          this.map.fitBounds(polygon.getBounds());
          this.drawing_overlay = polygon;
        break;

      }
    },

    removeDrawingOverlay: function() {
      if(!$.isEmptyObject(this.drawing_overlay)) {
        this.drawing_overlay.setMap(null);
      }
      this.drawing_overlay = {};
    },

    removeSpatialFilter: function() {
      $.each(this.drawing_types, function(k, v) {
        EXPLORER.backbone.removeFilter({ searchableFieldName: v });
      });
    },

    addFilter: function(type) {
      var filter = {};
      switch(type) {
        case 'circle':
          filter = EXPLORER.backbone.addActiveFilter({ searchableFieldName : 'geoellipse', valueList : this.circleParameters() });
        break;

        case 'rectangle':
          filter = EXPLORER.backbone.addActiveFilter({ searchableFieldName : 'georectangle', valueList : this.rectangleParameters() });
        break;

        case 'polygon':
          filter = EXPLORER.backbone.addActiveFilter({searchableFieldName : 'geopolygon', valueList : this.polygonParameters() });
        break;
      }
      return filter;
    }

  };

  return {
    init: function() { _private.init(); },
    setupMap: function(obj) {
      _private.setupMap(obj);
    },
    setBounds: function(obj) {
      _private.setBounds(obj);
    }
  };

}());<commit_msg>Fix when a line is made in place of a polygon<commit_after>/****************************
Copyright (c) 2013 Canadensys
Explorer Map
****************************/
/*global EXPLORER, $, window, document, console, jQuery, CartoDBLayer, google, _ */

EXPLORER.map = (function() {

  'use strict';

  var _private = {

    map: {},
    marker: {},
    cartodb_gmapsv3: {},
    drawing_manager: {},
    drawing_overlay: {},
    drawing_types: ["geoellipse", "georectangle", "geopolygon"],
    filter: {},

    init: function() {
      this.addBoundsMethod();
      this.cartoDBsetBounds();
      this.cartoDBgenerateTile();
      EXPLORER.backbone.bindToFilterList('add',this.onAddFilter,this);
      EXPLORER.backbone.bindToFilterList('remove',this.removeFilterListener,this);
    },

    // Adapted from http://tutorialspots.com/google-maps-javascript-api-v3-method-polygon-getbounds-515.html
    addBoundsMethod: function() {
      if (!google.maps.Polygon.prototype.getBounds) {
        google.maps.Polygon.prototype.getBounds = function(){
          var bounds = new google.maps.LatLngBounds();
          this.getPath().forEach(function(element,index){ bounds.extend(element); });
          return bounds;
        };
      }
    },

    cartoDBsetBounds: function() {
      CartoDBLayer.prototype.setBounds = function() { return; };
    },

    onAddFilter: function(filter) {
      var self = this, fieldName = filter.get('searchableFieldName'), valueList, coords, data, overlay_type;

      if($.inArray(fieldName, this.drawing_types) !== -1 && $.isEmptyObject(this.drawing_overlay)) {
        self.filter = filter;
        valueList = filter.get('valueList');

        switch (fieldName) {
          case this.drawing_types[0]:
            overlay_type = 'circle';
            coords = valueList[0].split(",");
            data = { coords : [coords[0],coords[1]], radius : parseInt(valueList[1], 10) };
          break;

          case this.drawing_types[1]:
            overlay_type = 'rectangle';
            coords = $.map(valueList.reverse(), function(n) { return n.split(","); });
            data = { coords : [ [coords[0], coords[1]], [coords[2], coords[3]] ] };
          break;

          case this.drawing_types[2]:
            overlay_type = 'polygon';
            coords = $.map(valueList, function(n) { return [ n.split(",") ]; });
            data = { coords : coords };
          break;
        }

        this.addDrawingOverlay({ type : fieldName, data : data });
        this.addDrawingOverlayListeners(overlay_type);
      }
    },

    removeFilterListener: function(filter) {
      if($.inArray(filter.get('searchableFieldName'), this.drawing_types) !== -1) {
        this.removeDrawingOverlay();
        this.filter = {};
      }
    },

    setBounds: function(filterList) {
      var self = this, spatial_filter = false, bounds;

      $.each(this.drawing_types, function(k, v) {
        if(filterList.where({ searchableFieldName : v }).length > 0) {
          spatial_filter = true;
          return;
        }
      });

      if(filterList.length > 0 && !spatial_filter) {
        $.ajax({
          method:'GET',
          url: EXPLORER.settings.baseUrl + EXPLORER.settings.wsPath + 'mapinfo?q='+encodeURIComponent(this.cartodb_gmapsv3.options.query || ''),
          dataType: 'json',
          success: function(result) {
            if(result.extentMin[1]*result.extentMax[1] > 0 &&
            self.getDistanceAtEquator(result.extentMin[1], result.extentMax[1]) < 6000) { //set bounds if distance at equator is < 6k km
              bounds = new google.maps.LatLngBounds();
              bounds.extend(new google.maps.LatLng(result.extentMin[0], result.extentMin[1]));
              bounds.extend(new google.maps.LatLng(result.extentMax[0], result.extentMax[1]));
              self.map.fitBounds(bounds);
            } else {
              self.map.setZoom(2);
              self.map.setCenter(new google.maps.LatLng(35, -15));
            }
          }
        });
      }
    },

    radians: function(x) {
      return x * Math.PI / 180;
    },

    //Adapted from http://stackoverflow.com/a/1502821
    getDistanceAtEquator: function(lng1, lng2) {
      var R = 6378.137, // Earth’s mean radius in km
          dLong = this.radians(lng2 - lng1),
          a = Math.sin(dLong / 2) * Math.sin(dLong / 2),
          c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
      return R * c;
    },

    cartoDBgenerateTile: function() {
      CartoDBLayer.prototype._generateTileJson = function() {
        var core_url = this._generateUrl("tiler"),
            base_url = core_url + '/database/dataportal/table/' + this.options.table_name + '/{z}/{x}/{y}',
            tile_url = base_url + '.png',
            grid_url = base_url + '.grid.json',
            query, style, interactivity;

        // SQL?
        if (this.options.query) {
          query = 'sql=' + encodeURIComponent(this.options.query.replace(/\{\{table_name\}\}/g,this.options.table_name));
          tile_url = this._addUrlData(tile_url, query);
          grid_url = this._addUrlData(grid_url, query);
        }

        // STYLE?
        if (this.options.tile_style) {
          style = 'style=' + encodeURIComponent(this.options.tile_style.replace(/\{\{table_name\}\}/g,this.options.table_name));
          tile_url = this._addUrlData(tile_url, style);
          grid_url = this._addUrlData(grid_url, style);
        }

        // INTERACTIVITY?
        if (this.options.interactivity) {
          interactivity = 'interactivity=' + encodeURIComponent(this.options.interactivity.replace(/ /g,''));
          tile_url = this._addUrlData(tile_url, interactivity);
          grid_url = this._addUrlData(grid_url, interactivity);
        }

        // Build up the tileJSON
        return {
          blankImage: '../img/blank_tile.png',
          tilejson: '1.0.0',
          scheme: 'xyz',
          name: this.options.table_name,
          tiles: [tile_url],
          grids: [grid_url],
          tiles_base: tile_url,
          grids_base: grid_url,
          opacity: this.options.opacity,
          formatter: function(options, data) {
            return data;
          }
        };
      };
    },

    setupMap: function(obj) {

      _.defaults(obj, {
        mapCanvasId : "map_canvas",
        tilerDomain : "tiles.example.com",
        tilerProtocol : "http",
        tilerPort : 80,
        mapQuery : "",
        mapCenter : [0,0],
        mapZoom : 3
      });

      this.map = new google.maps.Map($('#' + obj.mapCanvasId)[0], {
        center: new google.maps.LatLng(obj.mapCenter[0],obj.mapCenter[1]),
        defaults: {
          editable: true,
          strokeColor: '#0B0B09',
          fillColor: '#E7E7E7',
          fillOpacity: 0.4
        },
        zoom: obj.mapZoom,
        mapTypeId: google.maps.MapTypeId.TERRAIN,
        mapTypeControl: true
      });

      this.marker = new google.maps.Marker({
        position: null,
        map: this.map
      });

      this.addDrawingManager();
      this.addDrawingListeners();

      this.cartodb_gmapsv3 = new CartoDBLayer({
        map: this.map,
        marker: this.marker,
        table_name: 'occurrence',
        interactivity: 'auto_id',
        query: obj.mapQuery,
        map_style: false,
        infowindow: true,
        auto_bound: true,
        featureClick: this.onMapClick,
        tiler_domain: obj.tilerDomain,
        tiler_port: parseInt(obj.tilerPort,10),
        tiler_protocol: obj.tilerProtocol,
        featureOver: function() {
          this.map.setOptions({draggableCursor: 'pointer'});
        },
        featureOut: function() {
          this.map.setOptions({draggableCursor: 'default'});
        }
      });
    },

    onMapClick: function(e, latlng, pos, data) {
      var url = EXPLORER.settings.baseUrl + '/' + EXPLORER.settings.locale + '/' + EXPLORER.i18n.getLanguageResource('url.occurrence-preview') + '/' + data.auto_id;
      this.marker.setPosition(latlng);
      $.get(url,'context=map')
        .success(function(htmlFragment){
          EXPLORER.preview.replacePreviewContent(htmlFragment);
          EXPLORER.preview.show();
        })
         .error(function(jqXHR, textStatus, errorThrown){
           console.log(textStatus+':'+errorThrown);
        });
    },

    addDrawingManager: function() {
      this.drawing_manager = new google.maps.drawing.DrawingManager({
        drawingControl: true,
        drawingControlOptions: {
          position: google.maps.ControlPosition.TOP_CENTER,
          drawingModes: [
            google.maps.drawing.OverlayType.CIRCLE,
            google.maps.drawing.OverlayType.RECTANGLE,
            google.maps.drawing.OverlayType.POLYGON
          ]
        },
        circleOptions: this.map.defaults,
        rectangleOptions: this.map.defaults,
        polygonOptions: this.map.defaults
      });

      this.drawing_manager.setMap(this.map);
    },

    addDrawingListeners: function() {
      var self = this;

      google.maps.event.addListener(this.drawing_manager, 'drawingmode_changed', function() {
        if(self.drawing_manager.drawingMode) {
          self.removeDrawingOverlay();
          self.removeSpatialFilter();
          self.cartodb_gmapsv3.setInteraction(false);
        }
      });

      google.maps.event.addListener(this.drawing_manager, "overlaycomplete", function(e) {
        self.drawing_manager.setOptions({ drawingMode: null });
        self.drawing_overlay = e.overlay;
        self.filter = self.addFilter(e.type);
        self.addDrawingOverlayListeners(e.type);
        self.cartodb_gmapsv3.setInteraction(true);
      });
    },

    addDrawingOverlayListeners: function(type) {
      var self = this;

      switch(type) {
        case 'circle':
          $.each(["center", "bounds"], function(k, v) {
            google.maps.event.addListener(self.drawing_overlay, v +"_changed", function() {
              EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.circleParameters() });
            });
          });
        break;

        case 'rectangle':
          google.maps.event.addListener(self.drawing_overlay, 'bounds_changed', function() {
            EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.rectangleParameters() });
          });
        break;

        case 'polygon':
          if(!$.isEmptyObject(this.filter)) {
            $.each(["insert", "remove", "set"], function(k, v) {
              google.maps.event.addListener(self.drawing_overlay.getPath(), v +"_at", function() {
                EXPLORER.backbone.updateActiveFilter(self.filter, { valueList : self.polygonParameters() });
              });
            });
          }
        break;
      }
    },

    circleParameters: function() {
      var o = this.drawing_overlay;
      return [o.getCenter().lat()+','+o.getCenter().lng(),o.getRadius()];
    },

    rectangleParameters: function() {
      var o = this.drawing_overlay;
      return [o.getBounds().getNorthEast().lat() + ',' + o.getBounds().getNorthEast().lng(),
        o.getBounds().getSouthWest().lat() + ',' + o.getBounds().getSouthWest().lng()];
    },

    polygonParameters: function() {
      var o = this.drawing_overlay,
          searchValue = $.map(o.getPath().getArray(), function(n) { return [n.lat() + ',' + n.lng()]; });
      searchValue.push(searchValue[0]);
      return searchValue;
    },

    addDrawingOverlay: function(json) {
      var coord, center, options, circle, bbox, bounds, rectangle, paths, vertices, polygon;

      switch(json.type) {
        case this.drawing_types[0]:
          coord = json.data.coords;
          center = new google.maps.LatLng(coord[0], coord[1]);
          options = $.extend({ center : center, radius : json.data.radius }, this.map.defaults);
          circle = new google.maps.Circle(options);

          circle.setMap(this.map);
          this.map.fitBounds(circle.getBounds());
          this.drawing_overlay = circle;
        break;

        case this.drawing_types[1]:
          //bbox is an array of vertices eg [[lat0,lng0], [lat1,lng1]] expressed as [SW, NE]
          bbox = json.data.coords;
          bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(bbox[0][0], bbox[0][1]),
            new google.maps.LatLng(bbox[1][0], bbox[1][1])
          );
          options = $.extend({ bounds : bounds }, this.map.defaults);
          rectangle = new google.maps.Rectangle(options);

          rectangle.setMap(this.map);
          this.map.fitBounds(rectangle.getBounds());
          this.drawing_overlay = rectangle;
        break;

        case this.drawing_types[2]:
          //vertices is an array of arrays where last member is identical to first eg [[lat0,lng0], [lat1,lng1], [lat0,lng0]]
          vertices = json.data.coords;
          paths = $.map(vertices, function(n) { return new google.maps.LatLng(n[0], n[1]); });
          options = $.extend({ paths: paths }, this.map.defaults);
          polygon = new google.maps.Polygon(options);

          polygon.setMap(this.map);
          this.map.fitBounds(polygon.getBounds());
          this.drawing_overlay = polygon;
        break;

      }
    },

    removeDrawingOverlay: function() {
      if(!$.isEmptyObject(this.drawing_overlay)) {
        this.drawing_overlay.setMap(null);
      }
      this.drawing_overlay = {};
    },

    removeSpatialFilter: function() {
      $.each(this.drawing_types, function(k, v) {
        EXPLORER.backbone.removeFilter({ searchableFieldName: v });
      });
    },

    addFilter: function(type) {
      var filter = {};
      switch(type) {
        case 'circle':
          filter = EXPLORER.backbone.addActiveFilter({ searchableFieldName : 'geoellipse', valueList : this.circleParameters() });
        break;

        case 'rectangle':
          filter = EXPLORER.backbone.addActiveFilter({ searchableFieldName : 'georectangle', valueList : this.rectangleParameters() });
        break;

        case 'polygon':
          if(this.polygonParameters().length > 3) {
            filter = EXPLORER.backbone.addActiveFilter({searchableFieldName : 'geopolygon', valueList : this.polygonParameters() });
          }
        break;
      }
      return filter;
    }

  };

  return {
    init: function() { _private.init(); },
    setupMap: function(obj) {
      _private.setupMap(obj);
    },
    setBounds: function(obj) {
      _private.setBounds(obj);
    }
  };

}());<|endoftext|>


<commit_before>/**
 * @author: @AngularClass
 */

const helpers = require('./helpers');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev

/**
 * Webpack Plugins
 */
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
const DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CompressionPlugin = require('compression-webpack-plugin');
/**
 * Webpack Constants
 */
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 8080;
const METADATA = webpackMerge(commonConfig.metadata, {
  host: HOST,
  port: PORT,
  ENV: ENV,
  HMR: false
});

module.exports = webpackMerge(commonConfig, {

  /**
   * Switch loaders to debug mode.
   *
   * See: http://webpack.github.io/docs/configuration.html#debug
   */
  debug: false,

  /**
   * Developer tool to enhance debugging
   *
   * See: http://webpack.github.io/docs/configuration.html#devtool
   * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
   */
  devtool: 'source-map',

  /**
   * Options affecting the output of the compilation.
   *
   * See: http://webpack.github.io/docs/configuration.html#output
   */
  output: {

    /**
     * The output directory as absolute path (required).
     *
     * See: http://webpack.github.io/docs/configuration.html#output-path
     */
    path: helpers.root('dist'),

    /**
     * Specifies the name of each output file on disk.
     * IMPORTANT: You must not specify an absolute path here!
     *
     * See: http://webpack.github.io/docs/configuration.html#output-filename
     */
    filename: '[name].[chunkhash].bundle.js',

    /**
     * The filename of the SourceMaps for the JavaScript files.
     * They are inside the output.path directory.
     *
     * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
     */
    sourceMapFilename: '[name].[chunkhash].bundle.map',

    /**
     * The filename of non-entry chunks as relative path
     * inside the output.path directory.
     *
     * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
     */
    chunkFilename: '[id].[chunkhash].chunk.js'

  },

  /**
   * Add additional plugins to the compiler.
   *
   * See: http://webpack.github.io/docs/configuration.html#plugins
   */
  plugins: [

    /**
     * Plugin: WebpackMd5Hash
     * Description: Plugin to replace a standard webpack chunkhash with md5.
     *
     * See: https://www.npmjs.com/package/webpack-md5-hash
     */
    new WebpackMd5Hash(),

    /**
     * Plugin: DedupePlugin
     * Description: Prevents the inclusion of duplicate code into your bundle
     * and instead applies a copy of the function at runtime.
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
     * See: https://github.com/webpack/docs/wiki/optimization#deduplication
     */
    new DedupePlugin(),

    /**
     * Plugin: DefinePlugin
     * Description: Define free variables.
     * Useful for having development builds with debug logging or adding global constants.
     *
     * Environment helpers
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
     */
    // NOTE: when adding more properties make sure you include them in custom-typings.d.ts
    new DefinePlugin({
      'ENV': JSON.stringify(METADATA.ENV),
      'HMR': METADATA.HMR,
      'process.env': {
        'ENV': JSON.stringify(METADATA.ENV),
        'NODE_ENV': JSON.stringify(METADATA.ENV),
        'HMR': METADATA.HMR
      }
    }),

    /**
     * Plugin: UglifyJsPlugin
     * Description: Minimize all JavaScript output of chunks.
     * Loaders are switched into minimizing mode.
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
     */
    // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
    new UglifyJsPlugin({
      // beautify: true, //debug
      // mangle: false, //debug
      // dead_code: false, //debug
      // unused: false, //debug
      // deadCode: false, //debug
      // compress: {
      //   screw_ie8: true,
      //   keep_fnames: true,
      //   drop_debugger: false,
      //   dead_code: false,
      //   unused: false
      // }, // debug
      // comments: true, //debug

      beautify: false, //prod
      mangle: { screw_ie8 : true }, //prod
      compress: { screw_ie8: true }, //prod
      comments: false //prod
    }),

    /**
     * Plugin: NormalModuleReplacementPlugin
     * Description: Replace resources that matches resourceRegExp with newResource
     *
     * See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin
     */

    new NormalModuleReplacementPlugin(
      /angular2-hmr/,
      helpers.root('config/modules/angular2-hmr-prod.js')
    ),

    /**
     * Plugin: IgnorePlugin
     * Description: Don’t generate modules for requests matching the provided RegExp.
     *
     * See: http://webpack.github.io/docs/list-of-plugins.html#ignoreplugin
     */

    // new IgnorePlugin(/angular2-hmr/),

    /**
     * Plugin: CompressionPlugin
     * Description: Prepares compressed versions of assets to serve
     * them with Content-Encoding
     *
     * See: https://github.com/webpack/compression-webpack-plugin
     */
    new CompressionPlugin({
      regExp: /\.css$|\.html$|\.js$|\.map$/,
      threshold: 2 * 1024
    })

  ],

  /**
   * Static analysis linter for TypeScript advanced options configuration
   * Description: An extensible linter for the TypeScript language.
   *
   * See: https://github.com/wbuchwalter/tslint-loader
   */
  tslint: {
    emitErrors: true,
    failOnHint: true,
    resourcePath: 'src'
  },

  /**
   * Html loader advanced options
   *
   * See: https://github.com/webpack/html-loader#advanced-options
   */
  // TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor
  htmlLoader: {
    minimize: true,
    removeAttributeQuotes: false,
    caseSensitive: true,
    customAttrSurround: [
      [/#/, /(?:)/],
      [/\*/, /(?:)/],
      [/\[?\(?/, /(?:)/]
    ],
    customAttrAssign: [/\)?\]?=/]
  },

  /*
   * Include polyfills or mocks for various node stuff
   * Description: Node configuration
   *
   * See: https://webpack.github.io/docs/configuration.html#node
   */
  node: {
    global: 'window',
    crypto: 'empty',
    process: false,
    module: false,
    clearImmediate: false,
    setImmediate: false
  }

});
<commit_msg>chore(build): fix prod build<commit_after>/**
 * @author: @AngularClass
 */

const helpers = require('./helpers');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev

/**
 * Webpack Plugins
 */
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
const DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CompressionPlugin = require('compression-webpack-plugin');
/**
 * Webpack Constants
 */
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 8080;
const METADATA = webpackMerge(commonConfig.metadata, {
  host: HOST,
  port: PORT,
  ENV: ENV,
  HMR: false
});

module.exports = webpackMerge(commonConfig, {

  /**
   * Switch loaders to debug mode.
   *
   * See: http://webpack.github.io/docs/configuration.html#debug
   */
  debug: false,

  /**
   * Developer tool to enhance debugging
   *
   * See: http://webpack.github.io/docs/configuration.html#devtool
   * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
   */
  devtool: 'source-map',

  /**
   * Options affecting the output of the compilation.
   *
   * See: http://webpack.github.io/docs/configuration.html#output
   */
  output: {

    /**
     * The output directory as absolute path (required).
     *
     * See: http://webpack.github.io/docs/configuration.html#output-path
     */
    path: helpers.root('dist'),

    /**
     * Specifies the name of each output file on disk.
     * IMPORTANT: You must not specify an absolute path here!
     *
     * See: http://webpack.github.io/docs/configuration.html#output-filename
     */
    filename: '[name].[chunkhash].bundle.js',

    /**
     * The filename of the SourceMaps for the JavaScript files.
     * They are inside the output.path directory.
     *
     * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
     */
    sourceMapFilename: '[name].[chunkhash].bundle.map',

    /**
     * The filename of non-entry chunks as relative path
     * inside the output.path directory.
     *
     * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
     */
    chunkFilename: '[id].[chunkhash].chunk.js'

  },

  /**
   * Add additional plugins to the compiler.
   *
   * See: http://webpack.github.io/docs/configuration.html#plugins
   */
  plugins: [

    /**
     * Plugin: WebpackMd5Hash
     * Description: Plugin to replace a standard webpack chunkhash with md5.
     *
     * See: https://www.npmjs.com/package/webpack-md5-hash
     */
    new WebpackMd5Hash(),

    /**
     * Plugin: DedupePlugin
     * Description: Prevents the inclusion of duplicate code into your bundle
     * and instead applies a copy of the function at runtime.
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
     * See: https://github.com/webpack/docs/wiki/optimization#deduplication
     */
    new DedupePlugin(),

    /**
     * Plugin: DefinePlugin
     * Description: Define free variables.
     * Useful for having development builds with debug logging or adding global constants.
     *
     * Environment helpers
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
     */
    // NOTE: when adding more properties make sure you include them in custom-typings.d.ts
    new DefinePlugin({
      'ENV': JSON.stringify(METADATA.ENV),
      'HMR': METADATA.HMR,
      'process.env': {
        'ENV': JSON.stringify(METADATA.ENV),
        'NODE_ENV': JSON.stringify(METADATA.ENV),
        'HMR': METADATA.HMR
      }
    }),

    /**
     * Plugin: UglifyJsPlugin
     * Description: Minimize all JavaScript output of chunks.
     * Loaders are switched into minimizing mode.
     *
     * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
     */
    // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
    new UglifyJsPlugin({
      // beautify: true, //debug
      // mangle: false, //debug
      // dead_code: false, //debug
      // unused: false, //debug
      // deadCode: false, //debug
      // compress: {
      //   screw_ie8: true,
      //   keep_fnames: true,
      //   drop_debugger: false,
      //   dead_code: false,
      //   unused: false
      // }, // debug
      // comments: true, //debug

      beautify: false, //prod
      mangle: false,
      compress: { screw_ie8: true }, //prod
      comments: false //prod
    }),

    /**
     * Plugin: NormalModuleReplacementPlugin
     * Description: Replace resources that matches resourceRegExp with newResource
     *
     * See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin
     */

    new NormalModuleReplacementPlugin(
      /angular2-hmr/,
      helpers.root('config/modules/angular2-hmr-prod.js')
    ),

    /**
     * Plugin: IgnorePlugin
     * Description: Don’t generate modules for requests matching the provided RegExp.
     *
     * See: http://webpack.github.io/docs/list-of-plugins.html#ignoreplugin
     */

    // new IgnorePlugin(/angular2-hmr/),

    /**
     * Plugin: CompressionPlugin
     * Description: Prepares compressed versions of assets to serve
     * them with Content-Encoding
     *
     * See: https://github.com/webpack/compression-webpack-plugin
     */
    new CompressionPlugin({
      regExp: /\.css$|\.html$|\.js$|\.map$/,
      threshold: 2 * 1024
    })

  ],

  /**
   * Static analysis linter for TypeScript advanced options configuration
   * Description: An extensible linter for the TypeScript language.
   *
   * See: https://github.com/wbuchwalter/tslint-loader
   */
  tslint: {
    emitErrors: true,
    failOnHint: true,
    resourcePath: 'src'
  },

  /**
   * Html loader advanced options
   *
   * See: https://github.com/webpack/html-loader#advanced-options
   */
  // TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor
  htmlLoader: {
    minimize: true,
    removeAttributeQuotes: false,
    caseSensitive: true,
    customAttrSurround: [
      [/#/, /(?:)/],
      [/\*/, /(?:)/],
      [/\[?\(?/, /(?:)/]
    ],
    customAttrAssign: [/\)?\]?=/]
  },

  /*
   * Include polyfills or mocks for various node stuff
   * Description: Node configuration
   *
   * See: https://webpack.github.io/docs/configuration.html#node
   */
  node: {
    global: 'window',
    crypto: 'empty',
    process: false,
    module: false,
    clearImmediate: false,
    setImmediate: false
  }

});
<|endoftext|>


<commit_before>const { series, concurrent } = require('nps-utils');

module.exports = {
  scripts: {
    all: series.nps('build', 'apps-and-watch'),
    appsAndWatch: concurrent.nps('apps', 'watch'),
    apps: concurrent.nps('bree', 'api', 'web'),

    bree: 'nodemon bree.js',
    api: 'nodemon api.js',
    web: 'nodemon web.js',

    watch: 'gulp watch',
    clean: 'gulp clean',
    build: 'gulp build',
    publishAssets: 'gulp publish',

    lintJs: 'gulp xo',
    lintMd: 'gulp remark',
    lintPug: 'gulp pug',
    lint: concurrent.nps('lint-js', 'lint-md', 'lint-pug'),

    // <https://github.com/kentcdodds/nps-utils/issues/24>
    pretest: concurrent.nps('lint', 'build', 'pretest-redis'),
    // <https://stackoverflow.com/a/16974060/3586413>
    pretestRedis:
      "redis-cli EVAL \"return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))\" 0 limit_test:*",

    test: 'ava',
    testCoverage: series('nps pretest', 'nyc ava'),
    testUpdateSnapshots: series('nps pretest', 'ava --update-snapshots'),

    coverage: 'nyc report --reporter=text-lcov > coverage.lcov && codecov'
  }
};
<commit_msg>fix: fixed pretestRedis<commit_after>const { series, concurrent } = require('nps-utils');

module.exports = {
  scripts: {
    all: series.nps('build', 'apps-and-watch'),
    appsAndWatch: concurrent.nps('apps', 'watch'),
    apps: concurrent.nps('bree', 'api', 'web'),

    bree: 'nodemon bree.js',
    api: 'nodemon api.js',
    web: 'nodemon web.js',

    watch: 'gulp watch',
    clean: 'gulp clean',
    build: 'gulp build',
    publishAssets: 'gulp publish',

    lintJs: 'gulp xo',
    lintMd: 'gulp remark',
    lintPug: 'gulp pug',
    lint: concurrent.nps('lint-js', 'lint-md', 'lint-pug'),

    // <https://github.com/kentcdodds/nps-utils/issues/24>
    pretest: concurrent.nps('lint', 'build', 'pretest-redis'),
    // <https://stackoverflow.com/a/16974060/3586413>
    pretestRedis:
      "redis-cli EVAL \"return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))\" 0 *_limit_test:*",

    test: 'ava',
    testCoverage: series('nps pretest', 'nyc ava'),
    testUpdateSnapshots: series('nps pretest', 'ava --update-snapshots'),

    coverage: 'nyc report --reporter=text-lcov > coverage.lcov && codecov'
  }
};
<|endoftext|>


<commit_before>function augmentServices(services)
{
    var idx, requiredServices, service;

    requiredServices = {
        'alfresco/services/DocumentService' : true
    };

    for (idx = 0; idx < services.length; idx++)
    {
        if (typeof services[idx].name === 'string' && requiredServices.hasOwnProperty(services[idx].name))
        {
            requiredServices[services[idx].name] = false;
        }
        else if (typeof services[idx] === 'string' && requiredServices.hasOwnProperty(services[idx]))
        {
            requiredServices[services[idx]] = false;
        }
    }

    for (service in requiredServices)
    {
        if (requiredServices.hasOwnProperty(service))
        {
            if (requiredServices[service] === true)
            {
                services.push({
                    name : service,
                    config : {}
                });
            }
        }
    }
}

function buildMainPanel()
{
    var model;

    model = {
        name : 'alfresco/core/ProcessWidgets',
        config : {
            pubSubScope : 'TRASH_ITEM_LIST/',
            widgets : [ {
                name : 'alfresco/lists/Paginator',
                config : {
                    documentsPerPage : 20,
                    pageSizes : [ 20, 50, 100 ],
                    style : 'text-align:center;',
                    widgetsBefore : [ {
                        name : 'alfresco/documentlibrary/AlfSelectDocumentListItems'
                    } ],
                    widgetsAfter : [ {
                        name : 'alfresco/documentlibrary/AlfSelectedItemsMenuBarPopup',
                        config : {
                            // can't believe "selected-items.label" is not a global label
                            // we prefix it to not mess with any global labels others may have added
                            // TODO Report bug / enhancement
                            label : 'trash-browser.paginator.selected-items.label',
                            passive : false,
                            itemKeyProperty : 'nodeRef',
                            widgets : [
                            // TODO bulk actions
                            ]
                        }
                    } ]
                }
            }, {
                name : 'alfresco/documentlibrary/AlfDocumentList',
                config : {
                    // reloadDataTopic : 'RELOAD_TRASH_ITEMS',
                    rawData : false,
                    nodeRef : 'archive://SpacesStore/57928a6b-fe20-46e4-a032-554de9c9d586',
                    // loadDataPublishTopic : 'dummy', // TODO Set service topic
                    loadDataPublishPayload : {
                    // TODO Fill with whatever the service needs
                    },
                    // TODO Report enhancement - filtering should not require these form topic cludges
                    filteringTopics : [ '_valueChangeOf_ITEM_NAME', '_valueChangeOf_KEYWORDS' ],
                    widgetsForFilters : [ {
                        name : 'alfresco/forms/controls/TextBox',
                        config : {
                            // TODO Report enhancement - filter widgets should align properly
                            // TODO Report enhancement - simple width customisation
                            style : 'vertical-align:top;',
                            fieldId : 'ITEM_NAME',
                            name : 'itemName',
                            label : 'trash-browser.filter.itemName.label',
                            placeHolder : 'trash-browser.filter.itemName.placeHolder'
                        }
                    }, {
                        name : 'alfresco/forms/controls/TextBox',
                        config : {
                            // TODO Report enhancement - filter widgets should align properly
                            // TODO Report enhancement - simple width customisation
                            style : 'vertical-align:top;',
                            fieldId : 'KEYWORDS',
                            name : 'keywords',
                            label : 'trash-browser.filter.keywords.label',
                            placeHolder : 'trash-browser.filter.keywords.placeHolder'
                        }
                    } ],
                    usePagination : true,
                    currentPageSize : 20,
                    itemsProperty : 'items', // TODO Set to whatever we get back from a service
                    widgets : [ {
                        name : 'alfresco/documentlibrary/views/AlfSimpleView',
                        config : {
                            additionalCssClasses : 'bordered',
                            widgetsForHeader : [],
                            widgets : [ {
                                name : 'alfresco/lists/views/layouts/Row',
                                config : {
                                    // TODO Report bug - property zebraStriping without effect
                                    additionalCssClasses : 'zebra-striping',
                                    // TODO Report enhancement - simple CellProperty widget
                                    // TODO Report enhancement - support of expanded (alternative) value as tooltip / mouseover
                                    widgets : [ {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Selector',
                                                itemKey : 'nodeRef',
                                                publishGlobal : false,
                                                publishToParent : false
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Thumbnail',
                                                config : {
                                                    showDocumentPreview : true,
                                                    publishGlobal : false,
                                                    publishToParent : false
                                                }
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            // TODO Expand cell into a document library-like details view
                                            // TODO Consider how people might be able to customise view for different types of
                                            // archived
                                            // items
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Property',
                                                config : {
                                                    propertyToRender : 'node.properties.cm:name',
                                                    renderSize : 'medium'
                                                }
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            widgets : [ {
                                                name : 'alfresco/renderers/Actions',
                                                config : {
                                                    // TODO Report enhancement - make size of Actions configurable (it is frigging huge)
                                                    // TODO Report enhancement - Actions should allow providing custom actions like the
                                                    // pre-defined action widgets (currently customActions are mapped into AlfMenuItem
                                                    // dropping some options and adding some non-suppressable ones)
                                                    customActions : []
                                                }
                                            } ]
                                        }
                                    } ]
                                }
                            } ]
                        }
                    } ]
                }
            } ]
        }
    };

    return model;
}
<commit_msg>Correct validation<commit_after>/* exported augmentServices */
function augmentServices(services)
{
    var idx, requiredServices, service;

    requiredServices = {
        'alfresco/services/DocumentService' : true
    };

    for (idx = 0; idx < services.length; idx++)
    {
        if (typeof services[idx].name === 'string' && requiredServices.hasOwnProperty(services[idx].name))
        {
            requiredServices[services[idx].name] = false;
        }
        else if (typeof services[idx] === 'string' && requiredServices.hasOwnProperty(services[idx]))
        {
            requiredServices[services[idx]] = false;
        }
    }

    for (service in requiredServices)
    {
        if (requiredServices.hasOwnProperty(service))
        {
            if (requiredServices[service] === true)
            {
                services.push({
                    name : service,
                    config : {}
                });
            }
        }
    }
}

/* exported buildMainPanel */
function buildMainPanel()
{
    var model;

    model = {
        name : 'alfresco/core/ProcessWidgets',
        config : {
            pubSubScope : 'TRASH_ITEM_LIST/',
            widgets : [ {
                name : 'alfresco/lists/Paginator',
                config : {
                    documentsPerPage : 20,
                    pageSizes : [ 20, 50, 100 ],
                    style : 'text-align:center;',
                    widgetsBefore : [ {
                        name : 'alfresco/documentlibrary/AlfSelectDocumentListItems'
                    } ],
                    widgetsAfter : [ {
                        name : 'alfresco/documentlibrary/AlfSelectedItemsMenuBarPopup',
                        config : {
                            // can't believe "selected-items.label" is not a global label
                            // we prefix it to not mess with any global labels others may have added
                            // TODO Report bug / enhancement
                            label : 'trash-browser.paginator.selected-items.label',
                            passive : false,
                            itemKeyProperty : 'nodeRef',
                            widgets : [
                            // TODO bulk actions
                            ]
                        }
                    } ]
                }
            }, {
                name : 'alfresco/documentlibrary/AlfDocumentList',
                config : {
                    // reloadDataTopic : 'RELOAD_TRASH_ITEMS',
                    rawData : false,
                    nodeRef : 'archive://SpacesStore/57928a6b-fe20-46e4-a032-554de9c9d586',
                    // loadDataPublishTopic : 'dummy', // TODO Set service topic
                    loadDataPublishPayload : {
                    // TODO Fill with whatever the service needs
                    },
                    // TODO Report enhancement - filtering should not require these form topic cludges
                    filteringTopics : [ '_valueChangeOf_ITEM_NAME', '_valueChangeOf_KEYWORDS' ],
                    widgetsForFilters : [ {
                        name : 'alfresco/forms/controls/TextBox',
                        config : {
                            // TODO Report enhancement - filter widgets should align properly
                            // TODO Report enhancement - simple width customisation
                            style : 'vertical-align:top;',
                            fieldId : 'ITEM_NAME',
                            name : 'itemName',
                            label : 'trash-browser.filter.itemName.label',
                            placeHolder : 'trash-browser.filter.itemName.placeHolder'
                        }
                    }, {
                        name : 'alfresco/forms/controls/TextBox',
                        config : {
                            // TODO Report enhancement - filter widgets should align properly
                            // TODO Report enhancement - simple width customisation
                            style : 'vertical-align:top;',
                            fieldId : 'KEYWORDS',
                            name : 'keywords',
                            label : 'trash-browser.filter.keywords.label',
                            placeHolder : 'trash-browser.filter.keywords.placeHolder'
                        }
                    } ],
                    usePagination : true,
                    currentPageSize : 20,
                    itemsProperty : 'items', // TODO Set to whatever we get back from a service
                    widgets : [ {
                        name : 'alfresco/documentlibrary/views/AlfSimpleView',
                        config : {
                            additionalCssClasses : 'bordered',
                            widgetsForHeader : [],
                            widgets : [ {
                                name : 'alfresco/lists/views/layouts/Row',
                                config : {
                                    // TODO Report bug - property zebraStriping without effect
                                    additionalCssClasses : 'zebra-striping',
                                    // TODO Report enhancement - simple CellProperty widget
                                    // TODO Report enhancement - support of expanded (alternative) value as tooltip / mouseover
                                    widgets : [ {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Selector',
                                                itemKey : 'nodeRef',
                                                publishGlobal : false,
                                                publishToParent : false
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Thumbnail',
                                                config : {
                                                    showDocumentPreview : true,
                                                    publishGlobal : false,
                                                    publishToParent : false
                                                }
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            // TODO Expand cell into a document library-like details view
                                            // TODO Consider how people might be able to customise view for different types of
                                            // archived
                                            // items
                                            additionalCssClasses : 'smallpad',
                                            widgets : [ {
                                                name : 'alfresco/renderers/Property',
                                                config : {
                                                    propertyToRender : 'node.properties.cm:name',
                                                    renderSize : 'medium'
                                                }
                                            } ]
                                        }
                                    }, {
                                        name : 'alfresco/lists/views/layouts/Cell',
                                        config : {
                                            widgets : [ {
                                                name : 'alfresco/renderers/Actions',
                                                config : {
                                                    // TODO Report enhancement - make size of Actions configurable (it is frigging huge)
                                                    // TODO Report enhancement - Actions should allow providing custom actions like the
                                                    // pre-defined action widgets (currently customActions are mapped into AlfMenuItem
                                                    // dropping some options and adding some non-suppressable ones)
                                                    customActions : []
                                                }
                                            } ]
                                        }
                                    } ]
                                }
                            } ]
                        }
                    } ]
                }
            } ]
        }
    };

    return model;
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var should = require('should');
var sinon = require('sinon');
var setup = require('../_setup');
var Promise = require('bluebird');
var moment = require('moment');
require('should-sinon');

describe('Action formCiconia:', function () {
  var ciconiaRecord = {
    latitude: 42.1463749,
    longitude: 24.7492006,
    observationDateTime: '2016-12-20T12:15Z',
    monitoringCode: 'random_ciconia_1234',
    primarySubstrateType: {
      type: 'ciconia_substratum',
      label: {
        bg: 'ciconia_substratum',
        en: 'ciconia_substratum'
      }

    },
    electricityPole: {
      type: 'ciconia_column',
      label: {
        bg: 'Imm.',
        en: 'Imm.'
      }
    },
    typeElectricityPole: {
      type: 'ciconia_column_type',
      label: {
        bg: 'ciconia_column_type',
        en: 'ciconia_column_type'
      }
    },
    nestOnArtificialHumanMadePlatform: true,
    nestIsOnAnotherTypeOfSubstrate: 'blah blah',
    nestThisYearNotUtilizedByWhiteStorks: {
      type: 'ciconia_not_occupied',
      label: {
        bg: 'ciconia_not_occupied',
        en: 'ciconia_not_occupied'
      }
    },
    approximateDateStorksAppeared: '2015-03-10T12:15Z',
    approximateDateDisappearanceWhiteStorks: '2015-08-10T12:15Z',
    countJuvenilesInNest: 3,
    nestNotUsedForOverOneYear: 1,
    dataOnJuvenileMortalityFromElectrocutions: 1,
    dataOnJuvenilesExpelledFromParents: 1,
    diedOtherReasons: 23,
    reason: 'some reason',
    speciesNotes: 'some notes text',
    location: 'location somewhere',

    endDateTime: '10/12/2015 10:15',
    startDateTime: '09/12/2015 08:10',
    observers: 'Some test observers',
    rain: {
      type: 'main_rain',
      label: {
        bg: 'Ръми',
        en: 'Drizzle'
      }
    },
    temperature: 24.3,
    windDirection: {
      type: 'main_wind_direction',
      label: {
        bg: 'ENE',
        en: 'ENE'
      }
    },
    windSpeed: {
      type: 'main_wind_force',
      label: {
        bg: '2 - Лек бриз',
        en: '2 - Light breeze'
      }
    },
    cloudiness: {
      type: 'main_cloud_level',
      label: {
        bg: '33-66%',
        en: '33-66%'
      }
    },
    cloudsType: 'Light grey clouds',
    visibility: 5.5,
    mto: 'pretty nice weather',
    threats: [
      {
        type: 'main_threats',
        label: {
          bg: 'Култивация',
          en: 'Cultivation'
        }
      },
      {
        type: 'main_threats',
        label: {
          bg: 'Наторяване',
          en: 'Mulching'
        }
      }
    ],
    notes: 'some notes'
  };

  before(function () {
    return setup.init();
  });

  after(function () {
    return setup.finish();
  });

  describe('Guest user', function () {
    setup.describeAsGuest(function (runAction) {
      it('fails to create Ciconia record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          response.error.should.be.equal('Error: Please log in to continue');
        });
      });
    });
  }); // Guest user

  setup.describeAsAuth(function (runAction) {
    describe('fails to create without', function () {
      var required = ['latitude', 'longitude', 'observationDateTime', 'monitoringCode',
        'endDateTime', 'startDateTime', 'location', 'user'];

      required.forEach(function (property) {
        it(property, function () {
          var reqCiconiaObj = _.cloneDeep(ciconiaRecord);
          delete reqCiconiaObj[property];
          return runAction('formCiconia:create', reqCiconiaObj).then(function (response) {
            response.error.should.be.equal('Error: ' + property + ' is a required parameter for this action');
          });
        });
      });

    }); // fails to create without

    describe('CREATE', function () {
      it('creates Ciconia record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          should.not.exist(response.error);
          response.data.id.should.be.greaterThan(0);
        });
      });

      it('attaches the user created the record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          should.not.exist(response.error);
          response.data.user.should.be.equal(response.requesterUser.id);
        });
      });
    });

  }); // describeAsAuth

  describe('Get Ciconia record by id', function () {
    var ciconiaId;

    before(function () {
      return setup.runActionAsUser2('formCiconia:create', ciconiaRecord).then(function (response) {
        ciconiaId = response.data.id;
      });
    });

    it('is allowed if the requester user is the submitter', function () {
      return setup.runActionAsUser2('formCiconia:view', {id: ciconiaId}).then(function (response) {
        response.should.not.have.property('error');
        response.should.have.property('data');
      });
    });

    it('should return the correct row', function () {
      return setup.runActionAsUser2('formCiconia:view', {id: ciconiaId}).then(function (response) {
        response.should.not.have.property('error');
        response.data.id.should.be.equal(ciconiaId);
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('is allowed if the requester user is admin', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data');
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('is not allowed if the requester user is not the submitter', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsGuest(function (runAction) {
      it('is not allowed if the requester is guest  user', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

  }); // Get ciconia record by id

  describe('given some ciconia rows:', function () {
    setup.describeAsUser(function (runAction) {
      it('is allowed to list only his records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data').not.empty().instanceOf(Array);
          response.should.have.property('count').and.be.greaterThan(0);

          for (var i = 0; i < response.data.length; i++) {
            response.data[i].should.have.property('user');
            response.data[i].should.not.be.empty();
            response.data[i].user.should.be.equal(1);
          }
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('admin is allowed to list all records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data').not.empty().instanceOf(Array);
          response.should.have.property('count').and.be.greaterThan(3);
        });
      });
    });

    setup.describeAsGuest(function (runAction) {
      it('guest is not allowed to list any records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.have.property('error').not.empty();
          response.should.not.have.property('data');
          response.should.not.have.property('count');
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('filter user', function () {
        //Depends on users fixture third record AND formCiconia fixture
        return runAction('formCiconia:create', _.assign(ciconiaRecord, {user: 3})).then(function (response) {
          return runAction('formCiconia:list', {user: 3}).then(function (response){
            response.should.not.have.property('error');
            for (var i = 0; i < response.data.length; i++) {
              response.data[i].user.should.be.equal(3);
            }
          });
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('filter location', function () {
        return runAction('formCiconia:create', _.assign(ciconiaRecord, {location: 'some_unq_location'})).then(function (response) {
          return runAction('formCiconia:list', {location: 'some_unq_location'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(1);
            response.data[0].location.should.be.equal('some_unq_location');
          });
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('filter from_date', function () {
        return runAction('formCiconia:list', {from_date: '2016-12-20T10:15Z'}).then(function (response){
          response.should.not.have.property('error');
          response.data.length.should.be.equal(5);
        });
      });
      it('filter to_date', function () {
          return runAction('formCiconia:list', {to_date: '2016-12-20T10:15Z'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(2);
          });
      });
      it('filter from_date and to_date', function () {
          return runAction('formCiconia:list', {from_date: '2016-12-20T10:15Z', to_date: '2016-12-20T10:15Z'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(1);
          });
      });
    });

  }); // given some Ciconia rows

  describe('Edit ciconia row', function () {
    var ciconiaId;

    before(function () {
      return setup.runActionAsUser2('formCiconia:create', ciconiaRecord).then(function (response) {
        ciconiaId = response.data.id;
      });
    });

    it('is allowed if the requester is the submitter', function () {
      return setup.runActionAsUser2('formCiconia:edit', {id: ciconiaId, notes: 'some new notes'}).then(function (response) {
        response.should.not.have.property('error');
        return setup.api.models.formCiconia.findOne({where: {id: ciconiaId}}).then(function (ciconia) {
          ciconia.notes.should.be.equal('some new notes');
        });

      });
    });

    setup.describeAsGuest(function (runAction) {
      it('is not allowed if the requester is guest  user', function () {
        return runAction('formCiconia:edit', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('is not allowed if the requester user is not the submitter', function () {
        return runAction('formCiconia:edit', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('is allowed if the requester user is admin', function () {
        return runAction('formCiconia:edit', {id: ciconiaId, notes: 'some new notes'}).then(function (response) {
          response.should.not.have.property('error');
          return setup.api.models.formCiconia.findOne({where: {id: ciconiaId}}).then(function (ciconia) {
            ciconia.notes.should.be.equal('some new notes');
          });
        });
      });
    });

  }); // Edit ciconia row

});
<commit_msg>fix ciconia tests for mandatory fields<commit_after>var _ = require('lodash');
var should = require('should');
var sinon = require('sinon');
var setup = require('../_setup');
var Promise = require('bluebird');
var moment = require('moment');
require('should-sinon');

describe('Action formCiconia:', function () {
  var ciconiaRecord = {
    latitude: 42.1463749,
    longitude: 24.7492006,
    observationDateTime: '2016-12-20T12:15Z',
    monitoringCode: 'random_ciconia_1234',
    primarySubstrateType: {
      type: 'ciconia_substratum',
      label: {
        bg: 'ciconia_substratum',
        en: 'ciconia_substratum'
      }

    },
    electricityPole: {
      type: 'ciconia_column',
      label: {
        bg: 'Imm.',
        en: 'Imm.'
      }
    },
    typeElectricityPole: {
      type: 'ciconia_column_type',
      label: {
        bg: 'ciconia_column_type',
        en: 'ciconia_column_type'
      }
    },
    nestOnArtificialHumanMadePlatform: true,
    nestIsOnAnotherTypeOfSubstrate: 'blah blah',
    nestThisYearNotUtilizedByWhiteStorks: {
      type: 'ciconia_not_occupied',
      label: {
        bg: 'ciconia_not_occupied',
        en: 'ciconia_not_occupied'
      }
    },
    approximateDateStorksAppeared: '2015-03-10T12:15Z',
    approximateDateDisappearanceWhiteStorks: '2015-08-10T12:15Z',
    countJuvenilesInNest: 3,
    nestNotUsedForOverOneYear: 1,
    dataOnJuvenileMortalityFromElectrocutions: 1,
    dataOnJuvenilesExpelledFromParents: 1,
    diedOtherReasons: 23,
    reason: 'some reason',
    speciesNotes: 'some notes text',
    location: 'location somewhere',

    endDateTime: '10/12/2015 10:15',
    startDateTime: '09/12/2015 08:10',
    observers: 'Some test observers',
    rain: {
      type: 'main_rain',
      label: {
        bg: 'Ръми',
        en: 'Drizzle'
      }
    },
    temperature: 24.3,
    windDirection: {
      type: 'main_wind_direction',
      label: {
        bg: 'ENE',
        en: 'ENE'
      }
    },
    windSpeed: {
      type: 'main_wind_force',
      label: {
        bg: '2 - Лек бриз',
        en: '2 - Light breeze'
      }
    },
    cloudiness: {
      type: 'main_cloud_level',
      label: {
        bg: '33-66%',
        en: '33-66%'
      }
    },
    cloudsType: 'Light grey clouds',
    visibility: 5.5,
    mto: 'pretty nice weather',
    threats: [
      {
        type: 'main_threats',
        label: {
          bg: 'Култивация',
          en: 'Cultivation'
        }
      },
      {
        type: 'main_threats',
        label: {
          bg: 'Наторяване',
          en: 'Mulching'
        }
      }
    ],
    notes: 'some notes'
  };

  before(function () {
    return setup.init();
  });

  after(function () {
    return setup.finish();
  });

  describe('Guest user', function () {
    setup.describeAsGuest(function (runAction) {
      it('fails to create Ciconia record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          response.error.should.be.equal('Error: Please log in to continue');
        });
      });
    });
  }); // Guest user

  setup.describeAsAuth(function (runAction) {
    describe('fails to create without', function () {
      var required = ['latitude', 'longitude', 'observationDateTime', 'monitoringCode',
        'endDateTime', 'startDateTime', 'location'];

      required.forEach(function (property) {
        it(property, function () {
          var reqCiconiaObj = _.cloneDeep(ciconiaRecord);
          delete reqCiconiaObj[property];
          return runAction('formCiconia:create', reqCiconiaObj).then(function (response) {
            response.error.should.be.equal('Error: ' + property + ' is a required parameter for this action');
          });
        });
      });

    }); // fails to create without

    describe('CREATE', function () {
      it('creates Ciconia record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          should.not.exist(response.error);
          response.data.id.should.be.greaterThan(0);
        });
      });

      it('attaches the user created the record', function () {
        return runAction('formCiconia:create', ciconiaRecord).then(function (response) {
          should.not.exist(response.error);
          response.data.user.should.be.equal(response.requesterUser.id);
        });
      });
    });

  }); // describeAsAuth

  describe('Get Ciconia record by id', function () {
    var ciconiaId;

    before(function () {
      return setup.runActionAsUser2('formCiconia:create', ciconiaRecord).then(function (response) {
        ciconiaId = response.data.id;
      });
    });

    it('is allowed if the requester user is the submitter', function () {
      return setup.runActionAsUser2('formCiconia:view', {id: ciconiaId}).then(function (response) {
        response.should.not.have.property('error');
        response.should.have.property('data');
      });
    });

    it('should return the correct row', function () {
      return setup.runActionAsUser2('formCiconia:view', {id: ciconiaId}).then(function (response) {
        response.should.not.have.property('error');
        response.data.id.should.be.equal(ciconiaId);
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('is allowed if the requester user is admin', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data');
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('is not allowed if the requester user is not the submitter', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsGuest(function (runAction) {
      it('is not allowed if the requester is guest  user', function () {
        return runAction('formCiconia:view', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

  }); // Get ciconia record by id

  describe('given some ciconia rows:', function () {
    setup.describeAsUser(function (runAction) {
      it('is allowed to list only his records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data').not.empty().instanceOf(Array);
          response.should.have.property('count').and.be.greaterThan(0);

          for (var i = 0; i < response.data.length; i++) {
            response.data[i].should.have.property('user');
            response.data[i].should.not.be.empty();
            response.data[i].user.should.be.equal(1);
          }
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('admin is allowed to list all records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.not.have.property('error');
          response.should.have.property('data').not.empty().instanceOf(Array);
          response.should.have.property('count').and.be.greaterThan(3);
        });
      });
    });

    setup.describeAsGuest(function (runAction) {
      it('guest is not allowed to list any records', function () {
        return runAction('formCiconia:list', {}).then(function (response) {
          response.should.have.property('error').not.empty();
          response.should.not.have.property('data');
          response.should.not.have.property('count');
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('filter user', function () {
        //Depends on users fixture third record AND formCiconia fixture
        return runAction('formCiconia:create', _.assign(ciconiaRecord, {user: 3})).then(function (response) {
          return runAction('formCiconia:list', {user: 3}).then(function (response){
            response.should.not.have.property('error');
            for (var i = 0; i < response.data.length; i++) {
              response.data[i].user.should.be.equal(3);
            }
          });
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('filter location', function () {
        return runAction('formCiconia:create', _.assign(ciconiaRecord, {location: 'some_unq_location'})).then(function (response) {
          return runAction('formCiconia:list', {location: 'some_unq_location'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(1);
            response.data[0].location.should.be.equal('some_unq_location');
          });
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('filter from_date', function () {
        return runAction('formCiconia:list', {from_date: '2016-12-20T10:15Z'}).then(function (response){
          response.should.not.have.property('error');
          response.data.length.should.be.equal(5);
        });
      });
      it('filter to_date', function () {
          return runAction('formCiconia:list', {to_date: '2016-12-20T10:15Z'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(2);
          });
      });
      it('filter from_date and to_date', function () {
          return runAction('formCiconia:list', {from_date: '2016-12-20T10:15Z', to_date: '2016-12-20T10:15Z'}).then(function (response){
            response.should.not.have.property('error');
            response.data.length.should.be.equal(1);
          });
      });
    });

  }); // given some Ciconia rows

  describe('Edit ciconia row', function () {
    var ciconiaId;

    before(function () {
      return setup.runActionAsUser2('formCiconia:create', ciconiaRecord).then(function (response) {
        ciconiaId = response.data.id;
      });
    });

    it('is allowed if the requester is the submitter', function () {
      return setup.runActionAsUser2('formCiconia:edit', {id: ciconiaId, notes: 'some new notes'}).then(function (response) {
        response.should.not.have.property('error');
        return setup.api.models.formCiconia.findOne({where: {id: ciconiaId}}).then(function (ciconia) {
          ciconia.notes.should.be.equal('some new notes');
        });

      });
    });

    setup.describeAsGuest(function (runAction) {
      it('is not allowed if the requester is guest  user', function () {
        return runAction('formCiconia:edit', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsUser(function (runAction) {
      it('is not allowed if the requester user is not the submitter', function () {
        return runAction('formCiconia:edit', {id: ciconiaId}).then(function (response) {
          response.should.have.property('error').and.not.empty();
        });
      });
    });

    setup.describeAsAdmin(function (runAction) {
      it('is allowed if the requester user is admin', function () {
        return runAction('formCiconia:edit', {id: ciconiaId, notes: 'some new notes'}).then(function (response) {
          response.should.not.have.property('error');
          return setup.api.models.formCiconia.findOne({where: {id: ciconiaId}}).then(function (ciconia) {
            ciconia.notes.should.be.equal('some new notes');
          });
        });
      });
    });

  }); // Edit ciconia row

});
<|endoftext|>