<commit_before>import {
  TIMELINE_REFRESH_REQUEST,
  TIMELINE_REFRESH_SUCCESS,
  TIMELINE_REFRESH_FAIL,
  TIMELINE_UPDATE,
  TIMELINE_DELETE,
  TIMELINE_EXPAND_SUCCESS,
  TIMELINE_EXPAND_REQUEST,
  TIMELINE_EXPAND_FAIL,
  TIMELINE_SCROLL_TOP,
  TIMELINE_CONNECT,
  TIMELINE_DISCONNECT,
} from '../actions/timelines';
import {
  ACCOUNT_BLOCK_SUCCESS,
  ACCOUNT_MUTE_SUCCESS,
  ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';

const initialState = ImmutableMap();

const initialTimeline = ImmutableMap({
  unread: 0,
  online: false,
  top: true,
  loaded: false,
  isLoading: false,
  next: false,
  items: ImmutableList(),
});

const normalizeTimeline = (state, timeline, statuses, next, isPartial) => {
  const oldIds    = state.getIn([timeline, 'items'], ImmutableList());
  const ids       = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
  const wasLoaded = state.getIn([timeline, 'loaded']);
  const hadNext   = state.getIn([timeline, 'next']);

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    mMap.set('loaded', true);
    mMap.set('isLoading', false);
    if (!hadNext) mMap.set('next', next);
    mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids);
    mMap.set('isPartial', isPartial);
  }));
};

const appendNormalizedTimeline = (state, timeline, statuses, next) => {
  const oldIds = state.getIn([timeline, 'items'], ImmutableList());
  const ids    = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    mMap.set('isLoading', false);
    mMap.set('next', next);
    mMap.set('items', oldIds.concat(ids));
  }));
};

const updateTimeline = (state, timeline, status) => {
  const top        = state.getIn([timeline, 'top']);
  const ids        = state.getIn([timeline, 'items'], ImmutableList());
  const includesId = ids.includes(status.get('id'));
  const unread     = state.getIn([timeline, 'unread'], 0);

  if (includesId) {
    return state;
  }

  let newIds = ids;

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    if (!top) mMap.set('unread', unread + 1);
    if (top && ids.size > 40) newIds = newIds.take(20);
    mMap.set('items', newIds.unshift(status.get('id')));
  }));
};

const deleteStatus = (state, id, accountId, references) => {
  state.keySeq().forEach(timeline => {
    state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id));
  });

  // Remove reblogs of deleted status
  references.forEach(ref => {
    state = deleteStatus(state, ref[0], ref[1], []);
  });

  return state;
};

const filterTimelines = (state, relationship, statuses) => {
  let references;

  statuses.forEach(status => {
    if (status.get('account') !== relationship.id) {
      return;
    }

    references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]);
    state      = deleteStatus(state, status.get('id'), status.get('account'), references);
  });

  return state;
};

const filterTimeline = (timeline, state, relationship, statuses) =>
  state.updateIn([timeline, 'items'], ImmutableList(), list =>
    list.filterNot(statusId =>
      statuses.getIn([statusId, 'account']) === relationship.id
    ));

const updateTop = (state, timeline, top) => {
  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    if (top) mMap.set('unread', 0);
    mMap.set('top', top);
  }));
};

export default function timelines(state = initialState, action) {
  switch(action.type) {
  case TIMELINE_REFRESH_REQUEST:
  case TIMELINE_EXPAND_REQUEST:
    return state.update(action.timeline, initialTimeline, map => map.set('isLoading', true));
  case TIMELINE_REFRESH_FAIL:
  case TIMELINE_EXPAND_FAIL:
    return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
  case TIMELINE_REFRESH_SUCCESS:
    return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial);
  case TIMELINE_EXPAND_SUCCESS:
    return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next);
  case TIMELINE_UPDATE:
    return updateTimeline(state, action.timeline, fromJS(action.status));
  case TIMELINE_DELETE:
    return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf);
  case ACCOUNT_BLOCK_SUCCESS:
  case ACCOUNT_MUTE_SUCCESS:
    return filterTimelines(state, action.relationship, action.statuses);
  case ACCOUNT_UNFOLLOW_SUCCESS:
    return filterTimeline('home', state, action.relationship, action.statuses);
  case TIMELINE_SCROLL_TOP:
    return updateTop(state, action.timeline, action.top);
  case TIMELINE_CONNECT:
    return state.update(action.timeline, initialTimeline, map => map.set('online', true));
  case TIMELINE_DISCONNECT:
    return state.update(action.timeline, initialTimeline, map => map.set('online', false));
  default:
    return state;
  }
};
<commit_msg>Do not throw away statuses obtained via websocket when API request finishes (#6302)<commit_after>import {
  TIMELINE_REFRESH_REQUEST,
  TIMELINE_REFRESH_SUCCESS,
  TIMELINE_REFRESH_FAIL,
  TIMELINE_UPDATE,
  TIMELINE_DELETE,
  TIMELINE_EXPAND_SUCCESS,
  TIMELINE_EXPAND_REQUEST,
  TIMELINE_EXPAND_FAIL,
  TIMELINE_SCROLL_TOP,
  TIMELINE_CONNECT,
  TIMELINE_DISCONNECT,
} from '../actions/timelines';
import {
  ACCOUNT_BLOCK_SUCCESS,
  ACCOUNT_MUTE_SUCCESS,
  ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';

const initialState = ImmutableMap();

const initialTimeline = ImmutableMap({
  unread: 0,
  online: false,
  top: true,
  loaded: false,
  isLoading: false,
  next: false,
  items: ImmutableList(),
});

const normalizeTimeline = (state, timeline, statuses, next, isPartial) => {
  const oldIds    = state.getIn([timeline, 'items'], ImmutableList());
  const ids       = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
  const wasLoaded = state.getIn([timeline, 'loaded']);
  const hadNext   = state.getIn([timeline, 'next']);

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    mMap.set('loaded', true);
    mMap.set('isLoading', false);
    if (!hadNext) mMap.set('next', next);
    mMap.set('items', wasLoaded ? ids.concat(oldIds) : oldIds.concat(ids));
    mMap.set('isPartial', isPartial);
  }));
};

const appendNormalizedTimeline = (state, timeline, statuses, next) => {
  const oldIds = state.getIn([timeline, 'items'], ImmutableList());
  const ids    = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    mMap.set('isLoading', false);
    mMap.set('next', next);
    mMap.set('items', oldIds.concat(ids));
  }));
};

const updateTimeline = (state, timeline, status) => {
  const top        = state.getIn([timeline, 'top']);
  const ids        = state.getIn([timeline, 'items'], ImmutableList());
  const includesId = ids.includes(status.get('id'));
  const unread     = state.getIn([timeline, 'unread'], 0);

  if (includesId) {
    return state;
  }

  let newIds = ids;

  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    if (!top) mMap.set('unread', unread + 1);
    if (top && ids.size > 40) newIds = newIds.take(20);
    mMap.set('items', newIds.unshift(status.get('id')));
  }));
};

const deleteStatus = (state, id, accountId, references) => {
  state.keySeq().forEach(timeline => {
    state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id));
  });

  // Remove reblogs of deleted status
  references.forEach(ref => {
    state = deleteStatus(state, ref[0], ref[1], []);
  });

  return state;
};

const filterTimelines = (state, relationship, statuses) => {
  let references;

  statuses.forEach(status => {
    if (status.get('account') !== relationship.id) {
      return;
    }

    references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]);
    state      = deleteStatus(state, status.get('id'), status.get('account'), references);
  });

  return state;
};

const filterTimeline = (timeline, state, relationship, statuses) =>
  state.updateIn([timeline, 'items'], ImmutableList(), list =>
    list.filterNot(statusId =>
      statuses.getIn([statusId, 'account']) === relationship.id
    ));

const updateTop = (state, timeline, top) => {
  return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
    if (top) mMap.set('unread', 0);
    mMap.set('top', top);
  }));
};

export default function timelines(state = initialState, action) {
  switch(action.type) {
  case TIMELINE_REFRESH_REQUEST:
  case TIMELINE_EXPAND_REQUEST:
    return state.update(action.timeline, initialTimeline, map => map.set('isLoading', true));
  case TIMELINE_REFRESH_FAIL:
  case TIMELINE_EXPAND_FAIL:
    return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
  case TIMELINE_REFRESH_SUCCESS:
    return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial);
  case TIMELINE_EXPAND_SUCCESS:
    return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next);
  case TIMELINE_UPDATE:
    return updateTimeline(state, action.timeline, fromJS(action.status));
  case TIMELINE_DELETE:
    return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf);
  case ACCOUNT_BLOCK_SUCCESS:
  case ACCOUNT_MUTE_SUCCESS:
    return filterTimelines(state, action.relationship, action.statuses);
  case ACCOUNT_UNFOLLOW_SUCCESS:
    return filterTimeline('home', state, action.relationship, action.statuses);
  case TIMELINE_SCROLL_TOP:
    return updateTop(state, action.timeline, action.top);
  case TIMELINE_CONNECT:
    return state.update(action.timeline, initialTimeline, map => map.set('online', true));
  case TIMELINE_DISCONNECT:
    return state.update(action.timeline, initialTimeline, map => map.set('online', false));
  default:
    return state;
  }
};
<|endoftext|>


<commit_before>define(function(require, exports, module){

    module.exports = function() {
        return [
            {
                val: '1st_dish',
                name: 'первые блюда'
            },
            {
                val: '2st_dish',
                name: 'вторые блюда'
            },
            {
                val: 'side_dish',
                name: 'гарниры'
            },
            {
                val: 'snack',
                name: 'закуски'
            },
            {
                val: 'salad',
                name: 'салаты'
            },
            {
                val: 'desserts',
                name: 'десерты'
            },
            {
                val: 'sauces',
                name: 'соусы'
            },
            {
                val: 'meatless meals',
                name: 'постные блюда'
            },
            {
                val: 'bread',
                name: 'хлеб'
            }
        ]
    }

});<commit_msg>Fix for category filter<commit_after>define(function(require, exports, module){

    module.exports = function() {
        return [
            {
                val: '1st_dish',
                name: 'первые блюда'
            },
            {
                val: '2st_dish',
                name: 'вторые блюда'
            },
            {
                val: 'side_dish',
                name: 'гарниры'
            },
            {
                val: 'snack',
                name: 'закуски'
            },
            {
                val: 'salad',
                name: 'салаты'
            },
            {
                val: 'desserts',
                name: 'десерты'
            },
            {
                val: 'sauces',
                name: 'соусы'
            },
            {
                val: 'meatless meals',
                name: 'постные блюда'
            },
            {
                val: 'bread',
                name: 'хлеб'
            },
            {
                val: 'complex',
                name: 'комплекс'
            },
        ]
    }

});<|endoftext|>


<commit_before>'use strict';

angular.module('confRegistrationWebApp')
  .controller('ReviewRegistrationCtrl', function ($scope, $rootScope, $location, $route, $modal, $http, registration, conference, RegistrationCache, validateRegistrant) {
    $rootScope.globalPage = {
      type: 'registration',
      mainClass: 'front-form',
      bodyClass: 'frontend',
      title: conference.name,
      confId: conference.id,
      footer: false
    };

    if(registration.registrants.length === 0) {
      $location.path('/' + ($rootScope.registerMode || 'register') + '/' + conference.id + '/page/');
    }

    $scope.conference = conference;
    $scope.currentRegistration = registration;
    $scope.blocks = [];
    $scope.regValidate = [];

    if (angular.isDefined($rootScope.currentPayment)) {
      $rootScope.currentPayment.amount = registration.calculatedTotalDue;
    } else {
      $rootScope.currentPayment = {
        amount: 0
      };
    }

    angular.forEach(_.flatten(conference.registrationPages, 'blocks'), function (block) {
      if (block.type.indexOf('Content') === -1) {
        $scope.blocks.push(block);
      }
    });

    angular.forEach(registration.registrants, function (r) {
      $scope.regValidate[r.id] = validateRegistrant.validate(conference, r);
    });

    $scope.findAnswer = function (blockId) {
      return _.find($scope.answers, {blockId: blockId});
    };

    $scope.confirmRegistration = function () {
      jQuery('.confirm-registration').attr('value', 'Loading...');
      if ($rootScope.currentPayment.amount === 0 || 7 === 7) {
        setRegistrationAsCompleted();
        return;
      }

      var currentPayment = angular.copy($rootScope.currentPayment);
      currentPayment.readyToProcess = true;
      currentPayment.registrationId =  registration.id;

      $http.post('payments/', currentPayment).success(function () {
        setRegistrationAsCompleted();
        delete $rootScope.currentPayment;
      }).error(function () {
          var errorModalOptions = {
            templateUrl: 'views/modals/errorModal.html',
            controller: 'genericModal',
            backdrop: 'static',
            keyboard: false,
            resolve: {
              data: function () {
                return 'Your card was declined, please verify and re-enter your details or use a different card.';
              }
            }
          };
          $modal.open(errorModalOptions).result.then(function () {
            $location.path('/payment/' + conference.id);
          });
        });
    };

    var setRegistrationAsCompleted = function() {
      window.scrollTo(0, 0);
      registration.completed = true;

      RegistrationCache.update('registrations/' + registration.id, registration, function () {
        $scope.currentRegistration.completed = true;
        RegistrationCache.emptyCache();
      }, function () {
        $scope.currentRegistration.completed = false;
        alert('An error occurred while submitting your registration.');
      });
    };

    $scope.editRegistrant = function (id) {
      $location.path('/' + ($rootScope.registerMode || 'register') + '/' + conference.id + '/page/' + conference.registrationPages[0].id).search('reg', id);
    };

    $scope.removeRegistrant = function (id) {
      _.remove($scope.currentRegistration.registrants, function(r) { return r.id === id; });
      RegistrationCache.update('registrations/' + $scope.currentRegistration.id, $scope.currentRegistration, function() {
        RegistrationCache.emptyCache();
        $route.reload();
      });
    };

    $scope.editPayment = function () {
      $location.path('/payment/' + conference.id);
    };

    $scope.getRegistrantType = function(id){
      return _.find(conference.registrantTypes, { 'id': id });
    };

    $scope.isBlockInvalid = function(rId, bId){
      return _.contains($scope.regValidate[rId], bId);
    };

    $scope.allRegistrantsValid = function(){
      var returnVal = true;
      angular.forEach(registration.registrants, function (r) {
        if (angular.isUndefined($scope.regValidate[r.id])) {
          returnVal = false;
        }else{
          if($scope.regValidate[r.id].length){
            returnVal = false;
          }
        }
      });
      return returnVal;
    };

    $scope.registrantName = function(r) {
      var nameBlock = _.find(_.flatten(conference.registrationPages, 'blocks'), { 'profileType': 'NAME' }).id;
      var registrant = _.find(registration.registrants, { 'id': r.id });
      var returnStr;
      nameBlock = _.find(registrant.answers, { 'blockId': nameBlock });

      if(angular.isDefined((nameBlock))){
        nameBlock = nameBlock.value;
        if(angular.isDefined((nameBlock.firstName))){
          returnStr = nameBlock.firstName + ' ' + (nameBlock.lastName || '');
        }
      }

      return returnStr || _.find(conference.registrantTypes, { 'id': r.registrantTypeId }).name;
    };

    $scope.blockInRegType = function(block, regTypeId){
      return !_.contains(block.registrantTypes, regTypeId);
    };
  });
<commit_msg>fix issue with payment data not actually being POSTed<commit_after>'use strict';

angular.module('confRegistrationWebApp')
  .controller('ReviewRegistrationCtrl', function ($scope, $rootScope, $location, $route, $modal, $http, registration, conference, RegistrationCache, validateRegistrant) {
    $rootScope.globalPage = {
      type: 'registration',
      mainClass: 'front-form',
      bodyClass: 'frontend',
      title: conference.name,
      confId: conference.id,
      footer: false
    };

    if(registration.registrants.length === 0) {
      $location.path('/' + ($rootScope.registerMode || 'register') + '/' + conference.id + '/page/');
    }

    $scope.conference = conference;
    $scope.currentRegistration = registration;
    $scope.blocks = [];
    $scope.regValidate = [];

    if (angular.isDefined($rootScope.currentPayment)) {
      $rootScope.currentPayment.amount = registration.calculatedTotalDue;
    } else {
      $rootScope.currentPayment = {
        amount: 0
      };
    }

    angular.forEach(_.flatten(conference.registrationPages, 'blocks'), function (block) {
      if (block.type.indexOf('Content') === -1) {
        $scope.blocks.push(block);
      }
    });

    angular.forEach(registration.registrants, function (r) {
      $scope.regValidate[r.id] = validateRegistrant.validate(conference, r);
    });

    $scope.findAnswer = function (blockId) {
      return _.find($scope.answers, {blockId: blockId});
    };

    $scope.confirmRegistration = function () {
      jQuery('.confirm-registration').attr('value', 'Loading...');
      if ($rootScope.currentPayment.amount === 0) {
        setRegistrationAsCompleted();
        return;
      }

      var currentPayment = angular.copy($rootScope.currentPayment);
      currentPayment.readyToProcess = true;
      currentPayment.registrationId =  registration.id;

      $http.post('payments/', currentPayment).success(function () {
        setRegistrationAsCompleted();
        delete $rootScope.currentPayment;
      }).error(function () {
          var errorModalOptions = {
            templateUrl: 'views/modals/errorModal.html',
            controller: 'genericModal',
            backdrop: 'static',
            keyboard: false,
            resolve: {
              data: function () {
                return 'Your card was declined, please verify and re-enter your details or use a different card.';
              }
            }
          };
          $modal.open(errorModalOptions).result.then(function () {
            $location.path('/payment/' + conference.id);
          });
        });
    };

    var setRegistrationAsCompleted = function() {
      window.scrollTo(0, 0);
      registration.completed = true;

      RegistrationCache.update('registrations/' + registration.id, registration, function () {
        $scope.currentRegistration.completed = true;
        RegistrationCache.emptyCache();
      }, function () {
        $scope.currentRegistration.completed = false;
        alert('An error occurred while submitting your registration.');
      });
    };

    $scope.editRegistrant = function (id) {
      $location.path('/' + ($rootScope.registerMode || 'register') + '/' + conference.id + '/page/' + conference.registrationPages[0].id).search('reg', id);
    };

    $scope.removeRegistrant = function (id) {
      _.remove($scope.currentRegistration.registrants, function(r) { return r.id === id; });
      RegistrationCache.update('registrations/' + $scope.currentRegistration.id, $scope.currentRegistration, function() {
        RegistrationCache.emptyCache();
        $route.reload();
      });
    };

    $scope.editPayment = function () {
      $location.path('/payment/' + conference.id);
    };

    $scope.getRegistrantType = function(id){
      return _.find(conference.registrantTypes, { 'id': id });
    };

    $scope.isBlockInvalid = function(rId, bId){
      return _.contains($scope.regValidate[rId], bId);
    };

    $scope.allRegistrantsValid = function(){
      var returnVal = true;
      angular.forEach(registration.registrants, function (r) {
        if (angular.isUndefined($scope.regValidate[r.id])) {
          returnVal = false;
        }else{
          if($scope.regValidate[r.id].length){
            returnVal = false;
          }
        }
      });
      return returnVal;
    };

    $scope.registrantName = function(r) {
      var nameBlock = _.find(_.flatten(conference.registrationPages, 'blocks'), { 'profileType': 'NAME' }).id;
      var registrant = _.find(registration.registrants, { 'id': r.id });
      var returnStr;
      nameBlock = _.find(registrant.answers, { 'blockId': nameBlock });

      if(angular.isDefined((nameBlock))){
        nameBlock = nameBlock.value;
        if(angular.isDefined((nameBlock.firstName))){
          returnStr = nameBlock.firstName + ' ' + (nameBlock.lastName || '');
        }
      }

      return returnStr || _.find(conference.registrantTypes, { 'id': r.registrantTypeId }).name;
    };

    $scope.blockInRegType = function(block, regTypeId){
      return !_.contains(block.registrantTypes, regTypeId);
    };
  });
<|endoftext|>


<commit_before>/**
 * Created by thomashourlier on 12/01/15.
 */

angular.module('madbid.directive')
  .directive('bidderInfo', function(){
    return {
      restrict: 'E',
      require: '^ngModel',
      scope: {
        ngModel: '=',
        ngItemsModel: '=',
        bidderName: '=',
        auctionId: '='
      },
      template: '
{{ngModel[bidderName]}}
',
      controller: function(){

      },
      link: function($scope, $element, attrs){
          var container,
            i,
            j,
            ii,
            oldAuctionId = $scope.auctionId,
            bidder,
            categorie = [],
            data = [],
            bidderIndex = {},
            highCharts;

          for (i in $scope.ngModel){
             bidder = $scope.ngModel[i];
             for (j in bidder.bids){
                if (j === $scope.auctionId){
                    data.push({
                        name: i,
                        y: bidder.bids[j].updatePoints.length
                    });
                    bidderIndex[i] = data.length - 1;
                    break;
                }
             }
          }

          container = angular.element('

');
          angular.element($element[0]).append(container);
          container = $($element[0].firstChild);

          container.highcharts({
              chart: {
                  type: 'column'
              },
              title: {
                  text: 'Bidders for ' + $scope.ngItemsModel[$scope.auctionId].title || $scope.auctionId
              },
              subtitle: {
                  text: 'Since last reset / launch'
              },
              yAxis: {
                  min: 0,
                  title: {
                      text: 'Number of bids'
                  }
              },
              xAxis: {
                  type: 'category'
              },
              tooltip: {
                  headerFormat: '{point.key}
',
                  pointFormat: '
{series.name}: 	' +
                  '{point.y}
',
                  footerFormat: '
',
                  shared: true,
                  useHTML: true
              },
              plotOptions: {
                  column: {
                      pointPadding: 0.2,
                      borderWidth: 0
                  }
              },
              series: [{
                  name: 'Bids',
                  data: data,
                  color: 'rgba(119,152,191,0.9)'
              }]
          });

          highCharts = container.highcharts();

          $scope.$watch(function(){
              return $scope.auctionId + $scope.ngItemsModel[$scope.auctionId].updatePoints.length;
          }, function(newVal){
              if (newVal){
                  var start = +new Date(),
                      i,
                      j,
                      bidder,
                      highchartPoint,
                      categories = [],
                      graphCategorie = highCharts.xAxis[0].names,
                      shouldRedrawGraph = false,
                      data = [];

                  for (i in $scope.ngModel){
                      bidder = $scope.ngModel[i];
                      for (j in bidder.bids){
                          if (j === $scope.auctionId){
                              categories.push(i);
                              break;
                          }
                      }
                  }

                  if (categories.length !== graphCategorie.length){
                      shouldRedrawGraph = true;
                  }

                  if ($scope.auctionId !== oldAuctionId || shouldRedrawGraph){
                      for (i in $scope.ngModel){
                          bidder = $scope.ngModel[i];
                          for (j in bidder.bids){
                              if (j === $scope.auctionId){
                                  data.push({
                                      name: i,
                                      y: bidder.bids[j].updatePoints.length
                                  });
                                  break;
                              }
                          }
                      }

                      highCharts.series[0].remove(true);
                      highCharts.addSeries({
                          name: 'Bids',
                          data: data,
                          color: 'rgba(119,152,191,0.9)'
                      });
                  } else {
                      for (i in $scope.ngModel){
                          bidder = $scope.ngModel[i];

                          highchartPoint = highCharts.series[0].data[bidderIndex[i]];
                          for (j in bidder.bids){
                              if (j === $scope.auctionId){
                                  if (highchartPoint && (bidder.bids[j].updatePoints.length !== highchartPoint.y)){
                                      highchartPoint.update({
                                          name: i,
                                          y: bidder.bids[j].updatePoints.length
                                      }, true);
                                  }
                                  break;
                              }
                          }
                      }
                      highCharts.redraw();
                  }

                  highCharts.setTitle({
                      text: 'Bidders for ' + $scope.ngItemsModel[$scope.auctionId].title || $scope.auctionId
                  });
                  oldAuctionId = $scope.auctionId;

                  console.log('bidders', (+new Date() - start), 'ms');
              }
          });
      }
    };
  });<commit_msg>fix bug in biddersdirective<commit_after>/**
 * Created by thomashourlier on 12/01/15.
 */

angular.module('madbid.directive')
  .directive('bidderInfo', function(){
    return {
      restrict: 'E',
      require: '^ngModel',
      scope: {
        ngModel: '=',
        ngItemsModel: '=',
        bidderName: '=',
        auctionId: '='
      },
      template: '
{{ngModel[bidderName]}}
',
      controller: function(){

      },
      link: function($scope, $element, attrs){
          var container,
            i,
            j,
            ii,
            oldAuctionId = $scope.auctionId,
            bidder,
            categorie = [],
            data = [],
            bidderIndex = {},
            highCharts;

          for (i in $scope.ngModel){
             bidder = $scope.ngModel[i];
             for (j in bidder.bids){
                if (j === $scope.auctionId){
                    data.push({
                        name: i,
                        y: bidder.bids[j].updatePoints.length
                    });
                    bidderIndex[i] = data.length - 1;
                    break;
                }
             }
          }

          container = angular.element('

');
          angular.element($element[0]).append(container);
          container = $($element[0].firstChild);

          container.highcharts({
              chart: {
                  type: 'column'
              },
              title: {
                  text: 'Bidders for ' + $scope.ngItemsModel[$scope.auctionId].title || $scope.auctionId
              },
              subtitle: {
                  text: 'Since last reset / launch'
              },
              yAxis: {
                  min: 0,
                  title: {
                      text: 'Number of bids'
                  }
              },
              xAxis: {
                  type: 'category'
              },
              tooltip: {
                  headerFormat: '{point.key}
',
                  pointFormat: '
{series.name}: 	' +
                  '{point.y}
',
                  footerFormat: '
',
                  shared: true,
                  useHTML: true
              },
              plotOptions: {
                  column: {
                      pointPadding: 0.2,
                      borderWidth: 0
                  }
              },
              series: [{
                  name: 'Bids',
                  data: data,
                  color: 'rgba(119,152,191,0.9)'
              }]
          });

          highCharts = container.highcharts();

          $scope.$watch(function(){
              return $scope.auctionId + $scope.ngItemsModel[$scope.auctionId].updatePoints.length;
          }, function(newVal){
              if (newVal){
                  var start = +new Date(),
                      i,
                      j,
                      bidder,
                      highchartPoint,
                      categories = [],
                      graphCategorie = highCharts.xAxis[0].names,
                      shouldRedrawGraph = false,
                      data = [];

                  for (i in $scope.ngModel){
                      bidder = $scope.ngModel[i];
                      for (j in bidder.bids){
                          if (j === $scope.auctionId){
                              categories.push(i);
                              break;
                          }
                      }
                  }

                  if (categories.length !== graphCategorie.length){
                      shouldRedrawGraph = true;
                  }

                  if ($scope.auctionId !== oldAuctionId || shouldRedrawGraph){
                      for (i in $scope.ngModel){
                          bidder = $scope.ngModel[i];
                          for (j in bidder.bids){
                              if (j === $scope.auctionId){
                                  data.push({
                                      name: i,
                                      y: bidder.bids[j].updatePoints.length
                                  });
                                  bidderIndex[i] = data.length - 1;
                                  break;
                              }
                          }
                      }

                      highCharts.series[0].remove(true);
                      highCharts.addSeries({
                          name: 'Bids',
                          data: data,
                          color: 'rgba(119,152,191,0.9)'
                      });
                  } else {
                      for (i in $scope.ngModel){
                          bidder = $scope.ngModel[i];

                          highchartPoint = highCharts.series[0].data[bidderIndex[i]];
                          for (j in bidder.bids){
                              if (j === $scope.auctionId){
                                  if (highchartPoint && (bidder.bids[j].updatePoints.length !== highchartPoint.y)){
                                      highchartPoint.update({
                                          name: i,
                                          y: bidder.bids[j].updatePoints.length
                                      }, true);
                                  }
                                  break;
                              }
                          }
                      }
                      highCharts.redraw();
                  }

                  highCharts.setTitle({
                      text: 'Bidders for ' + $scope.ngItemsModel[$scope.auctionId].title || $scope.auctionId
                  });
                  oldAuctionId = $scope.auctionId;

                  console.log('bidders', (+new Date() - start), 'ms');
              }
          });
      }
    };
  });<|endoftext|>


<commit_before>'use strict';

angular.module('deckApp.tasks.api', [
  'restangular',
  'deckApp.kato.service',
  'deckApp.settings',
  'deckApp.urlBuilder',
  'deckApp.orchestratedItem.service'
])
  .factory('tasksApi', function(settings, Restangular, urlBuilder, $timeout, $q, kato, $exceptionHandler, orchestratedItem) {

    function getKatoTasks(task) {
      return task.getValueFor('kato.tasks');
    }

    function updateTask(original, updated) {
      original.status = updated.status;
      original.steps = updated.steps;
      original.endTime = updated.endTime;
      original.variables = updated.variables;
      if (updated.katoTasks && updated.katoTasks.length) {
        var katoTasks = getKatoTasks(original);
        katoTasks[katoTasks.length - 1].history = updated.katoTasks;
      }
    }

    function setTaskProperties(task) {

      task.pendingPolls = [];

      task.updateKatoTask = function(katoTask) {
        if (!katoTask) {
          $exceptionHandler('Error - no kato task found:', task.plain());
          return;
        }
        var katoTasks = task.getValueFor('kato.tasks');
        if (katoTasks && katoTasks.length && katoTasks[katoTasks.length - 1].id === katoTask.id) {
          var lastTask = katoTasks[katoTasks.length - 1];
          angular.copy(katoTask.asPondKatoTask(), lastTask);
        } else {
          if (katoTasks) {
            katoTasks.push(katoTask.asPondKatoTask());
          }
          task.variables.push({key: 'kato.tasks', value: [katoTask.asPondKatoTask()]});
        }
      };

      task.getValueFor = function(key) {
        if (!task.variables) {
          return null;
        }
        var matching = task.variables.filter(function(item) {
          return item.key === key;
        });
        return matching.length > 0 ? matching[0].value : null;
      };

      function filterToPhase(katoTasks, phase) {
        if (katoTasks && phase) {
          return katoTasks.filter(function(task) {
            return task.history.some(function(step) {
              return step.phase === phase;
            });
          });
        }
        return katoTasks;
      }

      function refreshPondTaskForKato(task, phase, deferred) {
        return function() {
          if (!deferred.promise.cancelled) {
            task.get().then(function (updatedTask) {
              updateTask(task, updatedTask);
              task.getCompletedKatoTask(phase, deferred).then(deferred.resolve, deferred.reject);
            });
          }
        };
      }

      task.getCompletedKatoTask = function(phaseFilter, chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();

        var katoTasks = filterToPhase(getKatoTasks(task), phaseFilter);
        var katoStatus = katoTasks && katoTasks.length ? katoTasks[katoTasks.length-1].status : null;

        var failed = task.isFailed || (katoStatus && katoStatus.failed),
            succeeded = katoStatus && katoStatus.completed && !katoStatus.failed,
            running = !failed && !succeeded,
            katoTaskId = task.getValueFor('kato.last.task.id');

        if (failed) {
          var rejectWith = katoTasks ? katoTasks[katoTasks.length-1] : null;
          deferred.reject(rejectWith);
        }

        if (succeeded) {
          deferred.resolve(katoTasks[katoTasks.length-1]);
        }

        if (running && !deferred.promise.cancelled) {
          if (katoTaskId) {
            // check for new task id
            kato.getTask(task.getValueFor('application'), task.id, katoTaskId.id).get().then(
              function(katoTask) {
                task.updateKatoTask(katoTask);
                var katoWait = katoTask.waitUntilComplete();
                task.pendingPolls.push(katoWait);
                katoWait.then(
                  function(updatedKatoTask) {
                    if (filterToPhase([updatedKatoTask], phaseFilter).length && updatedKatoTask.isCompleted) {
                      deferred.resolve(updatedKatoTask);
                    } else {
                      $timeout(refreshPondTaskForKato(task, phaseFilter, deferred), 500);
                    }
                  },
                  deferred.reject,
                  task.updateKatoTask);
              },
              deferred.reject,
              task.updateKatoTask
            );
          } else {
            $timeout(refreshPondTaskForKato(task, phaseFilter, deferred), 1000);
          }
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.watchForTaskComplete = function(chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();
        if (task.isFailed) {
          deferred.reject(task);
        }
        if (task.isCompleted) {
          deferred.resolve(task);
        }
        if ( (task.isRunning || task.hasNotStarted) && !deferred.promise.cancelled) {
          $timeout(function () {
            task.get().then(function (updatedTask) {
              updateTask(task, updatedTask);
              task.watchForTaskComplete(deferred).then(deferred.resolve, deferred.reject);
            });
          }, 1000);
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.watchForForceRefresh = function(chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();
        if (task.isFailed) {
          deferred.reject(task);
        }
        if (task.isCompleted || task.isRunning) {
          var forceRefreshStep = task.steps.filter(function(step) { return step.name === 'forceCacheRefresh'; });
          if (forceRefreshStep.length && forceRefreshStep[0].status !== 'RUNNING') {
            var forceRefreshStatus = forceRefreshStep[0].status;
            if (forceRefreshStatus === 'COMPLETED') {
              deferred.resolve(task);
            }
            if (forceRefreshStatus === 'FAILED') {
              deferred.reject(task);
            }
          } else {
            if (task.isCompleted) {
              deferred.reject(task);
            } else {
              if (!deferred.promise.cancelled) {
                $timeout(function () {
                  task.get().then(function (updatedTask) {
                    updateTask(task, updatedTask);
                    task.watchForForceRefresh(deferred).then(deferred.resolve, deferred.reject);
                  });
                }, 500);
              }
            }
          }
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.cancelPolls = function cancelPolls() {
        task.pendingPolls.forEach(function(pendingPromise) {
          pendingPromise.cancelled = true;
        });
      };

      Object.defineProperties(task, {
        katoTasks: {
          get: function() {
            if (getKatoTasks(task)) {
              var katoTasks = getKatoTasks(task);
              return katoTasks[katoTasks.length -1].history;
            }
            return [];
          }
        },
        failureMessage: {
          get: function() {
            if ((task.isFailed || task.isStopped) && getKatoTasks(task)) {
              var katoTasks = getKatoTasks(task);
              var katoException = katoTasks[katoTasks.length -1].exception;
              return katoException ? katoException.message : 'No reason provided';
            }

            var generalException = task.getValueFor('exception');
            if (generalException) {
              return generalException.details.errors ? generalException.details.errors.join(', ') : 'No reason provided';
            }
            return false;
          }
        },
        href: {
          get: function() {
            return task.isCompleted ? urlBuilder.buildFromTask(task) : false;
          }
        },
        lastKatoMessage: {
          get: function() {
            var katoTasks = getKatoTasks(task);
            if (katoTasks) {
              var steps = katoTasks[katoTasks.length-1].history;
              var exception = katoTasks[katoTasks.length -1].exception;
              if (exception) {
                return exception.message || 'No reason provided';
              }
              return steps && steps.length ? steps[steps.length-1].status : 'No status available';
            }
            return null;
          }
        },
        history: {
          get: function() {
            var katoTasks = getKatoTasks(task);
            if (katoTasks && katoTasks.length) {
              return katoTasks[katoTasks.length-1].history;
            }
            return null;
          }
        }
      });
    }

    function setTaskCollectionProperties(taskCollection) {
      Object.defineProperties(taskCollection, {
        runningCount: {
          get: function() {
            return taskCollection.reduce(function(acc, current) {
              return ['NOT_STARTED', 'RUNNING'].indexOf(current.status) !== -1 ? acc + 1 : acc;
            }, 0);
          }
        }
      });
    }

    function configureRestangular() {
      return Restangular.withConfig(function(RestangularConfigurer) {
        RestangularConfigurer.addElementTransformer('tasks', true, function(taskCollection) {
          setTaskCollectionProperties(taskCollection);
          return taskCollection;
        });
        RestangularConfigurer.addElementTransformer('tasks', false, function(task) {

          orchestratedItem.defineProperties(task);
          if (task.steps && task.steps.length) {
            task.steps.forEach(orchestratedItem.defineProperties);
          }
          setTaskProperties(task);

          return task;
        });
      });
    }

    return configureRestangular();

  });
<commit_msg>Favor a general exception message (when available) over kato<commit_after>'use strict';

angular.module('deckApp.tasks.api', [
  'restangular',
  'deckApp.kato.service',
  'deckApp.settings',
  'deckApp.urlBuilder',
  'deckApp.orchestratedItem.service'
])
  .factory('tasksApi', function(settings, Restangular, urlBuilder, $timeout, $q, kato, $exceptionHandler, orchestratedItem) {

    function getKatoTasks(task) {
      return task.getValueFor('kato.tasks');
    }

    function updateTask(original, updated) {
      original.status = updated.status;
      original.steps = updated.steps;
      original.endTime = updated.endTime;
      original.variables = updated.variables;
      if (updated.katoTasks && updated.katoTasks.length) {
        var katoTasks = getKatoTasks(original);
        katoTasks[katoTasks.length - 1].history = updated.katoTasks;
      }
    }

    function setTaskProperties(task) {

      task.pendingPolls = [];

      task.updateKatoTask = function(katoTask) {
        if (!katoTask) {
          $exceptionHandler('Error - no kato task found:', task.plain());
          return;
        }
        var katoTasks = task.getValueFor('kato.tasks');
        if (katoTasks && katoTasks.length && katoTasks[katoTasks.length - 1].id === katoTask.id) {
          var lastTask = katoTasks[katoTasks.length - 1];
          angular.copy(katoTask.asPondKatoTask(), lastTask);
        } else {
          if (katoTasks) {
            katoTasks.push(katoTask.asPondKatoTask());
          }
          task.variables.push({key: 'kato.tasks', value: [katoTask.asPondKatoTask()]});
        }
      };

      task.getValueFor = function(key) {
        if (!task.variables) {
          return null;
        }
        var matching = task.variables.filter(function(item) {
          return item.key === key;
        });
        return matching.length > 0 ? matching[0].value : null;
      };

      function filterToPhase(katoTasks, phase) {
        if (katoTasks && phase) {
          return katoTasks.filter(function(task) {
            return task.history.some(function(step) {
              return step.phase === phase;
            });
          });
        }
        return katoTasks;
      }

      function refreshPondTaskForKato(task, phase, deferred) {
        return function() {
          if (!deferred.promise.cancelled) {
            task.get().then(function (updatedTask) {
              updateTask(task, updatedTask);
              task.getCompletedKatoTask(phase, deferred).then(deferred.resolve, deferred.reject);
            });
          }
        };
      }

      task.getCompletedKatoTask = function(phaseFilter, chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();

        var katoTasks = filterToPhase(getKatoTasks(task), phaseFilter);
        var katoStatus = katoTasks && katoTasks.length ? katoTasks[katoTasks.length-1].status : null;

        var failed = task.isFailed || (katoStatus && katoStatus.failed),
            succeeded = katoStatus && katoStatus.completed && !katoStatus.failed,
            running = !failed && !succeeded,
            katoTaskId = task.getValueFor('kato.last.task.id');

        if (failed) {
          var rejectWith = katoTasks ? katoTasks[katoTasks.length-1] : null;
          deferred.reject(rejectWith);
        }

        if (succeeded) {
          deferred.resolve(katoTasks[katoTasks.length-1]);
        }

        if (running && !deferred.promise.cancelled) {
          if (katoTaskId) {
            // check for new task id
            kato.getTask(task.getValueFor('application'), task.id, katoTaskId.id).get().then(
              function(katoTask) {
                task.updateKatoTask(katoTask);
                var katoWait = katoTask.waitUntilComplete();
                task.pendingPolls.push(katoWait);
                katoWait.then(
                  function(updatedKatoTask) {
                    if (filterToPhase([updatedKatoTask], phaseFilter).length && updatedKatoTask.isCompleted) {
                      deferred.resolve(updatedKatoTask);
                    } else {
                      $timeout(refreshPondTaskForKato(task, phaseFilter, deferred), 500);
                    }
                  },
                  deferred.reject,
                  task.updateKatoTask);
              },
              deferred.reject,
              task.updateKatoTask
            );
          } else {
            $timeout(refreshPondTaskForKato(task, phaseFilter, deferred), 1000);
          }
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.watchForTaskComplete = function(chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();
        if (task.isFailed) {
          deferred.reject(task);
        }
        if (task.isCompleted) {
          deferred.resolve(task);
        }
        if ( (task.isRunning || task.hasNotStarted) && !deferred.promise.cancelled) {
          $timeout(function () {
            task.get().then(function (updatedTask) {
              updateTask(task, updatedTask);
              task.watchForTaskComplete(deferred).then(deferred.resolve, deferred.reject);
            });
          }, 1000);
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.watchForForceRefresh = function(chainedDeferred) {
        var deferred = chainedDeferred || $q.defer();
        if (task.isFailed) {
          deferred.reject(task);
        }
        if (task.isCompleted || task.isRunning) {
          var forceRefreshStep = task.steps.filter(function(step) { return step.name === 'forceCacheRefresh'; });
          if (forceRefreshStep.length && forceRefreshStep[0].status !== 'RUNNING') {
            var forceRefreshStatus = forceRefreshStep[0].status;
            if (forceRefreshStatus === 'COMPLETED') {
              deferred.resolve(task);
            }
            if (forceRefreshStatus === 'FAILED') {
              deferred.reject(task);
            }
          } else {
            if (task.isCompleted) {
              deferred.reject(task);
            } else {
              if (!deferred.promise.cancelled) {
                $timeout(function () {
                  task.get().then(function (updatedTask) {
                    updateTask(task, updatedTask);
                    task.watchForForceRefresh(deferred).then(deferred.resolve, deferred.reject);
                  });
                }, 500);
              }
            }
          }
        }
        task.pendingPolls.push(deferred.promise);
        return deferred.promise;
      };

      task.cancelPolls = function cancelPolls() {
        task.pendingPolls.forEach(function(pendingPromise) {
          pendingPromise.cancelled = true;
        });
      };

      Object.defineProperties(task, {
        katoTasks: {
          get: function() {
            if (getKatoTasks(task)) {
              var katoTasks = getKatoTasks(task);
              return katoTasks[katoTasks.length -1].history;
            }
            return [];
          }
        },
        failureMessage: {
          get: function() {
            var generalException = task.getValueFor('exception');
            if (generalException) {
              return generalException.details.errors ? generalException.details.errors.join(', ') : 'No reason provided';
            }

            if ((task.isFailed || task.isStopped) && getKatoTasks(task)) {
              var katoTasks = getKatoTasks(task);
              var katoException = katoTasks[katoTasks.length -1].exception;
              return katoException ? katoException.message : 'No reason provided';
            }

            return false;
          }
        },
        href: {
          get: function() {
            return task.isCompleted ? urlBuilder.buildFromTask(task) : false;
          }
        },
        lastKatoMessage: {
          get: function() {
            var katoTasks = getKatoTasks(task);
            if (katoTasks) {
              var steps = katoTasks[katoTasks.length-1].history;
              var exception = katoTasks[katoTasks.length -1].exception;
              if (exception) {
                return exception.message || 'No reason provided';
              }
              return steps && steps.length ? steps[steps.length-1].status : 'No status available';
            }
            return null;
          }
        },
        history: {
          get: function() {
            var katoTasks = getKatoTasks(task);
            if (katoTasks && katoTasks.length) {
              return katoTasks[katoTasks.length-1].history;
            }
            return null;
          }
        }
      });
    }

    function setTaskCollectionProperties(taskCollection) {
      Object.defineProperties(taskCollection, {
        runningCount: {
          get: function() {
            return taskCollection.reduce(function(acc, current) {
              return ['NOT_STARTED', 'RUNNING'].indexOf(current.status) !== -1 ? acc + 1 : acc;
            }, 0);
          }
        }
      });
    }

    function configureRestangular() {
      return Restangular.withConfig(function(RestangularConfigurer) {
        RestangularConfigurer.addElementTransformer('tasks', true, function(taskCollection) {
          setTaskCollectionProperties(taskCollection);
          return taskCollection;
        });
        RestangularConfigurer.addElementTransformer('tasks', false, function(task) {

          orchestratedItem.defineProperties(task);
          if (task.steps && task.steps.length) {
            task.steps.forEach(orchestratedItem.defineProperties);
          }
          setTaskProperties(task);

          return task;
        });
      });
    }

    return configureRestangular();

  });
<|endoftext|>


<commit_before>(function(){

  app.factory('bungieService', BungieService);

  BungieService.$inject = ['$http'];

   function BungieService($http) {
    var bungieNetUserPromise = null;
    var guardianPromise = null;

    var factoryServices = {
      getBungieNetUser : getBungieNetUser
    }

    return factoryServices;

    /*********************************************************/

    function getBungieCookies() {
      return new Promise(function(resolve, reject) {
        chrome.cookies.getAll({
          'domain': '.bungie.net',
          'name': 'bungled'
        }, getAllCallback);

        function getAllCallback(cookies) {
          if (cookies.length > 0) {
            resolve(cookies[0].value);
          } else {
            reject(alert("Error: No cookies found."));
          };
        }
      });
    }

    /*********************************************************/

    function getBungieNetUser() {
      // Returns account information for the current user

      bungieNetUserPromise = bungieNetUserPromise || getBungieCookies()
        .then(getBungieNetUserRequest)
        .then($http)
        .then(processBungieNetRequest)
        .catch(function(error) {
          console.log("Failed!", error);
        })
        .then(generateMembership)
        .then(getGuardians);

      return bungieNetUserPromise;
    }

    function getBungieNetUserRequest(token) {
      console.log("getBungieNetUserRequest(token)", token); // dev

      return {
        method: "GET",
        url: "https://www.bungie.net/Platform/User/GetBungieNetUser/",
        headers: {
          "X-API-Key": apiKey,
          "x-crsf": token
        },
        withCredentials: true
      };
    }

    function processBungieNetRequest(response) {
      console.log("processBungieNetRequest(response)", response); // dev
      if (response.data.ErrorCode > 1) {
        console.log(response.data.ErrorStatus + "\n" + response.data.Message);
      };

      return response;
    }

    function generateMembership(response) {
      var userData = response.data.Response.user;
      var platformId = null;

      if (userData.xboxDisplayName) {
        platformId = 1;
        console.log("Platform: Xbox"); // dev
        handle = userData.xboxDisplayName;
        console.log(handle); // dev
      }

      if (userData.psnDisplayName) {
        platformId = 2;
        console.log("Platform: PlayStation"); // dev
        handle = userData.psnDisplayName;
        console.log(handle); // dev
      }
      console.log("membershipId:",userData.membershipId);

      return {
        handle : handle,
        id : userData.membershipId,
        platform : platformId
      };
    }

    /*********************************************************/

    function getGuardians(membership) {
      console.log(membership); // dev

      guardianPromise = getBungieCookies()
        .then(getGuardiansRequest.bind(null, membership))
        .then($http)
        .then(processGuardiansRequest)
        .then(generateGuardians);

      return guardianPromise;
    }

    function getGuardiansRequest(membership, token) {
      console.log("token : " + token + "\n" + "membership : " + membership); // dev
      return {
        method: "GET",
        url: "https://www.bungie.net/Platform/User/GetBungieAccount/" + membership.id + "/" + membership.platform + "/",
        headers : {
          "X-API-Key": apiKey,
          "x-crsf": token
        },
        withCredentials: true
      }
    }

    function processGuardiansRequest(response) {
      console.log(response); // dev

      return response;
    }

    function generateGuardians(response) {
      var guardianData = response.data.Response.destinyAccounts[0].characters;

      for (var i = 0; i < guardianData.length; i++) {
        console.log("Guardian"+ [i] + ": " + guardianData[i].characterId); // dev
      };

      var guardians = [
        {
          id : guardianData
        }
      ];

      return guardians;
    }

    /*********************************************************/

    function getInventories() {
      var inventoryPromise = getBungieCookies()
      .then(getGuardianInventoryRequest)
      .then($http)
      .then(processGuardianInventory);

      return inventoryPromise;
    }

    function getGuardianInventoryRequest(token, membership, guardian) {
      console.log("getGuardianInventoryRequest(token)", token); // dev
      // Returns the inventory for the supplied character.
      return {
        method: "GET",
        url: "https://bungie.net/Destiny/" + membership.platform + "/Account/" + membership.id + "/Character/" + guardian.id + "/Inventory/",
        headers: {
          "X-API-Key": apiKey,
          "x-crsf": token
        },
        withCredentials: true
      }
    }

    function processGuardianInventory(response) {
      console.log("processGuardianInventory(response)", response); // dev

      return response;
    }
  }
})();<commit_msg>#18: read 'bungledid' cookie from browser.<commit_after>(function(){

  app.factory('bungieService', BungieService);

  BungieService.$inject = ['$http'];

   function BungieService($http) {
    var bungieNetUserPromise = null;
    var guardianPromise = null;

    var factoryServices = {
      getBungieNetUser : getBungieNetUser
    }

    return factoryServices;

    /*********************************************************/

    function getBungieCookies() {
      // Gets all Bungie.net cookies from browser, searches for the
      // 'bungled' and 'bungledid' cookies, then returns their values.

      var cookieData = {
        bungled : null,
        bungledid : null
      };

      return new Promise(function(resolve, reject) {
        chrome.cookies.getAll({
          'domain': '.bungie.net'
        }, getAllCallback);

        function getAllCallback(cookies) {
          if (cookies.length > 0) {
            for (var i = 0; i < cookies.length; i++) {
              if (cookies[i].name === "bungled") {
                // set 'bungled' value
                cookieData.bungled = cookies[i].value;
              };
              if (cookies[i].name === "bungledid") {
                // set 'bungledid' value
                cookieData.bungledid = cookies[i].value;
              };
            };
            resolve(cookieData);
          } else {
            reject(alert("Error: No cookies found."));
          };
        }
      });
    }

    /*********************************************************/

    function getBungieNetUser() {
      // Returns account information for the current user

      bungieNetUserPromise = bungieNetUserPromise || getBungieCookies()
        .then(getBungieNetUserRequest)
        .then($http)
        .then(processBungieNetRequest)
        .catch(function(error) {
          console.log("Failed!", error);
        })
        .then(generateMembership)
        .then(getGuardians);

      return bungieNetUserPromise;
    }

    function getBungieNetUserRequest(cookie) {
      console.log("getBungieNetUserRequest(cookie)", cookie); // dev

      return {
        method: "GET",
        url: "https://www.bungie.net/Platform/User/GetBungieNetUser/",
        headers: {
          "X-API-Key": apiKey,
          "x-crsf": cookie.bungled
        },
        withCredentials: true
      };
    }

    function processBungieNetRequest(response) {
      console.log("processBungieNetRequest(response)", response); // dev
      if (response.data.ErrorCode > 1) {
        console.log(response.data.ErrorStatus + "\n" + response.data.Message);
      };

      return response;
    }

    function generateMembership(response) {
      var userData = response.data.Response.user;
      var platformId = null;

      if (userData.xboxDisplayName) {
        platformId = 1;
        console.log("Platform: Xbox"); // dev
        handle = userData.xboxDisplayName;
        console.log(handle); // dev
      }

      if (userData.psnDisplayName) {
        platformId = 2;
        console.log("Platform: PlayStation"); // dev
        handle = userData.psnDisplayName;
        console.log(handle); // dev
      }
      console.log("membershipId:",userData.membershipId);

      return {
        handle : handle,
        id : userData.membershipId,
        platform : platformId
      };
    }

    /*********************************************************/

    function getGuardians(membership) {
      console.log(membership); // dev

      guardianPromise = getBungieCookies()
        .then(getGuardiansRequest.bind(null, membership))
        .then($http)
        .then(processGuardiansRequest)
        .then(generateGuardians);

      return guardianPromise;
    }

    function getGuardiansRequest(membership, cookie) {
      console.log("cookie : " + cookie + "\n" + "membership : " + membership); // dev

      return {
        method: "GET",
        url: "https://www.bungie.net/Platform/User/GetBungieAccount/" + membership.id + "/" + membership.platform + "/",
        headers : {
          "X-API-Key": apiKey,
          "x-crsf": cookie.bungled
        },
        withCredentials: true
      }
    }

    function processGuardiansRequest(response) {
      console.log(response); // dev

      return response;
    }

    function generateGuardians(response) {
      var guardianData = response.data.Response.destinyAccounts[0].characters;

      for (var i = 0; i < guardianData.length; i++) {
        console.log("Guardian"+ [i] + ": " + guardianData[i].characterId); // dev
      };

      var guardians = [
        {
          id : guardianData
        }
      ];

      return guardians;
    }

    /*********************************************************/

    function getInventories() {
      var inventoryPromise = getBungieCookies()
      .then(getGuardianInventoryRequest)
      .then($http)
      .then(processGuardianInventory);

      return inventoryPromise;
    }

    function getGuardianInventoryRequest(cookie, membership, guardian) {
      console.log("getGuardianInventoryRequest(token)", token); // dev
      // Returns the inventory for the supplied character.

      return {
        method: "GET",
        url: "https://bungie.net/Destiny/" + membership.platform + "/Account/" + membership.id + "/Character/" + guardian.id + "/Inventory/",
        headers: {
          "X-API-Key": apiKey,
          "x-crsf": cookie.bungled
        },
        withCredentials: true
      }
    }

    function processGuardianInventory(response) {
      console.log("processGuardianInventory(response)", response); // dev

      return response;
    }
  }
})();<|endoftext|>


<commit_before>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// 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.

/**
 * Base class that assists in working with a Sheet instance in a Spreadsheet.
 *
 * @constructor
 * @param {string} sheetId The sheet id.
 */
var BaseSheet = function(sheetId) {
  this.config = Configuration.getCurrent();
  this.sheetId = sheetId;
  this.spreadsheet = new BaseSpreadsheet();
  this.sheet = this.spreadsheet.getSheetById(parseInt(sheetId));
  this.sheetName = this.sheet.getSheetName();
};

/**
 * Returns a Range instance representing a row in the sheet. An optional start
 * postion for the column can be providied. If no start column position or
 * number of columns are given, the entire row is returned, regardless of
 * content.
 *
 * @param {number} rowNum The row to retrieve.
 * @param {number=} startCol An optional starting column postion.
 * @param {number=} numCols An optional number of columns.
 * @return {Range} A Range instance representing the row.
 */
BaseSheet.prototype.getRow = function(rowNum, startCol, numCols) {
  var row = this.getRows(rowNum, 1, startCol, numCols);
  return row;
};

/**
 * Returns a Range instance representing the given number of rows in the sheet.
 * An optional start postion for the column can be providied. If no start
 * column position or number of columns are given, the entire row is returned,
 * regardless of content.
 *
 * @param {number} rowNum The row to retrieve.
 * @param {number} numRows The number of rows to retrieve.
 * @param {number=} startCol An optional starting column postion.
 * @param {number=} numCols An optional number of columns.
 * @return {Range} A Range instance representing the row.
 */
BaseSheet.prototype.getRows = function(rowNum, numRows, startCol, numCols) {
  var colStart = startCol === undefined ? 1 : startCol;
  var maxCols = this.sheet.getMaxColumns();
  numCols = numCols || (maxCols - colStart + 1);
  var row = this.sheet.getRange(rowNum, colStart, numRows, numCols);
  return row;
};

/**
 * Returns a Range instance representing a column in the sheet. An optional
 * start postion for the row can be providied. If no start position or number
 * of rows are given, the entire row is returned, regardless of content.
 *
 * @param {number} colNum The column to retrieve.
 * @param {number=} startRow An optional starting row postion.
 * @param {number=} numRows An optional number of rows.
 * @return {Range} A Range instance representing the column.
 */
BaseSheet.prototype.getColumn = function(colNum, startRow, numRows) {
  var col = this.getColumns(colNum, 1, startRow, numRows);
  return col;
};

/**
 * Returns a Range instance representing the given number of columns in the
 * sheet. An optional start postion for the row can be providied. If no start
 * position or number of rows are given, the entire row is returned, regardless
 * of content.
 *
 * @param {number} colNum The column to retrieve.
 * @param {number} numCols The number of columns to retrieve.
 * @param {number=} startRow An optional starting row postion.
 * @param {number=} numRows An optional number of rows.
 * @return {Range} A Range instance representing the column.
 */
BaseSheet.prototype.getColumns = function(colNum, numCols, startRow, numRows) {
  var rowStart = startRow === undefined ? 1 : startRow;
  var maxRows = this.sheet.getMaxRows();
  numRows = numRows || (maxRows - rowStart + 1);
  var col = this.sheet.getRange(rowStart, colNum, numRows, numCols);
  return col;
};

/**
 * Deletes the current sheet.
 */
BaseSheet.prototype.remove = function() {
  var ss = this.spreadsheet.getSpreadsheet();
  ss.deleteSheet(this.sheet);
};<commit_msg>add method to get last row with content<commit_after>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// 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.

/**
 * Base class that assists in working with a Sheet instance in a Spreadsheet.
 *
 * @constructor
 * @param {string} sheetId The sheet id.
 */
var BaseSheet = function(sheetId) {
  this.config = Configuration.getCurrent();
  this.sheetId = sheetId;
  this.spreadsheet = new BaseSpreadsheet();
  this.sheet = this.spreadsheet.getSheetById(parseInt(sheetId));
  this.sheetName = this.sheet.getSheetName();
};

/**
 * Returns a Range instance representing a row in the sheet. An optional start
 * postion for the column can be providied. If no start column position or
 * number of columns are given, the entire row is returned, regardless of
 * content.
 *
 * @param {number} rowNum The row to retrieve.
 * @param {number=} startCol An optional starting column postion.
 * @param {number=} numCols An optional number of columns.
 * @return {Range} A Range instance representing the row.
 */
BaseSheet.prototype.getRow = function(rowNum, startCol, numCols) {
  var row = this.getRows(rowNum, 1, startCol, numCols);
  return row;
};

/**
 * Returns a Range instance representing the given number of rows in the sheet.
 * An optional start postion for the column can be providied. If no start
 * column position or number of columns are given, the entire row is returned,
 * regardless of content.
 *
 * @param {number} rowNum The row to retrieve.
 * @param {number} numRows The number of rows to retrieve.
 * @param {number=} startCol An optional starting column postion.
 * @param {number=} numCols An optional number of columns.
 * @return {Range} A Range instance representing the row.
 */
BaseSheet.prototype.getRows = function(rowNum, numRows, startCol, numCols) {
  var colStart = startCol === undefined ? 1 : startCol;
  var maxCols = this.sheet.getMaxColumns();
  numCols = numCols || (maxCols - colStart + 1);
  var row = this.sheet.getRange(rowNum, colStart, numRows, numCols);
  return row;
};

/**
 * Returns a Range instance representing a column in the sheet. An optional
 * start postion for the row can be providied. If no start position or number
 * of rows are given, the entire row is returned, regardless of content.
 *
 * @param {number} colNum The column to retrieve.
 * @param {number=} startRow An optional starting row postion.
 * @param {number=} numRows An optional number of rows.
 * @return {Range} A Range instance representing the column.
 */
BaseSheet.prototype.getColumn = function(colNum, startRow, numRows) {
  var col = this.getColumns(colNum, 1, startRow, numRows);
  return col;
};

/**
 * Returns a Range instance representing the given number of columns in the
 * sheet. An optional start postion for the row can be providied. If no start
 * position or number of rows are given, the entire row is returned, regardless
 * of content.
 *
 * @param {number} colNum The column to retrieve.
 * @param {number} numCols The number of columns to retrieve.
 * @param {number=} startRow An optional starting row postion.
 * @param {number=} numRows An optional number of rows.
 * @return {Range} A Range instance representing the column.
 */
BaseSheet.prototype.getColumns = function(colNum, numCols, startRow, numRows) {
  var rowStart = startRow === undefined ? 1 : startRow;
  var maxRows = this.sheet.getMaxRows();
  numRows = numRows || (maxRows - rowStart + 1);
  var col = this.sheet.getRange(rowStart, colNum, numRows, numCols);
  return col;
};

/**
 * Returns the position of the last row that has content for the given column.
 *
 * @param {number} colNum The column number.
 * @param {number=} startRow An optional starting row position.
 * @param {number=} numRows An optional number of rows.
 * @return {number} The last row of the column that contains content.
 */
BaseSheet.prototype.getLastRow = function(colNum, startRow, numRows) {
  // Define range parameters.
  var rowStart = startRow === undefined ? 1 : startRow;
  var maxRows = this.sheet.getMaxRows();
  numRows = numRows || (maxRows - rowStart + 1);
  var colValues = this.getColumn(colNum, rowStart, numRows).getValues();
  var colValuesLength = colValues.length;

  // Search from the end of the column to the top for the first row with
  // content. Empty elements are removed from the colValues array.
  for (var i = 0; i < colValuesLength; i++) {
    if (colValues[colValuesLength - i - 1][0] === '') {
      colValues.pop();
    } else {
      break;
    }
  }
  return colValues.length;
};

/**
 * Deletes the current sheet.
 */
BaseSheet.prototype.remove = function() {
  var ss = this.spreadsheet.getSpreadsheet();
  ss.deleteSheet(this.sheet);
};<|endoftext|>