<commit_before>'use strict';

/**
 */
angular.module('openolitor-admin')
  .controller('AuslieferungenOverviewController', ['$q', '$scope', '$rootScope', '$filter',
    '$route',
    'DepotAuslieferungenModel', 'TourAuslieferungenModel',
    'PostAuslieferungenModel', 'NgTableParams', 'AUSLIEFERUNGSTATUS', 'msgBus',
    'ReportvorlagenService', 'localeSensitiveComparator', '$location', 'FilterQueryUtil', 'gettext',
    function($q, $scope, $rootScope, $filter, $route, DepotAuslieferungenModel,
      TourAuslieferungenModel, PostAuslieferungenModel, NgTableParams,
      AUSLIEFERUNGSTATUS, msgBus, ReportvorlagenService, localeSensitiveComparator,
      $location, FilterQueryUtil, gettext) {
      $rootScope.viewId = 'L-Aus';

      $scope.entries = [];
      $scope.filteredEntries = [];
      $scope.loading = false;
      $scope.model = {};

      $scope.search = {
        query: ''
      };

      var model = $route.current.$$route.model;
      var overviewModel;

      switch (model) {
        case 'Depot':
          overviewModel = DepotAuslieferungenModel;
          break;
        case 'Tour':
          overviewModel = TourAuslieferungenModel;
          break;
        case 'Post':
          overviewModel = PostAuslieferungenModel;
          break;
      }

      $scope.projektVorlagen = function() {
        return ReportvorlagenService.getVorlagen('Vorlage'+model+$scope.vorlageTyp);
      };

      $scope.statusL = [];
      angular.forEach(AUSLIEFERUNGSTATUS, function(value, key) {
        $scope.statusL.push({
          'id': key,
          'title': value
        });
      });

      $scope.hasData = function() {
        return $scope.entries !== undefined;
      };

      $scope.checkboxes = {
        checked: false,
        checkedAny: false,
        items: {},
        css: '',
        ids: []
      };

      // watch for check all checkbox
      $scope.$watch(function() {
        return $scope.checkboxes.checked;
      }, function(value) {
        angular.forEach($scope.filteredEntries, function(item) {
          $scope.checkboxes.items[item.id] = value;
        });
      });

      // watch for data checkboxes
      $scope.$watch(function() {
        return $scope.checkboxes.items;
      }, function() {
        var checked = 0,
          unchecked = 0,
          total = $scope.filteredEntries.length;
        $scope.checkboxes.ids = [];
        angular.forEach($scope.filteredEntries, function(item) {
          checked += ($scope.checkboxes.items[item.id]) || 0;
          unchecked += (!$scope.checkboxes.items[item.id]) || 0;
          if ($scope.checkboxes.items[item.id]) {
            $scope.checkboxes.ids.push(item.id);
          }
        });
        if ((unchecked === 0) || (checked === 0)) {
          $scope.checkboxes.checked = (checked === total) && checked > 0;
          $scope.checkboxes.checkedAny = (checked > 0);
        }
        // grayed checkbox
        else if ((checked !== 0 && unchecked !== 0)) {
          $scope.checkboxes.css = 'select-all:indeterminate';
          $scope.checkboxes.checkedAny = true;
        } else {
          $scope.checkboxes.css = 'select-all';
          $scope.checkboxes.checkedAny = true;
        }
      }, true);

      $scope.actions = [{
        label: gettext('Lieferschein drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.reportType = 'lieferschein';
          $scope.vorlageTyp = 'Lieferschein';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Lieferetiketten drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.$broadcast("resetDirectiveGenerateReport");
          $scope.reportType = 'lieferetiketten';
          $scope.vorlageTyp = 'Lieferetiketten';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Korbübersicht drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.$broadcast("resetDirectiveGenerateReport");
          $scope.reportType = 'korbuebersicht';
          $scope.vorlageTyp = 'Korbuebersicht';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Als ausgeliefert markieren'),
        iconClass: 'fa fa-bicycle',
        onExecute: function() {
          return overviewModel.ausliefern($scope.checkboxes.ids);
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }];

      if (!$scope.tableParams) {
        //use default tableParams
        $scope.tableParams = new NgTableParams({ // jshint ignore:line
          page: 1,
          count: 10,
          sorting: {
            datum: 'asc'
          },
          filter: {
            status: undefined
          }
        }, {
          filterDelay: 0,
          groupOptions: {
            isExpanded: true
          },
          exportODSModel: overviewModel,
          exportODSFilter: function() {
            return {
              f: $scope.search.filterQuery
            };
          },
          getData: function(params) {
            if (!$scope.entries) {
              return;
            }
            // use build-in angular filter
            var dataSet = $filter('filter')($scope.entries, $scope.search.queryQuery);
            // also filter by ngtable filters
            dataSet = $filter('filter')(dataSet, params.filter());
            dataSet = params.sorting ?
              $filter('orderBy')(dataSet, params.orderBy(), true, localeSensitiveComparator) :
              dataSet;

            $scope.filteredEntries = dataSet;

            params.total(dataSet.length);

            $location.search({'q': $scope.search.query, 'tf': JSON.stringify($scope.tableParams.filter())});

            return dataSet.slice((params.page() - 1) * params.count(),
              params.page() * params.count());
          }

        });

        var existingFilter = $location.search().tf;
        if (existingFilter) {
          $scope.tableParams.filter(JSON.parse(existingFilter));
        }
      }

      function search() {
        if ($scope.loading) {
          return;
        }
        $scope.tableParams.reload();

        $scope.loading = true;
        $scope.entries = overviewModel.query({
          f: $scope.search.filterQuery
        }, function(result) {
          $scope.entries = result;
          $scope.tableParams.reload();
          $scope.loading = false;
        });
      }

      var existingQuery = $location.search().q;
      if (existingQuery) {
        $scope.search.query = existingQuery;
      }

      $scope.closeBericht = function() {
        $scope.showGenerateReport = false;
      };

      $scope.closeBerichtFunct = function() {
        return $scope.closeBericht;
      };

      $scope.$watch('search.query', function() {
        $scope.search.filterQuery = FilterQueryUtil.transform($scope.search
          .query);
        $scope.search.queryQuery = FilterQueryUtil.withoutFilters($scope.search
          .query);
        search();
      }, true);

      msgBus.onMsg('EntityModified', $scope, function(event, msg) {
        if (msg.entity.indexOf('Auslieferung') >= 0) {
          $scope.entries.map(function(entry) {
            if(entry.id === msg.data.id) {
              angular.copy(msg.data, entry);
            }
          });
          $scope.$apply();
        }
      });
    }
  ]);
<commit_msg>sunu_#31_adding_new_rapport_for_totals<commit_after>'use strict';

/**
 */
angular.module('openolitor-admin')
  .controller('AuslieferungenOverviewController', ['$q', '$scope', '$rootScope', '$filter',
    '$route',
    'DepotAuslieferungenModel', 'TourAuslieferungenModel',
    'PostAuslieferungenModel', 'NgTableParams', 'AUSLIEFERUNGSTATUS', 'msgBus',
    'ReportvorlagenService', 'localeSensitiveComparator', '$location', 'FilterQueryUtil', 'gettext',
    function($q, $scope, $rootScope, $filter, $route, DepotAuslieferungenModel,
      TourAuslieferungenModel, PostAuslieferungenModel, NgTableParams,
      AUSLIEFERUNGSTATUS, msgBus, ReportvorlagenService, localeSensitiveComparator,
      $location, FilterQueryUtil, gettext) {
      $rootScope.viewId = 'L-Aus';

      $scope.entries = [];
      $scope.filteredEntries = [];
      $scope.loading = false;
      $scope.model = {};

      $scope.search = {
        query: ''
      };

      var model = $route.current.$$route.model;
      var overviewModel;

      switch (model) {
        case 'Depot':
          overviewModel = DepotAuslieferungenModel;
          break;
        case 'Tour':
          overviewModel = TourAuslieferungenModel;
          break;
        case 'Post':
          overviewModel = PostAuslieferungenModel;
          break;
      }

      $scope.projektVorlagen = function() {
        return ReportvorlagenService.getVorlagen('Vorlage'+model+$scope.vorlageTyp);
      };

      $scope.statusL = [];
      angular.forEach(AUSLIEFERUNGSTATUS, function(value, key) {
        $scope.statusL.push({
          'id': key,
          'title': value
        });
      });

      $scope.hasData = function() {
        return $scope.entries !== undefined;
      };

      $scope.checkboxes = {
        checked: false,
        checkedAny: false,
        items: {},
        css: '',
        ids: []
      };

      // watch for check all checkbox
      $scope.$watch(function() {
        return $scope.checkboxes.checked;
      }, function(value) {
        angular.forEach($scope.filteredEntries, function(item) {
          $scope.checkboxes.items[item.id] = value;
        });
      });

      // watch for data checkboxes
      $scope.$watch(function() {
        return $scope.checkboxes.items;
      }, function() {
        var checked = 0,
          unchecked = 0,
          total = $scope.filteredEntries.length;
        $scope.checkboxes.ids = [];
        angular.forEach($scope.filteredEntries, function(item) {
          checked += ($scope.checkboxes.items[item.id]) || 0;
          unchecked += (!$scope.checkboxes.items[item.id]) || 0;
          if ($scope.checkboxes.items[item.id]) {
            $scope.checkboxes.ids.push(item.id);
          }
        });
        if ((unchecked === 0) || (checked === 0)) {
          $scope.checkboxes.checked = (checked === total) && checked > 0;
          $scope.checkboxes.checkedAny = (checked > 0);
        }
        // grayed checkbox
        else if ((checked !== 0 && unchecked !== 0)) {
          $scope.checkboxes.css = 'select-all:indeterminate';
          $scope.checkboxes.checkedAny = true;
        } else {
          $scope.checkboxes.css = 'select-all';
          $scope.checkboxes.checkedAny = true;
        }
      }, true);

      $scope.actions = [{
        label: gettext('Lieferschein drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.reportType = 'lieferschein';
          $scope.vorlageTyp = 'Lieferschein';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Lieferetiketten drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.$broadcast("resetDirectiveGenerateReport");
          $scope.reportType = 'lieferetiketten';
          $scope.vorlageTyp = 'Lieferetiketten';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Korbübersicht drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.$broadcast("resetDirectiveGenerateReport");
          $scope.reportType = 'korbuebersicht';
          $scope.vorlageTyp = 'Korbuebersicht';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Korbdetails drucken'),
        iconClass: 'fa fa-print',
        onExecute: function() {
          $scope.$broadcast("resetDirectiveGenerateReport");
          $scope.reportType = 'korbdetails';
          $scope.vorlageTyp = 'Korbdetails';
          $scope.showGenerateReport = true;
          return true;
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }, {
        label: gettext('Als ausgeliefert markieren'),
        iconClass: 'fa fa-bicycle',
        onExecute: function() {
          return overviewModel.ausliefern($scope.checkboxes.ids);
        },
        isDisabled: function() {
          return !$scope.checkboxes.checkedAny;
        }
      }];

      if (!$scope.tableParams) {
        //use default tableParams
        $scope.tableParams = new NgTableParams({ // jshint ignore:line
          page: 1,
          count: 10,
          sorting: {
            datum: 'asc'
          },
          filter: {
            status: undefined
          }
        }, {
          filterDelay: 0,
          groupOptions: {
            isExpanded: true
          },
          exportODSModel: overviewModel,
          exportODSFilter: function() {
            return {
              f: $scope.search.filterQuery
            };
          },
          getData: function(params) {
            if (!$scope.entries) {
              return;
            }
            // use build-in angular filter
            var dataSet = $filter('filter')($scope.entries, $scope.search.queryQuery);
            // also filter by ngtable filters
            dataSet = $filter('filter')(dataSet, params.filter());
            dataSet = params.sorting ?
              $filter('orderBy')(dataSet, params.orderBy(), true, localeSensitiveComparator) :
              dataSet;

            $scope.filteredEntries = dataSet;

            params.total(dataSet.length);

            $location.search({'q': $scope.search.query, 'tf': JSON.stringify($scope.tableParams.filter())});

            return dataSet.slice((params.page() - 1) * params.count(),
              params.page() * params.count());
          }

        });

        var existingFilter = $location.search().tf;
        if (existingFilter) {
          $scope.tableParams.filter(JSON.parse(existingFilter));
        }
      }

      function search() {
        if ($scope.loading) {
          return;
        }
        $scope.tableParams.reload();

        $scope.loading = true;
        $scope.entries = overviewModel.query({
          f: $scope.search.filterQuery
        }, function(result) {
          $scope.entries = result;
          $scope.tableParams.reload();
          $scope.loading = false;
        });
      }

      var existingQuery = $location.search().q;
      if (existingQuery) {
        $scope.search.query = existingQuery;
      }

      $scope.closeBericht = function() {
        $scope.showGenerateReport = false;
      };

      $scope.closeBerichtFunct = function() {
        return $scope.closeBericht;
      };

      $scope.$watch('search.query', function() {
        $scope.search.filterQuery = FilterQueryUtil.transform($scope.search
          .query);
        $scope.search.queryQuery = FilterQueryUtil.withoutFilters($scope.search
          .query);
        search();
      }, true);

      msgBus.onMsg('EntityModified', $scope, function(event, msg) {
        if (msg.entity.indexOf('Auslieferung') >= 0) {
          $scope.entries.map(function(entry) {
            if(entry.id === msg.data.id) {
              angular.copy(msg.data, entry);
            }
          });
          $scope.$apply();
        }
      });
    }
  ]);
<|endoftext|>


<commit_before>/**
 * The StoriesKeep view.
 */
define([
  'jquery',
  'backbone',
  'underscore',
  'handlebars',
  'mps',
  'simplePagination',
  'text!static/templates/storiesKeep.handlebars',
], function($,Backbone,underscore,Handlebars,mps,simplePagination, storiesTPL) {

  'use strict';

  var StoriesKeepModel = Backbone.Model.extend({
    defaults: {
      total: null,
      perpage: null,
      page: null
    },
  })

  var StoriesKeepView = Backbone.View.extend({

    el: '#storiesKeepView',

    template: Handlebars.compile(storiesTPL),

    initialize: function() {
      if (!this.$el.length) {
        return
      }
      //CACHE
      this.$htmlbody = $('html, body');
      this.$sideBar = $('#sidebarNavView');
      this.$sourcesBox = $('#sources-box');
      this.$container = $('#crowdsourced-stories');
      this.$spinner = $('#sources-spinner');
      this.$listContainer = $('#storiesKeepList');
      this.$paginationContainer = $('#pagination-container');

      //VARS
      this.model = new StoriesKeepModel({
        total: this.$paginationContainer.data('total'),
        perpage: this.$paginationContainer.data('perpage'),
        page: this.$paginationContainer.data('page')
      });

      this.initPaginate();
    },

    initPaginate: function(){
      // pagination
      this.$paginationContainer.pagination({
        items: this.model.get('total'),
        itemsOnPage : this.model.get('perpage'),
        currentPage : this.model.get('page'),
        displayedPages: 3,
        selectOnClick: false,
        prevText: ' ',
        nextText: ' ',
        onPageClick: _.bind(function(pageNumber, event){
          event.preventDefault();
          this.$paginationContainer.pagination('drawPage', pageNumber);
          this.$spinner.addClass('start');
          this.$container.addClass('start');
          ($(window).width() >= 850 ) ? this.$htmlbody.animate({ scrollTop: this.$sideBar.offset().top }, 500) : this.$sourcesBox.animate({ scrollTop: 0 }, 500);
          this.loadAjaxStories(pageNumber);
          mps.publish('SourceStatic/Silentupdate',[{section: 'crowdsourced-stories', page: pageNumber}]);

        }, this )
      });
    },

    loadAjaxStories: function(page){
      $.ajax({
        url: '/stayinformed-stories.json',
        type: 'GET',
        dataType: 'json',
        data: {
          for_stay: true,
          page: page,
          perpage: this.model.get('perpage')
        },
        success: _.bind(function(data){
          this.parse(data);
        }, this ),
        error: function(err){
          console.log(err);
        }
      })
    },

    parse: function(data){
      this.data = _.map(data, _.bind(function(item){
        var img = (! item.media.length) ? null : item.media[item.media.length -1].preview_url;
        var detail = (item.details.length > 295) ? item.details.substr(0, 295)+'...' : item.details;
        return {
          title: item.title,
          details: detail,
          link: '/stories/'+item.id,
          map: (img) ? 'http://gfw2stories.s3.amazonaws.com/uploads/' + img : 'https://maps.googleapis.com/maps/api/staticmap?center=' + item.lat + ',' + item.lng + '&zoom=2&size=80x80',
        }
      }, this ));

      this.render();
    },

    render: function(){
      this.$spinner.removeClass('start');
      this.$container.removeClass('start');

      this.$listContainer.html(this.template({ stories : this.data }));
      mps.publish('SubItem/change');
    }

  });

  return StoriesKeepView;

});

<commit_msg>Stories: link of stories loaded via ajax need a fix, id is now renderizing well<commit_after>/**
 * The StoriesKeep view.
 */
define([
  'jquery',
  'backbone',
  'underscore',
  'handlebars',
  'mps',
  'simplePagination',
  'text!static/templates/storiesKeep.handlebars',
], function($,Backbone,underscore,Handlebars,mps,simplePagination, storiesTPL) {

  'use strict';

  var StoriesKeepModel = Backbone.Model.extend({
    defaults: {
      total: null,
      perpage: null,
      page: null
    },
  })

  var StoriesKeepView = Backbone.View.extend({

    el: '#storiesKeepView',

    template: Handlebars.compile(storiesTPL),

    initialize: function() {
      if (!this.$el.length) {
        return
      }
      //CACHE
      this.$htmlbody = $('html, body');
      this.$sideBar = $('#sidebarNavView');
      this.$sourcesBox = $('#sources-box');
      this.$container = $('#crowdsourced-stories');
      this.$spinner = $('#sources-spinner');
      this.$listContainer = $('#storiesKeepList');
      this.$paginationContainer = $('#pagination-container');

      //VARS
      this.model = new StoriesKeepModel({
        total: this.$paginationContainer.data('total'),
        perpage: this.$paginationContainer.data('perpage'),
        page: this.$paginationContainer.data('page')
      });

      this.initPaginate();
    },

    initPaginate: function(){
      // pagination
      this.$paginationContainer.pagination({
        items: this.model.get('total'),
        itemsOnPage : this.model.get('perpage'),
        currentPage : this.model.get('page'),
        displayedPages: 3,
        selectOnClick: false,
        prevText: ' ',
        nextText: ' ',
        onPageClick: _.bind(function(pageNumber, event){
          event.preventDefault();
          this.$paginationContainer.pagination('drawPage', pageNumber);
          this.$spinner.addClass('start');
          this.$container.addClass('start');
          ($(window).width() >= 850 ) ? this.$htmlbody.animate({ scrollTop: this.$sideBar.offset().top }, 500) : this.$sourcesBox.animate({ scrollTop: 0 }, 500);
          this.loadAjaxStories(pageNumber);
          mps.publish('SourceStatic/Silentupdate',[{section: 'crowdsourced-stories', page: pageNumber}]);

        }, this )
      });
    },

    loadAjaxStories: function(page){
      $.ajax({
        url: '/stayinformed-stories.json',
        type: 'GET',
        dataType: 'json',
        data: {
          for_stay: true,
          page: page,
          perpage: this.model.get('perpage')
        },
        success: _.bind(function(data){
          this.parse(data);
        }, this ),
        error: function(err){
          console.log(err);
        }
      })
    },

    parse: function(data){
      this.data = _.map(data, _.bind(function(item){
        var img = (! item.media.length) ? null : item.media[item.media.length -1].preview_url;
        var detail = (item.details.length > 295) ? item.details.substr(0, 295)+'...' : item.details;
        return {
          id: item.id,
          title: item.title,
          details: detail,
          link: '/stories/'+item.id,
          map: (img) ? 'http://gfw2stories.s3.amazonaws.com/uploads/' + img : 'https://maps.googleapis.com/maps/api/staticmap?center=' + item.lat + ',' + item.lng + '&zoom=2&size=80x80',
        }
      }, this ));

      this.render();
    },

    render: function(){
      this.$spinner.removeClass('start');
      this.$container.removeClass('start');
      this.$listContainer.html(this.template({ stories : this.data }));
      mps.publish('SubItem/change');
    }

  });

  return StoriesKeepView;

});

<|endoftext|>


<commit_before>/**

This is a plugin made based on:
- [1] Leaflet.utfgrid and
- [2] Leaflet.markercluster plugins;

[1] - https://github.com/danzel/Leaflet.utfgrid
[2] - https://github.com/Leaflet/Leaflet.markercluster

*/

'use strict';

L.Util.ajax = function(url, zoom, callback) {
  // the following is from JavaScript: The Definitive Guide
  // and https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest_in_IE6
  if (window.XMLHttpRequest === undefined) {
    window.XMLHttpRequest = function() {
      /*global ActiveXObject:true */
      try {
        return new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch  (e) {
        throw new Error("XMLHttpRequest is not supported");
      }
    };
  }

  var response, request = new XMLHttpRequest();
  request.open("GET", url);
  request.onreadystatechange = function() {
    /*jshint evil: true */
    if (request.readyState === 4 && request.status === 200) {
      if (window.JSON) {
        response = JSON.parse(request.responseText);
      } else {
        response = eval("(" + request.responseText + ")");
      }

      callback(response, zoom)
    }
  };
  request.send();
};

L.TileCluster = L.Class.extend({
  includes: L.Mixin.Events,
  options: {
    subdomains: 'abc',

    minZoom: 1,
    maxZoom: 18,
    tileSize: 256,

    useJsonP: false,
    pointerCursor: true
  },

  initialize: function(url, options) {
    L.Util.setOptions(this, options);

    this._url = url;
    this._cache = {};
    this._group = L.featureGroup();
    this._jsonp_prefix = 'cl_us_ter_';

    this._tiles = {};
    this._totalCount = 0;

    if (url.match(/callback={cb}/) && !this.options.useJsonP) {
      console.error('Must set useJsonP options if you want use a callback function!');
      return null;
    }

    if (!url.match(/callback={cb}/) && this.options.uoseJsonP) {
      console.error('Must add callback={cb} url param to use with JsonP mode!');
      return null;
    }

    if (!this.options.createIcon) {
      this.options.createIcon = this._defaultIconCreateFunction;
    }

    if (!this.options.calculateClusterQtd) {
      this.options.calculateClusterQtd = this._calculateClusterQtd;
    }

    if (!this.options.formatCount) {
      this.options.formatCount = this._formatCount;
    }

    if (this.options.useJsonP) {
      //Find a unique id in window we can use for our callbacks
      //Required for jsonP
      var i = 0;
      while (window[this._jsonp_prefix + i]) {
        i++;
      }
      this._windowKey = this._jsonp_prefix + i;
      window[this._windowKey] = {};
    }

    var subdomains = this.options.subdomains;
    if (typeof this.options.subdomains === 'string') {
      this.options.subdomains = subdomains.split('');
    }
  },

  _calculateClusterQtd: function(zoom) {
    return 1;
  },

  _formatCount: function(count) {
    return count;
  },

  onAdd: function(map) {
    this._map = map;
    this._container = this._map._container;

    this._group.addTo(this._map);

    this._update();

    var zoom = this._map.getZoom();

    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
      return;
    }

    this._group.on('mouseover', this._drawConvexHull, this);
    this._group.on('mouseout', this._removeConvexHull, this);
    if (this.options.clickCallback && typeof this.options.clickCallback === 'function') {
      this._group.on('click', this._clickCluster, this);
    }
    map.on('moveend', this._update, this);
    map.on('zoomend', this._update, this);
  },

  _update: function() {

    var bounds = this._map.getPixelBounds(),
        zoom = this._map.getZoom(),
        tileSize = this.options.tileSize;

    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
      return;
    }

    var nwTilePoint = new L.Point(
        Math.floor(bounds.min.x / tileSize),
        Math.floor(bounds.min.y / tileSize)),
      seTilePoint = new L.Point(
        Math.floor(bounds.max.x / tileSize),
        Math.floor(bounds.max.y / tileSize)),
        max = this._map.options.crs.scale(zoom) / tileSize;

    // Load all required ones
    for (var x = nwTilePoint.x; x <= seTilePoint.x; x++) {
      for (var y = nwTilePoint.y; y <= seTilePoint.y; y++) {

        var xw = (x + max) % max, yw = (y + max) % max;
        if (xw < 0 || yw < 0) {
          return;
        }

        var key = zoom + '_' + xw + '_' + yw;

        if (!this._tiles.hasOwnProperty(key)) {
          this._tiles[key] = key;
          if (!this._cache.hasOwnProperty(key)) {
            this._cache[key] = null;

            if (this.options.useJsonP) {
              this._loadTileP(zoom, xw, yw);
            } else {
              this._loadTile(zoom, xw, yw);
            }
          } else {
            this._drawCluster(this._cache[key], this, key, zoom);
          }
        }
      }
    }

    var tileBounds = L.bounds(
            bounds.min.divideBy(tileSize)._floor(),
            bounds.max.divideBy(tileSize)._floor());
    this._removeOtherTiles(tileBounds);
  },

  _removeTile: function(key) {
    var group = this._group;

    for (var index in group.getLayers()) {
      var layer = group.getLayers()[index];

      if (layer && layer.key === key) {
        group.removeLayer(layer);
      }
    }
  },

  updateCount: function() {
    this._totalCount = 0;

    for (var i in this._tiles) {
      var key = this._tiles[i];
      // console.log('key', key);

      var data = this._cache[key];

      if (data && data[0]) {
        for (var j in data) {
          var cluster = data[j];

          if (this._tiles.hasOwnProperty(key)) {
            this._totalCount += cluster.count;
          }
        }
      }
    }

    // if (oldCount != this._totalCount) {
      if (this.options.updateCountCallback && typeof this.options.updateCountCallback === 'function') {
        this.options.updateCountCallback.call(this, this._totalCount);
      }
    // }
  },

  _loadTileP: function(zoom, x, y) {
    var head = document.getElementsByTagName('head')[0],
        key = zoom + '_' + x + '_' + y,
        functionName = this._jsonp_prefix + key,
        wk = this._windowKey,
        self = this;

    var url = L.Util.template(this._url, L.Util.extend({
      s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
      z: zoom,
      x: x,
      y: y,
      cb: wk + '.' + functionName,
      cq: this.options.calculateClusterQtd(zoom)
    }, this.options));

    var script = document.createElement('script');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', url);

    window[wk][functionName] = function(data, zoom) {
      self._cache[key] = data;
      delete window[wk][functionName];
      head.removeChild(script);

      if (!zoom) {
        zoom = self._map.getZoom();
      }

      self._drawCluster(data, self, key, zoom);
    };

    head.appendChild(script);
  },

  _loadTile: function(zoom, x, y) {
    var url = L.Util.template(this._url, L.Util.extend({
      s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
      z: zoom,
      x: x,
      y: y,
      cq: this.options.calculateClusterQtd(zoom)
    }, this.options));

    var key = zoom + '_' + x + '_' + y;

    var self = this;
    L.Util.ajax(url, zoom,
      function(data, zoom) {
        self._cache[key] = data;
        self._drawCluster(data, self, key, zoom);
      }
    );
  },

  _removeOtherTiles: function (bounds) {
    this._removeConvexHull();

    var kArr, x, y, key;

    for (key in this._tiles) {
      kArr = key.split('_');
      x = parseInt(kArr[1], 10);
      y = parseInt(kArr[2], 10);

      // remove tile if it's out of bounds
      if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
        delete this._tiles[key];
        this._removeTile(key);
      }
    }
    this.updateCount();
  },

  onRemove: function() {
    var map = this._map;

    this._group.off('mouseover', this._drawConvexHull, this);
    this._group.off('mouseout', this._removeConvexHull, this);
    if (this.options.clickCallback && typeof this.options.clickCallback === 'function') {
      this._group.off('click', this._clickCluster, this);
    }
    map.off('moveend', this._update, this);
    map.off('zoomend', this._update, this);

    this.clearClusters();

    if (this.options.pointerCursor) {
      this._container.style.cursor = '';
    }

    this._map.removeLayer(this._group);
  },

  _removeConvexHull: function() {
    var ch = this._convexHull;

    if (ch && this._map.hasLayer(ch)) {
      try {
        this._map.removeLayer(ch);
      } catch (e) {
      }
    }

    this._convexHull = null;
  },

  clearClusters: function() {
    this._removeConvexHull();
    this._group.clearLayers();
  },

  _drawCluster: function(data, self, key, zoom) {
    self.updateCount();
    // Check if the zoom of cluster is the same of map
    if (data && data[0] && zoom == this._map.getZoom()) {
      for (var i in data) {
        var cluster = data[i];
        var coords = cluster.coords;
        var latlng = L.latLng(coords[0], coords[1]);

        if (cluster.count >= 2) {
          var clusterIcon = this.options.createIcon(cluster);

          var options = {
            icon: clusterIcon
          };

          if (this.options.clusterTooltip && cluster.count > 2) {
            options.title = this.options.clusterTooltip;
          }

          var clusterMarker = L.marker(latlng, options);

          clusterMarker.key = key;
          clusterMarker.id = i;
          this._group.addLayer(clusterMarker);
        } else if (cluster.count == 1) {
          var marker = L.marker(latlng);
          this._group.addLayer(marker);
        }
      }
    }
  },

  _clickCluster: function(event) {
    var key = event.layer.key;
    var id = event.layer.id;

    var data = this._cache[key];

    if (!data || !data[id]) {
      return;
    }

    data = data[id];

    data.polygon = this._wktToPolygon(data.stats.hull);

    this.options.clickCallback(event, data);
  },

  _drawConvexHull: function(event) {
    // If already had a convex hull drawed
    if (this._convexHull) {
      return;
    }

    var key = event.layer.key;
    var id = event.layer.id;

    var data = this._cache[key];

    if (!data || !data[id]) {
      return;
    }

    data = data[id];

    if (data && data.stats.hull) {
      if (data.count >= 2) {
        var wkt = data.stats.hull;
        this._convexHull = this._wktToPolygon(wkt);
        if (this._convexHull) {
          try {
            this._map.addLayer(this._convexHull);
          } catch (e) {
          }
        }
      }
    }
  },

  _wktToPolygon: function(wkt) {

    // Check if is a point
    if (wkt.match('POINT (.*)')) {
      return [];
    }

    // Convert a wkt POLYGON/LINESTRING to a Array of LatLng objects
    var string = wkt.replace('POLYGON', '');
    string = string.replace('LINESTRING', '');
    string = string.replace('(', '');
    string = string.replace('(', '');
    string = string.replace(')', '');
    string = string.replace(')', '');
    string = string.trim();

    var points = string.split(',');
    var lls = [];

    for (var i = 0; i < points.length; i++) {
      var point = points[i].trim();
      point = point.split(' ');

      var lat = parseFloat(point[0].trim());
      var lon = parseFloat(point[1].trim());

      lls.push(L.latLng(lat, lon));
    }

    return L.polygon(lls);
  },

  _defaultIconCreateFunction: function(cluster) {
    var childCount = cluster.count;

    var smallRange = 1000;
    var mediumRange = 100000;
    var largeRange = 1000000;
    var xlRange = 5000000;

    var c = ' marker-cluster-';
    if (childCount >= xlRange) {
      c += 'extra-large';
    } else if (childCount >= largeRange) {
      c += 'large';
    } else if (childCount >= mediumRange) {
      c += 'medium';
    } else {
      c += 'small';
    }

    var iconPoint = new L.Point(50, 50);
    var klass = 'small';

    if (childCount >= xlRange) {
      iconPoint = new L.Point(70, 70);
      klass = 'extra-large';
    } else if (childCount >= largeRange) {
      iconPoint = new L.Point(65, 65);
      klass = 'large';
    } else if (childCount >= mediumRange) {
      iconPoint = new L.Point(55, 55);
      klass = 'medium';
    }

    var formattedChildCount = childCount;

    if (this.formatCount && typeof this.formatCount === 'function') {
      formattedChildCount = this.formatCount(formattedChildCount);
    } else {
      formattedChildCount = this._formatCount(childCount);
    }

    return new L.DivIcon({ html: '
' + formattedChildCount + '
', className: 'marker-cluster' + c, iconSize: iconPoint });
  }
});

L.tileCluster = function(url, options) {
  return new L.TileCluster(url, options);
};<commit_msg>Clear markers in leaflet.tilecluster plugin<commit_after>/**

This is a plugin made based on:
- [1] Leaflet.utfgrid and
- [2] Leaflet.markercluster plugins;

[1] - https://github.com/danzel/Leaflet.utfgrid
[2] - https://github.com/Leaflet/Leaflet.markercluster

*/

'use strict';

L.Util.ajax = function(url, zoom, callback) {
  // the following is from JavaScript: The Definitive Guide
  // and https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest_in_IE6
  if (window.XMLHttpRequest === undefined) {
    window.XMLHttpRequest = function() {
      /*global ActiveXObject:true */
      try {
        return new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch  (e) {
        throw new Error("XMLHttpRequest is not supported");
      }
    };
  }

  var response, request = new XMLHttpRequest();
  request.open("GET", url);
  request.onreadystatechange = function() {
    /*jshint evil: true */
    if (request.readyState === 4 && request.status === 200) {
      if (window.JSON) {
        response = JSON.parse(request.responseText);
      } else {
        response = eval("(" + request.responseText + ")");
      }

      callback(response, zoom)
    }
  };
  request.send();
};

L.TileCluster = L.Class.extend({
  includes: L.Mixin.Events,
  options: {
    subdomains: 'abc',

    minZoom: 1,
    maxZoom: 18,
    tileSize: 256,

    useJsonP: false,
    pointerCursor: true
  },

  initialize: function(url, options) {
    L.Util.setOptions(this, options);

    this._url = url;
    this._cache = {};
    this._group = L.featureGroup();
    this._markers = L.featureGroup();
    this._jsonp_prefix = 'cl_us_ter_';

    this._tiles = {};
    this._totalCount = 0;

    if (url.match(/callback={cb}/) && !this.options.useJsonP) {
      console.error('Must set useJsonP options if you want use a callback function!');
      return null;
    }

    if (!url.match(/callback={cb}/) && this.options.uoseJsonP) {
      console.error('Must add callback={cb} url param to use with JsonP mode!');
      return null;
    }

    if (!this.options.createIcon) {
      this.options.createIcon = this._defaultIconCreateFunction;
    }

    if (!this.options.calculateClusterQtd) {
      this.options.calculateClusterQtd = this._calculateClusterQtd;
    }

    if (!this.options.formatCount) {
      this.options.formatCount = this._formatCount;
    }

    if (this.options.useJsonP) {
      //Find a unique id in window we can use for our callbacks
      //Required for jsonP
      var i = 0;
      while (window[this._jsonp_prefix + i]) {
        i++;
      }
      this._windowKey = this._jsonp_prefix + i;
      window[this._windowKey] = {};
    }

    var subdomains = this.options.subdomains;
    if (typeof this.options.subdomains === 'string') {
      this.options.subdomains = subdomains.split('');
    }
  },

  _calculateClusterQtd: function(zoom) {
    return 1;
  },

  _formatCount: function(count) {
    return count;
  },

  onAdd: function(map) {
    this._map = map;
    this._container = this._map._container;

    this._group.addTo(this._map);
    this._markers.addTo(this._map);

    this._update();

    var zoom = this._map.getZoom();

    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
      return;
    }

    this._group.on('mouseover', this._drawConvexHull, this);
    this._group.on('mouseout', this._removeConvexHull, this);
    if (this.options.clickCallback && typeof this.options.clickCallback === 'function') {
      this._group.on('click', this._clickCluster, this);
    }
    map.on('moveend', this._update, this);
    map.on('zoomend', this._update, this);
  },

  _update: function() {

    var bounds = this._map.getPixelBounds(),
        zoom = this._map.getZoom(),
        tileSize = this.options.tileSize;

    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
      return;
    }

    var nwTilePoint = new L.Point(
        Math.floor(bounds.min.x / tileSize),
        Math.floor(bounds.min.y / tileSize)),
      seTilePoint = new L.Point(
        Math.floor(bounds.max.x / tileSize),
        Math.floor(bounds.max.y / tileSize)),
        max = this._map.options.crs.scale(zoom) / tileSize;

    // Load all required ones
    for (var x = nwTilePoint.x; x <= seTilePoint.x; x++) {
      for (var y = nwTilePoint.y; y <= seTilePoint.y; y++) {

        var xw = (x + max) % max, yw = (y + max) % max;
        if (xw < 0 || yw < 0) {
          return;
        }

        var key = zoom + '_' + xw + '_' + yw;

        if (!this._tiles.hasOwnProperty(key)) {
          this._tiles[key] = key;
          if (!this._cache.hasOwnProperty(key)) {
            this._cache[key] = null;

            if (this.options.useJsonP) {
              this._loadTileP(zoom, xw, yw);
            } else {
              this._loadTile(zoom, xw, yw);
            }
          } else {
            this._drawCluster(this._cache[key], this, key, zoom);
          }
        }
      }
    }

    var tileBounds = L.bounds(
            bounds.min.divideBy(tileSize)._floor(),
            bounds.max.divideBy(tileSize)._floor());
    this._removeOtherTiles(tileBounds);
  },

  updateCount: function() {
    this._totalCount = 0;

    for (var i in this._tiles) {
      var key = this._tiles[i];
      var data = this._cache[key];

      if (data && data[0]) {
        for (var j in data) {
          var cluster = data[j];

          if (this._tiles.hasOwnProperty(key)) {
            this._totalCount += cluster.count;
          }
        }
      }
    }

    if (this.options.updateCountCallback && typeof this.options.updateCountCallback === 'function') {
      this.options.updateCountCallback.call(this, this._totalCount);
    }
  },

  _loadTileP: function(zoom, x, y) {
    var head = document.getElementsByTagName('head')[0],
        key = zoom + '_' + x + '_' + y,
        functionName = this._jsonp_prefix + key,
        wk = this._windowKey,
        self = this;

    var url = L.Util.template(this._url, L.Util.extend({
      s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
      z: zoom,
      x: x,
      y: y,
      cb: wk + '.' + functionName,
      cq: this.options.calculateClusterQtd(zoom)
    }, this.options));

    var script = document.createElement('script');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', url);

    window[wk][functionName] = function(data, zoom) {
      self._cache[key] = data;
      delete window[wk][functionName];
      head.removeChild(script);

      if (!zoom) {
        zoom = self._map.getZoom();
      }

      self._drawCluster(data, self, key, zoom);
    };

    head.appendChild(script);
  },

  _loadTile: function(zoom, x, y) {
    var url = L.Util.template(this._url, L.Util.extend({
      s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
      z: zoom,
      x: x,
      y: y,
      cq: this.options.calculateClusterQtd(zoom)
    }, this.options));

    var key = zoom + '_' + x + '_' + y;

    var self = this;
    L.Util.ajax(url, zoom,
      function(data, zoom) {
        self._cache[key] = data;
        self._drawCluster(data, self, key, zoom);
      }
    );
  },

  _removeOtherTiles: function (bounds) {
    this._removeConvexHull();

    var kArr, x, y, key;

    for (key in this._tiles) {
      kArr = key.split('_');
      x = parseInt(kArr[1], 10);
      y = parseInt(kArr[2], 10);

      // remove tile if it's out of bounds
      if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
        delete this._tiles[key];
        this._removeTile(key);
      }
    }
    this.updateCount();
  },

  _removeTile: function(key) {
    var group = this._group;

    for (var index in group.getLayers()) {
      var layer = group.getLayers()[index];

      if (layer && layer.key === key) {
        group.removeLayer(layer);
      }
    }

    var markers = this._markers;

    for (var index in markers.getLayers()) {
      var marker = markers.getLayers()[index];

      if (marker) {
        var markerKey = marker.key;

        if (key === markerKey) {
          markers.removeLayer(marker);
        }
      }
    }
  },

  onRemove: function() {
    var map = this._map;

    this._group.off('mouseover', this._drawConvexHull, this);
    this._group.off('mouseout', this._removeConvexHull, this);
    if (this.options.clickCallback && typeof this.options.clickCallback === 'function') {
      this._group.off('click', this._clickCluster, this);
    }
    map.off('moveend', this._update, this);
    map.off('zoomend', this._update, this);

    this.clearClusters();

    if (this.options.pointerCursor) {
      this._container.style.cursor = '';
    }

    this._map.removeLayer(this._group);
    this._map.removeLayer(this._markers);
  },

  _removeConvexHull: function() {
    var ch = this._convexHull;

    if (ch && this._map.hasLayer(ch)) {
      try {
        this._map.removeLayer(ch);
      } catch (e) {
      }
    }

    this._convexHull = null;
  },

  clearClusters: function() {
    this._removeConvexHull();
    this._group.clearLayers();
  },

  _drawCluster: function(data, self, key, zoom) {
    self.updateCount();
    // Check if the zoom of cluster is the same of map
    if (data && data[0] && zoom == this._map.getZoom()) {
      for (var i in data) {
        var cluster = data[i];
        var coords = cluster.coords;
        var latlng = L.latLng(coords[0], coords[1]);

        if (cluster.count >= 2) {
          var clusterIcon = this.options.createIcon(cluster);

          var options = {
            icon: clusterIcon
          };

          if (this.options.clusterTooltip && cluster.count > 2) {
            options.title = this.options.clusterTooltip;
          }

          var clusterMarker = L.marker(latlng, options);

          clusterMarker.key = key;
          clusterMarker.id = i;
          this._group.addLayer(clusterMarker);
        } else if (cluster.count == 1) {
          var marker = L.marker(latlng);
          marker.key = key;
          this._markers.addLayer(marker);
        }
      }
    }
  },

  _clickCluster: function(event) {
    var key = event.layer.key;
    var id = event.layer.id;

    var data = this._cache[key];

    if (!data || !data[id]) {
      return;
    }

    data = data[id];

    data.polygon = this._wktToPolygon(data.stats.hull);

    this.options.clickCallback(event, data);
  },

  _drawConvexHull: function(event) {
    // If already had a convex hull drawed
    if (this._convexHull) {
      return;
    }

    var key = event.layer.key;
    var id = event.layer.id;

    var data = this._cache[key];

    if (!data || !data[id]) {
      return;
    }

    data = data[id];

    if (data && data.stats.hull) {
      if (data.count >= 2) {
        var wkt = data.stats.hull;
        this._convexHull = this._wktToPolygon(wkt);
        if (this._convexHull) {
          try {
            this._map.addLayer(this._convexHull);
          } catch (e) {
          }
        }
      }
    }
  },

  _wktToPolygon: function(wkt) {

    // Check if is a point
    if (wkt.match('POINT (.*)')) {
      return [];
    }

    // Convert a wkt POLYGON/LINESTRING to a Array of LatLng objects
    var string = wkt.replace('POLYGON', '');
    string = string.replace('LINESTRING', '');
    string = string.replace('(', '');
    string = string.replace('(', '');
    string = string.replace(')', '');
    string = string.replace(')', '');
    string = string.trim();

    var points = string.split(',');
    var lls = [];

    for (var i = 0; i < points.length; i++) {
      var point = points[i].trim();
      point = point.split(' ');

      var lat = parseFloat(point[0].trim());
      var lon = parseFloat(point[1].trim());

      lls.push(L.latLng(lat, lon));
    }

    return L.polygon(lls);
  },

  _defaultIconCreateFunction: function(cluster) {
    var childCount = cluster.count;

    var smallRange = 1000;
    var mediumRange = 100000;
    var largeRange = 1000000;
    var xlRange = 5000000;

    var c = ' marker-cluster-';
    if (childCount >= xlRange) {
      c += 'extra-large';
    } else if (childCount >= largeRange) {
      c += 'large';
    } else if (childCount >= mediumRange) {
      c += 'medium';
    } else {
      c += 'small';
    }

    var iconPoint = new L.Point(50, 50);
    var klass = 'small';

    if (childCount >= xlRange) {
      iconPoint = new L.Point(70, 70);
      klass = 'extra-large';
    } else if (childCount >= largeRange) {
      iconPoint = new L.Point(65, 65);
      klass = 'large';
    } else if (childCount >= mediumRange) {
      iconPoint = new L.Point(55, 55);
      klass = 'medium';
    }

    var formattedChildCount = childCount;

    if (this.formatCount && typeof this.formatCount === 'function') {
      formattedChildCount = this.formatCount(formattedChildCount);
    } else {
      formattedChildCount = this._formatCount(childCount);
    }

    return new L.DivIcon({ html: '
' + formattedChildCount + '
', className: 'marker-cluster' + c, iconSize: iconPoint });
  }
});

L.tileCluster = function(url, options) {
  return new L.TileCluster(url, options);
};<|endoftext|>


<commit_before>import sinon from 'sinon'

export const contextProps = {
  projectId: 'test-project',
  hasWritePermissions: true,
  userHasFeature: () => true,
  refProviders: {},
  reindexReferences: () => {
    console.log('reindex references')
  },
  setRefProviderEnabled: provider => {
    console.log(`ref provider ${provider} enabled`)
  },
  setStartedFreeTrial: () => {
    console.log('started free trial')
  },
  rootFolder: [
    {
      docs: [{ _id: 'entity-1' }],
      fileRefs: [],
      folders: [],
    },
  ],
  initialSelectedEntityId: 'entity-1',
  onSelect: sinon.stub(),
}
<commit_msg>Check that user.refProviders[provider] is set to a truthy value (#4063)<commit_after>import sinon from 'sinon'

export const contextProps = {
  projectId: 'test-project',
  hasWritePermissions: true,
  userHasFeature: () => true,
  refProviders: { mendeley: false, zotero: false },
  reindexReferences: () => {
    console.log('reindex references')
  },
  setRefProviderEnabled: provider => {
    console.log(`ref provider ${provider} enabled`)
  },
  setStartedFreeTrial: () => {
    console.log('started free trial')
  },
  rootFolder: [
    {
      docs: [{ _id: 'entity-1' }],
      fileRefs: [],
      folders: [],
    },
  ],
  initialSelectedEntityId: 'entity-1',
  onSelect: sinon.stub(),
}
<|endoftext|>


<commit_before>'use strict';

var pagesdb = require('../../db/pagesdb')
var appLogger = require('../../utils/appLogger')

function deletePage(req, res, next) {
      pagesdb
        .deleteRow(req.params.pageUrl)
        .then( numRowsAffected => {
          res.status(200).end()
        })
        .catch( err => {
          console.error(err)
          appLogger.log.error({err, req, res})
          res.status(500).end()
        })
}

module.exports = deletePage<commit_msg>deletePage minor formatting<commit_after>'use strict';

var pagesdb = require('../../db/pagesdb')
var appLogger = require('../../utils/appLogger')

function deletePage(req, res, next) {
  pagesdb
    .deleteRow(req.params.pageUrl)
    .then( numRowsAffected => {
      res.status(200).end()
    })
    .catch( err => {
      console.error(err)
      appLogger.log.error({err, req, res})
      res.status(500).end()
    })
}

module.exports = deletePage<|endoftext|>


<commit_before>var WicketAjaxDebug = {

	showResponseText : false,

	debugWindowId : "wicketAjaxDebugWindow",

	debugWindowDragHandleId : "wicketAjaxDebugWindowHandle",

	debugWindowLogId : "wicketAjaxDebugWindowLogId",

	getDebugWindow : function()
	{
	    wicketGet(WicketAjaxDebug.debugWindowId);
	},

	showDebugWindow : function() {
	    wicketShow(WicketAjaxDebug.debugWindowId);
	},

	hideDebugWindow : function() {
	    wicketHide(WicketAjaxDebug.debugWindowId);
	},

    log : function(msg) {
        var d = wicketGet(WicketAjaxDebug.debugWindowLogId);
        var c = document.createElement("div");
        msg = msg.replace(/</g, "<");
        msg = msg.replace(/>/g, ">");
        msg = msg.replace(/\n/g, "
");
        msg = msg.replace(/ /g, " ");
        msg = msg.replace(/\t/g, "    ");
        c.innerHTML = msg;
        c.setAttribute("style","font-size: 82%; margin: 0px; padding:0px");
        d.appendChild(c);
        d.scrollTop = d.scrollHeight;
    },

    logError : function(msg) {
        WicketAjaxDebug.log("ERROR: "+msg);
    },

    logInfo : function(msg) {
        WicketAjaxDebug.log(" INFO: "+msg);
    },

    clearLog : function() {
        var d = wicketGet(WicketAjaxDebug.debugWindowLogId);
		d.innerHTML = "";
    },

	init : function() {

        if ( wicketAjaxDebugEnabled()) {
        	var wad=WicketAjaxDebug;
        	var dwid=wad.debugWindowId;
        	var dwdhid=wad.debugWindowDragHandleId;

			var firstTime = document.getElementById(dwid) == null;

			if (firstTime)
	            document.write(
					"
"+
					"
"+
					"
"+
					"
"+
					"				clear | "+
					"				close"+
					"
"+
					"
"+
					"				Wicket Ajax Debug Window (drag me here)"+
					"
"+
					"
"+
					"
"+
					"
"+
					"
" +
					"
"
	            );
            WicketDrag.init(wicketGet(dwdhid), wicketGet(dwid));

			if (firstTime)
	            document.write(

	             "
"
	            +"    WICKET AJAX DEBUG"
	            +"
");
        }
	}

};

WicketAjaxDebug.init();

<commit_msg>Nicer error message.<commit_after>var WicketAjaxDebug = {

	showResponseText : false,

	debugWindowId : "wicketAjaxDebugWindow",

	debugWindowDragHandleId : "wicketAjaxDebugWindowHandle",

	debugWindowLogId : "wicketAjaxDebugWindowLogId",

	getDebugWindow : function()
	{
	    wicketGet(WicketAjaxDebug.debugWindowId);
	},

	showDebugWindow : function() {
	    wicketShow(WicketAjaxDebug.debugWindowId);
	},

	hideDebugWindow : function() {
	    wicketHide(WicketAjaxDebug.debugWindowId);
	},

    log : function(msg, prefix) {
        var d = wicketGet(WicketAjaxDebug.debugWindowLogId);
        var c = document.createElement("div");
        msg = msg.replace(/</g, "<");
        msg = msg.replace(/>/g, ">");
        msg = msg.replace(/\n/g, "
");
        msg = msg.replace(/ /g, " ");
        msg = msg.replace(/\t/g, "    ");
        if (prefix != null)
        	msg = "" + prefix + " " + msg;
        c.innerHTML = msg;
        c.setAttribute("style","font-size: 82%; margin: 0px; padding:0px");
        d.appendChild(c);
        d.scrollTop = d.scrollHeight;
    },

    logError : function(msg) {
        WicketAjaxDebug.log(msg, "ERROR: ");
    },

    logInfo : function(msg) {
        WicketAjaxDebug.log(msg, "INFO: ");
    },

    clearLog : function() {
        var d = wicketGet(WicketAjaxDebug.debugWindowLogId);
		d.innerHTML = "";
    },

	init : function() {

        if ( wicketAjaxDebugEnabled()) {
        	var wad=WicketAjaxDebug;
        	var dwid=wad.debugWindowId;
        	var dwdhid=wad.debugWindowDragHandleId;

			var firstTime = document.getElementById(dwid) == null;

			if (firstTime)
	            document.write(
					"
"+
					"
"+
					"
"+
					"
"+
					"				clear | "+
					"				close"+
					"
"+
					"
"+
					"				Wicket Ajax Debug Window (drag me here)"+
					"
"+
					"
"+
					"
"+
					"
"+
					"
" +
					"
"
	            );
            WicketDrag.init(wicketGet(dwdhid), wicketGet(dwid));

			if (firstTime)
	            document.write(

	             "
"
	            +"    WICKET AJAX DEBUG"
	            +"
");
        }
	}

};

WicketAjaxDebug.init();

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Function.RegisterNamespace("Test.Aura.Library");

[Fixture]
Test.Aura.Library.LibraryIncludeRegistryTest = function () {

    Function.RegisterNamespace("Aura.Library");
    [Import("aura-impl/src/main/resources/aura/library/LibraryIncludeRegistry.js")]
    delete LibraryIncludeRegistry;

    var mockFramework = Mocks.GetMocks(Object.Global(), {
        "$A": {
            "assert": function(condition, message){ if (!condition) { throw new message }},
            "util": {
                "isString": function(obj){ return typeof obj === 'string' },
                "isFunction": function(obj){ return typeof obj === 'function' },
                "isObject": function(obj){ return typeof obj === 'object' },
                "isEmpty": function(obj){ return Object.keys(obj).length === {} },
                "globalEval": function(src){
                    var tmp = eval("(function () {" + src + "}())");
                    return tmp;
                }

            },
            clientService: {
                getSourceMapsUrl: function () {return;}
            }
        }
    });

    [Fixture]
    function GetLibraryInclude() {

        [Fact]
        function LibraryIncludeSimple() {
            // Arrange
            var expected = "cat";
            var actual;

            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:name", [], function() { return {name: "cat"}; });
                var object = target.getLibraryInclude("test:name");
                actual = object.name;
            });

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        function LibraryIncludeTwoDependencies() {
            // Arrange
            var expected = "john doe";
            var actual;

            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:name", ["test:first", "test:last"], function(first, last) {
                    return {name: first.name + " " + last.name};
                });
                target.addLibraryInclude("test:first", [], function() { return {name: "john"}; });
                target.addLibraryInclude("test:last", [], function() { return {name: "doe"}; });
                var object = target.getLibraryInclude("test:name");
                actual = object.name;
            });

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        function LibraryExporterWithErrorNotCauseValidLibraryFail() {
            var actual;
            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:one", [], function() { throw Error("error from exporter") });
                target.addLibraryInclude("test:two", [], function() { return "executes"; });

                try {
                    target.getLibraryInclude("test:one");
                    Assert.Fail("Expecting an error.");
                } catch(e) {}
                // the error is unexpectedly thrown if the invalid library is still in queue.
                actual = target.getLibraryInclude("test:two");
            });

            // Assert
            Assert.True(actual === "executes");
        }
    }
}
<commit_msg>fixing unit tests mock<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Function.RegisterNamespace("Test.Aura.Library");

[Fixture]
Test.Aura.Library.LibraryIncludeRegistryTest = function () {

    Function.RegisterNamespace("Aura.Library");
    [Import("aura-impl/src/main/resources/aura/library/LibraryIncludeRegistry.js")]
    delete LibraryIncludeRegistry;

    var mockFramework = Mocks.GetMocks(Object.Global(), {
        "$A": {
            "assert": function(condition, message){ if (!condition) { throw new message }},
            "util": {
                "isString": function(obj){ return typeof obj === 'string' },
                "isFunction": function(obj){ return typeof obj === 'function' },
                "isObject": function(obj){ return typeof obj === 'object' },
                "isEmpty": function(obj){ return Object.keys(obj).length === {} },
                "globalEval": function(src){
                    var returnableEx = /^(\s*)([{(["']|function\s*\()/;
                    var match = src.match(returnableEx);
                    if (match) src = src.replace(match[1], 'return ');
                    eval ("function x() {" + src + "}");
                    return x();
                }

            },
            clientService: {
                getSourceMapsUrl: function () {return;}
            }
        }
    });

    [Fixture]
    function GetLibraryInclude() {

        [Fact]
        function LibraryIncludeSimple() {
            // Arrange
            var expected = "cat";
            var actual;

            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:name", [], function lib() { return {name: "cat"}; });
                var object = target.getLibraryInclude("test:name");
                actual = object.name;
            });

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        function LibraryIncludeTwoDependencies() {
            // Arrange
            var expected = "john doe";
            var actual;

            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:name", ["test:first", "test:last"], function(first, last) {
                    return {name: first.name + " " + last.name};
                });
                target.addLibraryInclude("test:first", [], function lib() { return {name: "john"}; });
                target.addLibraryInclude("test:last", [], function lib() { return {name: "doe"}; });
                var object = target.getLibraryInclude("test:name");
                actual = object.name;
            });

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        function LibraryExporterWithErrorNotCauseValidLibraryFail() {
            var actual;
            // Act
            mockFramework(function(){
                var target = new Aura.Library.LibraryIncludeRegistry();
                target.addLibraryInclude("test:one", [], function() { throw Error("error from exporter") });
                target.addLibraryInclude("test:two", [], function() { return "executes"; });

                try {
                    target.getLibraryInclude("test:one");
                    Assert.Fail("Expecting an error.");
                } catch(e) {}
                // the error is unexpectedly thrown if the invalid library is still in queue.
                actual = target.getLibraryInclude("test:two");
            });

            // Assert
            Assert.True(actual === "executes");
        }
    }
}
<|endoftext|>


<commit_before>'use strict';

const db = require('@arangodb').db;
const createRouter = require('@arangodb/foxx/router');

const router = createRouter();

const GREETINGS_COLLECTION_NAME = 'greetings';

const greets = db._collection(GREETINGS_COLLECTION_NAME);
const MAX_GREETINGS = greets.count();

router.get('/greet', function (req, res) {
  // generate a random integer between 1 and the max number of greetings
  const key = Math.floor(Math.random()*MAX_GREETINGS) + 1;
  console.info("Generated random number: ", key);
  const data = greets.document(key.toString());
  console.info(data);
  res.send(JSON.stringify(data));
})
.response(['text/json'], 'A random greeting.')
.summary('Random greeting')
.description('Returns a random greeting.');

module.context.use(router);
<commit_msg>Changed response content type to application/json<commit_after>'use strict';

const db = require('@arangodb').db;
const createRouter = require('@arangodb/foxx/router');

const router = createRouter();

const GREETINGS_COLLECTION_NAME = 'greetings';

const greets = db._collection(GREETINGS_COLLECTION_NAME);
const MAX_GREETINGS = greets.count();

router.get('/greet', function (req, res) {
  // generate a random integer between 1 and the max number of greetings
  const key = Math.floor(Math.random()*MAX_GREETINGS) + 1;
  console.info("Generated random number: ", key);
  const data = greets.document(key.toString());
  console.info(data);
  res.setHeader('Content-Type', 'application/json');
  res.send(JSON.stringify(data));
})
.response(['application/json'], 'A random greeting.')
.summary('Random greeting')
.description('Returns a random greeting.');

module.context.use(router);
<|endoftext|>


<commit_before>'use strict';
/*global FB:false, console:false, $:false */

angular.module('fbCal').factory('fbEvents', function ($log, $q) {
  var getUserEventDetails = function() {
    var deferred = $q.defer();
    FB.api('/me', function(response) {
      if (response && !response.error) {
        console.log(response);
        getAllEvents(deferred, response.id);
      } else {
        deferred.reject();
      }
    });
    return deferred.promise;
  };

  var commentIdRegex = /\/([0-9_]+)\/comments/;
  var afterRegex = /after=([0-9a-zA-Z=]+)/;
  var untilRegex = /until=([0-9a-zA-Z]+)/;

  var getAllEvents = function(deferred, userId) {
    var curTime = Math.round(new Date().getTime() / 1000);
    var secondsInThreeMonths = 60 * 60 * 24 * 90;
    var threeMonthsAgo = (curTime - secondsInThreeMonths).toString();
    var finalEvents = [];
    getEventsData(threeMonthsAgo, userId, deferred, finalEvents, '');
  };

  var getEventsData = function(seconds, userId, deferred, finalEvents, pagingData) {
    FB.api('/me/events/created?since=' + seconds + pagingData, function(response) {
      if (response && !response.error) {
        finalEvents = $.merge(finalEvents, response.data);
        if (response.paging) {
          if (response.paging.cursors) {
            if (response.paging.cursors.after) {
              pagingData = '&after=' + response.paging.cursors.after;
              getEventsData(seconds, userId, deferred, finalEvents, pagingData);
            } else {
              deferred.resolve({data: finalEvents, userId: userId});
            }
          } else {
            var next = response.paging.next;
            var afterPattern = next.match(afterRegex);
            if (afterPattern) {
              pagingData = '&' + afterPattern[0];
              getEventsData(seconds, userId, deferred, finalEvents, pagingData);
            } else {
              var untilPattern = next.match(untilRegex);
              if (untilPattern) {
                pagingData = '&' + untilPattern[0];
                getEventsData(seconds, userId, deferred, finalEvents, pagingData);

              } else {
                console.error('Regex is not working');
                deferred.reject();
              }
            }
          }
        } else {
          deferred.resolve({data: finalEvents, userId: userId});
        }
      } else {
        deferred.reject();
      }
    });
  };
//look for after and until
  var parseUrl = function(url, gettingFeed) {
    var commentId;
    var afterPattern = url.match(afterRegex);
    if (afterPattern) {
      if (gettingFeed) {
        return {after : afterPattern[1]};
      } else {
        commentId = parseCommentId(url);
        return {id : commentId, after : afterPattern[1]};
      }
    } else {
      var untilPattern = url.match(untilRegex);
      if (untilPattern) {
        if (gettingFeed) {
          return {until : untilPattern[1]};
        } else {
          commentId = parseCommentId(url);
          return {id : commentId, until : untilPattern[1]};
        }
      } else {
        console.error('Could not parse Url');
      }
    }
  };

  var parseCommentId = function(url) {
    var commentIdPattern = url.match(commentIdRegex);
    if (commentIdPattern) {
      return commentIdPattern[1];
    } else {
      console.error('Could not parse Url');
    }
  };

  var getRsvpStatus = function(eventId) {
    var deferred = $q.defer();
    FB.api('/fql',
          {
            'q' : 'SELECT rsvp_status FROM event_member WHERE eid = ' + eventId + ' AND uid=me()'
          },
          function(response) {
            if (response && !response.error) {
              var rsvp_status = response.data[0].rsvp_status;
              if (rsvp_status === 'attending') {
                deferred.resolve('Going');
              } else if (rsvp_status === 'maybe') {
                deferred.resolve('Maybe');
              } else if (rsvp_status === 'declined') {
                deferred.resolve('Declined');
              } else {
                deferred.resolve('RSVP');
              }
            } else {
              deferred.reject();
            }
          });
    return deferred.promise;
  };

  var shareEvent = function(eventId) {
    console.log('running');
    FB.ui({
           method: 'share',
           href: 'https://www.facebook.com/events/' + eventId,
          }, function() {});
  };

  var rsvp = ['attending', 'maybe', 'declined'];

  var processInteraction = function(action, id, message) {
    console.log('performing ' + action);
    var deferred = $q.defer();
    if (rsvp.indexOf(action) >= 0) {
      changeAttendingStatus(action, id, deferred);
    } else if (action === 'post') {
      post(id, deferred, message, true);
    } else if (action === 'like' || action === 'likeComment') {
      like(id, deferred, true);
    } else if (action === 'unlike' || action === 'unlikeComment') {
      like(id, deferred, false);
    } else if (action === 'comment') {
      post(id, deferred, message, false);
    } else {
      deletePost(id, deferred);
    }
    return deferred.promise;
  };

  var post = function(id, deferred, message, post) {
    var link;
    console.log(message);
    if (post) {
      link = '/feed';
    } else {
      link = '/comments';
    }
    FB.api('/' + id + link,
           'POST',
           {
              'message': message
           },
           function(response) {
             if (response && !response.error) {
               FB.api("/" + response.id,
                      function(response) {
                        if (response && !response.error) {
                          deferred.resolve(response);
                        } else {
                          console.log(response.error);
                          deferred.reject();
                        }
                      });
             } else {
              console.log(response.error);
               deferred.reject();
             }
           });
  };

  var deletePost = function(id, deferred) {
    FB.api('/' + id,
           'DELETE',
           function (response) {
            if (response && !response.error) {
              deferred.resolve(true);
            } else {
              deferred.reject();
            }
          });
  };

  var like = function(id, deferred, like) {
    console.log(id);
    var method;
    if (like) {
      method = 'POST';
    } else {
      method = 'DELETE';
    }
    FB.api('/' + id + '/likes',
           method,
           function (response) {
             if (response && !response.error) {
               deferred.resolve(true);
             } else {
               console.log(response.error);
               deferred.reject();
             }
           });

  };

  var changeAttendingStatus = function(action, id, deferred) {
    FB.api('/' + id + '/' + action,
           'POST',
           function(response) {
             if (response && !response.error) {
               deferred.resolve(true);
             } else {
               console.log(response.error);
               deferred.reject();
             }
           });
  };

  return {
    shareEvent: shareEvent,
    getUserEventDetails: getUserEventDetails,
    processInteraction: processInteraction,
    getRsvpStatus: getRsvpStatus,
    parseUrl: parseUrl
  };
});<commit_msg>Fixed a bug where a Facebook error on checking for RSVP status could result in undefined things happening to the RSVP status displayed to the visitor in the modal<commit_after>'use strict';
/*global FB:false, $:false */

/**
 * This factory handles all dealings with Facebook events on the client side.
 *
 * Facebook Terminology:
 * A post is a status on a feed on an event on Facebook.
 * A comment is a comment to a status on Facebook.
 *
 * @author Jeffrey Chan
 */

angular.module('fbCal').factory('fbEvents', function ($log, $q) {

  /**
   * Gets the user ID of the user and then if successful get the event data.
   * This function is called by the settings panel if getting the user's access
   * token on settings load was successful. Now, it attempts to get the event
   * data with the access token to save this work from being done by the server.
   * If it fails or gets the data for the wrong user, the server is called
   * to get the data.
   *
   * @return {Object} A promise to return the user ID and the event data
   */
  var getUserEventDetails = function() {
    var deferred = $q.defer();
    FB.api('/me', function(response) {
      if (response && !response.error) {
        getAllEvents(deferred, response.id);
      } else {
        deferred.reject();
      }
    });
    return deferred.promise;
  };

  var commentIdRegex = /\/([0-9_]+)\/comments/;
  var afterRegex = /after=([0-9a-zA-Z=]+)/;
  var untilRegex = /until=([0-9a-zA-Z]+)/;

/**
 * Sets up the time parameter needed to get all user events and then calls the
 * functions to get all events with the time parameter. The time parameter tells
 * the event getter function how far back to look for events. Right now, we are
 * searching for all events created by the user starting from 3 months ago to
 * anytime in the future. This number can be increased or decreased depending
 * on the developer's preference and best judgement.
 *
 * @param  {Object} deferred A promise object
 * @param  {String} userId   The ID of the user. It is passed along from the
 *                           function calling it and will be returned through
 *                           the promise to the original function in the
 *                           settings controller that is getting the event data.
 *                           The ID is not used in this function.
 */
  var getAllEvents = function(deferred, userId) {
    var curTime = Math.round(new Date().getTime() / 1000);
    var secondsInThreeMonths = 60 * 60 * 24 * 90;
    var threeMonthsAgo = (curTime - secondsInThreeMonths).toString();
    var finalEvents = [];
    getEventsData(threeMonthsAgo, userId, deferred, finalEvents, '');
  };

  /**
   * Gets event data for the user and fulfills the promise if successful.
   *
   * Because Facebook does not return all the user's events in one API call
   * (limited to 25 max per call), we have to use the paging data returned by
   * the first call to make the next few calls. Thus, this function is
   * recursive and keeps running until Facebook does not return any paging data
   * signifying that we have reached the end. It continually fills the
   * finalEvents array with the data it gets from each page. When done, it sends
   * the finalEvents array through the promise.
   *
   * @param  {Number} seconds     The amount of seconds to go back in time when
   *                              looking for user events.
   * @param  {String} userId      The ID of the user we are getting events for.
   *                              It is not used here, only passed back in the
   *                              successful promise response.
   * @param  {Object} deferred    The Promise Object
   * @param  {Array} finalEvents
   * @param  {String} pagingData  Data needed by the Facebook SDK telling it
   *                              which page of event data to retrieve
   */
  var getEventsData = function(seconds, userId, deferred, finalEvents, pagingData) {
    FB.api('/me/events/created?since=' + seconds + pagingData, function(response) {
      if (response && !response.error) {
        finalEvents = $.merge(finalEvents, response.data);
        if (response.paging) {
          if (response.paging.cursors) {
            if (response.paging.cursors.after) {
              pagingData = '&after=' + response.paging.cursors.after;
              getEventsData(seconds, userId, deferred, finalEvents, pagingData);
            } else {
              deferred.resolve({data: finalEvents, userId: userId});
            }
          } else {
            var next = response.paging.next;
            var afterPattern = next.match(afterRegex);
            if (afterPattern) {
              pagingData = '&' + afterPattern[0];
              getEventsData(seconds, userId, deferred, finalEvents, pagingData);
            } else {
              var untilPattern = next.match(untilRegex);
              if (untilPattern) {
                pagingData = '&' + untilPattern[0];
                getEventsData(seconds, userId, deferred, finalEvents, pagingData);

              } else {
                $log.error('Regex is not working');
                deferred.reject();
              }
            }
          }
        } else {
          deferred.resolve({data: finalEvents, userId: userId});
        }
      } else {
        deferred.reject();
      }
    });
  };

  /**
   * Parses the given Facebook URL looking for the paging data.
   *
   * The paging data will eventually be sent to be used by the server.
   * This function will be used by the modal and because it is open to the
   * visitor, all work getting event data is done on the server
   * (exception: visitor interactions with event (e.g. posting, liking)).
   *
   * @param  {String} url         The Facebook URL to parse
   * @param  {String} gettingFeed Whether or not we are getting more statuses.
   *                              If not, we are getting comments and thus
   *                              must also parse the comment ID from the URL.
   *                              That work is done by calling another function.
   * @return {Object}             An object containing the data parsed from the
   *                              URL.
   */
  var parseUrl = function(url, gettingFeed) {
    var commentId;
    var afterPattern = url.match(afterRegex);
    if (afterPattern) {
      if (gettingFeed) {
        return {after : afterPattern[1]};
      } else {
        commentId = parseCommentId(url);
        if (commentId) {
          return {id : commentId, after : afterPattern[1]};
        }
      }
    } else {
      var untilPattern = url.match(untilRegex);
      if (untilPattern) {
        if (gettingFeed) {
          return {until : untilPattern[1]};
        } else {
          commentId = parseCommentId(url);
          if (commentId) {
            return {id : commentId, until : untilPattern[1]};
          }
        }
      } else {
        $log.error('Could not parse Url for Paging Data');
      }
    }
  };

  /**
   * Parses the URL for the comment ID. As hinted in the previous function
   * (parseURL), this comment ID is needed by the server to get more comments
   * for a status the site visitor is interested in.
   *
   * @param  {String} url The URL to parse
   * @return {String}     The parsed comment ID; if not available, the function
   *                      throws an error.
   */
  var parseCommentId = function(url) {
    var commentIdPattern = url.match(commentIdRegex);
    if (commentIdPattern) {
      return commentIdPattern[1];
    } else {
      $log.error('Could not parse Url for Comment ID');
    }
  };

  /**
   * Gets the RSVP status of the user.
   *
   * This function is called by the modal once the Facebook SDK is done
   * initializing and if we were able to succesfully get the visitor's
   * access token. Otherwise, the default status shown to the user is "RSVP".
   *
   * @param  {String} eventId The event we are getting the user's RSVP status
   *                          for
   * @return {Object}         Promise to return the user's RSVP status
   */
  var getRsvpStatus = function(eventId) {
    var deferred = $q.defer();
    FB.api('/fql',
          {
            'q' : 'SELECT rsvp_status FROM event_member WHERE eid = ' + eventId + ' AND uid=me()'
          },
          function(response) {
            if (response && !response.error) {
              var rsvp_status = response.data[0].rsvp_status;
              if (rsvp_status === 'attending') {
                deferred.resolve('Going');
              } else if (rsvp_status === 'maybe') {
                deferred.resolve('Maybe');
              } else if (rsvp_status === 'declined') {
                deferred.resolve('Declined');
              } else {
                deferred.resolve('RSVP');
              }
            } else {
              deferred.resolve('RSVP');
            }
          });
    return deferred.promise;
  };

  /**
   * This function is used to share the event on Facebook. It's called when
   * the user clicks to share the event via Facebook.
   *
   * @param  {String} eventId The event ID of the event to be shared
   */
  var shareEvent = function(eventId) {
    FB.ui({
           method: 'share',
           href: 'https://www.facebook.com/events/' + eventId,
          }, function() {});
  };

  var rsvp = ['attending', 'maybe', 'declined'];

  /**
   * Processes the passed in Facebook action that the site visitors wants to do
   * by calling the appropriate action function.
   *
   * @param  {String} action  The action the user wants to perform
   * @param  {String} id      The event ID of the event we are performing the
   *                          action on unless we are commenting. Then, it is
   *                          the id of the status we are commenting on.
   * @param  {String} message If posting/commenting, this is the message the
   *                          user wants to post/comment.
   * @return {Object}         Promise to return whether the Facebook action was
   *                          successful. For posts and comments, the
   *                          post/comment object is returned so that it can
   *                          shown in the modal.
   */
  var processInteraction = function(action, id, message) {
    var deferred = $q.defer();
    if (rsvp.indexOf(action) >= 0) {
      changeAttendingStatus(action, id, deferred);
    } else if (action === 'post') {
      post(id, deferred, message, true);
    } else if (action === 'like' || action === 'likeComment') {
      like(id, deferred, true);
    } else if (action === 'unlike' || action === 'unlikeComment') {
      like(id, deferred, false);
    } else if (action === 'comment') {
      post(id, deferred, message, false);
    } else {
      deletePost(id, deferred);
    }
    return deferred.promise;
  };

  /**
   * Posts to Facebook either a comment to a status or a post to the feed.
   *
   * @param  {String} id       If posting, this is the event ID of the event
   *                           whose feed we are posting to. If commenting, it
   *                           is the id of the status we are commenting on.
   * @param  {Object} deferred Promise Object - If sucessful, the promise is
   *                           fulfilled by getting the comment/post data from
   *                           Facebook and then returning that data.
   * @param  {String} message  The message to be posted/commented
   * @param  {Boolean} post    Whether or not we are posting. If not, we are
   *                           commenting
   */
  var post = function(id, deferred, message, post) {
    var link;
    if (post) {
      link = '/feed';
    } else {
      link = '/comments';
    }
    FB.api('/' + id + link,
           'POST',
           {
              'message': message
           },
           function(response) {
             if (response && !response.error) {
               FB.api("/" + response.id,
                      function(response) {
                        if (response && !response.error) {
                          deferred.resolve(response);
                        } else {
                          deferred.reject();
                        }
                      });
             } else {
               deferred.reject();
             }
           });
  };

  /**
   * This deletes the post/comment the visitor wants removed from Facebook.
   *
   * @param  {String} id       The ID of the post/comment to be deleted
   * @param  {Object} deferred The Promise Object - We return whether or not
   *                           the promise has been successfully fulfilled.
   */
  var deletePost = function(id, deferred) {
    FB.api('/' + id,
           'DELETE',
           function (response) {
            if (response && !response.error) {
              deferred.resolve(true);
            } else {
              deferred.reject();
            }
          });
  };

  /**
   * This function handles all liking/unliking of posts and comments.
   *
   * @param  {String} id       The ID of the object to be liked.
   * @param  {Object} deferred The Promise Object - We return whether or not the
   *                           promise has been successfully fulfulled.
   * @param  {Boolean} like    Whether or not we are liking. If not, we are
   *                           unliking.
   */
  var like = function(id, deferred, like) {
    var method;
    if (like) {
      method = 'POST';
    } else {
      method = 'DELETE';
    }
    FB.api('/' + id + '/likes',
           method,
           function (response) {
             if (response && !response.error) {
               deferred.resolve(true);
             } else {
               deferred.reject();
             }
           });

  };

  /**
   * This function handles all the changing of the visitor's RSVP status
   * to an event.
   *
   * @param  {String} action   The RSVP status the visitor wants to change to.
   * @param  {String} id       The event that the visitor is changing her RSVP
   *                           status to.
   * @param  {Object} deferred The Promise Object - We return whether or not the
   *                           promise has been successfully fulfilled.
   */
  var changeAttendingStatus = function(action, id, deferred) {
    FB.api('/' + id + '/' + action,
           'POST',
           function(response) {
             if (response && !response.error) {
               deferred.resolve(true);
             } else {
               deferred.reject();
             }
           });
  };

  return {
    shareEvent: shareEvent,
    getUserEventDetails: getUserEventDetails,
    processInteraction: processInteraction,
    getRsvpStatus: getRsvpStatus,
    parseUrl: parseUrl
  };
});<|endoftext|>