<commit_before>/*jslint node: true */
'use strict';

angular.module('myApp.controllers', [])
    .controller('LakeListCtrl', [
        '$scope', 'UserLocationService', 'LakeDataProviderService', 'LatLngDistanceService',
        function($scope, UserLocationService, LakeDataProviderService, LatLngDistanceService) {
            /* Controller for the lake list */
            var lakeList = LakeDataProviderService.getListOfLakesWithDescription();

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    var lakeListWithDistance = lakeList.map(function(lake) {
                        // distance calculated by long/lat in meters
                        var distance = LatLngDistanceService.distanceTo(res, lake.location);

                        return {
                            'name': lake.name,
                            'description': lake.description,
                            'attributes': lake.attributes,
                            'distance': distance / 1000
                        };
                    });

                    $scope.lakeList = lakeListWithDistance;
                }, function error() {
                    $scope.lakeList = lakeList; // no distance nor locations
                });
        }
    ])
    .controller('MapCtrl', ['$scope', '$modal', 'leafletData', 'leafletEvents', 'LakeDataProviderService', 'UserLocationService', 'mapCenter',
        function($scope, $modal, leafletData, leafletEvents, LakeDataProviderService, UserLocationService, mapCenter) {
            /* Controller for the lake map providing an overview */
            console.log(mapCenter);
            angular.extend($scope, {
                center: mapCenter,
                defaults: {
                    tileLayer: 'https://{s}.tiles.mapbox.com/v3/foobar123.j5b19dpp/{z}/{x}/{y}.png',
                    tileLayerOptions: {
                        attribution: '© Mapbox © OpenStreetMap contributors',
                        detectRetina: true,
                        reuseTiles: true,
                    }
                }
            });

            $scope.markers = LakeDataProviderService.getLakeLocationMarkers();

            var userLocationMarkerIcon = {
                'iconUrl': 'public/img/marker-red.png',
                'shadowUrl': 'public/img/marker-shadow.png',
                'iconSize': [25, 41],
                'shadowSize': [41, 41],
                'popupAnchor': [0, -39]
            };

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    $scope.markers.userLocationMarker = {
                        'lat': res.lat,
                        'lng': res.lng,
                        'icon': userLocationMarkerIcon,
                        'message': 'Aktueller Standpunkt'
                    };
                });

            $scope.$on('leafletDirectiveMarker.click', function(event, leafletEvent) {
                if (leafletEvent.markerName !== 'userLocationMarker') {
                    /* jshint unused:false */
                    var modalInstance = $modal.open({
                        'controller': 'ModalInstanceCtrl',
                        'templateUrl': 'public/partials/lakeDescriptionModal.html',
                        'resolve': {
                            'data': function() {
                                return $scope.markers[leafletEvent.markerName].data;
                            }
                        }
                    });
                }
            });
        }
    ])
    .controller('MainCtrl', ['$scope', '$window', '$modal', 'appTitle', 'footNotice', 'contributors', 'labInfo',
        function($scope, $window, $modal, appTitle, footNotice, contributors, labInfo) {
            var footCols = 0;
            $window.document.title = appTitle; // set page title

            $scope.title = appTitle; // sets h1

            // build footer and increment column count for bootstrap grid cols
            $scope.footNotice = footNotice;
            footCols++;

            $scope.contributors = contributors;
            footCols++;

            // logo and link with title
            $scope.labInfo = labInfo;
            footCols++;

            if (footCols > 0) {
                $scope.footerColumns = (12 / footCols); // FIXME: what about 5, 7 and so on?
            } else {
                $scope.footerCloumns = 1;
            }

            // show help modal
            $scope.showHelpModal = function() {
                /* jshint unused:false */
                var modalInstance = $modal.open({
                    'controller': 'ModalInstanceCtrl',
                    'templateUrl': 'public/partials/faq.html',
                    'resolve': {
                        'data': function() {
                            return null;
                        }
                    }
                });
            };
        }
    ])
    .controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'data',
        function($scope, $modalInstance, data) {
            $scope.data = data;
            $scope.dismiss = function() {
                $modalInstance.dismiss();
            };
        }
    ]);
<commit_msg>removed debug output<commit_after>/*jslint node: true */
'use strict';

angular.module('myApp.controllers', [])
    .controller('LakeListCtrl', [
        '$scope', 'UserLocationService', 'LakeDataProviderService', 'LatLngDistanceService',
        function($scope, UserLocationService, LakeDataProviderService, LatLngDistanceService) {
            /* Controller for the lake list */
            var lakeList = LakeDataProviderService.getListOfLakesWithDescription();

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    var lakeListWithDistance = lakeList.map(function(lake) {
                        // distance calculated by long/lat in meters
                        var distance = LatLngDistanceService.distanceTo(res, lake.location);

                        return {
                            'name': lake.name,
                            'description': lake.description,
                            'attributes': lake.attributes,
                            'distance': distance / 1000
                        };
                    });

                    $scope.lakeList = lakeListWithDistance;
                }, function error() {
                    $scope.lakeList = lakeList; // no distance nor locations
                });
        }
    ])
    .controller('MapCtrl', ['$scope', '$modal', 'leafletData', 'leafletEvents', 'LakeDataProviderService', 'UserLocationService', 'mapCenter',
        function($scope, $modal, leafletData, leafletEvents, LakeDataProviderService, UserLocationService, mapCenter) {
            /* Controller for the lake map providing an overview */
            angular.extend($scope, {
                center: mapCenter,
                defaults: {
                    tileLayer: 'https://{s}.tiles.mapbox.com/v3/foobar123.j5b19dpp/{z}/{x}/{y}.png',
                    tileLayerOptions: {
                        attribution: '© Mapbox © OpenStreetMap contributors',
                        detectRetina: true,
                        reuseTiles: true,
                    }
                }
            });

            $scope.markers = LakeDataProviderService.getLakeLocationMarkers();

            var userLocationMarkerIcon = {
                'iconUrl': 'public/img/marker-red.png',
                'shadowUrl': 'public/img/marker-shadow.png',
                'iconSize': [25, 41],
                'shadowSize': [41, 41],
                'popupAnchor': [0, -39]
            };

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    $scope.markers.userLocationMarker = {
                        'lat': res.lat,
                        'lng': res.lng,
                        'icon': userLocationMarkerIcon,
                        'message': 'Aktueller Standpunkt'
                    };
                });

            $scope.$on('leafletDirectiveMarker.click', function(event, leafletEvent) {
                if (leafletEvent.markerName !== 'userLocationMarker') {
                    /* jshint unused:false */
                    var modalInstance = $modal.open({
                        'controller': 'ModalInstanceCtrl',
                        'templateUrl': 'public/partials/lakeDescriptionModal.html',
                        'resolve': {
                            'data': function() {
                                return $scope.markers[leafletEvent.markerName].data;
                            }
                        }
                    });
                }
            });
        }
    ])
    .controller('MainCtrl', ['$scope', '$window', '$modal', 'appTitle', 'footNotice', 'contributors', 'labInfo',
        function($scope, $window, $modal, appTitle, footNotice, contributors, labInfo) {
            var footCols = 0;
            $window.document.title = appTitle; // set page title

            $scope.title = appTitle; // sets h1

            // build footer and increment column count for bootstrap grid cols
            $scope.footNotice = footNotice;
            footCols++;

            $scope.contributors = contributors;
            footCols++;

            // logo and link with title
            $scope.labInfo = labInfo;
            footCols++;

            if (footCols > 0) {
                $scope.footerColumns = (12 / footCols); // FIXME: what about 5, 7 and so on?
            } else {
                $scope.footerCloumns = 1;
            }

            // show help modal
            $scope.showHelpModal = function() {
                /* jshint unused:false */
                var modalInstance = $modal.open({
                    'controller': 'ModalInstanceCtrl',
                    'templateUrl': 'public/partials/faq.html',
                    'resolve': {
                        'data': function() {
                            return null;
                        }
                    }
                });
            };
        }
    ])
    .controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'data',
        function($scope, $modalInstance, data) {
            $scope.data = data;
            $scope.dismiss = function() {
                $modalInstance.dismiss();
            };
        }
    ]);
<|endoftext|>


<commit_before><commit_msg>small refactor<commit_after><|endoftext|>


<commit_before>var $homepage = $('#homepage');
var $event = $('#event');
var $name = $('#name');
var $admin = $('#event');
var $404 = $('#not-found');

page.base('/');
// page('*', logRoute);

page('/', logRoute, function() {
  showPage($homepage);
  $('.nav-main').hide();
});

page('name', logRoute, function() {
  showPage($name);
  $('.nav-main').hide();
});

page('event', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
  $('.nav-main').show();
});

page('eventhash/:eventHash', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
  $('.nav-main').show();
});

//////////////////////////////////////
page('event/timing', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function() {
  // CalendarView.initCalendarView();
  showPage($event);
  $('#timing').show();
  $('#googleAPI').hide();
  $('.nav-main').show();
  CalendarView.initCalendarView();

});

page(':id/event/timing', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  // CalendarView.initCalendarView();
  showPage($event);
  $('#timing').show();
  $('#googleAPI').hide();
  CalendarView.initCalendarView();
});

//////////////////////////////////////
page('event/status', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#status-content').show();
  $('#googleAPI').show();
  $('.nav-main').show();
});

//////////////////////////////////////
page('event/clusters', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#cluster').show();
  $('#googleAPI').show();
  $('.nav-main').show();
  TopicView.topicCloudInit('cloud');
  TopicController.initCloudItemClickHandler();
});

//////////////////////////////////////
page('event/add', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#add').show();
  $('#googleAPI').show();
  $('.nav-main').show();
});

//gets text input from the event submission form and logs it to page and advances to name page
$('#create-event').on('submit', function(event) {
  event.preventDefault();
  var eventValue = $('#event-value').val();
  console.log(eventValue);
  EventController.createEvent(eventValue, function() {
    page.show('name');
    $('#name-value').focus();
    // history.pushState({},'','/name');//this was commented
    // showPage($name); //this was commented
  });
});

//gets text input from the name submission form and posts to the api and advances to event page
$('#create-name').on('submit', function(event){
  event.preventDefault();
  var nameValue = $('#name-value').val();
  console.log(nameValue);
  EventController.createUserName(nameValue);
  page.show('event');
  $('.nav-main').show();
  // history.pushState({},'','/event'); //this was commented
  // EventController.initEventPage(); //this was commented
});

//This function creates a nw ahref button and appends to the nav bar. the a href is given
//to the cluster section. Can not figure out out to dynamically make a route
$('#add').on('submit', function(event) {
  event.preventDefault();
  var topic = $('#topic').val().trim();
  if(topic){
    $('#topic').val('');
    console.log(topic);
    page('event/' + topic, logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
      showPage($event);
      $('#newClustersHere').append('

');
      $('#' + topic).show();
      TopicView.topicCloudInit(topic);
      $('#newClustersHere').append('
 <form class="row" action="index.html" method="post"> <input class="u-full-width" type="text" name="word" placeholder="Create Option"> <input class="button-primary u-full-width" type="button" name="submit" value="CREATE"> <input type="text" visibility="hidden" value="lksaf9pwurp2o"> <input type="text" value="we09r20lksjdf">');
      $('#googleAPI').hide();
      $('.nav-main').show();
    });
    $('' + topic + '').prependTo('#event-navigation');
  }
  // location = '/event/clusters';
});
$('#clear-topic').on('click', function(){
  $('a').remove('#new-topic');
});

page();

function showPage($element) {
  $('.page').hide();
  $element.fadeIn();
}

function logRoute(ctx, next) {
  console.log('page.js route called: ',ctx.path);
  if (next) next();
}
<commit_msg>hide a couple info divs<commit_after>var $homepage = $('#homepage');
var $event = $('#event');
var $name = $('#name');
var $admin = $('#event');
var $404 = $('#not-found');

page.base('/');
// page('*', logRoute);

page('/', logRoute, function() {
  showPage($homepage);
  $('.nav-main').hide();
});

page('name', logRoute, function() {
  showPage($name);
  $('.nav-main').hide();
});

page('event', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
  $('.nav-main').show();
});

page('eventhash/:eventHash', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
  $('.nav-main').show();
});

//////////////////////////////////////
page('event/timing', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function() {
  // CalendarView.initCalendarView();
  showPage($event);
  $('#timing').show();
  $('#googleAPI').hide();
  $('.nav-main').show();
  CalendarView.initCalendarView();

});

page(':id/event/timing', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  // CalendarView.initCalendarView();
  showPage($event);
  $('#timing').show();
  $('#googleAPI').hide();
  CalendarView.initCalendarView();
});

//////////////////////////////////////
page('event/status', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#status-content').show();
  $('#googleAPI').show();
  $('.nav-main').show();
});

//////////////////////////////////////
page('event/clusters', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#cluster').show();
  $('#googleAPI').show();
  $('.nav-main').show();
  TopicView.topicCloudInit('cloud');
  TopicController.initCloudItemClickHandler();
});

//////////////////////////////////////
page('event/add', logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView,function() {
  showPage($event);
  $('#add').show();
  $('#googleAPI').show();
  $('.nav-main').show();
});

//gets text input from the event submission form and logs it to page and advances to name page
$('#create-event').on('submit', function(event) {
  event.preventDefault();
  var eventValue = $('#event-value').val();
  console.log(eventValue);
  EventController.createEvent(eventValue, function() {
    page.show('name');
    $('#name-value').focus();
    // history.pushState({},'','/name');//this was commented
    // showPage($name); //this was commented
  });
});

//gets text input from the name submission form and posts to the api and advances to event page
$('#create-name').on('submit', function(event){
  event.preventDefault();
  var nameValue = $('#name-value').val();
  console.log(nameValue);
  EventController.createUserName(nameValue);
  page.show('event');
  $('.nav-main').show();
  // history.pushState({},'','/event'); //this was commented
  // EventController.initEventPage(); //this was commented
});

//This function creates a nw ahref button and appends to the nav bar. the a href is given
//to the cluster section. Can not figure out out to dynamically make a route
$('#add').on('submit', function(event) {
  event.preventDefault();
  var topic = $('#topic').val().trim();
  if(topic){
    $('#topic').val('');
    console.log(topic);
    page('event/' + topic, logRoute, EventController.initEventPage, EventView.initEventView, HomeView.initHomeView, function(){
      showPage($event);
      $('#newClustersHere').append('

');
      $('#' + topic).show();
      TopicView.topicCloudInit(topic);
      $('#newClustersHere').append('
 <form class="row" action="index.html" method="post"> <input class="u-full-width" type="text" name="word" placeholder="Create Option"> <input class="button-primary u-full-width" type="button" name="submit" value="CREATE"> <input type="text" visibility="hidden" value="lksaf9pwurp2o"> <input type="text" value="we09r20lksjdf">
');
      $('#googleAPI').hide();
      $('.nav-main').show();
    });
    $('' + topic + '').prependTo('#event-navigation');
  }
  // location = '/event/clusters';
});
$('#clear-topic').on('click', function(){
  $('a').remove('#new-topic');
});

page();

function showPage($element) {
  $('.page').hide();
  $element.fadeIn();
}

function logRoute(ctx, next) {
  console.log('page.js route called: ',ctx.path);
  if (next) next();
}
<|endoftext|>


<commit_before>'use strict';

angular.module('app.directives', []).
  directive('datetime', [
    function() {
      return {
        restrict: 'EA',
        require: 'ngModel',
        scope: {
          ngModel: '=',
          dayFormat: "=",
          monthFormat: "=",
          yearFormat: "=",
          dayHeaderFormat: "=",
          dayTitleFormat: "=",
          monthTitleFormat: "=",
          showWeeks: "=",
          startingDay: "=",
          yearRange: "=",
          dateFormat: "=",
          minDate: "=",
          maxDate: "=",
          dateOptions: "=",
          dateDisabled: "&",
          hourStep: "=",
          minuteStep: "=",
          showMeridian: "=",
          meredians: "=",
          mousewheel: "=",
          readonlyTime: "@"
        },
        template: function(elem, attrs) {
          function dashCase(name, separator) {
            return name.replace(/[A-Z]/g, function(letter, pos) {
              return (pos ? '-' : '') + letter.toLowerCase();
            });
          }

          function createAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "\" ";
            } else {
              return '';
            }
          }

          function createFuncAttr(innerAttr, funcArgs, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "({" + funcArgs + "})\" ";
            } else {
              return '';
            }
          }

          function createEvalAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + attrs[dateTimeAttr] + "\" ";
            } else {
              return dashCase(innerAttr);
            }
          }

          function createAttrConcat(previousAttrs, attr) {
            return previousAttrs + createAttr.apply(null, attr)
          }
          var tmpl = "
" +
            "<input class=\"form-control\" type=\"text\" ng-click=\"open($event)\" is-open=\"opened\" ng-model=\"ngModel\" " + [
              ["minDate"],
              ["maxDate"],
              ["dayFormat"],
              ["monthFormat"],
              ["yearFormat"],
              ["dayHeaderFormat"],
              ["dayTitleFormat"],
              ["monthTitleFormat"],
              ["startingDay"],
              ["yearRange"],
              ["datepickerOptions", "dateOptions"]
          ].reduce(createAttrConcat, '') +
            createFuncAttr("dateDisabled", "date: date, mode: mode") +
            createEvalAttr("datepickerPopup", "dateFormat") +
            "/>\n" +
            "
\n" +
            "
\n" +
            "<timepicker " + [
              ["hourStep"],
              ["minuteStep"],
              ["showMeridian"],
              ["meredians"],
              ["mousewheel"]
          ].reduce(createAttrConcat, '') +
            createEvalAttr("readonlyInput", "readonlyTime") +
            "></timepicker>\n" +
            "
";
          return tmpl;
        },
        controller: ['$scope',
          function($scope) {
            $scope.time_change = function() {
              if (angular.isDefined($scope.ngModel) && angular.isDefined($scope.time)) {
                $scope.ngModel.setHours($scope.time.getHours(), $scope.time.getMinutes());
              }
            }
            $scope.open = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              $scope.opened = true;
            };
          }
        ],
        link: function(scope) {
          scope.$watch(function() {
            return scope.ngModel;
          }, function(ngModel) {
            scope.time = ngModel;
          });
        }
      }
    }
  ]);
<commit_msg>Removed redundant datetimepicker declaration<commit_after>'use strict';

angular.module('app.directives', []);<|endoftext|>


<commit_before>(function () {
  var app = angular.module('jumpstarter',
    ['ui.bootstrap', 'tabs', 'basic', 'barracks', 'research', 'items', 'facilities', 'world', 'airforce']);

  // Services
  app.factory('auth', ['$http', '$window', function ($http, $window) {
    var auth = {};

    auth.saveToken = function(token) {
      $window.localStorage['jumpstarter-token'] = token;
    };

    auth.getToken = function(token) {
      return $window.localStorage['jumpstarter-token'];
    };

    auth.getPayload = function(token) {
      return JSON.parse($window.atob(token.split('.')[1]));
    };

    auth.isLoggedIn = function() {
      var token = auth.getToken();
      if (token) {
        var payload = auth.getPayload(token);
        return payload.exp > Date.now() / 1000;
      } else {
        return false;
      }
    };

    auth.currentUser = function() {
      if (auth.isLoggedIn()) {
        var token = auth.getToken();
        var payload = auth.getPayload(token);
        return payload.username;
      }
    };

    auth.register = function(user) {
      return $http.post('/register', user).success(function(data) {
        auth.saveToken(data.token);
      });
    };

    auth.login = function(user) {
      return $http.post('/login', user).success(function(data) {
        auth.saveToken(data.token);
      })
    };

    auth.logout = function(user) {
      $window.localStorage.removeItem('jumpstarter-token');
    };

    return auth;
  }]);

  app.controller('JumpStarterCtrl', ['$scope', '$http', function ($scope, $http) {
    $scope.Ranks = [
      { name: "PFC", enum: "eRank_Rookie" },
      { name: "SPEC", enum: "eRank_Squaddie" },
      { name: "LCPL", enum: "eRank_Corporal" },
      { name: "CPL", enum: "eRank_Sergeant" },
      { name: "SGT", enum: "eRank_Lieutenant" },
      { name: "TSGT", enum: "eRank_Captain" },
      { name: "GSGT", enum: "eRank_Major" },
      { name: "MSGT", enum: "eRank_Colonel" }
    ];

    $scope.Classes = [
      { name: "None", enum: "eSC_None" },
      { name: "Sniper", enum: 11 },
      { name: "Scout", enum: 21 },
      { name: "Assault", enum: 14 },
      { name: "Infantry", enum: 24 },
      { name: "Rocketeer", enum: 12 },
      { name: "Gunner", enum: 22 },
      { name: "Medic", enum: 13 },
      { name: "Engineer", enum: 23 }
    ];

    $scope.Genders = [
      { name: "", enum: "eGender_None" },
      { name: "M", enum: "eGender_Male" },
      { name: "F", enum: "eGender_Female" }
    ];

    $scope.Countries = [
      "Unspecified"
    ];

    $scope.PsiRanks = [
      { name: "None", enum: 0 },
      { name: "Awakened", enum: 1 },
      { name: "Sensitive", enum: 2 },
      { name: "Talent", enum: 3 },
      { name: "Adept", enum: 4 },
      { name: "Psion", enum: 5 },
      { name: "Master", enum: 6 }
    ];

    $scope.Continents = [
      { enum: "eContinent_NorthAmerica", name: "North America" },
      { enum: "eContinent_SouthAmerica", name: "South America" },
      { enum: "eContinent_Europe", name: "Europe" },
      { enum: "eContinent_Africa", name: "Africa" },
      { enum: "eContinent_Asia", name: "Asia" }
    ];

    $scope.Tiles = [
      { "enum": "eTile_Excavated", "name": "Excavated Tile" },
      { "enum": "eTile_Steam", "name": "Steam Vent" },
      { "enum": "eTile_ExcavatedSteam", "name": "Excavated Steam" }
    ];

    $scope.getNameFromEnum = function (dataSet, enumVal) {
      if (dataSet.length == 0)
      {
        return "";
      }

      var results = dataSet.filter(function (v) {
        return v.enum === enumVal;
      });
      if (results.length == 0) {
        return "";
      }
      return results[0].name;
    };

    $scope.getPerkName = function (perkEnum) {
      return $scope.getNameFromEnum($scope.Perks, perkEnum);
    };

    $scope.getItemName = function(itemEnum) {
      return $scope.getNameFromEnum($scope.Items, itemEnum);
    };

    $scope.getFacilityOrTileName = function(facEnum) {
      var name = $scope.getNameFromEnum($scope.Facilities, facEnum);
      if (name != "")
        return name;
      else
        return $scope.getNameFromEnum($scope.Tiles, facEnum);
    };

    $scope.getCountryName = function(countryEnum) {
        return $scope.getNameFromEnum($scope.CouncilMembers, countryEnum);
    };

    $scope.getContinentName = function(continentEnum) {
      return $scope.getNameFromEnum($scope.Continents, continentEnum);
    };

    $scope.getResearchName = function(e) {
      return $scope.getNameFromEnum($scope.Research, e);
    };

    $scope.getFoundryName = function(e) {
      return $scope.getNameFromEnum($scope.Foundry, e);
    };

    $scope.getOTSName = function(e) {
      return $scope.getNameFromEnum($scope.OTS, e);
    };

    $scope.getClassName = function(e) {
      return $scope.getNameFromEnum($scope.Classes, e);
    };

    $scope.getRankName = function(e) {
      return $scope.getNameFromEnum($scope.Ranks, e);
    };

    $scope.getRankIndex = function(r) {
      for (var i = 0; i < $scope.Ranks.length; ++i) {
        if ($scope.Ranks[i].enum === r) {
          return i;
        }
      }
      return -1;
    };

    $scope.getPsiRankIndex = function(r) {
      for (var i = 0; i < $scope.PsiRanks.length; ++i) {
        if ($scope.PsiRanks[i].enum === r) {
          return i;
        }
      }
      return -1;
    };

    $scope.getCountryIndex = function(countryName) {
      return $scope.Countries.indexOf(countryName)-1;
    };

    $http.get("data/countries.json").then(function (response) {
      $scope.Countries = response.data;
    });

    $http.get("data/class-perks.json").then(function (response) {
      $scope.ClassPerks = response.data;
    });

    $http.get("data/perks.json").then(function (response) {
      $scope.Perks = response.data;
    });

    $http.get("data/psi-perks.json").then(function (response) {
      $scope.PsiPerks = response.data;
    });

    $http.get("data/class-stats.json").then(function (response) {
      $scope.ClassStats = response.data;
    });

    $http.get("data/research.json").then(function (response) {
      $scope.Research = response.data;
    });

    $http.get("data/foundry.json").then(function (response) {
      $scope.Foundry = response.data;
    });

    $http.get("data/ots.json").then(function (response) {
      $scope.OTS = response.data;
    });

    $http.get("data/items.json").then(function (response) {
      $scope.Items = response.data;
    });

    $http.get("data/ship-weapons.json").then(function (response) {
      $scope.ShipWeapons = response.data;
    });

    $http.get("data/facilities.json").then(function (response) {
      $scope.Facilities = response.data;
    });

    $http.get("data/council-members.json").then(function (response) {
        $scope.CouncilMembers = response.data;
    });

    $scope.ini = {
      title: "",
      author: "",
      startDate: "",
      exaltClues: -1,
      slingshotDelay: -1,
      alienResearch: -1,
      alienResources: -1,
      xcomThreat: -1,
      credits: -1,
      fragments: -1,
      alloys: -1,
      elerium: -1,
      scientists: -1,
      engineers: -1,
      meld: -1,
      randombases: -1,

      soldiers: [],
      bulkSoldiers: [0, 0, 0, 0, 0, 0, 0, 0],
      research: [],
      foundry: [],
      ots: [],
      items: [],
      facilities: [
        ["eFacility_None", "eFacility_None", "eFacility_SmallRadar", "eFacility_AccessLift", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"]
      ],
      countries: {},
      airforce: []
    };

    $scope.ini.countries.eCountry_Canada = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_USA = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Mexico = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Argentina = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Brazil = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Egypt = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Nigeria = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_SouthAfrica = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_UK = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_France = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Germany = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Russia = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_India = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_China = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Japan = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Australia = {panic: 0, satellite:false, alienbase:false};

    this.buildIni = function() {
     $http.post("/buildini", $scope.ini).then(function (response) {
       var blob = new Blob([response.data], {type: "text/plain"});
       var url = window.URL || window.webkitURL;
       var link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
       var event = document.createEvent("MouseEvents");

       link.href=  url.createObjectURL(blob);
       link.download = "DefaultJumpStart.ini";
       event.initEvent('click', true, false);
       link.dispatchEvent(event);
      });
    }

  }]);

  // Workaround for triggering change events on keyboard use with select elements.
  app.directive("select", function () {
    return {
      restrict: "E",
      require: "?ngModel",
      scope: false,
      link: function (scope, element, attrs, ngModel) {
        if (!ngModel) {
          return;
        }
        element.bind("keyup", function () {
          element.triggerHandler("change");
        })
      }
    }
  });

  app.directive('selectListPanel', function() {
    return {
      restrict: "E",
      scope: {
        title: "@",
        list: "=",
        opts: "=",
        order: "@",
        render: "&"
      },
      link: function($scope, element, attrs) {
        $scope.currentItem = "";

        $scope.addItem = function(item) {
          $scope.list.push(item);
          $scope.currentItem = "";
        };

        $scope.removeItem = function(idx) {
          $scope.list.splice(idx, 1);
        };

        $scope.isItemInvalid = function(item) {
          return item == "" || $scope.list.indexOf(item) != -1;
        };

        $scope.removePresent = function(value) {
          return $scope.list.indexOf(value.name) == -1;
        }
      },
      templateUrl: 'select-list-panel.html'
    }
  });

})();

<commit_msg>Rename excavated tile for better ordering<commit_after>(function () {
  var app = angular.module('jumpstarter',
    ['ui.bootstrap', 'tabs', 'basic', 'barracks', 'research', 'items', 'facilities', 'world', 'airforce']);

  // Services
  app.factory('auth', ['$http', '$window', function ($http, $window) {
    var auth = {};

    auth.saveToken = function(token) {
      $window.localStorage['jumpstarter-token'] = token;
    };

    auth.getToken = function(token) {
      return $window.localStorage['jumpstarter-token'];
    };

    auth.getPayload = function(token) {
      return JSON.parse($window.atob(token.split('.')[1]));
    };

    auth.isLoggedIn = function() {
      var token = auth.getToken();
      if (token) {
        var payload = auth.getPayload(token);
        return payload.exp > Date.now() / 1000;
      } else {
        return false;
      }
    };

    auth.currentUser = function() {
      if (auth.isLoggedIn()) {
        var token = auth.getToken();
        var payload = auth.getPayload(token);
        return payload.username;
      }
    };

    auth.register = function(user) {
      return $http.post('/register', user).success(function(data) {
        auth.saveToken(data.token);
      });
    };

    auth.login = function(user) {
      return $http.post('/login', user).success(function(data) {
        auth.saveToken(data.token);
      })
    };

    auth.logout = function(user) {
      $window.localStorage.removeItem('jumpstarter-token');
    };

    return auth;
  }]);

  app.controller('JumpStarterCtrl', ['$scope', '$http', function ($scope, $http) {
    $scope.Ranks = [
      { name: "PFC", enum: "eRank_Rookie" },
      { name: "SPEC", enum: "eRank_Squaddie" },
      { name: "LCPL", enum: "eRank_Corporal" },
      { name: "CPL", enum: "eRank_Sergeant" },
      { name: "SGT", enum: "eRank_Lieutenant" },
      { name: "TSGT", enum: "eRank_Captain" },
      { name: "GSGT", enum: "eRank_Major" },
      { name: "MSGT", enum: "eRank_Colonel" }
    ];

    $scope.Classes = [
      { name: "None", enum: "eSC_None" },
      { name: "Sniper", enum: 11 },
      { name: "Scout", enum: 21 },
      { name: "Assault", enum: 14 },
      { name: "Infantry", enum: 24 },
      { name: "Rocketeer", enum: 12 },
      { name: "Gunner", enum: 22 },
      { name: "Medic", enum: 13 },
      { name: "Engineer", enum: 23 }
    ];

    $scope.Genders = [
      { name: "", enum: "eGender_None" },
      { name: "M", enum: "eGender_Male" },
      { name: "F", enum: "eGender_Female" }
    ];

    $scope.Countries = [
      "Unspecified"
    ];

    $scope.PsiRanks = [
      { name: "None", enum: 0 },
      { name: "Awakened", enum: 1 },
      { name: "Sensitive", enum: 2 },
      { name: "Talent", enum: 3 },
      { name: "Adept", enum: 4 },
      { name: "Psion", enum: 5 },
      { name: "Master", enum: 6 }
    ];

    $scope.Continents = [
      { enum: "eContinent_NorthAmerica", name: "North America" },
      { enum: "eContinent_SouthAmerica", name: "South America" },
      { enum: "eContinent_Europe", name: "Europe" },
      { enum: "eContinent_Africa", name: "Africa" },
      { enum: "eContinent_Asia", name: "Asia" }
    ];

    $scope.Tiles = [
      { "enum": "eTile_Excavated", "name": "Excavated" },
      { "enum": "eTile_Steam", "name": "Steam Vent" },
      { "enum": "eTile_ExcavatedSteam", "name": "Excavated Steam" }
    ];

    $scope.getNameFromEnum = function (dataSet, enumVal) {
      if (dataSet.length == 0)
      {
        return "";
      }

      var results = dataSet.filter(function (v) {
        return v.enum === enumVal;
      });
      if (results.length == 0) {
        return "";
      }
      return results[0].name;
    };

    $scope.getPerkName = function (perkEnum) {
      return $scope.getNameFromEnum($scope.Perks, perkEnum);
    };

    $scope.getItemName = function(itemEnum) {
      return $scope.getNameFromEnum($scope.Items, itemEnum);
    };

    $scope.getFacilityOrTileName = function(facEnum) {
      var name = $scope.getNameFromEnum($scope.Facilities, facEnum);
      if (name != "")
        return name;
      else
        return $scope.getNameFromEnum($scope.Tiles, facEnum);
    };

    $scope.getCountryName = function(countryEnum) {
        return $scope.getNameFromEnum($scope.CouncilMembers, countryEnum);
    };

    $scope.getContinentName = function(continentEnum) {
      return $scope.getNameFromEnum($scope.Continents, continentEnum);
    };

    $scope.getResearchName = function(e) {
      return $scope.getNameFromEnum($scope.Research, e);
    };

    $scope.getFoundryName = function(e) {
      return $scope.getNameFromEnum($scope.Foundry, e);
    };

    $scope.getOTSName = function(e) {
      return $scope.getNameFromEnum($scope.OTS, e);
    };

    $scope.getClassName = function(e) {
      return $scope.getNameFromEnum($scope.Classes, e);
    };

    $scope.getRankName = function(e) {
      return $scope.getNameFromEnum($scope.Ranks, e);
    };

    $scope.getRankIndex = function(r) {
      for (var i = 0; i < $scope.Ranks.length; ++i) {
        if ($scope.Ranks[i].enum === r) {
          return i;
        }
      }
      return -1;
    };

    $scope.getPsiRankIndex = function(r) {
      for (var i = 0; i < $scope.PsiRanks.length; ++i) {
        if ($scope.PsiRanks[i].enum === r) {
          return i;
        }
      }
      return -1;
    };

    $scope.getCountryIndex = function(countryName) {
      return $scope.Countries.indexOf(countryName)-1;
    };

    $http.get("data/countries.json").then(function (response) {
      $scope.Countries = response.data;
    });

    $http.get("data/class-perks.json").then(function (response) {
      $scope.ClassPerks = response.data;
    });

    $http.get("data/perks.json").then(function (response) {
      $scope.Perks = response.data;
    });

    $http.get("data/psi-perks.json").then(function (response) {
      $scope.PsiPerks = response.data;
    });

    $http.get("data/class-stats.json").then(function (response) {
      $scope.ClassStats = response.data;
    });

    $http.get("data/research.json").then(function (response) {
      $scope.Research = response.data;
    });

    $http.get("data/foundry.json").then(function (response) {
      $scope.Foundry = response.data;
    });

    $http.get("data/ots.json").then(function (response) {
      $scope.OTS = response.data;
    });

    $http.get("data/items.json").then(function (response) {
      $scope.Items = response.data;
    });

    $http.get("data/ship-weapons.json").then(function (response) {
      $scope.ShipWeapons = response.data;
    });

    $http.get("data/facilities.json").then(function (response) {
      $scope.Facilities = response.data;
    });

    $http.get("data/council-members.json").then(function (response) {
        $scope.CouncilMembers = response.data;
    });

    $scope.ini = {
      title: "",
      author: "",
      startDate: "",
      exaltClues: -1,
      slingshotDelay: -1,
      alienResearch: -1,
      alienResources: -1,
      xcomThreat: -1,
      credits: -1,
      fragments: -1,
      alloys: -1,
      elerium: -1,
      scientists: -1,
      engineers: -1,
      meld: -1,
      randombases: -1,

      soldiers: [],
      bulkSoldiers: [0, 0, 0, 0, 0, 0, 0, 0],
      research: [],
      foundry: [],
      ots: [],
      items: [],
      facilities: [
        ["eFacility_None", "eFacility_None", "eFacility_SmallRadar", "eFacility_AccessLift", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"],
        ["eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None", "eFacility_None"]
      ],
      countries: {},
      airforce: []
    };

    $scope.ini.countries.eCountry_Canada = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_USA = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Mexico = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Argentina = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Brazil = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Egypt = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Nigeria = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_SouthAfrica = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_UK = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_France = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Germany = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Russia = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_India = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_China = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Japan = {panic: 0, satellite:false, alienbase:false};
    $scope.ini.countries.eCountry_Australia = {panic: 0, satellite:false, alienbase:false};

    this.buildIni = function() {
     $http.post("/buildini", $scope.ini).then(function (response) {
       var blob = new Blob([response.data], {type: "text/plain"});
       var url = window.URL || window.webkitURL;
       var link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
       var event = document.createEvent("MouseEvents");

       link.href=  url.createObjectURL(blob);
       link.download = "DefaultJumpStart.ini";
       event.initEvent('click', true, false);
       link.dispatchEvent(event);
      });
    }

  }]);

  // Workaround for triggering change events on keyboard use with select elements.
  app.directive("select", function () {
    return {
      restrict: "E",
      require: "?ngModel",
      scope: false,
      link: function (scope, element, attrs, ngModel) {
        if (!ngModel) {
          return;
        }
        element.bind("keyup", function () {
          element.triggerHandler("change");
        })
      }
    }
  });

  app.directive('selectListPanel', function() {
    return {
      restrict: "E",
      scope: {
        title: "@",
        list: "=",
        opts: "=",
        order: "@",
        render: "&"
      },
      link: function($scope, element, attrs) {
        $scope.currentItem = "";

        $scope.addItem = function(item) {
          $scope.list.push(item);
          $scope.currentItem = "";
        };

        $scope.removeItem = function(idx) {
          $scope.list.splice(idx, 1);
        };

        $scope.isItemInvalid = function(item) {
          return item == "" || $scope.list.indexOf(item) != -1;
        };

        $scope.removePresent = function(value) {
          return $scope.list.indexOf(value.name) == -1;
        }
      },
      templateUrl: 'select-list-panel.html'
    }
  });

})();

<|endoftext|>


<commit_before><commit_msg>fix(tracking): disable in dev<commit_after><|endoftext|>


<commit_before>/* @flow */
/* global TW */

import { exportData, importData } from "./actions/importExportActions";
import {
  removeAllSavedTabs,
  removeSavedTabs,
  setSavedTabs,
  setTotalTabsRemoved,
  setTotalTabsUnwrangled,
  setTotalTabsWrangled,
} from "./actions/localStorageActions";

type WrangleOption = "exactURLMatch" | "hostnameAndTitleMatch" | "withDuplicates";

// A map of tabId => timestamp
const defaultTabTimes: { [tabId: string]: number } = {};

/**
 * Stores the tabs in a separate variable to log Last Accessed time.
 * @type {Object}
 */
const TabManager = {
  tabTimes: defaultTabTimes,

  closedTabs: {
    clear() {
      TW.store.dispatch(removeAllSavedTabs());
    },

    // @todo: move to filter system for consistency
    findPositionById(id: number): ?number {
      const { savedTabs } = TW.store.getState().localStorage;
      for (let i = 0; i < savedTabs.length; i++) {
        if (savedTabs[i].id === id) {
          return i;
        }
      }
      return null;
    },

    findPositionByURL(url: ?string = ""): number {
      return TW.store.getState().localStorage.savedTabs.findIndex((item) => {
        return item.url === url && url != null;
      });
    },

    findPositionByHostnameAndTitle(url: string = "", title: string = ""): number {
      const hostB = new URL(url).hostname;
      return TW.store.getState().localStorage.savedTabs.findIndex((tab) => {
        const hostA = new URL(tab.url || "").hostname;
        return hostA === hostB && tab.title === title;
      });
    },

    unwrangleTabs(sessionTabs: Array<{ session: ?chrome$Session, tab: chrome$Tab }>) {
      const { localStorage } = TW.store.getState();
      const installDate = localStorage.installDate;
      let countableTabsUnwrangled = 0;
      sessionTabs.forEach((sessionTab) => {
        if (sessionTab.session == null || sessionTab.session.tab == null) {
          chrome.tabs.create({ active: false, url: sessionTab.tab.url });
        } else {
          chrome.sessions.restore(sessionTab.session.tab.sessionId);
        }

        // Count only those tabs closed after install date because users who upgrade will not have
        // an accurate count of all tabs closed. The updaters' install dates will be the date of
        // the upgrade, after which point TW will keep an accurate count of closed tabs.
        // $FlowFixMe
        if (sessionTab.tab.closedAt >= installDate) countableTabsUnwrangled++;
      });

      // Done opening them all, now get all of the restored tabs out of the store.
      TW.store.dispatch(removeSavedTabs(sessionTabs.map((sessionTab) => sessionTab.tab)));

      const totalTabsUnwrangled = localStorage.totalTabsUnwrangled;
      TW.store.dispatch(setTotalTabsUnwrangled(totalTabsUnwrangled + countableTabsUnwrangled));
    },

    getURLPositionFilterByWrangleOption(option: WrangleOption): (tab: chrome$Tab) => number {
      if (option === "hostnameAndTitleMatch") {
        return (tab: chrome$Tab): number => {
          return TabManager.closedTabs.findPositionByHostnameAndTitle(tab.url, tab.title);
        };
      } else if (option === "exactURLMatch") {
        return (tab: chrome$Tab): number => {
          return TabManager.closedTabs.findPositionByURL(tab.url);
        };
      }

      // `'withDupes'` && default
      return () => {
        return -1;
      };
    },

    wrangleTabs(tabs: Array<Object>) {
      const maxTabs = TW.settings.get("maxTabs");
      let totalTabsWrangled = TW.store.getState().localStorage.totalTabsWrangled;
      const wrangleOption = TW.settings.get("wrangleOption");
      const findURLPositionByWrangleOption = this.getURLPositionFilterByWrangleOption(
        wrangleOption
      );

      let nextSavedTabs = TW.store.getState().localStorage.savedTabs.slice();
      for (let i = 0; i < tabs.length; i++) {
        if (tabs[i] === null) {
          console.log("Weird bug, backtrace this...");
        }

        const existingTabPosition = findURLPositionByWrangleOption(tabs[i]);
        const closingDate = new Date().getTime();

        if (existingTabPosition > -1) {
          nextSavedTabs.splice(existingTabPosition, 1);
        }

        tabs[i].closedAt = closingDate;
        nextSavedTabs.unshift(tabs[i]);
        totalTabsWrangled += 1;

        // Close it in Chrome.
        chrome.tabs.remove(tabs[i].id);
      }

      if (nextSavedTabs.length - maxTabs > 0) {
        nextSavedTabs = nextSavedTabs.splice(0, maxTabs);
      }

      TW.store.dispatch(setSavedTabs(nextSavedTabs));
      TW.store.dispatch(setTotalTabsWrangled(totalTabsWrangled));
    },
  },

  initTabs(tabs: Array<chrome$Tab>) {
    for (let i = 0; i < tabs.length; i++) {
      TabManager.updateLastAccessed(tabs[i]);
    }
  },

  /* Re-export so these can be executed in the context of the Tab Manager. */
  exportData,
  importData,

  /**
   * Wrapper function to get all tab times regardless of time inactive
   * @return {Array}
   */
  getAll(): Array<number> {
    return TabManager.getOlderThen();
  },

  /**
   * Returns tab times (hash of tabId : lastAccess)
   * @param time
   *  If null, returns all.
   * @return {Array}
   */
  getOlderThen(time?: number): Array<number> {
    const ret = [];
    for (const i in this.tabTimes) {
      if (Object.prototype.hasOwnProperty.call(this.tabTimes, i)) {
        if (!time || this.tabTimes[i] < time) {
          ret.push(parseInt(i, 10));
        }
      }
    }
    return ret;
  },

  getWhitelistMatch(url: string): boolean {
    const whitelist = TW.settings.get("whitelist");
    for (let i = 0; i < whitelist.length; i++) {
      if (url.indexOf(whitelist[i]) !== -1) {
        return whitelist[i];
      }
    }
    return false;
  },

  isLocked(tabId: number): boolean {
    const lockedIds = TW.settings.get("lockedIds");
    if (lockedIds.indexOf(tabId) !== -1) {
      return true;
    }
    return false;
  },

  isWhitelisted(url: string): boolean {
    return this.getWhitelistMatch(url) !== false;
  },

  lockTab(tabId: number) {
    const lockedIds = TW.settings.get("lockedIds");

    if (tabId > 0 && lockedIds.indexOf(tabId) === -1) {
      lockedIds.push(tabId);
    }
    TW.settings.set("lockedIds", lockedIds);
  },

  removeTab(tabId: number) {
    const totalTabsRemoved = TW.store.getState().localStorage.totalTabsRemoved;
    TW.store.dispatch(setTotalTabsRemoved(totalTabsRemoved + 1));
    delete TabManager.tabTimes[String(tabId)];
  },

  replaceTab(addedTabId: number, removedTabId: number) {
    TabManager.removeTab(removedTabId);
    TabManager.updateLastAccessed(addedTabId);
  },

  unlockTab(tabId: number) {
    const lockedIds = TW.settings.get("lockedIds");
    if (lockedIds.indexOf(tabId) > -1) {
      lockedIds.splice(lockedIds.indexOf(tabId), 1);
    }
    TW.settings.set("lockedIds", lockedIds);
  },

  updateClosedCount() {
    let text;
    if (TW.settings.get("showBadgeCount")) {
      const savedTabsLength = TW.store.getState().localStorage.savedTabs.length;
      text = savedTabsLength.length === 0 ? "" : savedTabsLength.toString();
    } else {
      text = "";
    }
    chrome.browserAction.setBadgeText({ text });
  },

  updateLastAccessed(tabOrTabId: chrome$Tab | number | Array<chrome$Tab>) {
    let tabId;
    if (Array.isArray(tabOrTabId)) {
      tabOrTabId.map(TabManager.updateLastAccessed.bind(this));
      return;
    } else if (typeof tabOrTabId === "number") {
      tabId = tabOrTabId;
      TabManager.tabTimes[String(tabId)] = new Date().getTime();
    } else {
      tabId = tabOrTabId.id;
      TabManager.tabTimes[String(tabId)] = tabOrTabId?.lastAccessed ?? new Date().getTime();
    }

    if (typeof tabId !== "number") {
      console.log("Error: `tabId` is not an number", tabId);
      return;
    }
  },
};

export default TabManager;
<commit_msg>Check for non-number Tab ID early on.<commit_after>/* @flow */
/* global TW */

import { exportData, importData } from "./actions/importExportActions";
import {
  removeAllSavedTabs,
  removeSavedTabs,
  setSavedTabs,
  setTotalTabsRemoved,
  setTotalTabsUnwrangled,
  setTotalTabsWrangled,
} from "./actions/localStorageActions";

type WrangleOption = "exactURLMatch" | "hostnameAndTitleMatch" | "withDuplicates";

// A map of tabId => timestamp
const defaultTabTimes: { [tabId: string]: number } = {};

/**
 * Stores the tabs in a separate variable to log Last Accessed time.
 * @type {Object}
 */
const TabManager = {
  tabTimes: defaultTabTimes,

  closedTabs: {
    clear() {
      TW.store.dispatch(removeAllSavedTabs());
    },

    // @todo: move to filter system for consistency
    findPositionById(id: number): ?number {
      const { savedTabs } = TW.store.getState().localStorage;
      for (let i = 0; i < savedTabs.length; i++) {
        if (savedTabs[i].id === id) {
          return i;
        }
      }
      return null;
    },

    findPositionByURL(url: ?string = ""): number {
      return TW.store.getState().localStorage.savedTabs.findIndex((item) => {
        return item.url === url && url != null;
      });
    },

    findPositionByHostnameAndTitle(url: string = "", title: string = ""): number {
      const hostB = new URL(url).hostname;
      return TW.store.getState().localStorage.savedTabs.findIndex((tab) => {
        const hostA = new URL(tab.url || "").hostname;
        return hostA === hostB && tab.title === title;
      });
    },

    unwrangleTabs(sessionTabs: Array<{ session: ?chrome$Session, tab: chrome$Tab }>) {
      const { localStorage } = TW.store.getState();
      const installDate = localStorage.installDate;
      let countableTabsUnwrangled = 0;
      sessionTabs.forEach((sessionTab) => {
        if (sessionTab.session == null || sessionTab.session.tab == null) {
          chrome.tabs.create({ active: false, url: sessionTab.tab.url });
        } else {
          chrome.sessions.restore(sessionTab.session.tab.sessionId);
        }

        // Count only those tabs closed after install date because users who upgrade will not have
        // an accurate count of all tabs closed. The updaters' install dates will be the date of
        // the upgrade, after which point TW will keep an accurate count of closed tabs.
        // $FlowFixMe
        if (sessionTab.tab.closedAt >= installDate) countableTabsUnwrangled++;
      });

      // Done opening them all, now get all of the restored tabs out of the store.
      TW.store.dispatch(removeSavedTabs(sessionTabs.map((sessionTab) => sessionTab.tab)));

      const totalTabsUnwrangled = localStorage.totalTabsUnwrangled;
      TW.store.dispatch(setTotalTabsUnwrangled(totalTabsUnwrangled + countableTabsUnwrangled));
    },

    getURLPositionFilterByWrangleOption(option: WrangleOption): (tab: chrome$Tab) => number {
      if (option === "hostnameAndTitleMatch") {
        return (tab: chrome$Tab): number => {
          return TabManager.closedTabs.findPositionByHostnameAndTitle(tab.url, tab.title);
        };
      } else if (option === "exactURLMatch") {
        return (tab: chrome$Tab): number => {
          return TabManager.closedTabs.findPositionByURL(tab.url);
        };
      }

      // `'withDupes'` && default
      return () => {
        return -1;
      };
    },

    wrangleTabs(tabs: Array<Object>) {
      const maxTabs = TW.settings.get("maxTabs");
      let totalTabsWrangled = TW.store.getState().localStorage.totalTabsWrangled;
      const wrangleOption = TW.settings.get("wrangleOption");
      const findURLPositionByWrangleOption = this.getURLPositionFilterByWrangleOption(
        wrangleOption
      );

      let nextSavedTabs = TW.store.getState().localStorage.savedTabs.slice();
      for (let i = 0; i < tabs.length; i++) {
        if (tabs[i] === null) {
          console.log("Weird bug, backtrace this...");
        }

        const existingTabPosition = findURLPositionByWrangleOption(tabs[i]);
        const closingDate = new Date().getTime();

        if (existingTabPosition > -1) {
          nextSavedTabs.splice(existingTabPosition, 1);
        }

        tabs[i].closedAt = closingDate;
        nextSavedTabs.unshift(tabs[i]);
        totalTabsWrangled += 1;

        // Close it in Chrome.
        chrome.tabs.remove(tabs[i].id);
      }

      if (nextSavedTabs.length - maxTabs > 0) {
        nextSavedTabs = nextSavedTabs.splice(0, maxTabs);
      }

      TW.store.dispatch(setSavedTabs(nextSavedTabs));
      TW.store.dispatch(setTotalTabsWrangled(totalTabsWrangled));
    },
  },

  initTabs(tabs: Array<chrome$Tab>) {
    for (let i = 0; i < tabs.length; i++) {
      TabManager.updateLastAccessed(tabs[i]);
    }
  },

  /* Re-export so these can be executed in the context of the Tab Manager. */
  exportData,
  importData,

  /**
   * Wrapper function to get all tab times regardless of time inactive
   * @return {Array}
   */
  getAll(): Array<number> {
    return TabManager.getOlderThen();
  },

  /**
   * Returns tab times (hash of tabId : lastAccess)
   * @param time
   *  If null, returns all.
   * @return {Array}
   */
  getOlderThen(time?: number): Array<number> {
    const ret = [];
    for (const i in this.tabTimes) {
      if (Object.prototype.hasOwnProperty.call(this.tabTimes, i)) {
        if (!time || this.tabTimes[i] < time) {
          ret.push(parseInt(i, 10));
        }
      }
    }
    return ret;
  },

  getWhitelistMatch(url: string): boolean {
    const whitelist = TW.settings.get("whitelist");
    for (let i = 0; i < whitelist.length; i++) {
      if (url.indexOf(whitelist[i]) !== -1) {
        return whitelist[i];
      }
    }
    return false;
  },

  isLocked(tabId: number): boolean {
    const lockedIds = TW.settings.get("lockedIds");
    if (lockedIds.indexOf(tabId) !== -1) {
      return true;
    }
    return false;
  },

  isWhitelisted(url: string): boolean {
    return this.getWhitelistMatch(url) !== false;
  },

  lockTab(tabId: number) {
    const lockedIds = TW.settings.get("lockedIds");

    if (tabId > 0 && lockedIds.indexOf(tabId) === -1) {
      lockedIds.push(tabId);
    }
    TW.settings.set("lockedIds", lockedIds);
  },

  removeTab(tabId: number) {
    const totalTabsRemoved = TW.store.getState().localStorage.totalTabsRemoved;
    TW.store.dispatch(setTotalTabsRemoved(totalTabsRemoved + 1));
    delete TabManager.tabTimes[String(tabId)];
  },

  replaceTab(addedTabId: number, removedTabId: number) {
    TabManager.removeTab(removedTabId);
    TabManager.updateLastAccessed(addedTabId);
  },

  unlockTab(tabId: number) {
    const lockedIds = TW.settings.get("lockedIds");
    if (lockedIds.indexOf(tabId) > -1) {
      lockedIds.splice(lockedIds.indexOf(tabId), 1);
    }
    TW.settings.set("lockedIds", lockedIds);
  },

  updateClosedCount() {
    let text;
    if (TW.settings.get("showBadgeCount")) {
      const savedTabsLength = TW.store.getState().localStorage.savedTabs.length;
      text = savedTabsLength.length === 0 ? "" : savedTabsLength.toString();
    } else {
      text = "";
    }
    chrome.browserAction.setBadgeText({ text });
  },

  updateLastAccessed(tabOrTabId: chrome$Tab | number | Array<chrome$Tab>) {
    let tabId;
    if (Array.isArray(tabOrTabId)) {
      tabOrTabId.map(TabManager.updateLastAccessed.bind(this));
      return;
    } else if (typeof tabOrTabId !== "number" && typeof tabOrTabId.id !== "number") {
      console.log("Error: `tabOrTabId.id` is not an number", tabOrTabId.id);
      return;
    } else if (typeof tabOrTabId === "number") {
      tabId = tabOrTabId;
      TabManager.tabTimes[String(tabId)] = new Date().getTime();
    } else {
      tabId = tabOrTabId.id;
      TabManager.tabTimes[String(tabId)] = tabOrTabId?.lastAccessed ?? new Date().getTime();
    }
  },
};

export default TabManager;
<|endoftext|>


<commit_before>define(['jquery', 'appearanceUtils'], function($, utils) {
   return {
      // where
      selector: function(pull) {
         return pull.state == 'open';
      },
      // order by
      sort: function(pull) {
         return pull.created_at;
      },
      // Allows custom modifications of each pull's display
      adjust: function(pull, node) {
         // If the pull is over 30 days old...
         if (Date.now() - (new Date(pull.created_at)) > 2590000000 ) {
            // Mark it in red
            $(node).addClass('bg-warning');
         }
      },
      navbar: "#restore-buttons",
      // Functions to stick status information in indicators at the bottom of each pull
      indicators: {
         qa_remaining: function qa_remaining(pull, node) {
            var required = pull.status.qa_req;
            var completed = pull.status.QA.length;
            node.text("QA " + completed + "/" + required);
         },
         cr_remaining: function cr_remaining(pull, node) {
            var required = pull.status.cr_req;
            var completed = pull.status.CR.length;
            node.text("CR " + completed + "/" + required);
         },
         status: function status(pull, node) {
            if (pull.status.commit_status) {
            var commit_status = pull.status.commit_status.data;
               var title = commit_status.description;
               var url   = commit_status.target_url;
               var state = commit_status.state;

               var link = $('');
               node.append(link);
               link.tooltip();
               switch(commit_status.state) {
                  case 'pending':
                  link.append('');
                  break;
                  case 'success':
                  link.append('');
                  break;
                  case 'error':
                  link.append('');
                  break;
                  case 'failure':
                  link.append('');
                  break;
               }
            }
         },
         user_icon: function user_icon(pull, node) {
            if (pull.is_mine()) {
               node.append('');
            }
         }
      },
      columns: [
         {
            title: "Special Pulls",
            id: "uniqPulls",
            selector: function(pull) {
               return (pull.deploy_blocked() || pull.status.ready) && !pull.dev_blocked();
            },
            sort: function(pull) {
               return pull.deploy_blocked() ? 0 : 1;
            },
            adjust: function(pull, node) {
               if (pull.deploy_blocked()) {
                  node.addClass('list-group-item-danger');
               }
            },
            triggers: {
               onCreate: function(blob, container) {
                  blob.removeClass('panel-default').addClass('panel-primary');
               },
               onUpdate: function(blob, container) {
                  utils.hideIfEmpty(container, blob, '.pull');
               }
            },
            shrinkToButton: true
         },
         {
            title: "dev_blocked Pulls",
            id: "blockPulls",
            selector: function(pull) {
               return pull.dev_blocked();
            }
         },
         {
            title: "CR Pulls",
            id: "crPulls",
            selector: function(pull) {
               return !pull.cr_done() && !pull.dev_blocked();
            },
            indicators: {
               cr_remaining: function(pull, node) {
                  var required = pull.status.cr_req;
                  var remaining = required - pull.status.CR.length;

                  if (remaining === 1) {
                     node.addClass('label label-danger');
                  }
               },
               qa_remaining: function(pull, node) {
                  var required = pull.status.qa_req;
                  var remaining = required - pull.status.QA.length;

                  if (remaining === 0) {
                     node.addClass('label label-success');
                  }
               }
            }
         },
         {
            title: "QA Pulls",
            id: "qaPulls",
            selector: function(pull) {
               return !pull.qa_done() && !pull.dev_blocked();
            },
            indicators: {
               qa_remaining: function(pull, node) {
                  var required = pull.status.qa_req;
                  var remaining = required - pull.status.QA.length;

                  if (remaining === 1) {
                     node.addClass('label label-danger');
                  }
               },
               cr_remaining: function(pull, node) {
                  var required = pull.status.cr_req;
                  var remaining = required - pull.status.CR.length;

                  if (remaining === 0) {
                     node.addClass('label label-success');
                  }
               }
            }

         }
      ]
   };
});
<commit_msg>Color status indicators<commit_after>define(['jquery', 'appearanceUtils'], function($, utils) {
   return {
      // where
      selector: function(pull) {
         return pull.state == 'open';
      },
      // order by
      sort: function(pull) {
         return pull.created_at;
      },
      // Allows custom modifications of each pull's display
      adjust: function(pull, node) {
         // If the pull is over 30 days old...
         if (Date.now() - (new Date(pull.created_at)) > 2590000000 ) {
            // Mark it in red
            $(node).addClass('bg-warning');
         }
      },
      navbar: "#restore-buttons",
      // Functions to stick status information in indicators at the bottom of each pull
      indicators: {
         qa_remaining: function qa_remaining(pull, node) {
            var required = pull.status.qa_req;
            var completed = pull.status.QA.length;
            node.text("QA " + completed + "/" + required);
         },
         cr_remaining: function cr_remaining(pull, node) {
            var required = pull.status.cr_req;
            var completed = pull.status.CR.length;
            node.text("CR " + completed + "/" + required);
         },
         status: function status(pull, node) {
            if (pull.status.commit_status) {
            var commit_status = pull.status.commit_status.data;
               var title = commit_status.description;
               var url   = commit_status.target_url;
               var state = commit_status.state;

               var link = $('');
               node.append(link);
               link.tooltip();
               switch(commit_status.state) {
                  case 'pending':
                  link.append('');
                  break;
                  case 'success':
                  link.append('');
                  break;
                  case 'error':
                  link.append('');
                  break;
                  case 'failure':
                  link.append('');
                  break;
               }
            }
         },
         user_icon: function user_icon(pull, node) {
            if (pull.is_mine()) {
               node.append('');
            }
         }
      },
      columns: [
         {
            title: "Special Pulls",
            id: "uniqPulls",
            selector: function(pull) {
               return (pull.deploy_blocked() || pull.status.ready) && !pull.dev_blocked();
            },
            sort: function(pull) {
               return pull.deploy_blocked() ? 0 : 1;
            },
            adjust: function(pull, node) {
               if (pull.deploy_blocked()) {
                  node.addClass('list-group-item-danger');
               }
            },
            triggers: {
               onCreate: function(blob, container) {
                  blob.removeClass('panel-default').addClass('panel-primary');
               },
               onUpdate: function(blob, container) {
                  utils.hideIfEmpty(container, blob, '.pull');
               }
            },
            shrinkToButton: true
         },
         {
            title: "dev_blocked Pulls",
            id: "blockPulls",
            selector: function(pull) {
               return pull.dev_blocked();
            }
         },
         {
            title: "CR Pulls",
            id: "crPulls",
            selector: function(pull) {
               return !pull.cr_done() && !pull.dev_blocked();
            },
            indicators: {
               cr_remaining: function(pull, node) {
                  var required = pull.status.cr_req;
                  var remaining = required - pull.status.CR.length;

                  if (remaining === 1) {
                     node.addClass('label label-danger');
                  }
               },
               qa_remaining: function(pull, node) {
                  var required = pull.status.qa_req;
                  var remaining = required - pull.status.QA.length;

                  if (remaining === 0) {
                     node.addClass('label label-success');
                  }
               }
            }
         },
         {
            title: "QA Pulls",
            id: "qaPulls",
            selector: function(pull) {
               return !pull.qa_done() && !pull.dev_blocked();
            },
            indicators: {
               qa_remaining: function(pull, node) {
                  var required = pull.status.qa_req;
                  var remaining = required - pull.status.QA.length;

                  if (remaining === 1) {
                     node.addClass('label label-danger');
                  }
               },
               cr_remaining: function(pull, node) {
                  var required = pull.status.cr_req;
                  var remaining = required - pull.status.CR.length;

                  if (remaining === 0) {
                     node.addClass('label label-success');
                  }
               }
            }

         }
      ]
   };
});
<|endoftext|>


<commit_before>import mongoose from 'mongoose';
import request from 'supertest-as-promised';
import httpStatus from 'http-status';
import chai, { expect } from 'chai';
import app from '../../index';

chai.config.includeStack = true;

/**
 * root level hooks
 */
after((done) => {
  // required because https://github.com/Automattic/mongoose/issues/1251#issuecomment-65793092
  mongoose.models = {};
  mongoose.modelSchemas = {};
  mongoose.connection.close();
  done();
});

describe('## Issue APIs', () => {
  let issue = {
    code: 'test',
    context: '<title>WordPress.com: Create a free we...</title>',
    message: 'Check that the title element describes the document.',
    selector: 'html > head > title',
    type: 'notice',
    typeCode: '3',
    reportId: '58dd2c6038880c5fe44825b6',
    url: 'url'
  };
  let issue2;

  describe('# POST /api/issues', () => {
    it('should create a new issue', (done) => {
      request(app)
        .post('/api/issues')
        .send(issue)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal(issue.code);
          expect(res.body.context).to.equal(issue.context);
          expect(res.body.message).to.equal(issue.message);
          expect(res.body.selector).to.equal(issue.selector);
          expect(res.body.context).to.equal(issue.context);
          expect(res.body.type).to.equal(issue.type);
          expect(res.body.reportId).to.equal(issue.reportId);
          expect(res.body.url).to.equal(issue.url);
          issue = res.body;
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues', () => {
    it('should get issue listing', (done) => {
      // newly installed versions may have a new DB
      // we need to post an issue first to see a list (more than one)
      issue2 = issue;
      request(app)
        .post('/api/issues')
        .send(issue2)
        .then((res) => {
          issue2 = res.body;
          request(app)
            .get('/api/issues')
            .expect(httpStatus.OK);
        })
        .catch(done);
      done();
    });

    it('should respect limit and query parameter', (done) => {
      request(app)
        .get('/api/issues')
        .query({ limit: 1, skip: 1 })
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.length).to.equal(1);
          expect(res.body[0]._id).to.equal(issue._id);
          done();
        })
        .catch(done);
    });

    it('should report error with message - Not found, when issue does not exists', (done) => {
      request(app)
        .get('/api/issues/56c787ccc67fc16ccc1a5e92')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Not Found');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues/:issueId', () => {
    it('should get issue details', (done) => {
      request(app)
        .get(`/api/issues/${issue._id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal(issue.code);
          expect(res.body.context).to.equal(issue.context);
          expect(res.body.message).to.equal(issue.message);
          expect(res.body.selector).to.equal(issue.selector);
          expect(res.body.context).to.equal(issue.context);
          expect(res.body.type).to.equal(issue.type);
          expect(res.body.reportId).to.equal(issue.reportId);
          expect(res.body.url).to.equal(issue.url);
          done();
        })
        .catch(done);
    });

    it('should report error with message - Not found, when issue does not exists', (done) => {
      request(app)
        .get('/api/issues/56c787ccc67fc16ccc1a5e92')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Not Found');
          done();
        })
        .catch(done);
    });
  });

  describe('# PUT /api/issues/:issueId', () => {
    it('should update issue details', (done) => {
      issue.code = 'KK';
      request(app)
        .put(`/api/issues/${issue._id}`)
        .send(issue)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal('KK');
          expect(res.body.context).to.equal(issue.context);
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues/', () => {
    it('should get all issues', (done) => {
      request(app)
        .get('/api/issues')
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body).to.be.an('array');
          done();
        })
        .catch(done);
    });
  });

  describe('# DELETE /api/issues/', () => {
    it('should delete issue', (done) => {
      request(app)
        .delete(`/api/issues/${issue._id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal('KK');
          expect(res.body.context).to.equal(issue.context);
          done();
        })
        // delete issue2
        .then(() => request(app)
          .delete(`/api/issues/${issue2._id}`)
          .expect(httpStatus.OK)
          .catch(done)
        );
    });
  });
});
<commit_msg>Added tests for should respect code and reportId parameters and should respect limit and skip parameters<commit_after>import mongoose from 'mongoose';
import request from 'supertest-as-promised';
import httpStatus from 'http-status';
import chai, { expect } from 'chai';
import app from '../../index';

chai.config.includeStack = true;

let issuesData = [
  {
    code: 'imageMissingAlt',
    context: '',
    message: 'Different code and reportId',
    selector: 'html > head > img',
    type: 'warning',
    typeCode: '3',
    reportId: 'c5fe44825b658dd2c6038880',
    url: 'url'
  },
  {
    code: 'inaccessibleTitle',
    context: '<title>The worst accessibility problem ever...</title>',
    message: 'Check that the title element describes the document.',
    selector: 'html > head > title',
    type: 'notice',
    typeCode: '3',
    reportId: '58dd2c6038880c5fe44825b6',
    url: 'url'
  },
  {
    code: 'imageMissingAlt',
    context: '',
    message: 'Check that the image has alt text.',
    selector: 'html > head > img',
    type: 'warning',
    typeCode: '3',
    reportId: '58dd2c6038880c5fe44825b6',
    url: 'url'
  }
];

let lastIssue = issuesData.slice(-1)[0];

after((done) => {
  // required because https://github.com/Automattic/mongoose/issues/1251#issuecomment-65793092
  mongoose.models = {};
  mongoose.modelSchemas = {};
  mongoose.connection.close();
  done();
});

describe('## Issue APIs', () => {

  describe('# POST /api/issues', () => {

    it('should have test data', (done) => {
      for (let i = 0; i < issuesData.length - 1; i++) {
        request(app)
          .post('/api/issues')
          .send(issuesData[i])
          .then((res) => {
            issuesData[i] = res.body;
          });
      }
      done();
    });
    it('should create a new issue', (done) => {
      request(app)
        .post('/api/issues')
        .send(lastIssue)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal(lastIssue.code);
          expect(res.body.context).to.equal(lastIssue.context);
          expect(res.body.message).to.equal(lastIssue.message);
          expect(res.body.selector).to.equal(lastIssue.selector);
          expect(res.body.context).to.equal(lastIssue.context);
          expect(res.body.type).to.equal(lastIssue.type);
          expect(res.body.reportId).to.equal(lastIssue.reportId);
          expect(res.body.url).to.equal(lastIssue.url);
          lastIssue = res.body;
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues', () => {

    it('should get issue listing', (done) => {
      request(app)
        .get('/api/issues')
        .expect(httpStatus.OK)
        .catch(done);
      done();
    });

    it('should respect limit and skip parameters', (done) => {
      let secondIssueId;
      request(app)
        .get('/api/issues')
        .then((res) => {
          secondIssueId = res.body[1]._id;
          return request(app)
            .get('/api/issues')
            .query({ limit: 1, skip: 1 })
            .expect(httpStatus.OK);
        })
        .then((res) => {
          expect(res.body.length).to.equal(1);
          expect(res.body[0]._id).to.equal(secondIssueId);
          done();
        })
        .catch(done);
    });

    it('should respect code and reportId parameters', (done) => {
      request(app)
        .get('/api/issues')
        .query({ code: 'imageMissingAlt', reportId: 'c5fe44825b658dd2c6038880' })
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body[0].message).to.equal('Different code and reportId');
          done();
        })
        .catch(done);
    });

    it('should report error with message - Not found, when issue does not exists', (done) => {
      request(app)
        .get('/api/issues/56c787ccc67fc16ccc1a5e92')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Not Found');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues/:issueId', () => {
    it('should get issue details', (done) => {
      request(app)
        .get(`/api/issues/${lastIssue._id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal(lastIssue.code);
          expect(res.body.context).to.equal(lastIssue.context);
          expect(res.body.message).to.equal(lastIssue.message);
          expect(res.body.selector).to.equal(lastIssue.selector);
          expect(res.body.context).to.equal(lastIssue.context);
          expect(res.body.type).to.equal(lastIssue.type);
          expect(res.body.reportId).to.equal(lastIssue.reportId);
          expect(res.body.url).to.equal(lastIssue.url);
          done();
        })
        .catch(done);
    });

    it('should report error with message - Not found, when issue does not exists', (done) => {
      request(app)
        .get('/api/issues/56c787ccc67fc16ccc1a5e92')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Not Found');
          done();
        })
        .catch(done);
    });
  });

  describe('# PUT /api/issues/:issueId', () => {
    it('should update issue details', (done) => {
      lastIssue.code = 'KK';
      request(app)
        .put(`/api/issues/${lastIssue._id}`)
        .send(lastIssue)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal('KK');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /api/issues/', () => {
    it('should get all issues', (done) => {
      request(app)
        .get('/api/issues')
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body).to.be.an('array');
          done();
        })
        .catch(done);
    });
  });

  describe('# DELETE /api/issues/', () => {
    it('should delete issue', (done) => {
      // Delete all test data.
      for (let i = 0; i < issuesData.length - 1; i++) {
        let issue = issuesData[i];
        request(app)
          .delete(`/api/issues/${lastIssue._id}`);
      }
      // Test final deletion.
      let issue = issuesData[issuesData.length];
      request(app)
        .delete(`/api/issues/${lastIssue._id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          expect(res.body.code).to.equal('KK');
          expect(res.body.context).to.equal(lastIssue.context);
          done();
        })
        .catch(done);
    });
  });
});
<|endoftext|>


<commit_before>var TiBeacons = require('org.beuckman.tibeacons');

TiBeacons.addEventListener("beaconRanges", function(event) {

    for (var i in event.beacons) {
        var b = event.beacons[i];
        switch (b.proximity) {
            case "immediate":
                notify("Found "+beacon.major+"/"+beacon.minor+" in immediate proximity!");
                break;
            case "near":
                notify("Found "+beacon.major+"/"+beacon.minor+" in near proximity!");
                break;
        }
    }

});

function notify(msg) {
    var notification = Ti.App.iOS.scheduleLocalNotification({
        alertBody : msg,
        alertAction : "OK",
        userInfo : {
            "hello" : "world"
        },
        //    sound:"whoosh.mp3",
        date : new Date(new Date().getTime() + 5) // 5 milliseconds after being asked
    });
}

TiBeacons.startRangingForBeacons({
    uuid : "00000000-0000-0000-0000-000000000000",
    identifier : "TiBeacon Test"
});

<commit_msg>fixed bug in bgservice<commit_after>var TiBeacons = require('org.beuckman.tibeacons');

TiBeacons.addEventListener("beaconRanges", function(event) {

    for (var i in event.beacons) {
        var b = event.beacons[i];
        switch (b.proximity) {
            case "immediate":
                notify("Found "+b.major+"/"+b.minor+" in immediate proximity!");
                break;
            case "near":
                notify("Found "+b.major+"/"+b.minor+" in near proximity!");
                break;
        }
    }

});

function notify(msg) {
    var notification = Ti.App.iOS.scheduleLocalNotification({
        alertBody : msg,
        alertAction : "OK",
        userInfo : {
            "hello" : "world"
        },
        //    sound:"whoosh.mp3",
        date : new Date(new Date().getTime() + 5) // 5 milliseconds after being asked
    });
}

TiBeacons.startRangingForBeacons({
    uuid : "00000000-0000-0000-0000-000000000000",
    identifier : "TiBeacon Test"
});

<|endoftext|>


<commit_before>'use strict';

import path from 'path';
import fs from 'fs';

/**
 * Utility function to construct JavaScript object for directory & files structure.
 */
exports.getDirectoryTree = function directoryTree (projPath, deepScan, extensions) {
	const name = path.basename(projPath);
	const item = { projPath, name };
	item.isFile = false;
	let stats;

	try {
    stats = fs.statSync(projPath);
  } catch (e) {
    return null;
  }

	if (stats.isFile()) {
		const ext = path.extname(projPath).toLowerCase();
		if (extensions && extensions.length && extensions.indexOf(ext) === -1) {
      return null;
    }
		item.isFile = true;
		item.size = stats.size;  // File size in bytes
		item.extension = ext;
	} else if (stats.isDirectory()) {
		try {
			if(deepScan) {
				item.children = fs.readdirSync(projPath)
					.map(child => directoryTree(path.join(projPath, child), true, extensions))
					.filter(e => !!e);
			} else {
        item.children = fs.readdirSync(projPath)
        	.map(child => directoryTree(path.join(projPath, child), false, extensions))
          .filter(e => !!e);
			}
      if (!item.children.length) {
        return null;
      }
      item.size = item.children.reduce((prev, cur) => prev + cur.size, 0);
		} catch(ex) {
      /**
       * User does not have permissions, ignore directory
       */
			if (ex.code === "EACCES") {
        return null;
      }
		}
	} else {
    /**
     * Set item.size = 0 for devices, FIFO and sockets ?
     */
		return null;
	}
	return item;
}
<commit_msg>Adds comment<commit_after>'use strict';

import path from 'path';
import fs from 'fs';

/**
 * Utility function to construct object for directory & files structure
 * @param {String} projPath - project location
 * @param {Boolean} deepScan - deep scan into sub-directory
 * @param {String} extensions - file extensions
 */
exports.getDirectoryTree = function directoryTree (projPath, deepScan, extensions) {
	const name = path.basename(projPath);
	const item = { projPath, name };
	item.isFile = false;
	let stats;

	try {
    stats = fs.statSync(projPath);
  } catch (e) {
    return null;
  }

	if (stats.isFile()) {
		const ext = path.extname(projPath).toLowerCase();
		if (extensions && extensions.length && extensions.indexOf(ext) === -1) {
      return null;
    }
		item.isFile = true;
		item.size = stats.size;  // File size in bytes
		item.extension = ext;
	} else if (stats.isDirectory()) {
		try {
			if(deepScan) {
				item.children = fs.readdirSync(projPath)
					.map(child => directoryTree(path.join(projPath, child), true, extensions))
					.filter(e => !!e);
			} else {
        item.children = fs.readdirSync(projPath)
        	.map(child => directoryTree(path.join(projPath, child), false, extensions))
          .filter(e => !!e);
			}
      if (!item.children.length) {
        return null;
      }
      item.size = item.children.reduce((prev, cur) => prev + cur.size, 0);
		} catch(ex) {
      /**
       * User does not have permissions, ignore directory
       */
			if (ex.code === "EACCES") {
        return null;
      }
		}
	} else {
    /**
     * Set item.size = 0 for devices, FIFO and sockets ?
     */
		return null;
	}
	return item;
}
<|endoftext|>


<commit_before>dojo.provide("dojox.data.PersevereStore");
dojo.require("dojox.data.JsonRestStore");
dojo.require("dojox.rpc.Client"); // Persevere supports this and it improves reliability
if(dojox.rpc.OfflineRest){
	dojo.require("dojox.json.query"); // this is so we can perform queries locally
}

// PersevereStore is an extension of JsonRestStore to handle Persevere's special features

dojox.json.ref._useRefs = true; // Persevere supports referencing
dojox.json.ref.serializeFunctions = true; // Persevere supports persisted functions

dojo.declare("dojox.data.PersevereStore",dojox.data.JsonRestStore,{
	_toJsonQuery: function(args){

		// performs conversion of Dojo Data query objects and sort arrays to JSONQuery strings
		if(args.query && typeof args.query == "object"){
			// convert Dojo Data query objects to JSONQuery
			var jsonQuery = "[?(", first = true;
			for(var i in args.query){
				if(args.query[i]!="*"){ // full wildcards can be ommitted
					jsonQuery += (first ? "" : "&") + "@[" + dojo._escapeString(i) + "]=" + dojox.json.ref.toJson(args.query[i]);
					first = false;
				}
			}
			if(!first){
				// use ' instead of " for quoting in JSONQuery, and end with ]
				jsonQuery += ")]";
			}else{
				jsonQuery = "";
			}
			args.queryStr = jsonQuery.replace(/\\"|"/g,function(t){return t == '"' ? "'" : t;});
		}else if(!args.query || args.query == '*'){
			args.query = "";
		}

		var sort = args.sort;
		if(sort){
			// if we have a sort order, add that to the JSONQuery expression
			args.queryStr = args.queryStr || (typeof args.query == 'string' ? args.query : "");
			first = true;
			for(i = 0; i < sort.length; i++){
				args.queryStr += (first ? '[' : ',') + (sort[i].descending ? '\\' : '/') + "@[" + dojo._escapeString(sort[i].attribute) + "]";
				first = false;
			}
			if(!first){
				args.queryStr += ']';
			}
		}
		if(typeof args.queryStr == 'string'){
			args.queryStr = args.queryStr.replace(/\\"|"/g,function(t){return t == '"' ? "'" : t;});
			return args.queryStr;
		}
		return args.query;
	},
	fetch: function(args){
		this._toJsonQuery(args);
		return this.inherited(arguments);
	},
	isUpdateable: function(){
		if(!dojox.json.query){
			return this.inherited(arguments);
		}
		return true;
	},
	matchesQuery: function(item,request){
		if(!dojox.json.query){
			return this.inherited(arguments);
		}
		request._jsonQuery = request._jsonQuery || dojox.json.query(this._toJsonQuery(request));
		return request._jsonQuery([item]).length;
	},
	clientSideFetch: function(/*Object*/ request,/*Array*/ baseResults){
		if(!dojox.json.query){
			return this.inherited(arguments);
		}
		request._jsonQuery = request._jsonQuery || dojox.json.query(this._toJsonQuery(request));
		return request._jsonQuery(baseResults);
	},
	querySuperSet: function(argsSuper,argsSub){
		if(!dojox.json.query){
			return this.inherited(arguments);
		}
		if(!argsSuper.query){
			return argsSub.query;
		}
		return this.inherited(arguments);
	}

});
dojox.data.PersevereStore.getStores = function(/*String?*/path,/*Boolean?*/sync){
	// summary:
	//		Creates Dojo data stores for all the table/classes on a Persevere server
	// path:
	// 		URL of the Persevere server's root, this normally just "/"
	// 		which is the default value if the target is not provided
	// callback:
	// 		Allows the operation to happen asynchronously
	// return:
	// 		A map/object of datastores. The name of each property is a the name of a store,
	// 		and the value is the actual data store object.
	path = (path && (path.match(/\/$/) ? path : (path + '/'))) || '/';
	if(path.match(/^\w*:\/\//)){
		// if it is cross-domain, we will use window.name for communication
		dojo.require("dojox.io.xhrWindowNamePlugin");
		dojox.io.xhrWindowNamePlugin(path, dojox.io.xhrPlugins.fullHttpAdapter, true);
	}
	var rootService= dojox.rpc.Rest(path,true);
	var lastSync = dojox.rpc._sync;
	dojox.rpc._sync = sync;
	var dfd = rootService("root");//dojo.xhrGet({url: target, sync:!callback, handleAs:'json'});
	var results;
	dfd.addBoth(function(schemas){
		for(var i in schemas){
			if(typeof schemas[i] == 'object'){
				schemas[i] = new dojox.data.PersevereStore({target:new dojo._Url(path,i) + '',schema:schemas[i]});
			}
		}
		return (results = schemas);
	});
	dojox.rpc._sync = lastSync;
	return sync ? results : dfd;
};
dojox.data.PersevereStore.addProxy = function(){
	// summary:
	//		Invokes the XHR proxy plugin. Call this if you will be using x-site data.
	dojo.require("dojox.io.xhrPlugins"); // also not necessary, but we can register that Persevere supports proxying
	dojox.io.xhrPlugins.addProxy("/proxy/");
};
<commit_msg>Updated PersevereStore to extend JsonQueryRestStore<commit_after>dojo.provide("dojox.data.PersevereStore");
dojo.require("dojox.data.JsonQueryRestStore");
dojo.require("dojox.rpc.Client"); // Persevere supports this and it improves reliability

// PersevereStore is an extension of JsonRestStore to handle Persevere's special features

dojox.json.ref.serializeFunctions = true; // Persevere supports persisted functions

dojo.declare("dojox.data.PersevereStore",dojox.data.JsonQueryRestStore,{
});
dojox.data.PersevereStore.getStores = function(/*String?*/path,/*Boolean?*/sync){
	// summary:
	//		Creates Dojo data stores for all the table/classes on a Persevere server
	// path:
	// 		URL of the Persevere server's root, this normally just "/"
	// 		which is the default value if the target is not provided
	// sync:
	// 		Indicates that the operation should happen synchronously.
	// return:
	// 		A map/object of datastores will be returned if it is performed asynchronously,
	// 		otherwise it will return a Deferred object that will provide the map/object.
	// 		The name of each property is a the name of a store,
	// 		and the value is the actual data store object.
	path = (path && (path.match(/\/$/) ? path : (path + '/'))) || '/';
	if(path.match(/^\w*:\/\//)){
		// if it is cross-domain, we will use window.name for communication
		dojo.require("dojox.io.xhrScriptPlugin");
		dojox.io.xhrScriptPlugin(path, "callback", dojox.io.xhrPlugins.fullHttpAdapter);
	}
	var rootService= dojox.rpc.Rest(path,true);
	dojox.rpc._sync = sync;
	var dfd = rootService("Class/");//dojo.xhrGet({url: target, sync:!callback, handleAs:'json'});
	var results;
	var stores = {};
	dfd.addBoth(function(schemas){
		for(var i in schemas){
			if(typeof schemas[i] == 'object'){
				stores[schemas[i].id] = new dojox.data.PersevereStore({target:new dojo._Url(path,schemas[i].id) + '',schema:schemas[i]});
			}
		}
		return (results = stores);
	});
	return sync ? results : dfd;
};
dojox.data.PersevereStore.addProxy = function(){
	// summary:
	//		Invokes the XHR proxy plugin. Call this if you will be using x-site data.
	dojo.require("dojox.io.xhrPlugins"); // also not necessary, but we can register that Persevere supports proxying
	dojox.io.xhrPlugins.addProxy("/proxy/");
};
<|endoftext|>