diff --git a/.eslintrc.json b/.eslintrc.json index 70059ade3..83152626c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,8 +2,7 @@ "parser": "babel-eslint", "extends": [ "eslint:recommended", - "google", - "plugin:angular/johnpapa" + "google" ], "env": { "browser": true, diff --git a/beeline/SafeInterval.js b/beeline/SafeInterval.js index aeb55ff75..b181d2b5e 100644 --- a/beeline/SafeInterval.js +++ b/beeline/SafeInterval.js @@ -1,43 +1,43 @@ -import assert from 'assert'; - -export class SafeInterval { - constructor(fn, interval, retryTimeout) { - this.isRunning = false; - this.timeout = null; - - retryTimeout = retryTimeout || interval; - - //fn returns a Promise - this.loop = function() { - this.timeout = null; - - var promise = this.currentPromise = fn(); - - this.currentPromise - .then(()=>{ - if (promise == this.currentPromise && this.isRunning) { - this.timeout = setTimeout(this.loop, interval); - } - }) - .catch((err) => { - console.log(err) - if (promise == this.currentPromise && this.isRunning) { - this.timeout = setTimeout(this.loop, retryTimeout); - } - }) - }.bind(this); - } - - stop() { - this.isRunning = false; - if (this.timeout !== null) { - clearTimeout(this.timeout); - } - } - - start() { - if (this.isRunning) return; - this.isRunning = true; - this.loop(); - } -} +import assert from 'assert' + +export class SafeInterval { + constructor (fn, interval, retryTimeout) { + this.isRunning = false + this.timeout = null + + retryTimeout = retryTimeout || interval + + // fn returns a Promise + this.loop = function () { + this.timeout = null + + let promise = this.currentPromise = fn() + + this.currentPromise + .then(()=>{ + if (promise == this.currentPromise && this.isRunning) { + this.timeout = setTimeout(this.loop, interval) + } + }) + .catch((err) => { + console.log(err) + if (promise == this.currentPromise && this.isRunning) { + this.timeout = setTimeout(this.loop, retryTimeout) + } + }) + }.bind(this) + } + + stop () { + this.isRunning = false + if (this.timeout !== null) { + clearTimeout(this.timeout) + } + } + + start () { + if (this.isRunning) return + this.isRunning = true + this.loop() + } +} diff --git a/beeline/SafeScheduler.js b/beeline/SafeScheduler.js index 8ed36520d..9f80dbb1d 100644 --- a/beeline/SafeScheduler.js +++ b/beeline/SafeScheduler.js @@ -1,40 +1,40 @@ -import assert from 'assert'; - -export class SafeScheduler { - constructor(fn, hours, minutes = 0, seconds = 0) { - this.isRunning = false; - this.timeout = null; - - //fn returns a Promise - this.loop = function() { - this.timeout = null; - - fn() - .then(()=>{ - if (this.isRunning) { - this.timeout = setTimeout(this.loop, - new Date().setHours(hours, minutes, seconds) - Date.now() - ); - } - }) - .catch(() => { - if (this.isRunning) { - this.timeout = setTimeout(this.loop, 60000 /* retryTimeout */); - } - }) - }.bind(this); - } - - stop() { - this.isRunning = false; - if (this.timeout !== null) { - clearTimeout(this.timeout); - } - } - - start() { - assert (!this.isRunning); - this.isRunning = true; - this.loop(); - } -} +import assert from 'assert' + +export class SafeScheduler { + constructor (fn, hours, minutes = 0, seconds = 0) { + this.isRunning = false + this.timeout = null + + // fn returns a Promise + this.loop = function () { + this.timeout = null + + fn() + .then(()=>{ + if (this.isRunning) { + this.timeout = setTimeout(this.loop, + new Date().setHours(hours, minutes, seconds) - Date.now() + ) + } + }) + .catch(() => { + if (this.isRunning) { + this.timeout = setTimeout(this.loop, 60000 /* retryTimeout */) + } + }) + }.bind(this) + } + + stop () { + this.isRunning = false + if (this.timeout !== null) { + clearTimeout(this.timeout) + } + } + + start () { + assert(!this.isRunning) + this.isRunning = true + this.loop() + } +} diff --git a/beeline/directives/autocomplete.js b/beeline/directives/autocomplete.js index 15eff1617..10869b133 100644 --- a/beeline/directives/autocomplete.js +++ b/beeline/directives/autocomplete.js @@ -1,33 +1,32 @@ export default ['uiGmapGoogleMapApi', - function(uiGmapGoogleMapApi) { + function (uiGmapGoogleMapApi) { return { scope: true, - link(scope, element, attribute) { + link (scope, element, attribute) { uiGmapGoogleMapApi.then((googleMaps) => { - // Initialize it with google autocomplete scope.autocomplete = new googleMaps.places.Autocomplete(element[0], { - componentRestrictions: {country: 'SG'} - }); - scope.autocompleteService = new googleMaps.places.AutocompleteService(); - scope.placesService = new google.maps.places.PlacesService(element[0]); + componentRestrictions: {country: 'SG'}, + }) + scope.autocompleteService = new googleMaps.places.AutocompleteService() + scope.placesService = new google.maps.places.PlacesService(element[0]) // Bind the place change property as a listener // If a proper autocomplete option is selected then just callback // Otherwise make a best effort attempt to find one with the free text scope.autocomplete.addListener('place_changed', () => { - let place = scope.autocomplete.getPlace(); + let place = scope.autocomplete.getPlace() // Augment the object with the autocomplete string - place.description = element[0].value; + place.description = element[0].value // Also set it as the query text paramter for consistency with the // "free text" scenario - place.queryText = place.description; + place.queryText = place.description // If a proper autocomplete option is selected then just callback // Also do so if theres nothing to autocomplete if (place.geometry || place.name.length === 0) { scope.$apply(() => { - scope.$eval(attribute['placeChanged'], { '$event': place }); - }); + scope.$eval(attribute['placeChanged'], {'$event': place}) + }) } // If free text is entered then try to complete it // "free text" is an object with just a name attribute specified @@ -36,55 +35,56 @@ export default ['uiGmapGoogleMapApi', // Start by manually calling the autocomplete service scope.autocompleteService.getPlacePredictions({ componentRestrictions: {country: 'SG'}, - input: place.name + input: place.name, }, (predictions) => { // If no results found then just shortcircuit with the empty place if (!predictions || predictions.length === 0) { scope.$apply(() => { - scope.$eval(attribute['placeChanged'], { '$event': place }); - }); - return; + scope.$eval(attribute['placeChanged'], {'$event': place}) + }) + return } // Grab the top prediction and get the details // Apply the details as the full result scope.placesService.getDetails({ - placeId: predictions[0].place_id - }, result => { + placeId: predictions[0].place_id, + }, (result) => { // If we fail getting the details then shortcircuit if (!result) { scope.$apply(() => { - scope.$eval(attribute['placeChanged'], { '$event': place }); - }); - return; + scope.$eval(attribute['placeChanged'], {'$event': place}) + }) + return } // Otherwise return the fully formed place - place = result; + place = result // Augment the object with the prediction string - place.description = predictions[0].description; + place.description = predictions[0].description // Augment the query result with the original query text - place.queryText = element[0].value; + place.queryText = element[0].value // Return the found place scope.$apply(() => { - scope.$eval(attribute['placeChanged'], { '$event': place }); - }); - }); - }); + scope.$eval(attribute['placeChanged'], {'$event': place}) + }) + }) + }) } - }); + }) // Blur on enter - element[0].addEventListener("keypress", function(event) { - if (event.key === "Enter") this.blur(); - }); + element[0].addEventListener('keypress', function (event) { + if (event.key === 'Enter') this.blur() + }) // Hack to get ionic fast tap working nicely with google maps // see http://ionicframework.com/docs/v1/api/page/tap/ - element[0].addEventListener("focus", function(event) { - const pacContainers = document.querySelectorAll('.pac-container'); - for (let pac of pacContainers) { pac.dataset.tapDisabled = true; } - }); - - }); - } + element[0].addEventListener('focus', function (event) { + const pacContainers = document.querySelectorAll('.pac-container') + for (let pac of pacContainers) { + pac.dataset.tapDisabled = true +} + }) + }) + }, } }] diff --git a/beeline/directives/beelineBindHtml.js b/beeline/directives/beelineBindHtml.js index 0c55c4aed..28cbf7b0b 100644 --- a/beeline/directives/beelineBindHtml.js +++ b/beeline/directives/beelineBindHtml.js @@ -4,27 +4,26 @@ export default ['$compile', function ($compile) { return { restrict: 'A', scope: false, - link(scope, elem, attrs) { + link (scope, elem, attrs) { scope.$watch(attrs.beelineBindHtml, (html) => { - elem[0].innerHTML = html || ''; + elem[0].innerHTML = html || '' scope.$openOpenLink = (href) => { if (typeof cordova !== 'undefined') { - cordova.InAppBrowser.open(href, '_system'); + cordova.InAppBrowser.open(href, '_system') + } else { + window.open(href, '_blank') } - else { - window.open(href, '_blank'); - } - }; + } angular.forEach(elem.find('a'), (value, key) => { - if (!value.href) return; + if (!value.href) return - value.setAttribute("ng-click", `$openOpenLink(${JSON.stringify(value.href)})`) + value.setAttribute('ng-click', `$openOpenLink(${JSON.stringify(value.href)})`) - $compile(value)(scope); + $compile(value)(scope) }) }) - } + }, } }] diff --git a/beeline/directives/bookingBreadcrumbs/bookingBreadcrumbs.js b/beeline/directives/bookingBreadcrumbs/bookingBreadcrumbs.js index 166bfb974..3542af675 100644 --- a/beeline/directives/bookingBreadcrumbs/bookingBreadcrumbs.js +++ b/beeline/directives/bookingBreadcrumbs/bookingBreadcrumbs.js @@ -1,22 +1,21 @@ export default ['$rootScope', -function breadcrumbs($rootScope) { +function breadcrumbs ($rootScope) { return { template: `
`, scope: { step: '@', }, - link: function(scope, elem, attr) { + link: function (scope, elem, attr) { scope.breadcrumbs_dir = 'img/'+$rootScope.o.APP.PREFIX + 'booking-breadcrumbs/' scope.imgNames = [ 'ProgressBar01_ChooseStops.svg', 'ProgressBar02_ChooseDates.svg', 'ProgressBar03_ReviewBooking.svg', 'ProgressBar04_MakePayment.svg', - ]; - - } - }; + ] + }, + } }] diff --git a/beeline/directives/busStopSelector/busStopSelector.js b/beeline/directives/busStopSelector/busStopSelector.js index d5ff706c5..f0b03a814 100644 --- a/beeline/directives/busStopSelector/busStopSelector.js +++ b/beeline/directives/busStopSelector/busStopSelector.js @@ -11,7 +11,7 @@ export default ['$state', '$ionicModal', '$http', 'uiGmapGoogleMapApi', template: busStopSelectorTemplate, scope: { busStops: '=', - ngModel: "=", + ngModel: '=', change: '=', placeholder: '@', title: '@', @@ -26,14 +26,14 @@ export default ['$state', '$ionicModal', '$http', 'uiGmapGoogleMapApi', busStopSelectorDialog.show( _.assign({selectedStop: scope.ngModel}, _.pick(scope, [ - 'busStops', 'markerOptions', 'title', 'button', 'pinOptions' + 'busStops', 'markerOptions', 'title', 'button', 'pinOptions', ]))) .then((selectedStop) => { - scope.ngModel = selectedStop; + scope.ngModel = selectedStop }) } - scope.formatTime = formatTime; + scope.formatTime = formatTime }, - }; -}]; + } +}] diff --git a/beeline/directives/companyInfoBroker.js b/beeline/directives/companyInfoBroker.js index 3409ebf30..887296ffd 100644 --- a/beeline/directives/companyInfoBroker.js +++ b/beeline/directives/companyInfoBroker.js @@ -1,6 +1,6 @@ export default ['CompanyService', - function(CompanyService) { + function (CompanyService) { return { replace: true, template: '', @@ -8,18 +8,18 @@ export default ['CompanyService', 'companyId': '<', 'company': '=', }, - link: function(scope, element, attributes) { - scope.$watch('companyId', function(companyId) { + link: function (scope, element, attributes) { + scope.$watch('companyId', function (companyId) { if (!companyId) { scope.company = {} - return; + return } - var companyPromise = CompanyService.getCompany(+companyId) + let companyPromise = CompanyService.getCompany(+companyId) .then((company) => { scope.company = company - }); - }); + }) + }) }, - }; + } }] diff --git a/beeline/directives/companyTnc/companyTnc.js b/beeline/directives/companyTnc/companyTnc.js index 6b32a3934..075af94ce 100644 --- a/beeline/directives/companyTnc/companyTnc.js +++ b/beeline/directives/companyTnc/companyTnc.js @@ -1,10 +1,10 @@ -import commonmark from 'commonmark'; +import commonmark from 'commonmark' -var reader = new commonmark.Parser({safe: true}); -var writer = new commonmark.HtmlRenderer({safe: true}); +let reader = new commonmark.Parser({safe: true}) +let writer = new commonmark.HtmlRenderer({safe: true}) export default ['CompanyService', '$q', -function companyTnc(CompanyService, $q) { +function companyTnc (CompanyService, $q) { return { template: require('./companyTnc.html'), replace: false, @@ -12,28 +12,28 @@ function companyTnc(CompanyService, $q) { companyId: '=', features: '=', }, - link: function(scope, elem, attr) { - scope.company = {}; + link: function (scope, elem, attr) { + scope.company = {} - scope.$watch('companyId', function() { + scope.$watch('companyId', function () { if (!scope.companyId) { - scope.company = null; - return; + scope.company = null + return } - var companyPromise = CompanyService.getCompany(scope.companyId) + let companyPromise = CompanyService.getCompany(scope.companyId) .then((company) => { - scope.company = company; - scope.$emit('companyTnc.done'); - return company; - }); - }); + scope.company = company + scope.$emit('companyTnc.done') + return company + }) + }) scope.showTerms = () => { - if (!scope.company) return; + if (!scope.company) return - CompanyService.showTerms(scope.company.id); + CompanyService.showTerms(scope.company.id) } - } - }; + }, + } }] diff --git a/beeline/directives/countdown.js b/beeline/directives/countdown.js index 0baf7eea1..7c241f8bb 100644 --- a/beeline/directives/countdown.js +++ b/beeline/directives/countdown.js @@ -1,11 +1,10 @@ import moment from 'moment' export default ['$interval', - function($interval) { - + function ($interval) { return { scope: { boardTime: '<', - bookingEnds: '=' + bookingEnds: '=', }, template: `
@@ -13,36 +12,34 @@ export default ['$interval', Booking for the next trip has ended.
`, - link(scope, elem, attr) { - - var stopTime // so that we can cancel the time updates + link (scope, elem, attr) { + let stopTime // so that we can cancel the time updates // used to update the UI - function updateTime() { - scope.minsBeforeClose = moment(scope.boardTime).diff(moment(Date.now()), 'minutes'); + function updateTime () { + scope.minsBeforeClose = moment(scope.boardTime).diff(moment(Date.now()), 'minutes') } scope.$watch('boardTime', (bt) => { if (bt && !stopTime) { - scope.bookingEnds = false; - stopTime = $interval(updateTime, 100*30); + scope.bookingEnds = false + stopTime = $interval(updateTime, 100*30) } }) // watch the expression, and update the UI on change. - scope.$watch('minsBeforeClose', function(value) { + scope.$watch('minsBeforeClose', function (value) { if (value <= 0) { scope.bookingEnds = true $interval.cancel(stopTime) } - }); + }) // listen on DOM destroy (removal) event, and cancel the next UI update // to prevent updating time after the DOM element was removed. - scope.$on('$destroy', function() { - $interval.cancel(stopTime); - }); - - } + scope.$on('$destroy', function () { + $interval.cancel(stopTime) + }) + }, } }] diff --git a/beeline/directives/crowdstartShare.js b/beeline/directives/crowdstartShare.js index db4e030ff..5b595f784 100644 --- a/beeline/directives/crowdstartShare.js +++ b/beeline/directives/crowdstartShare.js @@ -1,5 +1,5 @@ export default ['$cordovaSocialSharing', 'rootScope', - function($cordovaSocialSharing, $rootScope) { + function ($cordovaSocialSharing, $rootScope) { return { replace: true, restrict: 'E', @@ -20,16 +20,16 @@ export default ['$cordovaSocialSharing', 'rootScope', scope: { 'routeId': '<', }, - link: function(scope, element, attributes) { - scope.showCopy = !window.cordova || false; - //if has cordova no need to show shareLink text area + link: function (scope, element, attributes) { + scope.showCopy = !window.cordova || false + // if has cordova no need to show shareLink text area // scope.shareLink = "Hey, check out this new Crowdstart route from "+$rootScope.o.APP.NAME +"! "+$rootScope.o.APP.INDEX+"#/tabs/crowdstart/"+scope.routeId+"/detail"; - scope.shareLink = `Hey, check out this new Crowdstart route from ${$rootScope.o.APP.NAME}! ${$rootScope.o.APP.INDEX}#/tabs/crowdstart/${scope.routeId}/detail` + scope.shareLink = `Hey, check out this new Crowdstart route from ${$rootScope.o.APP.NAME}! ${$rootScope.o.APP.INDEX}#/tabs/crowdstart/${scope.routeId}/detail` - scope.shareAnywhere = function() { + scope.shareAnywhere = function () { $cordovaSocialSharing.share(`Hey, check out this new Crowdstart route from ${$rootScope.o.APP.NAME}!`, - `New ${$rootScope.o.APP.NAME} Crowdstart Route`, null, `${$rootScope.o.APP.INDEX}#/tabs/crowdstart/${scope.routeId}/detail`); - }; + `New ${$rootScope.o.APP.NAME} Crowdstart Route`, null, `${$rootScope.o.APP.INDEX}#/tabs/crowdstart/${scope.routeId}/detail`) + } }, - }; + } }] diff --git a/beeline/directives/dailyTripsBroker.js b/beeline/directives/dailyTripsBroker.js index 2f41d99c0..5b17a8152 100644 --- a/beeline/directives/dailyTripsBroker.js +++ b/beeline/directives/dailyTripsBroker.js @@ -1,8 +1,8 @@ -import {SafeScheduler} from '../SafeScheduler'; +import {SafeScheduler} from '../SafeScheduler' // since it's broker, we allow 2-way binding for now and // view update the data model which controll relies on export default ['LiteRoutesService', '$timeout', - function(LiteRoutesService, $timeout) { + function (LiteRoutesService, $timeout) { return { replace: true, restrict: 'E', @@ -11,39 +11,39 @@ export default ['LiteRoutesService', '$timeout', 'tripLabel': '<', 'dailyTrips': '=', }, - link: function(scope, element, attributes) { - var timeout; + link: function (scope, element, attributes) { + let timeout - scope.dailyTrips = null; + scope.dailyTrips = null scope.$watch('tripLabel', (label) => { - if (timeout) timeout.stop(); + if (timeout) timeout.stop() if (!label) { - return; + return } - timeout = new SafeScheduler(() => grabTrips(label), 24, 1, 0); + timeout = new SafeScheduler(() => grabTrips(label), 24, 1, 0) - timeout.start(); - }); + timeout.start() + }) scope.$on('$destroy', () => { - if (timeout) timeout.stop(); - }); + if (timeout) timeout.stop() + }) - function grabTrips(label) { + function grabTrips (label) { return LiteRoutesService.fetchLiteRoute(label, true) .then((response)=>{ - var route = response[scope.tripLabel]; + let route = response[scope.tripLabel] - var now = new Date(); - var todayTrips = route.trips.filter(trip => trip.isRunning && - new Date(trip.date).getTime() == Date.UTC(now.getFullYear(), now.getMonth(),now.getDate())); + let now = new Date() + let todayTrips = route.trips.filter((trip) => trip.isRunning && + new Date(trip.date).getTime() == Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())) - scope.dailyTrips = _.sortBy(todayTrips, (trip)=>new Date(trip.tripStops[0].time)); + scope.dailyTrips = _.sortBy(todayTrips, (trip)=>new Date(trip.tripStops[0].time)) }) } }, - }; + } }] diff --git a/beeline/directives/extA.js b/beeline/directives/extA.js index e338277a4..a369c9551 100644 --- a/beeline/directives/extA.js +++ b/beeline/directives/extA.js @@ -8,16 +8,16 @@ function () { `, scope: { - href: '@' + href: '@', }, transclude: true, restrict: 'E', - controller: ['$scope', function($scope) { + controller: ['$scope', function ($scope) { $scope.openLink = function ($event) { - $event.preventDefault(); + $event.preventDefault() window.open($scope.href, '_system') } - }] + }], } } ) diff --git a/beeline/directives/fakeProgressBar.js b/beeline/directives/fakeProgressBar.js index c91f0ad62..4ec36cff7 100644 --- a/beeline/directives/fakeProgressBar.js +++ b/beeline/directives/fakeProgressBar.js @@ -1,5 +1,5 @@ export default ['$timeout', - function($timeout) { + function ($timeout) { return { template: ` @@ -9,14 +9,14 @@ export default ['$timeout', 'max': '<', }, link (scope, elem, attr) { - scope.progressValue = 0; - var timeout; - var makeProgress = function() { - scope.progressValue = (scope.progressValue + 1) % (scope.max+1); - timeout = $timeout(makeProgress, scope.interval); + scope.progressValue = 0 + let timeout + var makeProgress = function () { + scope.progressValue = (scope.progressValue + 1) % (scope.max+1) + timeout = $timeout(makeProgress, scope.interval) } - makeProgress(); - scope.$on('$destroy', ()=>$timeout.cancel(timeout)); - } + makeProgress() + scope.$on('$destroy', ()=>$timeout.cancel(timeout)) + }, } }] diff --git a/beeline/directives/fancyPrice/fancyPrice.js b/beeline/directives/fancyPrice/fancyPrice.js index 77f69bfef..39bc79a13 100644 --- a/beeline/directives/fancyPrice/fancyPrice.js +++ b/beeline/directives/fancyPrice/fancyPrice.js @@ -1,20 +1,18 @@ -export default function() { +export default function () { + function linkFn (scope, elem, attrs) { + scope.currency = scope.currency || '$' + scope.integer = 0 + scope.fraction = 0 - function linkFn(scope, elem, attrs) { - scope.currency = scope.currency || '$'; - scope.integer = 0; - scope.fraction = 0; - - scope.$watch('value', function() { - var floatValue = parseFloat(scope.value); + scope.$watch('value', function () { + let floatValue = parseFloat(scope.value) if (!isFinite(floatValue)) { - [scope.integer, scope.fraction] = ['', '']; - } - else { - [scope.integer, scope.fraction] = parseFloat(scope.value).toFixed(2).split('.'); + [scope.integer, scope.fraction] = ['', ''] + } else { + [scope.integer, scope.fraction] = parseFloat(scope.value).toFixed(2).split('.') } - }); + }) } return { @@ -29,6 +27,5 @@ export default function() { {{currency}} {{integer}}.{{fraction}} `, - }; - + } } diff --git a/beeline/directives/inServiceWindow.js b/beeline/directives/inServiceWindow.js index 607205065..7286c3953 100644 --- a/beeline/directives/inServiceWindow.js +++ b/beeline/directives/inServiceWindow.js @@ -1,5 +1,5 @@ -import {SafeInterval} from '../SafeInterval'; -import _ from 'lodash'; +import {SafeInterval} from '../SafeInterval' +import _ from 'lodash' export default ['$timeout', function ($timeout) { @@ -8,43 +8,43 @@ export default ['$timeout', restrict: 'E', template: '', scope: { - 'availableTrips' : '<', + 'availableTrips': '<', 'inServiceWindow': '=', }, - link: function(scope, element, attributes) { - var allStopsTime; - scope.inServiceWindow = null; - //check in service window every 1 min, if fails re-try in 1 sec - scope.timeout = new SafeInterval(()=>checkServiceWindow(scope.availableTrips), 1000*60, 1000); - scope.timeout.start(); + link: function (scope, element, attributes) { + let allStopsTime + scope.inServiceWindow = null + // check in service window every 1 min, if fails re-try in 1 sec + scope.timeout = new SafeInterval(()=>checkServiceWindow(scope.availableTrips), 1000*60, 1000) + scope.timeout.start() scope.$on('$destroy', () => { - if (scope.timeout) scope.timeout.stop(); - }); - //to restart the loop when available trips become not null + if (scope.timeout) scope.timeout.stop() + }) + // to restart the loop when available trips become not null scope.$watchCollection('availableTrips', ()=>{ - scope.timeout.stop(); - scope.timeout.start(); + scope.timeout.stop() + scope.timeout.start() }) - function checkServiceWindow(trips) { + function checkServiceWindow (trips) { if (!trips || trips.length == 0) { - scope.inServiceWindow = null; + scope.inServiceWindow = null } else { - var allStopsTime = _.flatten(trips.map(trip=>trip.tripStops)) - .map(stop=>stop.time).sort(); + let allStopsTime = _.flatten(trips.map((trip)=>trip.tripStops)) + .map((stop)=>stop.time).sort() if (allStopsTime) { - //15 min before 1st stop time - scope.startTime = new Date(allStopsTime[0]).getTime() - 1000*60*15; - scope.endTime = new Date(allStopsTime[allStopsTime.length-1]).getTime(); - scope.now = Date.now(); + // 15 min before 1st stop time + scope.startTime = new Date(allStopsTime[0]).getTime() - 1000*60*15 + scope.endTime = new Date(allStopsTime[allStopsTime.length-1]).getTime() + scope.now = Date.now() if (isFinite(scope.startTime) && isFinite(scope.endTime)) { - scope.inServiceWindow = scope.startTime <= scope.now && scope.now <= scope.endTime; + scope.inServiceWindow = scope.startTime <= scope.now && scope.now <= scope.endTime } else { - scope.inServiceWindow = false; + scope.inServiceWindow = false } } } - return Promise.resolve(); + return Promise.resolve() } - } + }, } }] diff --git a/beeline/directives/kickstartInfo/kickstartInfo.js b/beeline/directives/kickstartInfo/kickstartInfo.js index 266a39eaa..a42f3423e 100644 --- a/beeline/directives/kickstartInfo/kickstartInfo.js +++ b/beeline/directives/kickstartInfo/kickstartInfo.js @@ -7,7 +7,7 @@ export default function () { return { template: require('./kickstartInfo.html'), - restrict : 'E', + restrict: 'E', replace: false, scope: { route: '<', @@ -15,5 +15,5 @@ export default function () { preorderHide: ' - `, - scope: { - pings: '<', - idkey: '<', - overlay: '<' - }, - controller: ['$scope', function($scope) { - $scope.bearing = null; - $scope.busIcon = null; - $scope.icon = null; - - /** - Here's the algorithm: - - 1. For each bus, establish the direction - a) Take the first two pings - b) If the distance isn't big enough to be - certain of the direction, add another ping. Repeat - 2. Draw the icon based on the direction - - This function also caches the previous known angle and - avoids re-rendering the image - */ - const now = Date.now() - - busIconImage.imageLoadPromise.then(() => $scope.$digest()) - - $scope.$watchGroup(['pings', () => (typeof google !== 'undefined') && (busIconImage.loaded)], - ([pings, gapi]) => { - // Do not update if google maps is not loaded (we need Size and Point) - // Do not update if bus icon image is not loaded yet - if (!gapi || !pings) return - const bearing = bearingFromPings(pings) - const oldLocationStatus = $scope.locationStatus && $scope.locationStatus[index] - - const busIcon = ($scope.busIcon && $scope.bearing !== null && - Math.abs($scope.bearing - bearing) < 0.1) ? - $scope.busIcon : busIconImage.rotate(bearing, $scope.overlay || ''); - - $scope.busIcon = busIcon - $scope.icon = { - url: busIcon, - scaledSize: new google.maps.Size(80, 80), - anchor: new google.maps.Point(40, 40), - } - - $scope.coordinates = (pings.length > 0) ? pings[0].coordinates : null - $scope.bearing = bearing - }) - }], - }; - - function bearingFromPings(pings) { - if (pings.length < 2) { - return 0.75 * 2 * Math.PI; // DEFAULT - 270° - } - - const firstPingLngLat = pings[0].coordinates.coordinates - for (let i=1; i= 50 - || i === pings.length - 1) { - return BearingFromLngLats(firstPingLngLat, lastPingLngLat) - } - } - } - }] -) +import {SafeInterval} from '../SafeInterval' +const leftPad = require('left-pad') + +angular.module('beeline') +.directive('mapBusIcon', ['TripService', 'uiGmapGoogleMapApi', '$timeout', 'RotatedImage', +'LngLatDistance', 'BearingFromLngLats', + function (TripService, uiGmapGoogleMapApi, $timeout, RotatedImage, LngLatDistance, + BearingFromLngLats) { + const busIconImage = new RotatedImage('./img/busTop-small.png') + + return { + replace: false, + restrict: 'E', + template: ` + + `, + scope: { + pings: '<', + idkey: '<', + overlay: '<', + }, + controller: ['$scope', function ($scope) { + $scope.bearing = null + $scope.busIcon = null + $scope.icon = null + + /** + Here's the algorithm: + + 1. For each bus, establish the direction + a) Take the first two pings + b) If the distance isn't big enough to be + certain of the direction, add another ping. Repeat + 2. Draw the icon based on the direction + + This function also caches the previous known angle and + avoids re-rendering the image + */ + const now = Date.now() + + busIconImage.imageLoadPromise.then(() => $scope.$digest()) + + $scope.$watchGroup(['pings', () => (typeof google !== 'undefined') && (busIconImage.loaded)], + ([pings, gapi]) => { + // Do not update if google maps is not loaded (we need Size and Point) + // Do not update if bus icon image is not loaded yet + if (!gapi || !pings) return + const bearing = bearingFromPings(pings) + const oldLocationStatus = $scope.locationStatus && $scope.locationStatus[index] + + const busIcon = ($scope.busIcon && $scope.bearing !== null && + Math.abs($scope.bearing - bearing) < 0.1) ? + $scope.busIcon : busIconImage.rotate(bearing, $scope.overlay || '') + + $scope.busIcon = busIcon + $scope.icon = { + url: busIcon, + scaledSize: new google.maps.Size(80, 80), + anchor: new google.maps.Point(40, 40), + } + + $scope.coordinates = (pings.length > 0) ? pings[0].coordinates : null + $scope.bearing = bearing + }) + }], + } + + function bearingFromPings (pings) { + if (pings.length < 2) { + return 0.75 * 2 * Math.PI // DEFAULT - 270° + } + + const firstPingLngLat = pings[0].coordinates.coordinates + for (let i=1; i= 50 + || i === pings.length - 1) { + return BearingFromLngLats(firstPingLngLat, lastPingLngLat) + } + } + } + }] +) diff --git a/beeline/directives/mapBusPolyRoute.js b/beeline/directives/mapBusPolyRoute.js index ee268c256..cb2ec142a 100644 --- a/beeline/directives/mapBusPolyRoute.js +++ b/beeline/directives/mapBusPolyRoute.js @@ -3,7 +3,7 @@ import {SafeInterval} from '../SafeInterval' angular.module('beeline') .directive('mapBusPolyRoute', ['TripService', 'uiGmapGoogleMapApi', '$timeout', 'RotatedImage', 'LngLatDistance', 'BearingFromLngLats', - function(TripService, uiGmapGoogleMapApi, $timeout, RotatedImage, LngLatDistance, + function (TripService, uiGmapGoogleMapApi, $timeout, RotatedImage, LngLatDistance, BearingFromLngLats) { return { replace: false, @@ -20,7 +20,7 @@ angular.module('beeline') hasTrackingData: '=?', routeMessage: '=?', }, - controller: ['$scope', function($scope) { + controller: ['$scope', function ($scope) { $scope.map = { busLocations: [ { @@ -53,7 +53,7 @@ angular.module('beeline') $scope.timeout.start() }) - async function pingLoop() { + async function pingLoop () { if (!$scope.availableTrips) return $scope.statusMessages = $scope.statusMessages || [] diff --git a/beeline/directives/mapBusStops.js b/beeline/directives/mapBusStops.js index 69b034fa0..743316ab5 100644 --- a/beeline/directives/mapBusStops.js +++ b/beeline/directives/mapBusStops.js @@ -1,5 +1,5 @@ export default ['uiGmapGoogleMapApi', 'LiteRoutesService', 'uiGmapCtrlHandle', - function(uiGmapGoogleMapApi, LiteRoutesService, uiGmapCtrlHandle) { + function (uiGmapGoogleMapApi, LiteRoutesService, uiGmapCtrlHandle) { return { replace: false, require: '^uiGmapGoogleMap', @@ -25,14 +25,13 @@ export default ['uiGmapGoogleMapApi', 'LiteRoutesService', 'uiGmapCtrlHandle', 'availableTrips': '<', 'isLiteFrequent': ' { - scope.googleMaps = googleMaps; + scope.googleMaps = googleMaps scope.boardMarker = { icon: { url: 'img/map/MapRoutePickupStop@2x.png', @@ -52,28 +51,28 @@ export default ['uiGmapGoogleMapApi', 'LiteRoutesService', 'uiGmapCtrlHandle', }) scope.$watch('availableTrips', (availableTrips) => { - if (!availableTrips || availableTrips.length==0) return; - scope.tripStops = LiteRoutesService.computeLiteStops(availableTrips); - uiGmapCtrlHandle.mapPromise(scope, ctrl).then(panToStops); + if (!availableTrips || availableTrips.length==0) return + scope.tripStops = LiteRoutesService.computeLiteStops(availableTrips) + uiGmapCtrlHandle.mapPromise(scope, ctrl).then(panToStops) }) scope.applyTapBoard = function (stop) { - scope.disp.popupStop = stop; + scope.disp.popupStop = stop } scope.closeWindow = function () { - scope.disp.popupStop = null; + scope.disp.popupStop = null } - function panToStops(map) { - var bounds = new scope.googleMaps.LatLngBounds(); + function panToStops (map) { + let bounds = new scope.googleMaps.LatLngBounds() for (let tripStop of scope.tripStops) { bounds.extend(new google.maps.LatLng(tripStop.coordinates.coordinates[1], - tripStop.coordinates.coordinates[0])); + tripStop.coordinates.coordinates[0])) } google.maps.event.trigger(map, 'resize') - map.fitBounds(bounds); + map.fitBounds(bounds) } }, - }; + } }] diff --git a/beeline/directives/mapPolyRoute.js b/beeline/directives/mapPolyRoute.js index 75bce9745..ee3a33fc2 100644 --- a/beeline/directives/mapPolyRoute.js +++ b/beeline/directives/mapPolyRoute.js @@ -1,4 +1,4 @@ -export default function() { +export default function () { return { replace: false, template: ` @@ -7,12 +7,12 @@ export default function() { scope: { 'routePath': '<', }, - link: function(scope, element, attributes) { + link: function (scope, element, attributes) { scope.strokeOptions = { color: '#4b3863', weight: 3.0, - opacity: 0.7 - }; + opacity: 0.7, + } }, - }; + } } diff --git a/beeline/directives/markdownRenderer.js b/beeline/directives/markdownRenderer.js index 1af8b0117..a450cc115 100644 --- a/beeline/directives/markdownRenderer.js +++ b/beeline/directives/markdownRenderer.js @@ -1,19 +1,19 @@ -import commonmark from 'commonmark'; +import commonmark from 'commonmark' -var reader = new commonmark.Parser({safe: true}); -var writer = new commonmark.HtmlRenderer({safe: true}); +let reader = new commonmark.Parser({safe: true}) +let writer = new commonmark.HtmlRenderer({safe: true}) -export default function() { +export default function () { return { replace: true, template: '
', scope: { data: '<', }, - link: function(scope, element, attributes) { + link: function (scope, element, attributes) { scope.$watch('data', (data) => { - scope.markdownHTML = data && writer.render(reader.parse(data)); + scope.markdownHTML = data && writer.render(reader.parse(data)) }) }, - }; + } } diff --git a/beeline/directives/moreInfo/moreInfo.js b/beeline/directives/moreInfo/moreInfo.js index 2f380c56a..cb354e20e 100644 --- a/beeline/directives/moreInfo/moreInfo.js +++ b/beeline/directives/moreInfo/moreInfo.js @@ -6,7 +6,7 @@ export default function () { companyId: '<', features: '<', }, - link: function(scope, elem, attr) { - } - }; + link: function (scope, elem, attr) { + }, + } } diff --git a/beeline/directives/myLocation.js b/beeline/directives/myLocation.js index 5597cacb7..4a3bfdf6b 100644 --- a/beeline/directives/myLocation.js +++ b/beeline/directives/myLocation.js @@ -1,7 +1,6 @@ export default ['uiGmapGoogleMapApi', - function(uiGmapGoogleMapApi) { - + function (uiGmapGoogleMapApi) { return { template: ` { scope.markerOptions.icon = { url: 'img/userLocation.svg', - anchor: new googleMaps.Point(6,6), + anchor: new googleMaps.Point(6, 6), } - var watch = navigator.geolocation.watchPosition( + let watch = navigator.geolocation.watchPosition( (success) => { scope.coords = { latitude: success.coords.latitude, longitude: success.coords.longitude, - }; - scope.radius = success.coords.accuracy; + } + scope.radius = success.coords.accuracy scope.$digest() }, (error) => { - scope.coords = null; + scope.coords = null scope.$digest() }, { enableHighAccuracy: false, - }); + }) scope.$on('destroy', () => { - navigator.geolocation.clearWatch(watch); + navigator.geolocation.clearWatch(watch) }) }) - } + }, } }] diff --git a/beeline/directives/poweredByBeeline/poweredByBeeline.js b/beeline/directives/poweredByBeeline/poweredByBeeline.js index 94a62a8b1..c6ac817b8 100644 --- a/beeline/directives/poweredByBeeline/poweredByBeeline.js +++ b/beeline/directives/poweredByBeeline/poweredByBeeline.js @@ -1,24 +1,24 @@ -import querystring from 'querystring'; +import querystring from 'querystring' export default ['$rootScope', 'p', function ($rootScope, p) { return { template: require('./poweredByBeeline.html'), - restrict : 'E', + restrict: 'E', replace: false, scope: { - powerHide:'UserService.getUser(), (user)=>{ - $scope.isLoggedIn = !!user; + $scope.isLoggedIn = !!user CreditsService.fetchUserCredits().then((userCredits) => { $scope.userCredits = userCredits - }); + }) CreditsService.fetchReferralCredits().then((referralCredits) => { $scope.referralCredits = referralCredits - }); + }) - //update ridesRemaining when user login at the booking summary page + // update ridesRemaining when user login at the booking summary page RoutesService.fetchRoutePassCount().then((routePassCountMap) => { - assert($scope.booking.routeId); + assert($scope.booking.routeId) if (!$scope.booking.route) { RoutesService.getRoute($scope.booking.routeId).then((route)=>{ - $scope.booking.route = route; + $scope.booking.route = route if (routePassCountMap) { $scope.booking.route.ridesRemaining = routePassCountMap[$scope.booking.routeId] $scope.booking.applyRoutePass = ($scope.booking.route.ridesRemaining > 0) } }) - } - else { + } else { if (routePassCountMap) { $scope.booking.route.ridesRemaining = routePassCountMap[$scope.booking.routeId] $scope.booking.applyRoutePass = ($scope.booking.route.ridesRemaining > 0) } } - }); - + }) }) - async function recomputePrices() { - assert($scope.booking.routeId); + async function recomputePrices () { + assert($scope.booking.routeId) if (!$scope.booking.route) { $scope.booking.route = await RoutesService.getRoute($scope.booking.routeId) let routeToRidesRemainingMap = await RoutesService.fetchRoutePassCount() @@ -67,46 +65,47 @@ export default [ // Provide a price summary first (don't count total due) // This allows the page to resize earlier, so that when // users scroll down the bounce works ok. - $scope.priceInfo = $scope.priceInfo || {}; - $scope.priceInfo.pricesPerTrip = BookingService.summarizePrices($scope.booking); + $scope.priceInfo = $scope.priceInfo || {} + $scope.priceInfo.pricesPerTrip = BookingService.summarizePrices($scope.booking) - $scope.isCalculating++; + $scope.isCalculating++ var promise = BookingService.computePriceInfo($scope.booking) .then((priceInfo) => { // Check to ensure that the order of // replies don't affect the result - if (promise != latestRequest) - return; - $scope.priceInfo = priceInfo; - $scope.price = priceInfo.totalDue; + if (promise != latestRequest) { +return +} + $scope.priceInfo = priceInfo + $scope.price = priceInfo.totalDue $scope.ridesUsed = $scope.booking.applyRoutePass ? Math.min($scope.booking.route.ridesRemaining, priceInfo.tripCount) : 0 - $scope.totalRoutePassesUsed = _.sumBy($scope.priceInfo.routePass, x => - parseFloat(x.debit)) - $scope.errorMessage = null; + $scope.totalRoutePassesUsed = _.sumBy($scope.priceInfo.routePass, (x) => - parseFloat(x.debit)) + $scope.errorMessage = null }) .catch((error) => { - $scope.priceInfo = {}; - $scope.price = undefined; - $scope.errorMessage = error.data.message; + $scope.priceInfo = {} + $scope.price = undefined + $scope.errorMessage = error.data.message }) .then(stopCalculating) - latestRequest = promise; + latestRequest = promise } - var latestRequest = null; + var latestRequest = null $scope.$watch( - () => _.pick($scope.booking, ['selectedDates', 'applyRoutePass', 'applyCredits', 'applyReferralCredits', 'promoCode' /* , qty */]), - recomputePrices, true); + () => _.pick($scope.booking, ['selectedDates', 'applyRoutePass', 'applyCredits', 'applyReferralCredits', 'promoCode']), + recomputePrices, true) $scope.$on( 'priceCalculator.recomputePrices', - recomputePrices); + recomputePrices) - $scope.removePromoCode = function(){ - $scope.booking.promoCode = null; + $scope.removePromoCode = function () { + $scope.booking.promoCode = null } - }] - }; - }]; + }], + } + }] diff --git a/beeline/directives/progressBar/progressBar.js b/beeline/directives/progressBar/progressBar.js index d2323d98c..4f4adc548 100644 --- a/beeline/directives/progressBar/progressBar.js +++ b/beeline/directives/progressBar/progressBar.js @@ -1,7 +1,7 @@ -import progressBar from './progressBar.html'; +import progressBar from './progressBar.html' export default [ - function() { + function () { return { restrict: 'E', template: progressBar, @@ -12,13 +12,13 @@ export default [ detail: '<', needed: '<', }, - link: function(scope, elem, attr) { + link: function (scope, elem, attr) { scope.$watchGroup(['backer1', 'pax1'], () => { - scope.percentage = Math.min((scope.backer1/scope.pax1), 1); + scope.percentage = Math.min((scope.backer1/scope.pax1), 1) // if (!isFinite(scope.moreNeeded)) // scope.moreNeeded = ''; }) - } + }, } - } + }, ] diff --git a/beeline/directives/qtyInput/qtyInput.js b/beeline/directives/qtyInput/qtyInput.js index 4a03272ba..5652b9139 100644 --- a/beeline/directives/qtyInput/qtyInput.js +++ b/beeline/directives/qtyInput/qtyInput.js @@ -1,43 +1,44 @@ -export default function() { +export default function () { + function linkFn (scope, elem, attrs) { + scope.default = scope.default || 0 - function linkFn(scope, elem, attrs) { - scope.default = scope.default || 0; - - scope.valueGetterSetter = function(nv) { - var newValue = parseInt(nv); - if (arguments.length == 0) - return scope.value; + scope.valueGetterSetter = function (nv) { + let newValue = parseInt(nv) + if (arguments.length == 0) { +return scope.value +} if (!isFinite(newValue) || newValue > scope.max || newValue < scope.min) { - return scope.value; + return scope.value + } else { + return scope.value = newValue } - else { - return scope.value = newValue; - } - }; + } - scope.up = function() { - scope.value = parseInt(scope.value); - if (!isFinite(scope.value)) - scope.value = scope.default; - var newValue = scope.value + 1; + scope.up = function () { + scope.value = parseInt(scope.value) + if (!isFinite(scope.value)) { +scope.value = scope.default +} + let newValue = scope.value + 1 if (newValue > scope.max) { - newValue = scope.max; + newValue = scope.max } - scope.value = newValue; - }; - scope.down = function() { - scope.value = parseInt(scope.value); - if (!isFinite(scope.value)) - scope.value = scope.default; - var newValue = scope.value - 1; + scope.value = newValue + } + scope.down = function () { + scope.value = parseInt(scope.value) + if (!isFinite(scope.value)) { +scope.value = scope.default +} + let newValue = scope.value - 1 if (newValue < 1) { - newValue = 1; + newValue = 1 } - scope.value = newValue; - }; + scope.value = newValue + } } return { @@ -52,6 +53,5 @@ export default function() { placeholder: '@', }, template: require('./qtyInput.html'), - }; - + } } diff --git a/beeline/directives/revGeocode/revGeocode.js b/beeline/directives/revGeocode/revGeocode.js index 4b1fef646..a2abe2754 100644 --- a/beeline/directives/revGeocode/revGeocode.js +++ b/beeline/directives/revGeocode/revGeocode.js @@ -9,9 +9,9 @@ export default [ '$http', 'OneMapService', 'UserService', - function($http, + function ($http, OneMapService, - UserService){ + UserService) { return { restrict: 'E', transclude: true, @@ -34,44 +34,43 @@ export default [ {{y | number:4}}, {{x | number:4}} `, - link: async function(scope, elem) { - scope.geocodeW = {}//`${scope.y}, ${scope.x}` - var oneMapToken = await OneMapService.token(); - //var url = `http://staging.beeline.sg/onemap/revgeocode?location=${scope.x},${scope.y}`; + link: async function (scope, elem) { + scope.geocodeW = {}// `${scope.y}, ${scope.x}` + let oneMapToken = await OneMapService.token() + // var url = `http://staging.beeline.sg/onemap/revgeocode?location=${scope.x},${scope.y}`; - function updateDescription() { + function updateDescription () { if (scope.geocodeW && scope.geocodeW.GeocodeInfo && scope.geocodeW.GeocodeInfo[0].ROAD) { scope.description1 = titleCase(scope.geocodeW.GeocodeInfo[0].BLOCK) - + ' ' + titleCase(scope.geocodeW.GeocodeInfo[0].ROAD); - scope.description2 = titleCase(scope.geocodeW.GeocodeInfo[0].BUILDINGNAME); - } - else { + + ' ' + titleCase(scope.geocodeW.GeocodeInfo[0].ROAD) + scope.description2 = titleCase(scope.geocodeW.GeocodeInfo[0].BUILDINGNAME) + } else { scope.description1 = parseFloat(scope.y).toFixed(4) + ', ' + parseFloat(scope.x).toFixed(4) - scope.description2 = null; + scope.description2 = null } } - function geocode() { + function geocode () { scope.geocodePromiseW = UserService.beeline({ method: 'GET', - url: `/onemap/revgeocode?location=${scope.x},${scope.y}` + url: `/onemap/revgeocode?location=${scope.x},${scope.y}`, }) .then((response) => { // console.log(response); - scope.geocodeW = response.data; - updateDescription(); + scope.geocodeW = response.data + updateDescription() }) } - scope.$watchGroup(['x', 'y'], geocode); + scope.$watchGroup(['x', 'y'], geocode) // Hack to reverse the erasure of the description when suggestion page is reloaded scope.$watchGroup(['description1', 'description2'], function () { if (scope.description1 == undefined || scope.description2 == undefined) { - updateDescription(); + updateDescription() } - }); + }) }, /* link(...) */ - }; - } - ]; + } + }, + ] diff --git a/beeline/directives/routeItem/animatedRoute.js b/beeline/directives/routeItem/animatedRoute.js index 6deef2b5b..6ec1dea59 100644 --- a/beeline/directives/routeItem/animatedRoute.js +++ b/beeline/directives/routeItem/animatedRoute.js @@ -1,7 +1,7 @@ // https://cloudcannon.com/deconstructions/2014/11/15/facebook-content-placeholder-deconstruction.html -angular.module('beeline').directive('animatedRoute', function() { +angular.module('beeline').directive('animatedRoute', function () { return { - template: require('./animatedRoute.html') + template: require('./animatedRoute.html'), } }) diff --git a/beeline/directives/routeItem/kickstartRoute.js b/beeline/directives/routeItem/kickstartRoute.js index 1342e8668..0577442fe 100644 --- a/beeline/directives/routeItem/kickstartRoute.js +++ b/beeline/directives/routeItem/kickstartRoute.js @@ -4,12 +4,12 @@ export default ['KickstarterService', return { template: require('./kickstartRoute.html'), scope: { - 'route': '<' + 'route': '<', }, - controller: ['$scope', function($scope) { + controller: ['$scope', function ($scope) { $scope.bids = {} $scope.$watch(() => KickstarterService.getBids(), - bids => $scope.bids = bids) - }] + (bids) => $scope.bids = bids) + }], } }] diff --git a/beeline/directives/routeItem/liteRoute.js b/beeline/directives/routeItem/liteRoute.js index a0a25b2f0..a3a9a6e62 100644 --- a/beeline/directives/routeItem/liteRoute.js +++ b/beeline/directives/routeItem/liteRoute.js @@ -3,7 +3,7 @@ export default function () { return { template: require('./liteRoute.html'), scope: { - 'route': '<' - } + 'route': '<', + }, } } diff --git a/beeline/directives/routeItem/regularRoute.js b/beeline/directives/routeItem/regularRoute.js index 8f09ecdf0..7f5b60289 100644 --- a/beeline/directives/routeItem/regularRoute.js +++ b/beeline/directives/routeItem/regularRoute.js @@ -3,7 +3,7 @@ export default function () { return { template: require('./regularRoute.html'), scope: { - 'route': '<' - } + 'route': '<', + }, } } diff --git a/beeline/directives/routeItem/routeItem.js b/beeline/directives/routeItem/routeItem.js index dedacb217..204de788d 100644 --- a/beeline/directives/routeItem/routeItem.js +++ b/beeline/directives/routeItem/routeItem.js @@ -1,7 +1,7 @@ -import routeItemTemplate from './routeItem.html'; +import routeItemTemplate from './routeItem.html' export default ['$state', 'BookingService', -function($state, BookingService) { +function ($state, BookingService) { return { replace: false, template: routeItemTemplate, @@ -20,7 +20,7 @@ function($state, BookingService) { endLocation: '?routeItemEndLocation', description: '?routeItemDescription', }, - link: function(scope, element, attributes) { + link: function (scope, element, attributes) { }, - }; + } }] diff --git a/beeline/directives/searchButton.js b/beeline/directives/searchButton.js index 6033fe0a9..499cda934 100644 --- a/beeline/directives/searchButton.js +++ b/beeline/directives/searchButton.js @@ -1,4 +1,4 @@ -export default function() { +export default function () { return { restrict: 'E', replace: true, @@ -8,5 +8,5 @@ export default function() {   Search in Map `, - }; + } } diff --git a/beeline/directives/searchInput.js b/beeline/directives/searchInput.js index f1956efc2..e69a2ff74 100644 --- a/beeline/directives/searchInput.js +++ b/beeline/directives/searchInput.js @@ -25,19 +25,19 @@ angular.module('beeline').directive('searchInput', function () { `, - link(scope, elem, attr) { - scope.$watch('searchText' , (qt) => { - if(!qt || qt.trim().length < 3) { - scope.queryText = "" + link (scope, elem, attr) { + scope.$watch('searchText', (qt) => { + if (!qt || qt.trim().length < 3) { + scope.queryText = '' } else { scope.queryText = qt.trim() } }) scope.keypress = function (e) { - if (e.key === "Enter") { + if (e.key === 'Enter') { e.target.blur() } } - } + }, } }) diff --git a/beeline/directives/startEndPicker/startEndPicker.js b/beeline/directives/startEndPicker/startEndPicker.js index bf43e80a9..cd26eea76 100644 --- a/beeline/directives/startEndPicker/startEndPicker.js +++ b/beeline/directives/startEndPicker/startEndPicker.js @@ -16,7 +16,6 @@ export default [ uiGmapIsReady, $cordovaGeolocation ) { - return { restrict: 'E', transclude: true, @@ -34,20 +33,20 @@ export default [ }, link: function (scope, elem, attrs) { scope.map = defaultMapOptions({ - events: { //empty functions - to be overwritten - dragstart : function(map, e, args) {}, - zoom_changed : function(map, e, args) {}, - dragend : function(map, e, args) {}, - click : function(map, e, args) {} + events: { // empty functions - to be overwritten + dragstart: function (map, e, args) {}, + zoom_changed: function (map, e, args) {}, + dragend: function (map, e, args) {}, + click: function (map, e, args) {}, }, boardMarkerOptions: {}, alightMarkerOptions: {}, lineIcons: {}, - }); + }) scope.prompt = scope.prompt || 'Next' - console.log(scope.setPoint); - scope.setPoint = scope.setPoint === undefined ? 'start' : scope.setPoint; + console.log(scope.setPoint) + scope.setPoint = scope.setPoint === undefined ? 'start' : scope.setPoint scope.startPoint = _.extend({ text: '', coordinates: null, @@ -56,7 +55,7 @@ export default [ text: '', coordinates: null, }, scope.endPoint || {}) - scope.lineBetween = []; + scope.lineBetween = [] scope.$watchGroup([ 'startPoint.coordinates', @@ -66,113 +65,111 @@ export default [ scope.endPoint.coordinates) { scope.lineBetween = [ scope.startPoint.coordinates, - scope.endPoint.coordinates + scope.endPoint.coordinates, ] - } - else { - scope.lineBetween = []; + } else { + scope.lineBetween = [] } }) - var gmapResolve; - var gmapReady = new Promise((resolve) => gmapResolve = resolve); - scope.mapReady = gmapResolve; - gmapReady.then(function x() { - var gmap = scope.map.control.getGMap(); + let gmapResolve + let gmapReady = new Promise((resolve) => gmapResolve = resolve) + scope.mapReady = gmapResolve + gmapReady.then(function x () { + let gmap = scope.map.control.getGMap() scope.map.boardMarkerOptions = { icon: { url: 'img/board.png', - scaledSize: new google.maps.Size(20,20), - anchor: new google.maps.Point(5,5), + scaledSize: new google.maps.Size(20, 20), + anchor: new google.maps.Point(5, 5), }, - }; + } scope.map.alightMarkerOptions = { icon: { url: 'img/alight.png', - scaledSize: new google.maps.Size(20,20), - anchor: new google.maps.Point(5,5), + scaledSize: new google.maps.Size(20, 20), + anchor: new google.maps.Point(5, 5), }, - }; + } scope.map.lineIcons = [{ icon: { path: 1, scale: 3, - strokeColor: '#333' + strokeColor: '#333', }, offset: '20%', - repeat: '50px' - }]; + repeat: '50px', + }] - var inputElems = elem[0].querySelectorAll('INPUT'); - var pickupautocomp = new google.maps.places.Autocomplete(inputElems[0]); - var dropoffautocomp = new google.maps.places.Autocomplete(inputElems[1]); + let inputElems = elem[0].querySelectorAll('INPUT') + let pickupautocomp = new google.maps.places.Autocomplete(inputElems[0]) + let dropoffautocomp = new google.maps.places.Autocomplete(inputElems[1]) - pickupautocomp.addListener('place_changed', function(event) { - var pickupPos = pickupautocomp.getPlace().geometry.location; + pickupautocomp.addListener('place_changed', function (event) { + let pickupPos = pickupautocomp.getPlace().geometry.location scope.startPoint.coordinates = { lat: pickupPos.lat(), - lng: pickupPos.lng() + lng: pickupPos.lng(), } scope.startPoint.text = pickupautocomp.getPlace().formatted_address - inputElems[0].blur(); + inputElems[0].blur() setTimeout(() => { - gmap.setZoom(15); - gmap.panTo(pickupPos); - updateLocationText(gmap); + gmap.setZoom(15) + gmap.panTo(pickupPos) + updateLocationText(gmap) }, 100) - }); + }) - dropoffautocomp.addListener('place_changed', function() { - var dropoffPos = dropoffautocomp.getPlace().geometry.location; + dropoffautocomp.addListener('place_changed', function () { + let dropoffPos = dropoffautocomp.getPlace().geometry.location scope.endPoint.coordinates = { lat: dropoffPos.lat(), - lng: dropoffPos.lng() + lng: dropoffPos.lng(), } scope.endPoint.text = dropoffautocomp.getPlace().formatted_address - inputElems[1].blur(); + inputElems[1].blur() setTimeout(() => { - gmap.setZoom(15); - gmap.panTo(dropoffPos); - updateLocationText(gmap); + gmap.setZoom(15) + gmap.panTo(dropoffPos) + updateLocationText(gmap) }, 100) - }); + }) scope.map.events = { click: () => { if (scope.inFocusElement) { - scope.inFocusElement.blur(); + scope.inFocusElement.blur() } }, - dragstart: function(map, e, args) { + dragstart: function (map, e, args) { }, - zoom_changed: function(map, e, args) { - updateCenter(map); - updateLocationText(map, e, args); + zoom_changed: function (map, e, args) { + updateCenter(map) + updateLocationText(map, e, args) }, - dragend : function(map, e, args) { - updateCenter(map); - updateLocationText(map, e, args); + dragend: function (map, e, args) { + updateCenter(map) + updateLocationText(map, e, args) }, } - //drop down list disappears before the clicked item is registered, - //this will disable the click event on the lists' containers + // drop down list disappears before the clicked item is registered, + // this will disable the click event on the lists' containers setTimeout(() => { - var contain = document.getElementsByClassName('pac-container'); - angular.element(contain).attr('data-tap-disabled', 'true'); + let contain = document.getElementsByClassName('pac-container') + angular.element(contain).attr('data-tap-disabled', 'true') }, 500) }) - function fitToPoints() { - var gmap = scope.map.control.getGMap(); + function fitToPoints () { + let gmap = scope.map.control.getGMap() if (scope.startPoint.coordinates && scope.endPoint.coordinates) { - - var bounds = new google.maps.LatLngBounds(); + let bounds = new google.maps.LatLngBounds() bounds.extend(new google.maps.LatLng({ lat: scope.startPoint.coordinates.latitude, @@ -183,148 +180,143 @@ export default [ lng: scope.endPoint.coordinates.longitude, })) - gmap.fitBounds(bounds); - } - else { + gmap.fitBounds(bounds) + } else { gmap.setCenter({ lat: 1.38, lng: 103.8, }) - gmap.setZoom(11); + gmap.setZoom(11) } } - scope.$watch('control', function() { + scope.$watch('control', function () { if (scope.control) { - scope.control.fitToPoints = fitToPoints; + scope.control.fitToPoints = fitToPoints } - }); - scope.nextBtnClick = function() { + }) + scope.nextBtnClick = function () { if (scope.setPoint == 'start') { if (scope.startPoint.coordinates) { - if (scope.endPoint.coordinates) { /* End point has been previously set, don't reset it */ - scope.setPoint = null; - fitToPoints(); - } - else { + if (scope.endPoint.coordinates) {/* End point has been previously set, don't reset it */ + scope.setPoint = null + fitToPoints() + } else { scope.setPoint = 'end' } } - } - else if (scope.setPoint == 'end') { + } else if (scope.setPoint == 'end') { if (scope.endPoint.coordinates) { scope.setPoint = null - fitToPoints(); + fitToPoints() } - } - else { + } else { // FIXME: optimize this using a $parse scope.$parent.$eval(scope.onsubmit) } - }; - scope.setSetPoint = function(what) { - if (scope.disabled) - return; - scope.setPoint = what; + } + scope.setSetPoint = function (what) { + if (scope.disabled) { +return +} + scope.setPoint = what if (scope[what + 'Point'].coordinates) { scope.map.control.getGMap().panTo({ lat: scope.startPoint.coordinates.latitude, lng: scope.startPoint.coordinates.longitude, - }); + }) } } - function updateCenter(map) { + function updateCenter (map) { if (scope.setPoint == 'start') { scope.startPoint.coordinates = { latitude: map.center.lat(), longitude: map.center.lng(), - }; - } - else if (scope.setPoint == 'end') { + } + } else if (scope.setPoint == 'end') { scope.endPoint.coordinates = { latitude: map.center.lat(), longitude: map.center.lng(), - }; + } } } - function updateLocationText(map) { - if (!scope.setPoint) - return; + function updateLocationText (map) { + if (!scope.setPoint) { +return +} - var geocoder = new google.maps.Geocoder(); - geocoder.geocode({latLng: map.getCenter()}, function(r, s) { - if (!scope.setPoint) - return; - var center = map.getCenter().toJSON(); - var point = scope[scope.setPoint + 'Point'] - if (s == 'OK') - { - point.text = r[0].formatted_address; - } - else { + let geocoder = new google.maps.Geocoder() + geocoder.geocode({latLng: map.getCenter()}, function (r, s) { + if (!scope.setPoint) { +return +} + let center = map.getCenter().toJSON() + let point = scope[scope.setPoint + 'Point'] + if (s == 'OK') { + point.text = r[0].formatted_address + } else { point.text = `${center.lat}, ${center.lng}` } point.coordinates = { latitude: center.lat, - longitude: center.lng + longitude: center.lng, } - }); + }) } - scope.inFocus = 0; - scope.inFocusElement = null; - scope.inputFocus = function($event, which) { - scope.setPoint = which; - var point = scope[which + 'Point']; + scope.inFocus = 0 + scope.inFocusElement = null + scope.inputFocus = function ($event, which) { + scope.setPoint = which + let point = scope[which + 'Point'] if (point.coordinates) { scope.map.control.getGMap().panTo({ lat: scope[which + 'Point'].coordinates.latitude, lng: scope[which + 'Point'].coordinates.longitude, - }); + }) } - scope.inFocusElement = $event.target; - scope.inFocus++; + scope.inFocusElement = $event.target + scope.inFocus++ } - scope.inputBlur = function($event, which) { - scope.inFocus--; + scope.inputBlur = function ($event, which) { + scope.inFocus-- } - scope.reset = function(which) { - scope[`${which}Point`].text = ''; - scope[`${which}Point`].coordinates = null; - elem[0].querySelector(`.input-${which}`).focus(); + scope.reset = function (which) { + scope[`${which}Point`].text = '' + scope[`${which}Point`].coordinates = null + elem[0].querySelector(`.input-${which}`).focus() } scope.nextAllowed = function () { - return (scope.setPoint && scope[scope.setPoint + 'Point'].coordinates) + return (scope.setPoint && scope[scope.setPoint + 'Point'].coordinates) || (!scope.setPoint && scope.isValid && scope.startPoint.coordinates && scope.endPoint.coordinates) } - scope.$on('mapRequireResize', async function() { - await uiGmapGoogleMapApi; - google.maps.event.trigger($scope.map.mapControl.getGMap(), 'resize'); + scope.$on('mapRequireResize', async function () { + await uiGmapGoogleMapApi + google.maps.event.trigger($scope.map.mapControl.getGMap(), 'resize') }) - //Click function for User Position Icon - scope.getUserLocation = function() { - var options = { + // Click function for User Position Icon + scope.getUserLocation = function () { + let options = { timeout: 5000, - enableHighAccuracy: true - }; + enableHighAccuracy: true, + } - //promise + // promise $cordovaGeolocation - .getCurrentPosition({ timeout: 5000, enableHighAccuracy: true }) - .then(function(userpos){ - var gmap = scope.map.control.getGMap() - gmap.panTo(new google.maps.LatLng(userpos.coords.latitude, userpos.coords.longitude)); - setTimeout(function(){ - gmap.setZoom(15); - }, 300); - - }, function(err){ - console.log('ERROR - ' + err); - }); + .getCurrentPosition({timeout: 5000, enableHighAccuracy: true}) + .then(function (userpos) { + let gmap = scope.map.control.getGMap() + gmap.panTo(new google.maps.LatLng(userpos.coords.latitude, userpos.coords.longitude)) + setTimeout(function () { + gmap.setZoom(15) + }, 300) + }, function (err) { + console.log('ERROR - ' + err) + }) } }, - }; - } -]; + } + }, +] diff --git a/beeline/directives/suggestionViewer/suggestionViewer.js b/beeline/directives/suggestionViewer/suggestionViewer.js index 2e9fd26c6..e68e1053a 100644 --- a/beeline/directives/suggestionViewer/suggestionViewer.js +++ b/beeline/directives/suggestionViewer/suggestionViewer.js @@ -22,25 +22,25 @@ export default [ endDescriptionB: '=', }, link: function (scope, elem, attrs) { - scope.map = defaultMapOptions(); + scope.map = defaultMapOptions() - scope.showStart = scope.showEnd = true; + scope.showStart = scope.showEnd = true scope.$watchGroup(['showStart', 'showEnd'], () => { scope.line = [ {latitude: scope.startLat, longitude: scope.startLng}, {latitude: scope.endLat, longitude: scope.endLng}, - ]; - scope.icons = dashedLineIcons(); - }); + ] + scope.icons = dashedLineIcons() + }) - var gmapResolve; - var gmapReady = new Promise((resolve) => gmapResolve = resolve); - scope.mapReady = gmapResolve; + let gmapResolve + let gmapReady = new Promise((resolve) => gmapResolve = resolve) + scope.mapReady = gmapResolve scope.fitMarkers = function () { gmapReady.then(() => { - var llBounds = new google.maps.LatLngBounds(); + let llBounds = new google.maps.LatLngBounds() llBounds.extend(new google.maps.LatLng({ lat: scope.startLat, lng: scope.startLng, @@ -49,34 +49,34 @@ export default [ lat: scope.endLat, lng: scope.endLng, })) - scope.map.control.getGMap().fitBounds(llBounds); - }); + scope.map.control.getGMap().fitBounds(llBounds) + }) } - uiGmapGoogleMapApi.then(function x() { + uiGmapGoogleMapApi.then(function x () { scope.map.boardMarkerOptions = { icon: { url: 'img/board.png', - scaledSize: new google.maps.Size(20,20), - anchor: new google.maps.Point(5,5), + scaledSize: new google.maps.Size(20, 20), + anchor: new google.maps.Point(5, 5), }, - }; + } scope.map.alightMarkerOptions = { icon: { url: 'img/alight.png', - scaledSize: new google.maps.Size(20,20), - anchor: new google.maps.Point(5,5), + scaledSize: new google.maps.Size(20, 20), + anchor: new google.maps.Point(5, 5), }, - }; - scope.fitMarkers(); - }); + } + scope.fitMarkers() + }) // FIXME - scope.$on('mapRequireResize', async function() { - await uiGmapGoogleMapApi; - google.maps.event.trigger($scope.map.mapControl.getGMap(), 'resize'); + scope.$on('mapRequireResize', async function () { + await uiGmapGoogleMapApi + google.maps.event.trigger($scope.map.mapControl.getGMap(), 'resize') }) - } - }) + }, + }), -]; +] diff --git a/beeline/directives/tripCode/tripCode.js b/beeline/directives/tripCode/tripCode.js index 96d1f0d24..ae785701a 100644 --- a/beeline/directives/tripCode/tripCode.js +++ b/beeline/directives/tripCode/tripCode.js @@ -1,6 +1,6 @@ -export default function() { +export default function () { return { template: ` {{codeStr[0]}} { if (code) { scope.codeStr = code.toString() - } - else { + } else { scope.codeStr = '' } }) - var exit = false; - function delay(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); + let exit = false + function delay (ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) } scope.$on('$destroy', () => exit = true); - (async function() { + (async function () { while (!exit) { - for (var i=0; i<4 && !exit; i++) { + for (let i=0; i<4 && !exit; i++) { let charElem = elem[0].querySelector(`.c${i}`) if (charElem.classList.contains('shrink')) { - charElem.classList.remove('shrink'); - } - else { - charElem.classList.add('shrink'); + charElem.classList.remove('shrink') + } else { + charElem.classList.add('shrink') } - await delay(250); + await delay(250) } } })() - .then(null, console.error); - } + .then(null, console.error) + }, } } diff --git a/beeline/main.js b/beeline/main.js index 2d6e9b08b..a246b3f32 100644 --- a/beeline/main.js +++ b/beeline/main.js @@ -1,18 +1,18 @@ import {formatDate, formatDateMMMdd, formatTime, formatTimeArray, - formatUTCDate, titleCase} from './shared/format'; -import {companyLogo, miniCompanyLogo} from './shared/imageSources'; + formatUTCDate, titleCase} from './shared/format' +import {companyLogo, miniCompanyLogo} from './shared/imageSources' // node imports -import compareVersions from 'compare-versions'; -import assert from 'assert'; +import compareVersions from 'compare-versions' +import assert from 'assert' // Angular imports -import MultipleDatePicker from 'multiple-date-picker/dist/multipleDatePicker'; +import MultipleDatePicker from 'multiple-date-picker/dist/multipleDatePicker' // Configuration Imports -import configureRoutes from './router.js'; +import configureRoutes from './router.js' -var app = angular.module('beeline', [ +let app = angular.module('beeline', [ 'ionic', 'ngCordova', 'uiGmapgoogle-maps', @@ -20,20 +20,20 @@ var app = angular.module('beeline', [ 'ngclipboard', ]) -require('angular-simple-logger'); -require('angular-google-maps'); -require('clipboard'); -require('ngclipboard'); -require('./directives/extA'); -require('./services/RotatedImageService'); -require('./services/GeoUtils'); -require('./directives/mapBusPolyRoute'); -require('./directives/mapBusIcon'); -require('./directives/routeItem/animatedRoute'); -require('./services/assetScopeModalService'); -require('./services/fastCheckoutService'); -require('./services/purchaseRoutePassService'); -require('./services/paymentService'); +require('angular-simple-logger') +require('angular-google-maps') +require('clipboard') +require('ngclipboard') +require('./directives/extA') +require('./services/RotatedImageService') +require('./services/GeoUtils') +require('./directives/mapBusPolyRoute') +require('./directives/mapBusIcon') +require('./directives/routeItem/animatedRoute') +require('./services/assetScopeModalService') +require('./services/fastCheckoutService') +require('./services/purchaseRoutePassService') +require('./services/paymentService') require('./services/bookingSummaryModalService') require('./services/SharedVariableService') require('./services/MapService') @@ -59,19 +59,19 @@ app .filter('routeEndRoad', () => (route) => (route && route.trips) ? route.trips[0].tripStops[route.trips[0].tripStops.length - 1].stop.road : '') .filter('companyLogo', () => companyLogo) .filter('miniCompanyLogo', () => miniCompanyLogo) -.filter('monthNames', function() { - return function(i) { - monthNames = 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','); - return monthNames[i]; - }; +.filter('monthNames', function () { + return function (i) { + monthNames = 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(',') + return monthNames[i] + } }) // round up a float number with optional precision -.filter('floatRoundUp', function() { - return function(number, precision) { +.filter('floatRoundUp', function () { + return function (number, precision) { if (!precision) precision = 2 - var temp = number * Math.pow(10, precision) - temp = Math.ceil(temp); - return temp / Math.pow(10,precision) + let temp = number * Math.pow(10, precision) + temp = Math.ceil(temp) + return temp / Math.pow(10, precision) } }) .factory('TicketService', require('./services/TicketService.js').default) @@ -167,105 +167,103 @@ app $locationProvider.html5Mode({enabled: true}) } }]) -.config(['$ionicConfigProvider', function($ionicConfigProvider) { - $ionicConfigProvider.tabs.position('bottom'); - $ionicConfigProvider.tabs.style('standard'); - $ionicConfigProvider.navBar.alignTitle('center'); - $ionicConfigProvider.scrolling.jsScrolling(false); - //kickstart-summary use default history stack - $ionicConfigProvider.backButton.previousTitleText(false).text(' '); +.config(['$ionicConfigProvider', function ($ionicConfigProvider) { + $ionicConfigProvider.tabs.position('bottom') + $ionicConfigProvider.tabs.style('standard') + $ionicConfigProvider.navBar.alignTitle('center') + $ionicConfigProvider.scrolling.jsScrolling(false) + // kickstart-summary use default history stack + $ionicConfigProvider.backButton.previousTitleText(false).text(' ') }]) .config(['$httpProvider', function ($httpProvider) { - $httpProvider.useApplyAsync(true); + $httpProvider.useApplyAsync(true) }]) -.config(['uiGmapGoogleMapApiProvider', function(uiGmapGoogleMapApiProvider) { +.config(['uiGmapGoogleMapApiProvider', function (uiGmapGoogleMapApiProvider) { if (process.env.GOOGLE_API_KEY) { uiGmapGoogleMapApiProvider.configure({ key: process.env.GOOGLE_API_KEY, - libraries: 'places,geometry' - }); + libraries: 'places,geometry', + }) } else { uiGmapGoogleMapApiProvider.configure({ client: 'gme-infocommunications', - libraries: 'places,geometry' - }); + libraries: 'places,geometry', + }) } }]) -.config(['$ionicConfigProvider', function($ionicConfigProvider) { - $ionicConfigProvider.views.transition('none'); +.config(['$ionicConfigProvider', function ($ionicConfigProvider) { + $ionicConfigProvider.views.transition('none') }]) -.run(['$ionicPlatform', function($ionicPlatform) { - $ionicPlatform.ready(function() { +.run(['$ionicPlatform', function ($ionicPlatform) { + $ionicPlatform.ready(function () { if (typeof IonicDeeplink !== 'undefined') { IonicDeeplink.route( {}, // No predetermined matches - function(match) {}, - function(nomatch) { - window.location.href = "#" + (nomatch.$link.fragment || nomatch.$link.path) + function (match) {}, + function (nomatch) { + window.location.href = '#' + (nomatch.$link.fragment || nomatch.$link.path) } - ); + ) } - }); + }) }]) -.run(['$rootScope', 'replace', 'p', function($rootScope, replace, p) { +.run(['$rootScope', 'replace', 'p', function ($rootScope, replace, p) { $rootScope.o = { ...p, - replace + replace, } }]) -.run(['$ionicPlatform', function($ionicPlatform) { - $ionicPlatform.ready(function() { +.run(['$ionicPlatform', function ($ionicPlatform) { + $ionicPlatform.ready(function () { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard // for form inputs) if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) { - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false); - cordova.plugins.Keyboard.disableScroll(false); + cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false) + cordova.plugins.Keyboard.disableScroll(false) } if (window.StatusBar) { // org.apache.cordova.statusbar required - StatusBar.styleLightContent(); + StatusBar.styleLightContent() } - }); + }) }]) -.run(['$ionicPopup', function($ionicPopup) { +.run(['$ionicPopup', function ($ionicPopup) { // Check that external dependencies have loaded if (typeof StripeCheckout === 'undefined' || typeof Stripe === 'undefined') { - document.addEventListener('online', () => { - window.location.reload(true); + window.location.reload(true) }) $ionicPopup.alert({ title: 'Unable to connect to the Internet', - template: `Please check your Internet connection` + template: `Please check your Internet connection`, }) .then(() => { - window.location.reload(true); + window.location.reload(true) }) } }]) -.run(['$rootScope', '$ionicTabsDelegate', function($rootScope, $ionicTabsDelegate) { +.run(['$rootScope', '$ionicTabsDelegate', function ($rootScope, $ionicTabsDelegate) { // hide/show tabs bar depending on how the route is configured - $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { if (toState.data && toState.data.hideTabs) { - $ionicTabsDelegate.showBar(false); - } - else { - $ionicTabsDelegate.showBar(true); + $ionicTabsDelegate.showBar(false) + } else { + $ionicTabsDelegate.showBar(true) } - }); + }) }]) .run(['RoutesService', 'KickstarterService', 'LiteRoutesService', 'TicketService', function (RoutesService, KickstarterService, LiteRoutesService, TicketService) { // Pre-fetch the routes - RoutesService.fetchRoutes(); - RoutesService.fetchRecentRoutes(); - KickstarterService.fetchCrowdstart(); - KickstarterService.fetchBids(); - LiteRoutesService.fetchLiteRoutes(); - TicketService.fetchTickets(); + RoutesService.fetchRoutes() + RoutesService.fetchRecentRoutes() + KickstarterService.fetchCrowdstart() + KickstarterService.fetchBids() + LiteRoutesService.fetchLiteRoutes() + TicketService.fetchTickets() }]) .run(['$templateCache', function ($templateCache) { $templateCache.put('templates/intro-slides.html', require('../www/templates/intro-slides.html')) @@ -279,42 +277,42 @@ app $templateCache.put('templates/tab-booking-confirmation.html', require('../www/templates/tab-booking-confirmation.html')) }]) -var devicePromise = new Promise((resolve, reject) => { +let devicePromise = new Promise((resolve, reject) => { if (window.cordova) { - document.addEventListener('deviceready', resolve, false); - } - else { + document.addEventListener('deviceready', resolve, false) + } else { console.log('No cordova detected') - resolve(); + resolve() } }) -app.service('DevicePromise', () => devicePromise); +app.service('DevicePromise', () => devicePromise) app.run(['UserService', '$ionicPopup', async function (UserService, $ionicPopup) { // Version check, if we're in an app - if (!window.cordova) - return; + if (!window.cordova) { +return +} - await devicePromise; + await devicePromise - assert(window.cordova.InAppBrowser); - assert(window.cordova.getAppVersion); - assert(window.device); + assert(window.cordova.InAppBrowser) + assert(window.cordova.getAppVersion) + assert(window.device) - var versionNumberPromise = cordova.getAppVersion.getVersionNumber(); + let versionNumberPromise = cordova.getAppVersion.getVersionNumber() - var versionRequirementsPromise = UserService.beeline({ + let versionRequirementsPromise = UserService.beeline({ method: 'GET', url: '/versionRequirements', }) - var [versionNumber, versionRequirementsResponse] = await Promise.all([ - versionNumberPromise, versionRequirementsPromise - ]); + let [versionNumber, versionRequirementsResponse] = await Promise.all([ + versionNumberPromise, versionRequirementsPromise, + ]) - var appRequirements = versionRequirementsResponse.data.commuterApp; - assert(appRequirements); + let appRequirements = versionRequirementsResponse.data.commuterApp + assert(appRequirements) if (compareVersions(versionNumber, appRequirements.minVersion) < 0) { while (true) { @@ -325,7 +323,7 @@ app.run(['UserService', '$ionicPopup', async function (UserService, $ionicPopup) }) if (appRequirements.upgradeUrl) { - cordova.InAppBrowser.open(appRequirements.upgradeUrl[device.platform], '_system'); + cordova.InAppBrowser.open(appRequirements.upgradeUrl[device.platform], '_system') } } } diff --git a/beeline/services/BookingService.js b/beeline/services/BookingService.js index 79a79785c..053a575f2 100644 --- a/beeline/services/BookingService.js +++ b/beeline/services/BookingService.js @@ -1,44 +1,43 @@ -import {NetworkError} from '../shared/errors'; +import {NetworkError} from '../shared/errors' import {formatDate, formatDateMMMdd, formatTime, formatUTCDate, - timeSinceMidnight} from '../shared/format'; -import _ from 'lodash'; + timeSinceMidnight} from '../shared/format' +import _ from 'lodash' export default ['UserService', 'CompanyService', 'RoutesService', '$http', - function(UserService, CompanyService, RoutesService, $http) { - this.prepareTrips = function(booking) { + function (UserService, CompanyService, RoutesService, $http) { + this.prepareTrips = function (booking) { // create a list of trips - var trips = []; + let trips = [] for (let dt of booking.selectedDates) { trips.push({ tripId: booking.route.tripsByDate[dt].id, boardStopId: booking.route.tripsByDate[dt] .tripStops - .filter(ts => booking.boardStopId == ts.stop.id) + .filter((ts) => booking.boardStopId == ts.stop.id) [0].id, alightStopId: booking.route.tripsByDate[dt] .tripStops - .filter(ts => booking.alightStopId == ts.stop.id) + .filter((ts) => booking.alightStopId == ts.stop.id) [0].id, - }); + }) } - return trips; - }; + return trips + } /* If a booking has selectedDates array, then it checks the prices. */ - this.computePriceInfo = function(booking) { + this.computePriceInfo = function (booking) { if (!booking.selectedDates || booking.selectedDates.length == 0) { return Promise.resolve({ total: 0, - }); - } - else { - var trips = this.prepareTrips(booking); + }) + } else { + let trips = this.prepareTrips(booking) - var rv = UserService.beeline({ + let rv = UserService.beeline({ method: 'POST', url: '/transactions/tickets/quote', data: { @@ -46,19 +45,19 @@ export default ['UserService', 'CompanyService', 'RoutesService', '$http', trips: trips, dryRun: true, promoCode: booking.promoCode ? { - code: booking.promoCode + code: booking.promoCode, } : { - code: '' // Allow default promo codes to be used + code: '', // Allow default promo codes to be used }, applyCredits: booking.applyCredits, applyReferralCredits: booking.applyReferralCredits, - applyRoutePass: !!booking.applyRoutePass + applyRoutePass: !!booking.applyRoutePass, }, }) .then((resp) => { // Find the 'payment' entry in the list of transaction itemss - var txItems = _.groupBy(resp.data.transactionItems, 'itemType'); - var totalBeforeDiscount = _.reduce(txItems.ticketSale, (sum, n) => { + let txItems = _.groupBy(resp.data.transactionItems, 'itemType') + let totalBeforeDiscount = _.reduce(txItems.ticketSale, (sum, n) => { return sum + parseFloat(n.credit) }, 0) @@ -72,59 +71,59 @@ export default ['UserService', 'CompanyService', 'RoutesService', '$http', credits: txItems['userCredit'], discounts: txItems.discount, totalBeforeDiscount, - }; + } }) .then(null, (err) => { - console.log(err.stack); - throw err; - }); + console.log(err.stack) + throw err + }) - return rv; + return rv } - }; + } - this.summarizePrices = function(booking) { + this.summarizePrices = function (booking) { if (!booking.selectedDates) { - return []; + return [] } - var dates = _.sortBy(booking.selectedDates); + let dates = _.sortBy(booking.selectedDates) - if (dates.length == 0) return []; + if (dates.length == 0) return [] - var current = {}; - var rv = []; + let current = {} + let rv = [] for (let dt of dates) { current = { startDate: dt, price: booking.route.tripsByDate[dt].price, - bookingInfo: booking.route.tripsByDate[dt].bookingInfo - }; - rv.push(current); + bookingInfo: booking.route.tripsByDate[dt].bookingInfo, + } + rv.push(current) } - return rv; - }; + return rv + } - this.computeChanges = function(route) { + this.computeChanges = function (route) { // convert dates (should be in ISO format therefore sortable) - route.trips = _.sortBy(route.trips, trip => trip.date); + route.trips = _.sortBy(route.trips, (trip) => trip.date) for (let trip of route.trips) { - trip.date = new Date(trip.date); + trip.date = new Date(trip.date) for (let tripStop of trip.tripStops) { - tripStop.time = new Date(tripStop.time); + tripStop.time = new Date(tripStop.time) } } // summarize trips by date - route.tripsByDate = _.keyBy(route.trips, t => t.date.getTime()) + route.tripsByDate = _.keyBy(route.trips, (t) => t.date.getTime()) - var changes = { + let changes = { timeChanges: [], priceChanges: [], stopChanges: [], - }; + } /** Produce an array of changes. @@ -142,11 +141,11 @@ export default ['UserService', 'CompanyService', 'RoutesService', '$http', humanReadable: Result of humanReadable(before, after) */ - function summarizeChanges(trips, comparable, humanReadable) { - var changes = []; + function summarizeChanges (trips, comparable, humanReadable) { + let changes = [] // var current = {}; - var lastComparable = undefined; - var lastTrip = undefined; + let lastComparable = undefined + let lastTrip = undefined for (let trip of trips) { // if (current.startDate == undefined) { @@ -154,18 +153,19 @@ export default ['UserService', 'CompanyService', 'RoutesService', '$http', // current.endDate = trip.date; // } - let valueComparable = comparable(trip); - if (lastComparable == undefined) - lastComparable = valueComparable; + let valueComparable = comparable(trip) + if (lastComparable == undefined) { +lastComparable = valueComparable +} if (lastComparable != valueComparable) { - let hr = humanReadable(lastTrip, trip); + let hr = humanReadable(lastTrip, trip) changes.push({ startDate: trip.date, humanReadable: hr, comparable: valueComparable, - }); + }) // current = { // startDate: trip.date, // endDate: trip.date, @@ -173,118 +173,118 @@ export default ['UserService', 'CompanyService', 'RoutesService', '$http', } // current.endDate = trip.date; - lastTrip = trip; - lastComparable = valueComparable; + lastTrip = trip + lastComparable = valueComparable } // if (changes.length != 0) { // changes.push(current); // } - return changes; + return changes } for (let trip of route.trips) { - trip.tripStops = _.sortBy(trip.tripStops, ts => ts.time); + trip.tripStops = _.sortBy(trip.tripStops, (ts) => ts.time) } // summarize price/stop/time changes.priceChanges = summarizeChanges(route.trips, (trip) => trip.price, - (bef, aft) => [`Ticket price changed from $${bef.price} to $${aft.price}`]); + (bef, aft) => [`Ticket price changed from $${bef.price} to $${aft.price}`]) changes.stopChanges = summarizeChanges(route.trips, - trip => trip.tripStops.map(ts => ts.stop.id).join(','), + (trip) => trip.tripStops.map((ts) => ts.stop.id).join(','), (bef, aft) => { - var stopInfo = {}; + let stopInfo = {} for (let ts of bef.tripStops) { - stopInfo[ts.stop.id] = ts.stop; + stopInfo[ts.stop.id] = ts.stop } for (let ts of aft.tripStops) { - stopInfo[ts.stop.id] = ts.stop; + stopInfo[ts.stop.id] = ts.stop } - var beforeStops = bef.tripStops.map(ts => ts.stop.id); - var afterStops = aft.tripStops.map(ts => ts.stop.id); + let beforeStops = bef.tripStops.map((ts) => ts.stop.id) + let afterStops = aft.tripStops.map((ts) => ts.stop.id) - var droppedStops = _.subtract(beforeStops, afterStops); - var newStops = _.subtract(afterStops, beforeStops); + let droppedStops = _.subtract(beforeStops, afterStops) + let newStops = _.subtract(afterStops, beforeStops) - var messages = []; + let messages = [] if (droppedStops.length > 0) { messages.push('Stops ' - + droppedStops.map(sid => stopInfo[sid].description).join(', ') - + ' no longer serviced'); + + droppedStops.map((sid) => stopInfo[sid].description).join(', ') + + ' no longer serviced') } if (newStops.length > 0) { messages.push('New stops ' - + newStops.map(sid => stopInfo[sid].description).join(', ') - + ' added to route'); + + newStops.map((sid) => stopInfo[sid].description).join(', ') + + ' added to route') } - return messages; - }); + return messages + }) - console.log(route.trips.map(t => t.date).join('\n')); + console.log(route.trips.map((t) => t.date).join('\n')) console.log( route.trips.map( - trip => trip.tripStops - .map(ts => (ts.time.getTime() % (24 * 60 * 60 * 1000)) + ':' + ts.stop.id) + (trip) => trip.tripStops + .map((ts) => (ts.time.getTime() % (24 * 60 * 60 * 1000)) + ':' + ts.stop.id) .sort() .join(',') - ).join('\n')); + ).join('\n')) changes.timeChanges = summarizeChanges(route.trips, - trip => trip.tripStops - .map(ts => (ts.time.getTime() % (24 * 60 * 60 * 1000)) + ':' + ts.stop.id) + (trip) => trip.tripStops + .map((ts) => (ts.time.getTime() % (24 * 60 * 60 * 1000)) + ':' + ts.stop.id) .sort() .join(','), (bef, aft) => { - var messages = []; + let messages = [] - var befStopInfo = {}; - var aftStopInfo = {}; + let befStopInfo = {} + let aftStopInfo = {} for (let ts of aft.tripStops) { - aftStopInfo[ts.stop.id] = ts; + aftStopInfo[ts.stop.id] = ts } for (let ts of bef.tripStops) { if (!(ts.stop.id in aftStopInfo)) { - continue; /* if stop was added, then it would have been handled by + continue /* if stop was added, then it would have been handled by stop change messages */ } - let befTime = formatTime(new Date(ts.time)); - let aftTime = formatTime(new Date(aftStopInfo[ts.stop.id].time)); + let befTime = formatTime(new Date(ts.time)) + let aftTime = formatTime(new Date(aftStopInfo[ts.stop.id].time)) - messages.push(`Arrival time at stop ${ts.stop.description} changed from ${befTime} to ${aftTime}`); + messages.push(`Arrival time at stop ${ts.stop.description} changed from ${befTime} to ${aftTime}`) } - return messages; - }); - return changes; - }; - - this.computeStops = function(trips) { - var tripStops = _.flatten(trips.map(trip => trip.tripStops)); - var uniqueStops = _.uniqBy(tripStops, ts => ts.stop.id); - var stopData = _.keyBy(uniqueStops, ts => ts.stop.id); - - var boardStops = _(uniqueStops) - .filter(ts => ts.canBoard) - .map(ts => { - return _.extend({canBoard: true, time: ts.time, timeSinceMidnight: timeSinceMidnight(ts.time)}, ts.stop); + return messages + }) + return changes + } + + this.computeStops = function (trips) { + let tripStops = _.flatten(trips.map((trip) => trip.tripStops)) + let uniqueStops = _.uniqBy(tripStops, (ts) => ts.stop.id) + let stopData = _.keyBy(uniqueStops, (ts) => ts.stop.id) + + let boardStops = _(uniqueStops) + .filter((ts) => ts.canBoard) + .map((ts) => { + return _.extend({canBoard: true, time: ts.time, timeSinceMidnight: timeSinceMidnight(ts.time)}, ts.stop) }) - .orderBy(s => s.timeSinceMidnight) - .value(); - var alightStops = _(uniqueStops) - .filter(ts => ts.canAlight) - .map(ts => { - return _.extend({canBoard: false, time: ts.time, timeSinceMidnight: timeSinceMidnight(ts.time)}, ts.stop); + .orderBy((s) => s.timeSinceMidnight) + .value() + let alightStops = _(uniqueStops) + .filter((ts) => ts.canAlight) + .map((ts) => { + return _.extend({canBoard: false, time: ts.time, timeSinceMidnight: timeSinceMidnight(ts.time)}, ts.stop) }) - .orderBy(s => s.timeSinceMidnight) - .value(); - return [boardStops, alightStops]; - }; + .orderBy((s) => s.timeSinceMidnight) + .value() + return [boardStops, alightStops] + } // Sets up booking sessions - var session = Date.now(); - this.newSession = () => ++session; - this.getSession = () => session; + let session = Date.now() + this.newSession = () => ++session + this.getSession = () => session }] diff --git a/beeline/services/CompanyService.js b/beeline/services/CompanyService.js index 7c4eb10ec..9943a8601 100644 --- a/beeline/services/CompanyService.js +++ b/beeline/services/CompanyService.js @@ -1,50 +1,50 @@ -import assert from 'assert'; -import commonmark from 'commonmark'; +import assert from 'assert' +import commonmark from 'commonmark' -var reader = new commonmark.Parser({safe: true}); -var writer = new commonmark.HtmlRenderer({safe: true}); +let reader = new commonmark.Parser({safe: true}) +let writer = new commonmark.HtmlRenderer({safe: true}) export default ['UserService', '$ionicModal', '$rootScope', '$q', -function CompanyService(UserService, $ionicModal, $rootScope, $q) { - var companyCache = {}; - var termsScope; +function CompanyService (UserService, $ionicModal, $rootScope, $q) { + let companyCache = {} + let termsScope return { - getCompany: function(id, ignoreCache) { - assert(typeof id === 'number'); - if (companyCache[id] && !ignoreCache) return companyCache[id]; + getCompany: function (id, ignoreCache) { + assert(typeof id === 'number') + if (companyCache[id] && !ignoreCache) return companyCache[id] return companyCache[id] = UserService.beeline({ url: '/companies/' + id, method: 'GET', }) - .then(function(response) { - return response.data; - }); + .then(function (response) { + return response.data + }) }, showTerms: function (id) { - termsScope = $rootScope.$new(); + termsScope = $rootScope.$new() termsScope.termsModal = $ionicModal.fromTemplate( require('../templates/termsModal.html'), { - scope: termsScope + scope: termsScope, } - ); + ) this.getCompany(id) .then((company) => { termsScope.company = { - termsHTML: writer.render(reader.parse(company.terms)) - }; - termsScope.termsModal.show(); + termsHTML: writer.render(reader.parse(company.terms)), + } + termsScope.termsModal.show() }) return new Promise((resolve, reject) => { termsScope.$on('modal.hidden', () => { termsScope.$destroy() - resolve(); + resolve() }) }) }, - }; + } }] diff --git a/beeline/services/CreditsService.js b/beeline/services/CreditsService.js index 3712cece9..cecb1f03b 100644 --- a/beeline/services/CreditsService.js +++ b/beeline/services/CreditsService.js @@ -1,15 +1,15 @@ -import _ from 'lodash'; -import assert from 'assert'; +import _ from 'lodash' +import assert from 'assert' export default ['$http', 'UserService', '$q', - function CreditsService($http, UserService, $q) { + function CreditsService ($http, UserService, $q) { // General credits - var userCreditsCache - var userCredits + let userCreditsCache + let userCredits // Referral credits - var referralCreditsCache - var referralCredits + let referralCreditsCache + let referralCredits UserService.userEvents.on('userChanged', () => { instance.fetchUserCredits(true) @@ -17,7 +17,7 @@ export default ['$http', 'UserService', '$q', }) var instance = { - getUserCredits: function(){ + getUserCredits: function () { return userCredits }, @@ -26,28 +26,28 @@ export default ['$http', 'UserService', '$q', // - ignoreCache - boolean // output: // - Promise containing amount of general credits associated with user - fetchUserCredits: function(ignoreCache){ - if(!ignoreCache && userCreditsCache) { + fetchUserCredits: function (ignoreCache) { + if (!ignoreCache && userCreditsCache) { return userCreditsCache } let user = UserService.getUser() - if(!user){ + if (!user) { return userCreditsCache = Promise.resolve( userCredits = null ) } else { return userCreditsCache = UserService.beeline({ method: 'GET', - url: '/credits' + url: '/credits', }).then((response) => { return userCredits = response.data }) } }, - getReferralCredits: function(){ + getReferralCredits: function () { return referralCredits }, @@ -56,21 +56,21 @@ export default ['$http', 'UserService', '$q', // - ignoreCache - boolean // output: // - Promise containing amount of referral credits associated with user - fetchReferralCredits: function(ignoreCache){ - if(!ignoreCache && referralCreditsCache) { + fetchReferralCredits: function (ignoreCache) { + if (!ignoreCache && referralCreditsCache) { return referralCreditsCache } let user = UserService.getUser() - if(!user){ + if (!user) { return referralCreditsCache = Promise.resolve( referralCredits = null ) } else { return referralCreditsCache = UserService.beeline({ method: 'GET', - url: '/user/referralCredits' + url: '/user/referralCredits', }).then((response) => { return referralCredits = response.data }) diff --git a/beeline/services/DateService.js b/beeline/services/DateService.js index 6f7798425..02107c21f 100644 --- a/beeline/services/DateService.js +++ b/beeline/services/DateService.js @@ -1,2 +1,2 @@ -export default () => ({date: new Date()}); +export default () => ({date: new Date()}) diff --git a/beeline/services/GeoUtils.js b/beeline/services/GeoUtils.js index 1a887feda..6c76bf25f 100644 --- a/beeline/services/GeoUtils.js +++ b/beeline/services/GeoUtils.js @@ -1,25 +1,25 @@ - -angular.module('beeline') -.factory('LngLatDistance', () => LngLatDistance) -.factory('BearingFromLngLats', () => BearingFromLngLats) - -function LngLatDistance(ll1, ll2) { - var rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] - var rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] - - var dx = (rr1[0] - rr2[0]) * Math.cos(0.5 * (rr1[1] + rr2[1])) - var dy = rr1[1] - rr2[1] - - var dist = Math.sqrt(dx * dx + dy * dy) * 6371000 - return dist -} - -function BearingFromLngLats(ll1, ll2) { - var rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] - var rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] - - var dx = (rr2[0] - rr1[0]) * Math.cos(0.5 * (rr1[1] + rr2[1])) - var dy = rr2[1] - rr1[1] - - return Math.atan2(dx, dy) -} + +angular.module('beeline') +.factory('LngLatDistance', () => LngLatDistance) +.factory('BearingFromLngLats', () => BearingFromLngLats) + +function LngLatDistance (ll1, ll2) { + let rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] + let rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] + + let dx = (rr1[0] - rr2[0]) * Math.cos(0.5 * (rr1[1] + rr2[1])) + let dy = rr1[1] - rr2[1] + + let dist = Math.sqrt(dx * dx + dy * dy) * 6371000 + return dist +} + +function BearingFromLngLats (ll1, ll2) { + let rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] + let rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] + + let dx = (rr2[0] - rr1[0]) * Math.cos(0.5 * (rr1[1] + rr2[1])) + let dy = rr2[1] - rr1[1] + + return Math.atan2(dx, dy) +} diff --git a/beeline/services/GoogleAnalytics.js b/beeline/services/GoogleAnalytics.js index f8f7bd7e9..21bcf4d38 100644 --- a/beeline/services/GoogleAnalytics.js +++ b/beeline/services/GoogleAnalytics.js @@ -1,46 +1,46 @@ -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ -(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), -m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -})(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); +(function (i, s, o, g, r, a, m) { +i['GoogleAnalyticsObject']=r; i[r]=i[r]||function () { +(i[r].q=i[r].q||[]).push(arguments) +}, i[r].l=1*new Date(); a=s.createElement(o), +m=s.getElementsByTagName(o)[0]; a.async=1; a.src=g; m.parentNode.insertBefore(a, m) +})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga') -export default function() { +export default function () { return function () { - window.ga.apply(window, arguments); + window.ga(...arguments) } } -var devicePromise = new Promise((resolve, reject) => { +let devicePromise = new Promise((resolve, reject) => { if (window.cordova) { - document.addEventListener('deviceready', resolve, false); - } - else { + document.addEventListener('deviceready', resolve, false) + } else { console.log('No cordova detected') - resolve(); + resolve() } }) angular.module('beeline') .run(['$rootScope', async function ($rootScope) { - await devicePromise; + await devicePromise if (window.cordova) { - const GA_LOCAL_STORAGE_KEY = 'ga:clientId'; + const GA_LOCAL_STORAGE_KEY = 'ga:clientId' // Set up cordova to use localstorage over cookies (file:/// doesn't // support cookies) ga('create', 'UA-79537959-1', { storage: 'none', - clientId: localStorage.getItem(GA_LOCAL_STORAGE_KEY) - }); + clientId: localStorage.getItem(GA_LOCAL_STORAGE_KEY), + }) ga((tracker) => { - localStorage.setItem(GA_LOCAL_STORAGE_KEY, tracker.get('clientId')); - }); + localStorage.setItem(GA_LOCAL_STORAGE_KEY, tracker.get('clientId')) + }) // We have a file:/// URL, but tell GA to ignore it - ga('set', 'checkProtocolTask', null); - } - else { - ga('create', 'UA-79537959-1', 'auto'); + ga('set', 'checkProtocolTask', null) + } else { + ga('create', 'UA-79537959-1', 'auto') } // The first page view ga('send', 'pageview', { @@ -60,8 +60,7 @@ angular.module('beeline') window.cordova.getAppVersion.getAppName().then((appName) => { ga('set', 'appName', appName) }) - } - else { + } else { ga('set', 'appVersion', window.location.origin) ga('set', 'appName', 'Beeline Web') } diff --git a/beeline/services/KickstarterService.js b/beeline/services/KickstarterService.js index 316c3926d..8eba0e347 100644 --- a/beeline/services/KickstarterService.js +++ b/beeline/services/KickstarterService.js @@ -1,16 +1,16 @@ -import querystring from 'querystring'; -import _ from 'lodash'; -import assert from 'assert'; -import {SafeInterval} from '../SafeInterval'; +import querystring from 'querystring' +import _ from 'lodash' +import assert from 'assert' +import {SafeInterval} from '../SafeInterval' -var transformKickstarterData = function (kickstarterRoutes) { - if (!kickstarterRoutes) return null; - for (let kickstarter of kickstarterRoutes){ - kickstarter.isActived = false; +let transformKickstarterData = function (kickstarterRoutes) { + if (!kickstarterRoutes) return null + for (let kickstarter of kickstarterRoutes) { + kickstarter.isActived = false if (kickstarter.bids && kickstarter.bids.length > 0) { - var bidsByTier = _.groupBy(kickstarter.bids, x => x.priceF); + var bidsByTier = _.groupBy(kickstarter.bids, (x) => x.priceF) kickstarter.notes.tier.map((tier)=>{ - var countCommitted = bidsByTier[tier.price] ? bidsByTier[tier.price].length :0; + let countCommitted = bidsByTier[tier.price] ? bidsByTier[tier.price].length :0 _.assign(tier, {count: countCommitted, moreNeeded: Math.max(tier.pax-countCommitted, 0)}) }) @@ -19,26 +19,26 @@ var transformKickstarterData = function (kickstarterRoutes) { _.assign(tier, {count: 0, moreNeeded: tier.pax}) }) } - //order tiers in price desc order - kickstarter.notes.tier = _.orderBy(kickstarter.notes.tier, x=>x.price, "desc"); - //if sb. commit $8, also commit $5 + // order tiers in price desc order + kickstarter.notes.tier = _.orderBy(kickstarter.notes.tier, (x)=>x.price, 'desc') + // if sb. commit $8, also commit $5 // kickstarter.notes.tier[1].count += kickstarter.notes.tier[0].count; - kickstarter.isActived = kickstarter.notes.tier[0].moreNeeded==0; + kickstarter.isActived = kickstarter.notes.tier[0].moreNeeded==0 - kickstarter.isExpired = false; - kickstarter.is7DaysOld = false; + kickstarter.isExpired = false + kickstarter.is7DaysOld = false - var now = new Date().getTime(); + let now = new Date().getTime() if (kickstarter.notes && kickstarter.notes.crowdstartExpiry) { - var expiryTime = new Date(kickstarter.notes.crowdstartExpiry).getTime(); + let expiryTime = new Date(kickstarter.notes.crowdstartExpiry).getTime() if (now >= expiryTime) { - kickstarter.isExpired = true; + kickstarter.isExpired = true if (now - expiryTime >= 7*1000*60*60*24) { - kickstarter.is7DaysOld = true; + kickstarter.is7DaysOld = true } - } else{ - var day = 1000 * 60 * 60 * 24; - kickstarter.daysLeft = Math.ceil((expiryTime - now)/day); + } else { + let day = 1000 * 60 * 60 * 24 + kickstarter.daysLeft = Math.ceil((expiryTime - now)/day) } } @@ -47,100 +47,99 @@ var transformKickstarterData = function (kickstarterRoutes) { kickstarter.isSuccess = kickstarter.tags.indexOf('success') != -1 kickstarter.isConverted = kickstarter.isFailed || kickstarter.isSuccess - //filter only isRunning trips - //sort trips date in ascending order - kickstarter.trips = _(kickstarter.trips).filter(x=>x.isRunning) - .orderBy(x=>x.date) - .value(); - //sort tripStops time in ascending order - _.forEach(kickstarter.trips, function(trip){ - trip.tripStops = _.orderBy(trip.tripStops, stop=>stop.time) - }); + // filter only isRunning trips + // sort trips date in ascending order + kickstarter.trips = _(kickstarter.trips).filter((x)=>x.isRunning) + .orderBy((x)=>x.date) + .value() + // sort tripStops time in ascending order + _.forEach(kickstarter.trips, function (trip) { + trip.tripStops = _.orderBy(trip.tripStops, (stop)=>stop.time) + }) - //calculate the pass expiry date - kickstarter.passExpired = false; - var firstTripDate = new Date(kickstarter.trips[0].date); - var passExpiryTime = new Date(firstTripDate.getFullYear(), firstTripDate.getMonth()+1, firstTripDate.getDate()).getTime(); - kickstarter.passExpired = (now >= passExpiryTime); - updateStatus(kickstarter); + // calculate the pass expiry date + kickstarter.passExpired = false + let firstTripDate = new Date(kickstarter.trips[0].date) + let passExpiryTime = new Date(firstTripDate.getFullYear(), firstTripDate.getMonth()+1, firstTripDate.getDate()).getTime() + kickstarter.passExpired = (now >= passExpiryTime) + updateStatus(kickstarter) } - return kickstarterRoutes; + return kickstarterRoutes } -var updateStatus = function(route){ - //status of kickstarter - route.status = ""; +var updateStatus = function (route) { + // status of kickstarter + route.status = '' if ((route.notes.tier[0].moreNeeded==0)) { - route.status = "Yay! Route is activated at $" + route.notes.tier[0].price.toFixed(2) + " per trip." + route.status = 'Yay! Route is activated at $' + route.notes.tier[0].price.toFixed(2) + ' per trip.' } else if (!route.isExpired) { - route.status = route.notes.tier[0].moreNeeded + " more pax to activate the route at $"+route.notes.tier[0].price.toFixed(2)+" per trip." + route.status = route.notes.tier[0].moreNeeded + ' more pax to activate the route at $'+route.notes.tier[0].price.toFixed(2)+' per trip.' } else if (route.isSuccess) { - route.status = "Campaign was successful! Check out the running routes for more info" + route.status = 'Campaign was successful! Check out the running routes for more info' } else { - route.status = "Campaign has expired and the route is not activated." + route.status = 'Campaign has expired and the route is not activated.' } } -var updateAfterBid = function(route, price) { - route.notes.tier[0].count = route.notes.tier[0].count + 1; - route.notes.tier[0].moreNeeded = Math.max(route.notes.tier[0].moreNeeded-1 ,0); - route.isActived = route.notes.tier[0].moreNeeded==0; - updateStatus(route); +let updateAfterBid = function (route, price) { + route.notes.tier[0].count = route.notes.tier[0].count + 1 + route.notes.tier[0].moreNeeded = Math.max(route.notes.tier[0].moreNeeded-1, 0) + route.isActived = route.notes.tier[0].moreNeeded==0 + updateStatus(route) } export default ['$http', 'UserService', '$q', '$rootScope', 'RoutesService', 'p', 'DevicePromise', - function KickstarterService($http, UserService,$q, $rootScope, RoutesService, p, DevicePromise) { - var kickstarterRoutesCache; - var bidsCache; - var kickstarterSummary = null, bidsById = null; - var kickstarterRoutesList = null, kickstarterRoutesById = null; - var nearbyKickstarterRoutesById = null; + function KickstarterService ($http, UserService, $q, $rootScope, RoutesService, p, DevicePromise) { + let kickstarterRoutesCache + let bidsCache + let kickstarterSummary = null, bidsById = null + let kickstarterRoutesList = null, kickstarterRoutesById = null + let nearbyKickstarterRoutesById = null UserService.userEvents.on('userChanged', () => { - fetchBids(true); - //to load route credits - RoutesService.fetchRoutePassCount(true); + fetchBids(true) + // to load route credits + RoutesService.fetchRoutePassCount(true) }) - //first load + // first load // every 1 hour should reload kickstarter information - var timeout = new SafeInterval(refresh, 1000*60*60, 1000*60); + let timeout = new SafeInterval(refresh, 1000*60*60, 1000*60) - function refresh() { - return Promise.all([fetchKickstarterRoutes(true),fetchBids(true), fetchNearbyKickstarterIds()]); + function refresh () { + return Promise.all([fetchKickstarterRoutes(true), fetchBids(true), fetchNearbyKickstarterIds()]) } - timeout.start(); + timeout.start() - function fetchBids(ignoreCache) { + function fetchBids (ignoreCache) { if (UserService.getUser()) { - if (bidsCache && !ignoreCache) return bidsCache; + if (bidsCache && !ignoreCache) return bidsCache return bidsCache = UserService.beeline({ method: 'GET', url: '/crowdstart/bids', }).then((response) => { // kickstarterSummary = response.data; - kickstarterSummary = response.data.map(bid => { + kickstarterSummary = response.data.map((bid) => { return { routeId: bid.routeId, bidPrice: bid.priceF, - status: bid.status + status: bid.status, } }) - bidsById = _.keyBy(kickstarterSummary, r=>r.routeId); - return kickstarterSummary; - }); - } - else { - kickstarterSummary = []; - return $q.resolve(kickstarterSummary); + bidsById = _.keyBy(kickstarterSummary, (r)=>r.routeId) + return kickstarterSummary + }) + } else { + kickstarterSummary = [] + return $q.resolve(kickstarterSummary) } } - function fetchKickstarterRoutes(ignoreCache) { - if (kickstarterRoutesCache && !ignoreCache) return kickstarterRoutesCache; - var url = '/crowdstart/status'; + function fetchKickstarterRoutes (ignoreCache) { + if (kickstarterRoutesCache && !ignoreCache) return kickstarterRoutesCache + let url = '/crowdstart/status' if (p.transportCompanyId) { url += '?'+querystring.stringify({transportCompanyId: p.transportCompanyId}) } @@ -148,124 +147,124 @@ export default ['$http', 'UserService', '$q', method: 'GET', url: url, }).then((response)=>{ - //return expired kickstarter too - kickstarterRoutesList = transformKickstarterData(response.data); + // return expired kickstarter too + kickstarterRoutesList = transformKickstarterData(response.data) kickstarterRoutesById = _.keyBy(kickstarterRoutesList, 'id') return kickstarterRoutesList }) } - function getLocationPromise(enableHighAccuracy = false) { + function getLocationPromise (enableHighAccuracy = false) { return new Promise((resolve, reject)=>{ navigator.geolocation.getCurrentPosition((success)=>resolve(success), (error)=>reject(error), {enableHighAccuracy}) - }); + }) } - async function fetchNearbyKickstarterIds() { - let locationOrNull = null; + async function fetchNearbyKickstarterIds () { + let locationOrNull = null try { - await DevicePromise; - locationOrNull = await getLocationPromise(false); + await DevicePromise + locationOrNull = await getLocationPromise(false) } catch (err) { // Location not found -- suppress error - nearbyKickstarterRoutesById = nearbyKickstarterRoutesById || null; + nearbyKickstarterRoutesById = nearbyKickstarterRoutesById || null return new Promise((resolve, reject)=>{ - resolve(nearbyKickstarterRoutesById); + resolve(nearbyKickstarterRoutesById) }) } let coords = { latitude: locationOrNull.coords.latitude, longitude: locationOrNull.coords.longitude, - }; + } let nearbyPromise = UserService.beeline({ method: 'GET', url: '/routes/search_by_latlon?' + querystring.stringify( _.assign( - { maxDistance: 2000, + {maxDistance: 2000, startTime: Date.now(), tags: JSON.stringify(['crowdstart']), startLat: coords.latitude, - startLng: coords.longitude + startLng: coords.longitude, }, p.transportCompanyId ? {transportCompanyId: p.transportCompanyId}: {} ) - ) + ), }) let nearbyReversePromise = UserService.beeline({ method: 'GET', url: '/routes/search_by_latlon?' + querystring.stringify( _.assign( - { maxDistance: 2000, + {maxDistance: 2000, startTime: Date.now(), tags: JSON.stringify(['crowdstart']), endLat: coords.latitude, - endLng: coords.longitude + endLng: coords.longitude, }, p.transportCompanyId ? {transportCompanyId: p.transportCompanyId}: {} ) - ) + ), }) return Promise.all([nearbyPromise, nearbyReversePromise]).then((values) =>{ - let [np, nvp] = values; - return nearbyKickstarterRoutesById = _((np.data).concat(nvp.data)).map(r=>r.id).uniq().value(); - }); + let [np, nvp] = values + return nearbyKickstarterRoutesById = _((np.data).concat(nvp.data)).map((r)=>r.id).uniq().value() + }) } return { - //all crowdstart routes + // all crowdstart routes getCrowdstart: () => kickstarterRoutesList, fetchCrowdstart: (ignoreCache)=>fetchKickstarterRoutes(ignoreCache), - getCrowdstartById: function(routeId) { - return kickstarterRoutesById ? kickstarterRoutesById[routeId] : null; + getCrowdstartById: function (routeId) { + return kickstarterRoutesById ? kickstarterRoutesById[routeId] : null }, - //user personal bid information - getBids: function() { + // user personal bid information + getBids: function () { return kickstarterSummary }, fetchBids: (ignoreCache)=>fetchBids(ignoreCache), - isBid: function(routeId) { - return bidsById && bidsById[routeId] ? true : false + isBid: function (routeId) { + return bidsById && bidsById[routeId] ? true : false }, - getBidInfo: function(routeId) { - return kickstarterSummary ? kickstarterSummary.find(x=>x.routeId == routeId) : null; + getBidInfo: function (routeId) { + return kickstarterSummary ? kickstarterSummary.find((x)=>x.routeId == routeId) : null }, - //need to return a promise - hasBids: function() { + // need to return a promise + hasBids: function () { return bidsCache.then(()=>{ return kickstarterSummary && kickstarterSummary.length>0 && - kickstarterSummary.find(x=>x.status === 'bidded'); + kickstarterSummary.find((x)=>x.status === 'bidded') }) }, - createBid: function(route, boardStopId, alightStopId,bidPrice) { + createBid: function (route, boardStopId, alightStopId, bidPrice) { return UserService.beeline({ method: 'POST', url: `/crowdstart/routes/${route.id}/bids`, data: { - price: bidPrice - } + price: bidPrice, + }, }).then((response)=>{ - updateAfterBid(kickstarterRoutesById[route.id], bidPrice); + updateAfterBid(kickstarterRoutesById[route.id], bidPrice) kickstarterSummary = kickstarterSummary.concat([{ routeId: route.id, bidPrice: bidPrice, - status: 'bidded' + status: 'bidded', }]) - return response.data; + return response.data }) }, getNearbyKickstarterIds: ()=> { - return nearbyKickstarterRoutesById; + return nearbyKickstarterRoutesById }, fetchNearbyKickstarterIds: fetchNearbyKickstarterIds, diff --git a/beeline/services/LazyLoadService.js b/beeline/services/LazyLoadService.js index 0f965dda2..a5d70ef03 100644 --- a/beeline/services/LazyLoadService.js +++ b/beeline/services/LazyLoadService.js @@ -2,13 +2,13 @@ angular.module('beeline') .factory('LazyLoadService', () => lazy) -function lazy(fn) { - let hasValue = false; - let currentValue = null; +function lazy (fn) { + let hasValue = false + let currentValue = null return () => { if (!hasValue) { - hasValue = true; + hasValue = true currentValue = fn() } return currentValue diff --git a/beeline/services/LiteRouteSubscriptionService.js b/beeline/services/LiteRouteSubscriptionService.js index c9e42dee7..f2c55bd60 100644 --- a/beeline/services/LiteRouteSubscriptionService.js +++ b/beeline/services/LiteRouteSubscriptionService.js @@ -1,12 +1,11 @@ -import _ from 'lodash'; -import assert from 'assert'; - +import _ from 'lodash' +import assert from 'assert' export default ['$http', 'UserService', '$q', - function LiteRouteSubscriptionService($http, UserService, $q) { - var LiteRouteSubscriptionCache = null; - var liteRouteSubscriptionsSummary = []; + function LiteRouteSubscriptionService ($http, UserService, $q) { + let LiteRouteSubscriptionCache = null + let liteRouteSubscriptionsSummary = [] UserService.userEvents.on('userChanged', () => { @@ -15,40 +14,38 @@ export default ['$http', 'UserService', '$q', var instance = { - getSubscriptionSummary: function() { - return liteRouteSubscriptionsSummary; + getSubscriptionSummary: function () { + return liteRouteSubscriptionsSummary }, - getSubscriptions: function(ignoreCache) { + getSubscriptions: function (ignoreCache) { if (UserService.getUser()) { - if (LiteRouteSubscriptionCache && !ignoreCache) return liteRouteSubscriptionsSummary; + if (LiteRouteSubscriptionCache && !ignoreCache) return liteRouteSubscriptionsSummary return LiteRouteSubscriptionCache = UserService.beeline({ method: 'GET', url: '/liteRoutes/subscriptions', }).then((response) => { - liteRouteSubscriptionsSummary = response.data.map(subs=>subs.routeLabel); - return liteRouteSubscriptionsSummary; - }); - } - else { - liteRouteSubscriptionsSummary = []; - return $q.resolve([]); + liteRouteSubscriptionsSummary = response.data.map((subs)=>subs.routeLabel) + return liteRouteSubscriptionsSummary + }) + } else { + liteRouteSubscriptionsSummary = [] + return $q.resolve([]) } }, - isSubscribed: async function(label, ignoreCache) { - var subscriptions = await this.getSubscriptions(ignoreCache); - assert(subscriptions); + isSubscribed: async function (label, ignoreCache) { + let subscriptions = await this.getSubscriptions(ignoreCache) + assert(subscriptions) - var subscription = subscriptions.includes(label) + let subscription = subscriptions.includes(label) if (subscription) { - return true; + return true + } else { + return false } - else { - return false; - } - } - }; + }, + } - return instance; + return instance }] diff --git a/beeline/services/LiteRoutesService.js b/beeline/services/LiteRoutesService.js index 587fc197a..3bcdf8a84 100644 --- a/beeline/services/LiteRoutesService.js +++ b/beeline/services/LiteRoutesService.js @@ -3,116 +3,116 @@ // retrieve lists of trips running for certain lite route on certain date // driver pings for list of trips running for this route // subscriptions for certain lite route ( this may go to tickets service) -import querystring from 'querystring'; -import _ from 'lodash'; -import assert from 'assert'; -import moment from 'moment'; - -function transformTime(liteRoutesByLabel) { - for (let label in liteRoutesByLabel){ - var liteRoute = liteRoutesByLabel[label] - //no starting time and ending time +import querystring from 'querystring' +import _ from 'lodash' +import assert from 'assert' +import moment from 'moment' + +function transformTime (liteRoutesByLabel) { + for (let label in liteRoutesByLabel) { + let liteRoute = liteRoutesByLabel[label] + // no starting time and ending time if (!liteRoute.trips) { - liteRoute.startTime = null; - liteRoute.endTime = null; - return; + liteRoute.startTime = null + liteRoute.endTime = null + return } - var allTripStops = _.flatten(liteRoute.trips.map(trip=>trip.tripStops)); - var allStopTimes = allTripStops.map(stop=>stop.time).sort(); - liteRoute.startTime = allStopTimes[0]; - liteRoute.endTime = allStopTimes[allStopTimes.length-1]; + let allTripStops = _.flatten(liteRoute.trips.map((trip)=>trip.tripStops)) + let allStopTimes = allTripStops.map((stop)=>stop.time).sort() + liteRoute.startTime = allStopTimes[0] + liteRoute.endTime = allStopTimes[allStopTimes.length-1] } } export default ['$http', 'UserService', '$q', 'LiteRouteSubscriptionService', 'p', - function LiteRoutesService($http, UserService, $q, LiteRouteSubscriptionService, p) { - - var liteRoutesCache; - var liteRoutesPromise; + function LiteRoutesService ($http, UserService, $q, LiteRouteSubscriptionService, p) { + let liteRoutesCache + let liteRoutesPromise // For single lite route - var lastLiteRouteLabel = null; - var lastLiteRoutePromise = null; + let lastLiteRouteLabel = null + let lastLiteRoutePromise = null - var shouldRefreshLiteTickets = false; - var liteRoutes = null; + let shouldRefreshLiteTickets = false + let liteRoutes = null - function transformTime(liteRoutesByLabel) { - for (let label in liteRoutesByLabel){ - var liteRoute = liteRoutesByLabel[label] - //no starting time and ending time + function transformTime (liteRoutesByLabel) { + for (let label in liteRoutesByLabel) { + let liteRoute = liteRoutesByLabel[label] + // no starting time and ending time if (!liteRoute.trips) { - liteRoute.startTime = null; - liteRoute.endTime = null; - return; + liteRoute.startTime = null + liteRoute.endTime = null + return } - var minTripDate = _.min(liteRoute.trips.map(trip => trip.date)); - var tripAsMinTripDate = liteRoute.trips.filter(trip=>trip.date === minTripDate); - var tripStops = _.flatten(tripAsMinTripDate.map(trip=>trip.tripStops)); - var allStopTimes = tripStops.map(stop=>stop.time).sort(); - liteRoute.startTime = allStopTimes[0]; - liteRoute.endTime = allStopTimes[allStopTimes.length-1]; + var minTripDate = _.min(liteRoute.trips.map((trip) => trip.date)) + let tripAsMinTripDate = liteRoute.trips.filter((trip)=>trip.date === minTripDate) + let tripStops = _.flatten(tripAsMinTripDate.map((trip)=>trip.tripStops)) + let allStopTimes = tripStops.map((stop)=>stop.time).sort() + liteRoute.startTime = allStopTimes[0] + liteRoute.endTime = allStopTimes[allStopTimes.length-1] } } // TODO the same label lite route all data fileds should be the same except trips - //otherwise reduce make no sense - function transformLiteRouteData(data) { - var liteRoutesByLabel = _.reduce(data, function(result,value, key){ - var label = value.label; + // otherwise reduce make no sense + function transformLiteRouteData (data) { + let liteRoutesByLabel = _.reduce(data, function (result, value, key) { + let label = value.label if (result[label] && (result[label].trips || value.trips)) { - result[label].trips = result[label].trips.concat(value.trips); - } - else { - result[label] = value; - //mark isSubscribed as false - result[label].isSubscribed = false; + result[label].trips = result[label].trips.concat(value.trips) + } else { + result[label] = value + // mark isSubscribed as false + result[label].isSubscribed = false } - return result; - }, {}); - transformTime(liteRoutesByLabel); - //ignor the startingTime and endTime for now - return liteRoutesByLabel; + return result + }, {}) + transformTime(liteRoutesByLabel) + // ignor the startingTime and endTime for now + return liteRoutesByLabel } - //consolidate tripstops for lite route - //aggregate stop time for stops - function computeLiteStops(trips) { - var tripStops = _.map(trips, (trip)=>{return trip.tripStops}); - var allTripStops = _.flatten(tripStops); + // consolidate tripstops for lite route + // aggregate stop time for stops + function computeLiteStops (trips) { + let tripStops = _.map(trips, (trip)=>{ +return trip.tripStops +}) + let allTripStops = _.flatten(tripStops) - var boardStops = _.groupBy(allTripStops, function(tripStop){ + let boardStops = _.groupBy(allTripStops, function (tripStop) { return tripStop.stop.id - }); - var newStops = []; - for (let stopId in boardStops){ - var stop = boardStops[stopId][0].stop; - stop.canBoard = boardStops[stopId][0].canBoard; - var timeArray = _.map(boardStops[stopId], (stop)=>{ + }) + let newStops = [] + for (let stopId in boardStops) { + let stop = boardStops[stopId][0].stop + stop.canBoard = boardStops[stopId][0].canBoard + let timeArray = _.map(boardStops[stopId], (stop)=>{ return stop.time }) - var sortedTime = _(timeArray).uniq().sort().value(); - newStops.push(_.extend({"time": sortedTime}, stop)); + let sortedTime = _(timeArray).uniq().sort().value() + newStops.push(_.extend({'time': sortedTime}, stop)) } - return newStops; + return newStops } // Retrive the data on all lite routes // But limits the amount of data retrieved // getRoutes() now returns a list of routes, but with very limited // trip data (limited to 5 trips, no path) - function fetchLiteRoutes(ignoreCache, options) { - if (liteRoutesCache && !ignoreCache && !options) return liteRoutesCache; + function fetchLiteRoutes (ignoreCache, options) { + if (liteRoutesCache && !ignoreCache && !options) return liteRoutesCache - var url = '/routes?'; + let url = '/routes?' // Start at midnight to avoid cut trips in the middle // FIXME: use date-based search instead - var startDate = new Date(); - startDate.setHours(3,0,0,0,0) + let startDate = new Date() + startDate.setHours(3, 0, 0, 0, 0) - var finalOptions = _.assign({ + let finalOptions = _.assign({ startDate: startDate.getTime(), includePath: true, includeTrips: true, @@ -123,36 +123,37 @@ export default ['$http', 'UserService', '$q', 'LiteRouteSubscriptionService', 'p url += querystring.stringify(finalOptions) - var liteRoutesPromise = UserService.beeline({ + let liteRoutesPromise = UserService.beeline({ method: 'GET', url: url, }) - .then(function(response) { + .then(function (response) { // Checking that we have trips, so that users of it don't choke // on trips[0] - liteRoutes = response.data.filter(r => r.trips && r.trips.length); + liteRoutes = response.data.filter((r) => r.trips && r.trips.length) liteRoutes = transformLiteRouteData(liteRoutes) - return liteRoutes; - }); + return liteRoutes + }) // Cache the promise -- prevents two requests from being // in flight together - if (!options) - liteRoutesCache = liteRoutesPromise; - return liteRoutesPromise; + if (!options) { +liteRoutesCache = liteRoutesPromise +} + return liteRoutesPromise } - function fetchLiteRoute(liteRouteLabel, ignoreCache, options) { - assert.equal(typeof liteRouteLabel, 'string'); + function fetchLiteRoute (liteRouteLabel, ignoreCache, options) { + assert.equal(typeof liteRouteLabel, 'string') if (!ignoreCache && !options && lastLiteRouteLabel=== liteRouteLabel) { - return lastLiteRoutePromise; + return lastLiteRoutePromise } - var startDate = new Date(); - startDate.setHours(3,0,0,0,0) + let startDate = new Date() + startDate.setHours(3, 0, 0, 0, 0) - var finalOptions = _.assign({ + let finalOptions = _.assign({ startDate: startDate.getTime(), includeTrips: true, tags: JSON.stringify(['lite']), @@ -161,73 +162,71 @@ export default ['$http', 'UserService', '$q', 'LiteRouteSubscriptionService', 'p }, options, p.transportCompanyId ? {transportCompanyId: p.transportCompanyId}: {}) - var url = '/routes?'; - url+= querystring.stringify(finalOptions); + let url = '/routes?' + url+= querystring.stringify(finalOptions) - lastLiteRouteLabel = liteRouteLabel; + lastLiteRouteLabel = liteRouteLabel return lastLiteRoutePromise = UserService.beeline({ method: 'GET', url: url, }) - .then(function(response) { - var liteRouteData = transformLiteRouteData(response.data); - return liteRouteData; + .then(function (response) { + let liteRouteData = transformLiteRouteData(response.data) + return liteRouteData }) .catch((err) => { - console.error(err); - }); + console.error(err) + }) } return { fetchLiteRoutes: fetchLiteRoutes, fetchLiteRoute: fetchLiteRoute, - getLiteRoutes: function() { - return liteRoutes; + getLiteRoutes: function () { + return liteRoutes }, - subscribeLiteRoute: function(liteRouteLabel) { - var subscribePromise = UserService.beeline({ + subscribeLiteRoute: function (liteRouteLabel) { + let subscribePromise = UserService.beeline({ method: 'POST', url: '/liteRoutes/subscriptions', data: { routeLabel: liteRouteLabel, - } + }, }) - .then(function(response) { - shouldRefreshLiteTickets = true; + .then(function (response) { + shouldRefreshLiteTickets = true if (response.data) { LiteRouteSubscriptionService.getSubscriptionSummary().push(liteRouteLabel) - return true; - } - else{ - return false; + return true + } else { + return false } - }); - return subscribePromise; + }) + return subscribePromise }, - unsubscribeLiteRoute: function(liteRouteLabel) { - var unsubscribePromise = UserService.beeline({ + unsubscribeLiteRoute: function (liteRouteLabel) { + let unsubscribePromise = UserService.beeline({ method: 'DELETE', - url: '/liteRoutes/subscriptions/'+liteRouteLabel + url: '/liteRoutes/subscriptions/'+liteRouteLabel, }) - .then(function(response) { - shouldRefreshLiteTickets = true; + .then(function (response) { + shouldRefreshLiteTickets = true if (response.data) { - var index = LiteRouteSubscriptionService.getSubscriptionSummary().indexOf(liteRouteLabel) + let index = LiteRouteSubscriptionService.getSubscriptionSummary().indexOf(liteRouteLabel) LiteRouteSubscriptionService.getSubscriptionSummary().splice(index, 1) - return true; + return true + } else { + return false } - else{ - return false; - } - }); - return unsubscribePromise; + }) + return unsubscribePromise }, - getShouldRefreshLiteTickets: function() { - return shouldRefreshLiteTickets; + getShouldRefreshLiteTickets: function () { + return shouldRefreshLiteTickets }, - clearShouldRefreshLiteTickets: function() { - shouldRefreshLiteTickets = false; + clearShouldRefreshLiteTickets: function () { + shouldRefreshLiteTickets = false }, transformLiteRouteData: transformLiteRouteData, computeLiteStops: computeLiteStops, diff --git a/beeline/services/LoadingSpinner.js b/beeline/services/LoadingSpinner.js index 16529ac23..8d295b7bf 100644 --- a/beeline/services/LoadingSpinner.js +++ b/beeline/services/LoadingSpinner.js @@ -1,5 +1,5 @@ -import loadingTemplate from '../templates/loading.html'; -import assert from 'assert'; +import loadingTemplate from '../templates/loading.html' +import assert from 'assert' /** @@ -20,31 +20,31 @@ try { **/ export default ['$ionicLoading', - function($ionicLoading) { + function ($ionicLoading) { /* Number of promises being watched by loading spinner */ - var count = 0; + let count = 0 - function hide() { - count = Math.max(0, count - 1); + function hide () { + count = Math.max(0, count - 1) if (count === 0) { - $ionicLoading.hide(); + $ionicLoading.hide() } } - function show() { + function show () { if (count === 0) { - $ionicLoading.show({template: loadingTemplate}); + $ionicLoading.show({template: loadingTemplate}) } - count = count + 1; + count = count + 1 } return function (p) { - assert.strictEqual(typeof p.then, 'function'); - show(); + assert.strictEqual(typeof p.then, 'function') + show() p.then(hide, (err) => { - hide(); - throw err; + hide() + throw err }) - return p; + return p } }] diff --git a/beeline/services/MapOptions.js b/beeline/services/MapOptions.js index e84105442..0b30219bf 100644 --- a/beeline/services/MapOptions.js +++ b/beeline/services/MapOptions.js @@ -1,9 +1,9 @@ -var googleMaps; +let googleMaps export default [ 'uiGmapGoogleMapApi', '$cordovaGeolocation', - function(uiGmapGoogleMapApi, $cordovaGeolocation) { - var markerOptionsPromise = uiGmapGoogleMapApi.then((googleMaps) => { + function (uiGmapGoogleMapApi, $cordovaGeolocation) { + let markerOptionsPromise = uiGmapGoogleMapApi.then((googleMaps) => { return { markerOptions: { boardMarker: { @@ -43,52 +43,52 @@ export default [ routePath: { color: '#4b3863', weight: 3.0, - opacity: 0.7 + opacity: 0.7, }, crowdstartPath: { color: '#AAAAAA', weight: 3.0, - opacity: 0.4 + opacity: 0.4, }, actualPath: { color: '#000000', weight: 3.0, - opacity: 1.0 - } + opacity: 1.0, + }, }, bounds: { Singapore: { north: 1.516329, east: 104.08, south: 1.1954, - west: 103.5814 - } - } - }; - }); + west: 103.5814, + }, + }, + } + }) - this.defaultMapOptions = function(options) { - var mapOptions = _.assign({ + this.defaultMapOptions = function (options) { + let mapOptions = _.assign({ center: {latitude: 1.370244, longitude: 103.823315}, zoom: 11, bounds: { // so that autocomplete will mainly search within Singapore northeast: { latitude: 1.485152, - longitude: 104.091837 + longitude: 104.091837, }, southwest: { latitude: 1.205764, - longitude: 103.589899 - } + longitude: 103.589899, + }, }, control: {}, options: { disableDefaultUI: true, styles: [{ - featureType: "poi", + featureType: 'poi', stylers: [{ - visibility: "off" - }] + visibility: 'off', + }], }], draggable: true, gestureHandling: 'greedy', @@ -102,73 +102,71 @@ export default [ events: {}, markers: [], lines: [], - }, options || {}); + }, options || {}) markerOptionsPromise.then((options) => { - _.assign(mapOptions, options); + _.assign(mapOptions, options) }) - return mapOptions; - }; + return mapOptions + } - this.locateMe = function(mapControl) { - var options = { + this.locateMe = function (mapControl) { + let options = { timeout: 5000, - enableHighAccuracy: true - }; + enableHighAccuracy: true, + } // promise // FIXME: use navigator.geoLocation $cordovaGeolocation .getCurrentPosition({timeout: 5000, enableHighAccuracy: true}) - .then(function(userpos) { - if (!mapControl.getGMap) return; - - var gmap = mapControl.getGMap(); + .then(function (userpos) { + if (!mapControl.getGMap) return - gmap.panTo(new google.maps.LatLng(userpos.coords.latitude, userpos.coords.longitude)); - setTimeout(function() { - gmap.setZoom(17); - }, 300); + let gmap = mapControl.getGMap() - }, function(err) { - console.log('ERROR - ' + err); - }); - }; + gmap.panTo(new google.maps.LatLng(userpos.coords.latitude, userpos.coords.longitude)) + setTimeout(function () { + gmap.setZoom(17) + }, 300) + }, function (err) { + console.log('ERROR - ' + err) + }) + } this.disableMapLinks = function () { - setTimeout(function() { - var anchorElems = document.querySelectorAll('ui-gmap-google-map a[href]') + setTimeout(function () { + let anchorElems = document.querySelectorAll('ui-gmap-google-map a[href]') for (let i=0; i e.preventDefault()); - anchorElem.dataset['clickDisabled'] = true; + anchorElem.addEventListener('click', (e) => e.preventDefault()) + anchorElem.dataset['clickDisabled'] = true } } - }, 300); + }, 300) } - this.resizePreserveCenter = function(map) { - let oldCenter = map.getCenter(); - google.maps.event.trigger(map, 'resize'); - map.setCenter(oldCenter); - }; + this.resizePreserveCenter = function (map) { + let oldCenter = map.getCenter() + google.maps.event.trigger(map, 'resize') + map.setCenter(oldCenter) + } - this.formBounds = function(stops) { + this.formBounds = function (stops) { if (stops.length == 0) { - return; + return } - var bounds = new google.maps.LatLngBounds(); + let bounds = new google.maps.LatLngBounds() for (let s of stops) { bounds.extend(new google.maps.LatLng( s.coordinates.coordinates[1], s.coordinates.coordinates[0] - )); + )) } return bounds } - - } -]; + }, +] diff --git a/beeline/services/MapService.js b/beeline/services/MapService.js index b06e09c6e..f60e82b65 100644 --- a/beeline/services/MapService.js +++ b/beeline/services/MapService.js @@ -11,9 +11,9 @@ angular.module('beeline') emitter.on('search-item', (data) => { // ga site search // https://support.google.com/analytics/answer/1012264?hl=en - let page = window.location.hash.substr(1)+'/search?q=' + data + let page = window.location.hash.substr(1)+'/search?q=' + data GoogleAnalytics('send', 'pageview', { - page: page + page: page, }) }) return emitter diff --git a/beeline/services/OneMapService.js b/beeline/services/OneMapService.js index 4b7b394aa..26c8c7700 100644 --- a/beeline/services/OneMapService.js +++ b/beeline/services/OneMapService.js @@ -1,20 +1,20 @@ -import {NetworkError} from '../shared/errors'; -import {formatDate, formatDateMMMdd, formatTime, formatUTCDate} from '../shared/format'; +import {NetworkError} from '../shared/errors' +import {formatDate, formatDateMMMdd, formatTime, formatUTCDate} from '../shared/format' export default ['$http', - function($http) { - var tokenRequest; + function ($http) { + let tokenRequest return { - token() { - if (tokenRequest) - return tokenRequest; - else { + token () { + if (tokenRequest) { +return tokenRequest +} else { return tokenRequest = $http.get('http://www.onemap.sg/API/services.svc/getToken?accessKEY=qo/s2TnSUmfLz+32CvLC4RMVkzEFYjxqyti1KhByvEacEdMWBpCuSSQ+IFRT84QjGPBCuz/cBom8PfSm3GjEsGc8PkdEEOEr') .then((response) => { - console.log(response); - return response.data.GetToken[0].NewToken; - }); + console.log(response) + return response.data.GetToken[0].NewToken + }) } - } - }; + }, + } }] diff --git a/beeline/services/PlaceService.js b/beeline/services/PlaceService.js index 01447b057..7f8c42b77 100644 --- a/beeline/services/PlaceService.js +++ b/beeline/services/PlaceService.js @@ -1,10 +1,10 @@ angular.module('beeline').factory('PlaceService', ['uiGmapGoogleMapApi', 'LazyLoadService', - function placeService(uiGmapGoogleMapApi, LazyLoadService) { - var autocompleteService, placesService + function placeService (uiGmapGoogleMapApi, LazyLoadService) { + let autocompleteService, placesService uiGmapGoogleMapApi.then((googleMaps) => { - autocompleteService = LazyLoadService(() => new googleMaps.places.AutocompleteService()); + autocompleteService = LazyLoadService(() => new googleMaps.places.AutocompleteService()) placesService = LazyLoadService(() => new google.maps.places.PlacesService(document.createElement('div'))) }) @@ -19,29 +19,29 @@ angular.module('beeline').factory('PlaceService', ['uiGmapGoogleMapApi', 'LazyLo function getDetails (predictions, queryText) { return new Promise(function (resolve, reject) { // If no results found then nothing more to do - if (!placesService || !predictions || predictions.length === 0) reject(); + if (!placesService || !predictions || predictions.length === 0) reject() placesService().getDetails({ - placeId: predictions[0].place_id + placeId: predictions[0].place_id, }, (result) => { - if (!result) reject(); - let place = {queryText: queryText}; - place = _.assign(place,result); - resolve(place); + if (!result) reject() + let place = {queryText: queryText} + place = _.assign(place, result) + resolve(place) }) }) } - async function handleQuery(queryText) { + async function handleQuery (queryText) { let predictions = await getPlacePredictions({ componentRestrictions: {country: 'SG'}, - input: queryText - }); + input: queryText, + }) - let place = await getDetails(predictions, queryText); + let place = await getDetails(predictions, queryText) return place } - return { handleQuery: (queryText) => handleQuery(queryText) } + return {handleQuery: (queryText) => handleQuery(queryText)} }] ) diff --git a/beeline/services/RotatedImageService.js b/beeline/services/RotatedImageService.js index 46992f32f..80b014701 100644 --- a/beeline/services/RotatedImageService.js +++ b/beeline/services/RotatedImageService.js @@ -1,56 +1,56 @@ - -angular.module('beeline') -.factory('RotatedImage', function () { - const WIDTH=300 - const HEIGHT=300 - const canvas = document.createElement('canvas') - canvas.width = WIDTH - canvas.height = HEIGHT - - class RotatedImage { - constructor(imgSource) { - this.loaded = false - this.image = new Image() - this.image.src = imgSource - this.imageLoadPromise = new Promise((resolve) => { - this.image.onload = resolve - }) - .then(() => { - this.loaded = true - }) - } - - rotate(radians, overlayText) { - if (!this.loaded) { - return null - } - - const ctx = canvas.getContext('2d') - ctx.setTransform(1, 0, 0, 1, 0, 0); - //resetTransform not working in safari - // ctx.resetTransform() - ctx.clearRect(0, 0, WIDTH, HEIGHT) - - ctx.translate(WIDTH / 2, HEIGHT / 2) - ctx.rotate(radians) - ctx.translate(-WIDTH / 2, -HEIGHT / 2) - - ctx.drawImage(this.image, 0, 0, WIDTH, HEIGHT) - - - if (overlayText) { - ctx.font = '60px sans-serif' - ctx.fillStyle = 'white' - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - ctx.rotate(Math.PI) - ctx.fillText(overlayText + '', -WIDTH / 2, -HEIGHT / 2) - ctx.rotate(Math.PI) - } - - return canvas.toDataURL() - } - } - - return RotatedImage -}) + +angular.module('beeline') +.factory('RotatedImage', function () { + const WIDTH=300 + const HEIGHT=300 + const canvas = document.createElement('canvas') + canvas.width = WIDTH + canvas.height = HEIGHT + + class RotatedImage { + constructor (imgSource) { + this.loaded = false + this.image = new Image() + this.image.src = imgSource + this.imageLoadPromise = new Promise((resolve) => { + this.image.onload = resolve + }) + .then(() => { + this.loaded = true + }) + } + + rotate (radians, overlayText) { + if (!this.loaded) { + return null + } + + const ctx = canvas.getContext('2d') + ctx.setTransform(1, 0, 0, 1, 0, 0) + // resetTransform not working in safari + // ctx.resetTransform() + ctx.clearRect(0, 0, WIDTH, HEIGHT) + + ctx.translate(WIDTH / 2, HEIGHT / 2) + ctx.rotate(radians) + ctx.translate(-WIDTH / 2, -HEIGHT / 2) + + ctx.drawImage(this.image, 0, 0, WIDTH, HEIGHT) + + + if (overlayText) { + ctx.font = '60px sans-serif' + ctx.fillStyle = 'white' + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + ctx.rotate(Math.PI) + ctx.fillText(overlayText + '', -WIDTH / 2, -HEIGHT / 2) + ctx.rotate(Math.PI) + } + + return canvas.toDataURL() + } + } + + return RotatedImage +}) diff --git a/beeline/services/RoutesService.js b/beeline/services/RoutesService.js index 86a894ed5..8e2350841 100644 --- a/beeline/services/RoutesService.js +++ b/beeline/services/RoutesService.js @@ -1,57 +1,57 @@ -import querystring from 'querystring'; -import _ from 'lodash'; -import assert from 'assert'; +import querystring from 'querystring' +import _ from 'lodash' +import assert from 'assert' // Adapter function to convert what we get from the server into what we want // Ideally shouldn't need this if the server stays up to date // Transforms the data in place rather than making a new array // This is to save time since its a deep copy // and you wont need the original array anyway -function transformRouteData(data) { - _(data).each(function(route) { +function transformRouteData (data) { + _(data).each(function (route) { for (let trip of route.trips) { - assert.equal(typeof trip.date, 'string'); - trip.date = new Date(trip.date); + assert.equal(typeof trip.date, 'string') + trip.date = new Date(trip.date) for (let tripStop of trip.tripStops) { - assert.equal(typeof tripStop.time, 'string'); - tripStop.time = new Date(tripStop.time); + assert.equal(typeof tripStop.time, 'string') + tripStop.time = new Date(tripStop.time) } } - var firstTripStops = route.trips[0].tripStops; - route.startTime = firstTripStops[0].time; - route.startRoad = firstTripStops[0].stop.description; - route.endTime = firstTripStops[firstTripStops.length - 1].time; - route.endRoad = firstTripStops[firstTripStops.length - 1].stop.description; + let firstTripStops = route.trips[0].tripStops + route.startTime = firstTripStops[0].time + route.startRoad = firstTripStops[0].stop.description + route.endTime = firstTripStops[firstTripStops.length - 1].time + route.endRoad = firstTripStops[firstTripStops.length - 1].stop.description route.tripsByDate = _.keyBy(route.trips, - trip => trip.date.getTime()); - }); - return data; + (trip) => trip.date.getTime()) + }) + return data } export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', - function RoutesService($http, UserService, uiGmapGoogleMapApi, $q, p) { + function RoutesService ($http, UserService, uiGmapGoogleMapApi, $q, p) { // For all routes - var routesCache; - var activeRoutes; - var recentRoutesCache; - var recentRoutes; + let routesCache + let activeRoutes + let recentRoutesCache + let recentRoutes // For single routes - var lastRouteId = null; - var lastPromise = null; + let lastRouteId = null + let lastPromise = null // For Route Credits - var routePassesCache; - var tagToPassesMap; - var routePassCache; - var routeToRidesRemainingMap; - var routesWithRoutePassPromise; - var routesWithRoutePass; - var activatedKickstarterRoutes; - var routeToRoutePassTagsPromise = null; - var routeToRoutePassTags = null; + let routePassesCache + let tagToPassesMap + let routePassCache + let routeToRidesRemainingMap + let routesWithRoutePassPromise + let routesWithRoutePass + let activatedKickstarterRoutes + let routeToRoutePassTagsPromise = null + let routeToRoutePassTags = null UserService.userEvents.on('userChanged', () => { instance.fetchRecentRoutes(true) @@ -65,37 +65,37 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // Retrive the data on a single route, but pulls a lot more data // Pulls all the trips plus the route path // getRoute() will return the heavier stuff (all trips, availability, path) - getRoute: function(routeId, ignoreCache, options) { - assert.equal(typeof routeId, 'number'); + getRoute: function (routeId, ignoreCache, options) { + assert.equal(typeof routeId, 'number') if (!ignoreCache && !options && lastRouteId === routeId) { - return lastPromise; + return lastPromise } - var startDate = new Date(); - startDate.setHours(3,0,0,0,0) + let startDate = new Date() + startDate.setHours(3, 0, 0, 0, 0) - var finalOptions = _.assign({ + let finalOptions = _.assign({ startDate: startDate.getTime(), includeTrips: true, }, options) - lastRouteId = routeId; + lastRouteId = routeId return lastPromise = UserService.beeline({ method: 'GET', url: `/routes/${routeId}?${querystring.stringify(finalOptions)}`, }) - .then(function(response) { - transformRouteData([response.data]); - return response.data; + .then(function (response) { + transformRouteData([response.data]) + return response.data }) .catch((err) => { - console.error(err); - }); + console.error(err) + }) }, // Returns list of all routes - getRoutes: function(){ + getRoutes: function () { return activeRoutes }, @@ -104,17 +104,17 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // getRoutes() now returns a list of routes, but with very limited // trip data (limited to 5 trips, no path) // Return promise with all routes - fetchRoutes: function(ignoreCache, options) { - if (routesCache && !ignoreCache && !options) return routesCache; + fetchRoutes: function (ignoreCache, options) { + if (routesCache && !ignoreCache && !options) return routesCache - var url = '/routes?'; + let url = '/routes?' // Start at midnight to avoid cut trips in the middle // FIXME: use date-based search instead - var startDate = new Date(); - startDate.setHours(3,0,0,0,0) + let startDate = new Date() + startDate.setHours(3, 0, 0, 0, 0) - var finalOptions = _.assign({ + let finalOptions = _.assign({ startDate: startDate.getTime(), includeTrips: true, limitTrips: 5, @@ -125,25 +125,26 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', url += querystring.stringify(finalOptions) - var routesPromise = UserService.beeline({ + let routesPromise = UserService.beeline({ method: 'GET', url: url, }) - .then(function(response) { + .then(function (response) { // Checking that we have trips, so that users of it don't choke // on trips[0] - var routes = response.data.filter(r => r.trips && r.trips.length); + let routes = response.data.filter((r) => r.trips && r.trips.length) transformRouteData(routes) activeRoutes = routes - return routes; - }); + return routes + }) // Cache the promise -- prevents two requests from being // in flight together - if (!options) - routesCache = routesPromise; + if (!options) { +routesCache = routesPromise +} - return routesPromise; + return routesPromise }, /** @@ -162,7 +163,7 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', before this time @return {Promise} **/ - searchRoutes: function(search) { + searchRoutes: function (search) { // return Promise object return UserService.beeline({ method: 'GET', @@ -172,44 +173,44 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', endLat: search.endLat, endLng: search.endLng, arrivalTime: search.arrivalTime, - startTime: search.startTime, + startTime: search.startTime, endTime: search.endTime, - tags: JSON.stringify(['public']) + tags: JSON.stringify(['public']), }), - }).then(function(response) { - return transformRouteData(response.data); - }); + }).then(function (response) { + return transformRouteData(response.data) + }) }, // Retrieves the recent routes for a user // If not logged in then just returns an empty array - fetchRecentRoutes: function(ignoreCache) { + fetchRecentRoutes: function (ignoreCache) { if (UserService.getUser()) { - if (recentRoutesCache && !ignoreCache) return recentRoutesCache; + if (recentRoutesCache && !ignoreCache) return recentRoutesCache return recentRoutesCache = UserService.beeline({ method: 'GET', - url: '/routes/recent?limit=10' - }).then(function(response) { + url: '/routes/recent?limit=10', + }).then(function (response) { recentRoutes = response.data return recentRoutes - }); + }) } else { - //if user not logged in clear recentRoutes - recentRoutes = []; - return $q.resolve([]); + // if user not logged in clear recentRoutes + recentRoutes = [] + return $q.resolve([]) } }, - getRecentRoutes: function(){ + getRecentRoutes: function () { return recentRoutes }, // TODO: make a directive, otherwise literoute need to inject this routeservice decodeRoutePath: function (path) { - assert.strictEqual(typeof path, 'string'); + assert.strictEqual(typeof path, 'string') return uiGmapGoogleMapApi.then((googleMaps) => { // Array of LatLng objects - return googleMaps.geometry.encoding.decodePath(path); + return googleMaps.geometry.encoding.decodePath(path) }) }, @@ -218,21 +219,23 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', method: 'GET', url: `/routes/${routeId}/features`, }) - .then(function(response) { - return response.data; + .then(function (response) { + return response.data }) .catch((err) => { - console.error(err); - }); + console.error(err) + }) }, // Return an array of regions covered by a given array of routes - getUniqueRegionsFromRoutes: function(routes) { - return _(routes).map(function(route) {return route.regions;}) + getUniqueRegionsFromRoutes: function (routes) { + return _(routes).map(function (route) { +return route.regions +}) .flatten() .uniqBy('id') .sortBy('name') - .value(); + .value() }, // get all route passes associated with the user @@ -241,23 +244,22 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // - ignoreCache - boolean // output: // - Promise containing all route passes associated with user - fetchRoutePasses: function(ignoreCache){ - if(!ignoreCache && routePassesCache){ + fetchRoutePasses: function (ignoreCache) { + if (!ignoreCache && routePassesCache) { return routePassesCache } // Destroy the cache for dependent calls // This is a hack - routesWithRoutePassPromise = null; - routePassCache = null; + routesWithRoutePassPromise = null + routePassCache = null - let user = UserService.getUser(); - if(!user){ - return routePassesCache = Promise.resolve(tagToPassesMap = null); - } - else { + let user = UserService.getUser() + if (!user) { + return routePassesCache = Promise.resolve(tagToPassesMap = null) + } else { return routePassesCache = UserService.beeline({ method: 'GET', - url: '/route_passes' + url: '/route_passes', }).then((response) => { return tagToPassesMap = response.data }) @@ -270,8 +272,8 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // output: // - Object containing all route passes associated with user // - [tag provided] amount of credits specific to the tag - getRoutePasses: function(tag){ - if(tag && tagToPassesMap){ + getRoutePasses: function (tag) { + if (tag && tagToPassesMap) { return tagToPassesMap[tag] } else { return tagToPassesMap @@ -284,20 +286,20 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // - creditTag - string: tag associated with route // output: // - promise containing number of rides remaining on the route pass for specified route - getRoutePassCount: function(){ + getRoutePassCount: function () { return routeToRidesRemainingMap }, // New more abstracted method which differentiates between 0 and null // 0 means user is logged in a no credits found // null means not logged in so we don't know - getPassCountForRoute: function(routeId) { + getPassCountForRoute: function (routeId) { if (UserService.getUser()) { - if (!routeToRidesRemainingMap) return null; - let ridesRemaining = routeToRidesRemainingMap[routeId]; - return ridesRemaining ? ridesRemaining : 0; + if (!routeToRidesRemainingMap) return null + let ridesRemaining = routeToRidesRemainingMap[routeId] + return ridesRemaining ? ridesRemaining : 0 } else { - return null; + return null } }, @@ -306,27 +308,27 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // - ignoreCache - boolean to determine if cache should be ignored // output: // - promise containing a map of routeId to Rides Remaining - fetchRoutePassCount: function(ignoreCache){ - if(ignoreCache || !routePassCache){ + fetchRoutePassCount: function (ignoreCache) { + if (ignoreCache || !routePassCache) { let allRoutesPromise = this.fetchRoutes(ignoreCache) let allRoutePassesPromise = this.fetchRoutePasses(ignoreCache) - routePassCache = $q.all([allRoutesPromise, allRoutePassesPromise]).then(function(values){ + routePassCache = $q.all([allRoutesPromise, allRoutePassesPromise]).then(function (values) { let allRoutes = values[0] - let allRoutePasses = values[1]; - let allRoutePassTags = _.keys(allRoutePasses); + let allRoutePasses = values[1] + let allRoutePassTags = _.keys(allRoutePasses) routeToRidesRemainingMap = {} - allRoutes.forEach(function(route){ - let notableTags = _.intersection(route.tags, allRoutePassTags); - if(notableTags.length < 1) return //no credit for such route + allRoutes.forEach(function (route) { + let notableTags = _.intersection(route.tags, allRoutePassTags) + if (notableTags.length < 1) return // no credit for such route else { // support multiple tags e.g. crowdstart-140, rp-161 // calculate the rides left in the route pass - notableTags.forEach(function(tag) { - let passesAvailable = allRoutePasses[tag]; + notableTags.forEach(function (tag) { + let passesAvailable = allRoutePasses[tag] routeToRidesRemainingMap[route.id] = - (routeToRidesRemainingMap[route.id] || 0) + passesAvailable; + (routeToRidesRemainingMap[route.id] || 0) + passesAvailable }) } }) @@ -334,7 +336,6 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', }) } return routePassCache - }, // Generates a list of all routes, modifying those with route @@ -349,23 +350,23 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // ridesRemaining property // - updates routesWithRoutePass: array containing all avaialable routes, // modifying those with route credits remaining with a ridesRemaining property - fetchRoutesWithRoutePass: function(ignoreCache) { - if(ignoreCache || !routesWithRoutePassPromise){ + fetchRoutesWithRoutePass: function (ignoreCache) { + if (ignoreCache || !routesWithRoutePassPromise) { return routesWithRoutePassPromise = $q.all([ this.fetchRoutes(ignoreCache), this.fetchRoutePassCount(ignoreCache), ]).then(([allRoutes, routeToRidesRemainingMap]) => { - if(routeToRidesRemainingMap){ - routesWithRoutePass = allRoutes.map(route => { - var clone = _.clone(route); + if (routeToRidesRemainingMap) { + routesWithRoutePass = allRoutes.map((route) => { + let clone = _.clone(route) clone.ridesRemaining = (route.id in routeToRidesRemainingMap) ? - routeToRidesRemainingMap[route.id] : null; - return clone; + routeToRidesRemainingMap[route.id] : null + return clone }) activatedKickstarterRoutes = routesWithRoutePass.filter( - route => route.id in routeToRidesRemainingMap) + (route) => route.id in routeToRidesRemainingMap) - return routesWithRoutePass; + return routesWithRoutePass } else { return routesWithRoutePass = allRoutes } @@ -373,28 +374,27 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', } return routesWithRoutePassPromise - }, // Returns array containing all avaialable routes, // modifying those with route credits remaining with a ridesRemaining property // Updated by: fetchRoutesWithRoutePass - getRoutesWithRoutePass: function() { + getRoutesWithRoutePass: function () { return routesWithRoutePass }, // Returns array containing only those routes with // ridesRemaining property // Updated by: fetchRoutesWithRoutePass - getActivatedKickstarterRoutes: function(){ + getActivatedKickstarterRoutes: function () { return activatedKickstarterRoutes }, // Returns promise containing a map of all routeId to their corresponding tags // based on the route passes available to a user - fetchRoutePassTags: function(ignoreCache){ + fetchRoutePassTags: function (ignoreCache) { if (!ignoreCache && routeToRoutePassTagsPromise) { - return routeToRoutePassTagsPromise; + return routeToRoutePassTagsPromise } let routesPromise = this.fetchRoutesWithRoutePass() @@ -402,15 +402,15 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', return routeToRoutePassTagsPromise = $q.all([routesPromise, routePassesPromise]) .then(([routes, routePasses])=>{ - if(routePasses){ + if (routePasses) { routeToRoutePassTags = {} - routes.forEach(route => { - let routePassTags = _.keys(routePasses); + routes.forEach((route) => { + let routePassTags = _.keys(routePasses) let notableTags = _.intersection(route.tags, routePassTags) - if(notableTags.length >= 1){ + if (notableTags.length >= 1) { // sort in alphabetical order followed by // to encourage use of crowdstart credit before rp- - notableTags = _.sortBy(notableTags, function(tag) { + notableTags = _.sortBy(notableTags, function (tag) { return tag }) // filter out no balance tag @@ -433,47 +433,47 @@ export default ['$http', 'UserService', 'uiGmapGoogleMapApi', '$q', 'p', // Returns the route pass tag matched to a route if routeId is given // Otherwise, returns a map of all routeId to their corresponding tags // based on the route passes available to a user - getRoutePassTags: function(routeId){ - if(routeId && routeToRoutePassTags){ + getRoutePassTags: function (routeId) { + if (routeId && routeToRoutePassTags) { return routeToRoutePassTags[routeId] } else { return routeToRoutePassTags } }, - fetchPriceSchedule: function(routeId){ + fetchPriceSchedule: function (routeId) { return UserService.beeline({ method: 'GET', url: `/routes/${routeId}/price_schedule`, }) - .then(function(response) { + .then(function (response) { let priceSchedules = [] - _.forEach(response.data, (value , key) => { + _.forEach(response.data, (value, key) => { let quantity = parseInt(key) let singleSchedule = null if (quantity === 1) { - singleSchedule = {"quantity": 1, "price": parseFloat(value.price), "totalPrice": parseFloat(value.price)} + singleSchedule = {'quantity': 1, 'price': parseFloat(value.price), 'totalPrice': parseFloat(value.price)} } else { // in case no discount is found let discount = value.discount || 0 let price = (value.price / quantity) let originalPrice = discount + value.price let computedDiscount = (discount / originalPrice).toFixed(2) * 100 - singleSchedule = {"quantity": quantity, "price": price, "discount": computedDiscount, "totalPrice": parseFloat(value.price)} + singleSchedule = {'quantity': quantity, 'price': price, 'discount': computedDiscount, 'totalPrice': parseFloat(value.price)} } priceSchedules.push(singleSchedule) }) // sort the schedules from biggest quantity to 1 ticket - priceSchedules = _.sortBy(priceSchedules, function(schedule) { + priceSchedules = _.sortBy(priceSchedules, function (schedule) { return schedule.quantity }).reverse() return priceSchedules }) .catch((err) => { - console.error(err); - }); - } + console.error(err) + }) + }, - }; - return instance; + } + return instance }] diff --git a/beeline/services/SearchService.js b/beeline/services/SearchService.js index 5d569eaf1..7776b0a68 100644 --- a/beeline/services/SearchService.js +++ b/beeline/services/SearchService.js @@ -1,17 +1,16 @@ -import _ from 'lodash'; - -export default function SearchService() { +import _ from 'lodash' +export default function SearchService () { // Helper to calculate distance in meters between a pair of coordinates // faster but less accurate - function latlngDistance(ll1, ll2) { - var rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] - var rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] + function latlngDistance (ll1, ll2) { + let rr1 = [ll1[0] / 180 * Math.PI, ll1[1] / 180 * Math.PI] + let rr2 = [ll2[0] / 180 * Math.PI, ll2[1] / 180 * Math.PI] - var dx = (rr1[1] - rr2[1]) * Math.cos(0.5 * (rr1[0] + rr2[0])) - var dy = rr1[0] - rr2[0] + let dx = (rr1[1] - rr2[1]) * Math.cos(0.5 * (rr1[0] + rr2[0])) + let dy = rr1[0] - rr2[0] - var dist = Math.sqrt(dx * dx + dy * dy) * 6378137 + let dist = Math.sqrt(dx * dx + dy * dy) * 6378137 return dist } @@ -34,78 +33,78 @@ export default function SearchService() { return { - filterRoutesByText: function(routes, string) { - return routes.filter(route => this.routeContainsString(route, string)); + filterRoutesByText: function (routes, string) { + return routes.filter((route) => this.routeContainsString(route, string)) }, - filterRoutes: function(routes, regionId, string) { + filterRoutes: function (routes, regionId, string) { return this.filterRoutesByText(routes, string) }, - filterRoutesByPlace: function(routes, place) { - const maxDistance = 1000; // Arbitrary constant for closeness + filterRoutesByPlace: function (routes, place) { + const maxDistance = 1000 // Arbitrary constant for closeness // Check the trips stops of a route to see if any come close - let filteredRoutes = routes.filter(route => { + let filteredRoutes = routes.filter((route) => { return _.some(route.trips[0].tripStops, (tripStop) => { let distance = latlngDistance( [ tripStop.stop.coordinates.coordinates[1], - tripStop.stop.coordinates.coordinates[0] + tripStop.stop.coordinates.coordinates[0], ], [place.geometry.location.lat(), place.geometry.location.lng()] - ); - return distance < maxDistance; - }); - }); + ) + return distance < maxDistance + }) + }) - return filteredRoutes; + return filteredRoutes }, - filterRoutesByLngLat: function(routes, lnglat) { - const maxDistance = 500; // Arbitrary constant for closeness + filterRoutesByLngLat: function (routes, lnglat) { + const maxDistance = 500 // Arbitrary constant for closeness // Check the trips stops of a route to see if any come close - let filteredRoutes = routes.filter(route => { + let filteredRoutes = routes.filter((route) => { return _.some(route.trips[0].tripStops, (tripStop) => { let distance = latlngDistance( [ tripStop.stop.coordinates.coordinates[1], - tripStop.stop.coordinates.coordinates[0] + tripStop.stop.coordinates.coordinates[0], ], [lnglat[1], lnglat[0]] - ); - return distance < maxDistance; - }); - }); + ) + return distance < maxDistance + }) + }) - return filteredRoutes; + return filteredRoutes }, - filterRoutesByPlaceAndText: function(routes, place, text) { - let placeResults = this.filterRoutesByPlace(routes, place); - let textResults = this.filterRoutesByText(routes, text); - return _.unionBy(placeResults, textResults, 'id'); + filterRoutesByPlaceAndText: function (routes, place, text) { + let placeResults = this.filterRoutesByPlace(routes, place) + let textResults = this.filterRoutesByText(routes, text) + return _.unionBy(placeResults, textResults, 'id') }, // Input: a Route and a string // Output: True if route metatdata contains the string - routeContainsString: function(route, string) { - if (!string) return true; + routeContainsString: function (route, string) { + if (!string) return true - function containsIgnoreCase(s, t) { + function containsIgnoreCase (s, t) { if (typeof s === 'string') { // If the search phrase (t) is more than one word, just find t in s // Otherwise, split s and see if any words in s start with t - if (t.split(" ").length > 1) { + if (t.split(' ').length > 1) { return s.toUpperCase().includes(t.toUpperCase()) } else { // Split on non-alphanumeric chars let words = s.toUpperCase().split(/[^A-Za-z0-9]/) - return words.some(word => word.startsWith(t.toUpperCase())) + return words.some((word) => word.startsWith(t.toUpperCase())) } } else { - return false; + return false } } return containsIgnoreCase(route.name, string) || @@ -113,10 +112,10 @@ export default function SearchService() { containsIgnoreCase(route.schedule, string) || containsIgnoreCase(route.label, string) || (route.trips[0] && ( - route.trips[0].tripStops.some(ts => containsIgnoreCase(ts.stop.description, string)) || - route.trips[0].tripStops.some(ts => containsIgnoreCase(ts.stop.road, string)) - )); - } + route.trips[0].tripStops.some((ts) => containsIgnoreCase(ts.stop.description, string)) || + route.trips[0].tripStops.some((ts) => containsIgnoreCase(ts.stop.road, string)) + )) + }, - }; + } } diff --git a/beeline/services/ServerTimeService.js b/beeline/services/ServerTimeService.js index 8eba2700a..92ec443ce 100644 --- a/beeline/services/ServerTimeService.js +++ b/beeline/services/ServerTimeService.js @@ -1,11 +1,9 @@ angular.module('beeline') -.factory('ServerTime', ['UserService','$http', - function(UserService, $http) { - +.factory('ServerTime', ['UserService', '$http', + function (UserService, $http) { class ServerTime { - - sync() { + sync () { return new Promise((resolve) => { if (this.localServerTimeDiff) { resolve() @@ -15,20 +13,20 @@ angular.module('beeline') }) } - getTime() { - return Date.now() + parseInt(this.localServerTimeDiff ? this.localServerTimeDiff : 0) + getTime () { + return Date.now() + parseInt(this.localServerTimeDiff ? this.localServerTimeDiff : 0) } - _syncTime() { - const startTime = new Date(); + _syncTime () { + const startTime = new Date() const handler = (headers) => { - var timeDiff = new Date(headers.date) - (new Date()) + ((new Date()) - startTime) / 2; + let timeDiff = new Date(headers.date) - (new Date()) + ((new Date()) - startTime) / 2 this.localServerTimeDiff = timeDiff } // https://www.codeproject.com/Articles/790220/Accurate-time-in-JavaScript // return $http({url: "http://www.googleapis.com", method: 'GET'}) - return $http({url: "https://api.beeline.sg/user", method: 'GET'}) + return $http({url: 'https://api.beeline.sg/user', method: 'GET'}) .then( (response) => handler(response.headers()), (error) => handler(error.headers()) diff --git a/beeline/services/SharedVariableService.js b/beeline/services/SharedVariableService.js index 4e586cc0b..3fe549bc1 100644 --- a/beeline/services/SharedVariableService.js +++ b/beeline/services/SharedVariableService.js @@ -1,9 +1,8 @@ angular.module('beeline') -.factory('SharedVariableService', ['RoutesService', +.factory('SharedVariableService', ['RoutesService', (RoutesService) => { - - var sharedData = { + let sharedData = { stops: [], boardStops: [], alightStops: [], @@ -14,55 +13,55 @@ angular.module('beeline') liteTripStops: [], pingTrips: [], chosenStop: null, - }; + } - var instance = { - get: function() { + let instance = { + get: function () { return sharedData }, - set: function(mapObject) { + set: function (mapObject) { sharedData = _.assign(sharedData, mapObject) }, - setStops: function(stops) { + setStops: function (stops) { sharedData.stops = stops }, - setBoardStops: function(boardStops) { + setBoardStops: function (boardStops) { sharedData.boardStops = boardStops }, - setAlightStops: function(alightStops) { + setAlightStops: function (alightStops) { sharedData.alightStops = alightStops }, - setRoutePath: function(routePath) { + setRoutePath: function (routePath) { sharedData.routePath = routePath }, - setBoardStop: function(boardStop) { + setBoardStop: function (boardStop) { sharedData.boardStop = boardStop }, - setAlightStop: function(alightStop) { + setAlightStop: function (alightStop) { sharedData.alightStop = alightStop }, - setLiteTripStops: function(liteTripStops) { + setLiteTripStops: function (liteTripStops) { sharedData.liteTripStops = liteTripStops }, - setPingTrips: function(pingTrips) { + setPingTrips: function (pingTrips) { sharedData.pingTrips = pingTrips }, - setChosenStop: function(chosenStop) { + setChosenStop: function (chosenStop) { sharedData.chosenStop = chosenStop - } + }, } - return instance; + return instance }] ) diff --git a/beeline/services/StripeService.js b/beeline/services/StripeService.js index 23434883d..85532d0a3 100644 --- a/beeline/services/StripeService.js +++ b/beeline/services/StripeService.js @@ -1,36 +1,36 @@ export default ['UserService', '$ionicPopup', '$ionicPlatform', '$rootScope', - function initStripe(UserService, $ionicPopup, $ionicPlatform, $rootScope) { - var stripeKeyPromise = UserService.beeline({ + function initStripe (UserService, $ionicPopup, $ionicPlatform, $rootScope) { + let stripeKeyPromise = UserService.beeline({ url: '/stripe-key', method: 'GET', }) .then((response) => { - Stripe.setPublishableKey(response.data.publicKey); - return response.data.publicKey; - }); + Stripe.setPublishableKey(response.data.publicKey) + return response.data.publicKey + }) - function tokenFromStripeCheckout(description, amount, isAddPayment) { + function tokenFromStripeCheckout (description, amount, isAddPayment) { return stripeKeyPromise.then((stripeKey) => { return new Promise((resolve, reject) => { - var deregister; - var handler = StripeCheckout.configure({ + let deregister + let handler = StripeCheckout.configure({ key: stripeKey, locale: 'auto', // allowRememberMe: false, - token: function(token) { - deregister(); - resolve(token); + token: function (token) { + deregister() + resolve(token) }, - closed: function() { - deregister(); - resolve(null); + closed: function () { + deregister() + resolve(null) }, - }); + }) deregister = $ionicPlatform.registerBackButtonAction(() => { - handler.close(); - }, 401); + handler.close() + }, 401) let handlerOptions = { name: $rootScope.o.APP.NAME, @@ -46,61 +46,61 @@ export default ['UserService', '$ionicPopup', '$ionicPlatform', '$rootScope', handlerOptions = { name: 'Add Card Details', description: description, - panelLabel: "Add Card", + panelLabel: 'Add Card', allowRememberMe: false, - email: UserService.getUser().email + email: UserService.getUser().email, } } - handler.open(handlerOptions); - }); - }); - }; + handler.open(handlerOptions) + }) + }) + } - async function tokenFromCardIO(description, amount, isAddPayment) { - var cardDetails = await new Promise((resolve, reject) => CardIO.scan({ - "expiry": true, - "cvv": true, - "zip": false, - "suppressManual": false, - "suppressConfirm": false, - "hideLogo": true - }, resolve, () => resolve(null))); + async function tokenFromCardIO (description, amount, isAddPayment) { + let cardDetails = await new Promise((resolve, reject) => CardIO.scan({ + 'expiry': true, + 'cvv': true, + 'zip': false, + 'suppressManual': false, + 'suppressConfirm': false, + 'hideLogo': true, + }, resolve, () => resolve(null))) - if (cardDetails == null) return; + if (cardDetails == null) return - var tokenPromise = new Promise((resolve, reject) => Stripe.createToken({ - number: cardDetails["card_number"], - cvc: cardDetails["cvv"], - exp_month: cardDetails["expiry_month"], - exp_year: cardDetails["expiry_year"], + let tokenPromise = new Promise((resolve, reject) => Stripe.createToken({ + number: cardDetails['card_number'], + cvc: cardDetails['cvv'], + exp_month: cardDetails['expiry_month'], + exp_year: cardDetails['expiry_year'], }), (statusCode, response) => { - if (response.error) - reject(new Error(response.error.message)); - else - resolve(response); - }); + if (response.error) { +reject(new Error(response.error.message)) +} else { +resolve(response) +} + }) - return tokenPromise; - }; + return tokenPromise + } return { - async promptForToken(description, amount, isAddPayment) { - var tokenPromise; + async promptForToken (description, amount, isAddPayment) { + let tokenPromise if (window.CardIO) { - tokenPromise = tokenFromCardIO(description, amount, isAddPayment); - } - else if (StripeCheckout) { - tokenPromise = tokenFromStripeCheckout(description, amount, isAddPayment); + tokenPromise = tokenFromCardIO(description, amount, isAddPayment) + } else if (StripeCheckout) { + tokenPromise = tokenFromStripeCheckout(description, amount, isAddPayment) } tokenPromise.catch((err) => { - $ionicPopup.alert(`There was an error contacting Stripe. ${err && err.message}`); + $ionicPopup.alert(`There was an error contacting Stripe. ${err && err.message}`) }) - return tokenPromise; + return tokenPromise }, loaded: (typeof StripeCheckout !== 'undefined') ? true : false, - }; + } }] diff --git a/beeline/services/SuggestionService.js b/beeline/services/SuggestionService.js index 94f889022..be82285f9 100644 --- a/beeline/services/SuggestionService.js +++ b/beeline/services/SuggestionService.js @@ -1,60 +1,59 @@ export default ['$http', 'UserService', - function($http, UserService) { - var suggestions = []; - var selectedSuggestion = null; - var similarSuggestions = []; + function ($http, UserService) { + let suggestions = [] + let selectedSuggestion = null + let similarSuggestions = [] return { - get:function() { + get: function () { return UserService.beeline({ method: 'GET', - url: "/suggestions", - }); + url: '/suggestions', + }) }, - getSuggestions: function() { - return suggestions; + getSuggestions: function () { + return suggestions }, - getSuggestionById: function(id) { - for (var i = 0; i < suggestions.length; i++) { + getSuggestionById: function (id) { + for (let i = 0; i < suggestions.length; i++) { if (suggestions[i].id == id) { - console.log("found suggestion"); - return suggestions[i]; + console.log('found suggestion') + return suggestions[i] } } - return null; + return null }, - getSimilar: function() { + getSimilar: function () { return UserService.beeline({ method: 'GET', - url: "/suggestions/10126/similar", + url: '/suggestions/10126/similar', }) .then((response) => { - similarSuggestions = response.data; - return similarSuggestions; - }); + similarSuggestions = response.data + return similarSuggestions + }) }, - getSimilarSuggestions: function() { - return []; + getSimilarSuggestions: function () { + return [] }, - setSelectedSuggestion: function(suggestionId) { - console.log("setselectedsuggestion"); - console.log(suggestionId); - for (var i = 0; i < suggestions.length; i++) { + setSelectedSuggestion: function (suggestionId) { + console.log('setselectedsuggestion') + console.log(suggestionId) + for (let i = 0; i < suggestions.length; i++) { if (suggestions[i].id === suggestionId) { - selectedSuggestion = suggestions[i]; - + selectedSuggestion = suggestions[i] } } - console.log("-------------------"); - console.log("setselectedticket"); - console.log(selectedSuggestion); + console.log('-------------------') + console.log('setselectedticket') + console.log(selectedSuggestion) }, - getSelectedSuggestion: function() { + getSelectedSuggestion: function () { // need to handle if null - return selectedSuggestion; - } - }; + return selectedSuggestion + }, + } }] diff --git a/beeline/services/TicketService.js b/beeline/services/TicketService.js index 22ef43fb6..d8010e428 100644 --- a/beeline/services/TicketService.js +++ b/beeline/services/TicketService.js @@ -1,24 +1,24 @@ -import _ from 'lodash'; -import assert from 'assert'; -import querystring from 'querystring'; +import _ from 'lodash' +import assert from 'assert' +import querystring from 'querystring' export default ['$http', '$filter', 'UserService', 'p', - function TicketService($http, $filter, UserService, p) { - var ticketsCache = null; - var allTickets = null; - var ticketsByRouteId = null; + function TicketService ($http, $filter, UserService, p) { + let ticketsCache = null + let allTickets = null + let ticketsByRouteId = null - //set to true with setShouldRefreshTickets once a ticket is bought - //set to false once getCategorizedTickets is called - var shouldRefreshTickets = false; + // set to true with setShouldRefreshTickets once a ticket is bought + // set to false once getCategorizedTickets is called + let shouldRefreshTickets = false UserService.userEvents.on('userChanged', () => { fetchTickets(true) }) - function fetchTickets(ignoreCache) { - if (ticketsCache && !ignoreCache) return ticketsCache; - var url = '/tickets'; + function fetchTickets (ignoreCache) { + if (ticketsCache && !ignoreCache) return ticketsCache + let url = '/tickets' if (p.transportCompanyId) { url += '?'+querystring.stringify({transportCompanyId: p.transportCompanyId}) } @@ -26,74 +26,74 @@ export default ['$http', '$filter', 'UserService', 'p', method: 'GET', url: url, }).then((response) => { - ticketsByRouteId = _.groupBy(response.data, ticket => ticket.boardStop.trip.routeId); - return allTickets = response.data; - }); + ticketsByRouteId = _.groupBy(response.data, (ticket) => ticket.boardStop.trip.routeId) + return allTickets = response.data + }) } return { - getShouldRefreshTickets: function() { - return shouldRefreshTickets; + getShouldRefreshTickets: function () { + return shouldRefreshTickets }, - setShouldRefreshTickets: function() { - shouldRefreshTickets = true; + setShouldRefreshTickets: function () { + shouldRefreshTickets = true }, fetchTickets: fetchTickets, - getTickets: function(){ + getTickets: function () { return allTickets }, - getTicketsByRouteId(rid, ignoreCache) { + getTicketsByRouteId (rid, ignoreCache) { return this.fetchTickets(ignoreCache) .then(() => { - return ticketsByRouteId[rid]; - }); + return ticketsByRouteId[rid] + }) }, - fetchPreviouslyBookedDaysByRouteId: function(rid, ignoreCache) { + fetchPreviouslyBookedDaysByRouteId: function (rid, ignoreCache) { return this.getTicketsByRouteId(rid, ignoreCache) .then((tickets) => { - var dates = _.keyBy(tickets, t => new Date(t.boardStop.trip.date).getTime()) || {}; - return dates; + let dates = _.keyBy(tickets, (t) => new Date(t.boardStop.trip.date).getTime()) || {} + return dates }) }, - getTicketById: function(id, ignoreCache) { - assert.equal(typeof id, 'number'); - return this.fetchTickets(ignoreCache).then(function(tickets) { - return _.find(tickets, {id: id}); - }); + getTicketById: function (id, ignoreCache) { + assert.equal(typeof id, 'number') + return this.fetchTickets(ignoreCache).then(function (tickets) { + return _.find(tickets, {id: id}) + }) }, - getCategorizedTickets: function(ignoreCache) { - shouldRefreshTickets = false; - return this.fetchTickets(ignoreCache).then(function(tickets) { - var now = new Date(); - var lastMidnight = now.setHours(0, 0, 0, 0); - var nextMidnight = now.setHours(24, 0, 0, 0); - var categorizedTickets = {}; - categorizedTickets.today = tickets.filter(function(ticket) { + getCategorizedTickets: function (ignoreCache) { + shouldRefreshTickets = false + return this.fetchTickets(ignoreCache).then(function (tickets) { + let now = new Date() + let lastMidnight = now.setHours(0, 0, 0, 0) + let nextMidnight = now.setHours(24, 0, 0, 0) + let categorizedTickets = {} + categorizedTickets.today = tickets.filter(function (ticket) { return ticket.boardStop !== null && Date.parse(ticket.boardStop.time) >= lastMidnight && - Date.parse(ticket.boardStop.time) < nextMidnight; - }); - categorizedTickets.afterToday = tickets.filter(function(ticket) { + Date.parse(ticket.boardStop.time) < nextMidnight + }) + categorizedTickets.afterToday = tickets.filter(function (ticket) { return ticket.boardStop !== null && - Date.parse(ticket.boardStop.time) >= nextMidnight; - }); - return categorizedTickets; - }); + Date.parse(ticket.boardStop.time) >= nextMidnight + }) + return categorizedTickets + }) }, - hasNextTripTicket: function(routeId, nextTripDateInMills) { + hasNextTripTicket: function (routeId, nextTripDateInMills) { return this.fetchPreviouslyBookedDaysByRouteId(routeId) .then((dates) => { return dates && _.includes(dates, nextTripDateInMills) }) - } - }; + }, + } }] diff --git a/beeline/services/TripService.js b/beeline/services/TripService.js index 6ef3f3fb2..d62d002de 100644 --- a/beeline/services/TripService.js +++ b/beeline/services/TripService.js @@ -1,26 +1,26 @@ import assert from 'assert' export default ['UserService', - function TripService(UserService) { + function TripService (UserService) { return { - getTripData: function(id) { + getTripData: function (id) { assert(typeof id === 'number') return UserService.beeline({ method: 'GET', url: '/trips/' + id, - }).then(function(response) { + }).then(function (response) { return response.data }) }, - driverPings: function(id) { + driverPings: function (id) { assert(typeof id === 'number') return UserService.beeline({ method: 'GET', url: '/trips/' + id + '/latestInfo', timeout: 10000, - }).then(function(response) { + }).then(function (response) { for (let ping of response.data.pings) { ping.time = new Date(ping.time) } diff --git a/beeline/services/UserService.js b/beeline/services/UserService.js index de16cabc2..cba1112cf 100644 --- a/beeline/services/UserService.js +++ b/beeline/services/UserService.js @@ -1,219 +1,217 @@ -import querystring from 'querystring'; -import uuid from 'uuid'; -import _ from 'lodash'; -import assert from 'assert'; -import verifiedPromptTemplate from '../templates/verified-prompt.html'; -import requestingVerificationCodeTemplate from '../templates/requesting-verification-code.html'; -import sendingVerificationCodeTemplate from '../templates/sending-verification-code.html'; -import registeringWithServerTemplate from '../templates/registering-with-server.html'; -import EventEmitter from 'events'; -const VALID_PHONE_REGEX = /^[8-9]{1}[0-9]{7}$/; -const VALID_VERIFICATION_CODE_REGEX = /^[0-9]{6}$/; +import querystring from 'querystring' +import uuid from 'uuid' +import _ from 'lodash' +import assert from 'assert' +import verifiedPromptTemplate from '../templates/verified-prompt.html' +import requestingVerificationCodeTemplate from '../templates/requesting-verification-code.html' +import sendingVerificationCodeTemplate from '../templates/sending-verification-code.html' +import registeringWithServerTemplate from '../templates/registering-with-server.html' +import EventEmitter from 'events' +const VALID_PHONE_REGEX = /^[8-9]{1}[0-9]{7}$/ +const VALID_VERIFICATION_CODE_REGEX = /^[0-9]{6}$/ // user name must be at least 3 characters long, space in front // or after non-space characters are ignored e.g. " a c ", // "exe", "alieo" is valid name -const VALID_USER_NAME = /^\s*\S.+\S\s*$/; +const VALID_USER_NAME = /^\s*\S.+\S\s*$/ // This file is dynamically generated by webpack from environment variables export default ['$http', '$ionicPopup', '$ionicLoading', '$rootScope', 'LoginDialog', '$q', 'loadingSpinner', - function UserService($http, $ionicPopup, $ionicLoading, $rootScope, LoginDialog, $q, loadingSpinner) { - + function UserService ($http, $ionicPopup, $ionicLoading, $rootScope, LoginDialog, $q, loadingSpinner) { // //////////////////////////////////////////////////////////////////////////// // Private internal methods and variables // //////////////////////////////////////////////////////////////////////////// - var sessionToken = window.localStorage.sessionToken || null; - var user = window.localStorage.beelineUser ? - JSON.parse(window.localStorage.beelineUser) : null; - var userEvents = new EventEmitter(); + let sessionToken = window.localStorage.sessionToken || null + let user = window.localStorage.beelineUser ? + JSON.parse(window.localStorage.beelineUser) : null + let userEvents = new EventEmitter() // General purpose wrapper for making http requests to server // Adds the appropriate http headers and token if signed in - var beelineRequest = function(options) { - options.url = process.env.BACKEND_URL + options.url; - options.headers = options.headers || {}; + let beelineRequest = function (options) { + options.url = process.env.BACKEND_URL + options.url + options.headers = options.headers || {} // Attach the session token if logged in if (sessionToken) { - options.headers.authorization = 'Bearer ' + sessionToken; + options.headers.authorization = 'Bearer ' + sessionToken } // Attach headers to track execution environment if (window.device) { - options.headers['Beeline-Device-UUID'] = window.device.uuid; - options.headers['Beeline-Device-Model'] = window.device.model; - options.headers['Beeline-Device-Platform'] = window.device.platform; - options.headers['Beeline-Device-Version'] = window.device.version; - options.headers['Beeline-Device-Manufacturer'] = window.device.manufacturer; - options.headers['Beeline-Device-Serial'] = window.device.serial; - } - else { - window.localStorage.uuid = window.localStorage.uuid || uuid.v4(); - options.headers['Beeline-Device-UUID'] = window.localStorage.uuid; - options.headers['Beeline-Device-Model'] = window.navigator.userAgent; - options.headers['Beeline-Device-Platform'] = 'Browser'; + options.headers['Beeline-Device-UUID'] = window.device.uuid + options.headers['Beeline-Device-Model'] = window.device.model + options.headers['Beeline-Device-Platform'] = window.device.platform + options.headers['Beeline-Device-Version'] = window.device.version + options.headers['Beeline-Device-Manufacturer'] = window.device.manufacturer + options.headers['Beeline-Device-Serial'] = window.device.serial + } else { + window.localStorage.uuid = window.localStorage.uuid || uuid.v4() + options.headers['Beeline-Device-UUID'] = window.localStorage.uuid + options.headers['Beeline-Device-Model'] = window.navigator.userAgent + options.headers['Beeline-Device-Platform'] = 'Browser' } - options.headers['Beeline-App-Name'] = $rootScope.o.APP.NAME.replace(/\s/g, ''); - return $http(options); - }; + options.headers['Beeline-App-Name'] = $rootScope.o.APP.NAME.replace(/\s/g, '') + return $http(options) + } // Requests a verification code to be sent to a mobile number // Verification code is used to log in - var sendTelephoneVerificationCode = function(number) { + let sendTelephoneVerificationCode = function (number) { return beelineRequest({ method: 'POST', url: '/users/sendTelephoneVerification', data: { telephone: '+65' + number, alphanumericId: ($rootScope.o.APP.SMS_OTP_FROM).replace(/\s/g, ''), - appName: $rootScope.o.APP.NAME + appName: $rootScope.o.APP.NAME, }, - headers: {'Content-Type': 'application/json'} - }).then(function() { - return true; - }); - }; + headers: {'Content-Type': 'application/json'}, + }).then(function () { + return true + }) + } // Submit the received code and number for verification to the server - var verifyTelephone = function(telephoneNumber, code) { + let verifyTelephone = function (telephoneNumber, code) { return beelineRequest({ method: 'POST', url: '/users/verifyTelephone', data: { telephone: '+65' + telephoneNumber, - code: code - } + code: code, + }, }) - .then(function(response) { - sessionToken = response.data.sessionToken; - window.localStorage.setItem('sessionToken', sessionToken); - user = response.data.user; - userEvents.emit("userChanged"); - window.localStorage.setItem('beelineUser', JSON.stringify(user)); + .then(function (response) { + sessionToken = response.data.sessionToken + window.localStorage.setItem('sessionToken', sessionToken) + user = response.data.user + userEvents.emit('userChanged') + window.localStorage.setItem('beelineUser', JSON.stringify(user)) - return user; - }); - }; + return user + }) + } // Prepares an update of the telephone number // The returned update toke is used together with the verification number // @returns Promise. - var requestUpdateTelephone = function(telephone) { + let requestUpdateTelephone = function (telephone) { return beelineRequest({ url: '/user/requestUpdateTelephone', method: 'POST', - data: {newTelephone: '+65' + telephone} + data: {newTelephone: '+65' + telephone}, + }) + .then(function (response) { + return response.data.updateToken }) - .then(function(response) { - return response.data.updateToken; - }); - }; + } // Really tell the server to update the telephone // number. Pass this function the updateToken returned by // requestUpdateTelephone and the verification key received // by SMS - var updateTelephone = function(updateToken, verificationKey) { + let updateTelephone = function (updateToken, verificationKey) { return beelineRequest({ url: '/user/updateTelephone', method: 'POST', data: { code: verificationKey, - updateToken: updateToken - } + updateToken: updateToken, + }, + }) + .then(function (reponse) { + user = reponse.data + window.localStorage.setItem('beelineUser', JSON.stringify(user)) + return user }) - .then(function(reponse) { - user = reponse.data; - window.localStorage.setItem('beelineUser', JSON.stringify(user)); - return user; - }); - }; + } // Updates user fields - function updateUserInfo(update) { + function updateUserInfo (update) { return beelineRequest({ method: 'PUT', url: '/user', - data: update + data: update, + }) + .then(function (response) { + user = response.data + return user }) - .then(function(response) { - user = response.data; - return user; - }); - }; - - var logOut = function() { - sessionToken = null; - user = null; - userEvents.emit("userChanged"); - delete window.localStorage.sessionToken; - delete window.localStorage.beelineUser; - return Promise.resolve(); - }; + } + + let logOut = function () { + sessionToken = null + user = null + userEvents.emit('userChanged') + delete window.localStorage.sessionToken + delete window.localStorage.beelineUser + return Promise.resolve() + } // Queries the server to test if the session is still valid // Updates the user info if necessary // If the session is invalid then log out - var verifySession = function() { + let verifySession = function () { return beelineRequest({ url: '/user', - method: 'GET' + method: 'GET', }) - .then(function(response) { - user = response.data; + .then(function (response) { + user = response.data if (!user) { - logOut(); // user not found - return false; + logOut() // user not found + return false } userEvents.emit('userChanged') - return true; - }, function(error) { + return true + }, function (error) { if (error.status == 403 || error.status == 401) { - logOut(); - return false; + logOut() + return false } - }); - }; + }) + } - var getReferralMsg = function(){ - const shareMsgTemplate = "Hey, here is $10 credits for you to try out Beeline rides. \nVisit https://app.beeline.sg/#/welcome?refCode=" + let getReferralMsg = function () { + const shareMsgTemplate = 'Hey, here is $10 credits for you to try out Beeline rides. \nVisit https://app.beeline.sg/#/welcome?refCode=' return shareMsgTemplate + user.referralCode.code } // //////////////////////////////////////////////////////////////////////////// // UI methods // //////////////////////////////////////////////////////////////////////////// - var verifiedPrompt = function(options) { - var promptScope = $rootScope.$new(true); + let verifiedPrompt = function (options) { + let promptScope = $rootScope.$new(true) promptScope.form ={ - verifiedPromptForm : {} - }; + verifiedPromptForm: {}, + } promptScope.data = { inputs: options.inputs || [], - bodyText: options.bodyText || '' - }; - _.defaultsDeep(options,{ + bodyText: options.bodyText || '', + } + _.defaultsDeep(options, { template: verifiedPromptTemplate, title: '', subTitle: '', scope: promptScope, buttons: [ - { text: 'Cancel'}, + {text: 'Cancel'}, { text: 'OK', type: 'button-positive', - onTap: function(e) { + onTap: function (e) { if (promptScope.form.verifiedPromptForm.$valid) { - return promptScope.data; + return promptScope.data } - e.preventDefault(); - } - } - ] - }); - return $ionicPopup.show(options); - }; + e.preventDefault() + }, + }, + ], + }) + return $ionicPopup.show(options) + } - var promptTelephoneNumber = function(title, subtitle){ + let promptTelephoneNumber = function (title, subtitle) { return verifiedPrompt({ title: title, bodyText: subtitle, @@ -223,13 +221,13 @@ export default ['$http', '$ionicPopup', '$ionicLoading', '$rootScope', 'LoginDia name: 'phone', pattern: VALID_PHONE_REGEX, errorMsg: 'The phone no. you provide does not appear to be in the correct format. \ - Please provide a valid 8-digit phone no. starting with the number 8 or 9.' - } - ] + Please provide a valid 8-digit phone no. starting with the number 8 or 9.', + }, + ], }) } - var promptVerificationCode = function(telephone){ + let promptVerificationCode = function (telephone) { return verifiedPrompt({ title: 'Verification', bodyText: 'Enter the 6-digit code sent to '+telephone, @@ -237,135 +235,135 @@ export default ['$http', '$ionicPopup', '$ionicLoading', '$rootScope', 'LoginDia { type: 'tel', name: 'code', - pattern: VALID_VERIFICATION_CODE_REGEX - } - ] - }); + pattern: VALID_VERIFICATION_CODE_REGEX, + }, + ], + }) } // The combined prompt for phone number and subsequent prompt for verification code - var promptLogIn = async function() { + let promptLogIn = async function () { try { // Ask for telephone number - var result = await LoginDialog.show(); + let result = await LoginDialog.show() // if user close the model - if (!result) return; - var [telephoneNumber, wantVerification] = result; - if (!telephoneNumber) return; + if (!result) return + let [telephoneNumber, wantVerification] = result + if (!telephoneNumber) return if (wantVerification) { await loadingSpinner( sendTelephoneVerificationCode(telephoneNumber) - ); + ) } // Ask for verification code - var verificationCode = await promptVerificationCode(telephoneNumber); - if (!verificationCode) return; - var user = await loadingSpinner( + let verificationCode = await promptVerificationCode(telephoneNumber) + if (!verificationCode) return + let user = await loadingSpinner( verifyTelephone(telephoneNumber, verificationCode.code) - ); + ) // Is the user name null? - checkNewUser(user); - return user; + checkNewUser(user) + return user } // If an error occurs at any point stop and alert the user - catch(error) { + catch (error) { if (error.status === 401) { $ionicPopup.alert({ - title: "Incorrect login", - subTitle: error && error.data && error.data.message - }); + title: 'Incorrect login', + subTitle: error && error.data && error.data.message, + }) } else { $ionicPopup.alert({ - title: "Error while trying to connect to server.", - subTitle: error && error.data && error.data.message - }); + title: 'Error while trying to connect to server.', + subTitle: error && error.data && error.data.message, + }) } - throw error; // Allow the calling function to catch the error - }; - }; + throw error // Allow the calling function to catch the error + } + } - let loginIfNeeded = async function() { - if (user) return user; + let loginIfNeeded = async function () { + if (user) return user else { - let user = await promptLogIn(); - if (user) return user; - else throw new Error("Log in aborted"); + let user = await promptLogIn() + if (user) return user + else throw new Error('Log in aborted') } - }; + } // Registration Sequence used for Welcome page (via Referral Link) // Verifies telephone number and prompts for name and email for registration // Saves referral code to user data - var registerViaReferralWelcome = async function(telephoneNumber, refCode, refCodeOwner){ + let registerViaReferralWelcome = async function (telephoneNumber, refCode, refCodeOwner) { try { - if (!telephoneNumber) return; + if (!telephoneNumber) return await loadingSpinner( sendTelephoneVerificationCode(telephoneNumber) ) // Ask for verification code - var verificationCode = await promptVerificationCode(telephoneNumber); - if (!verificationCode) return; + let verificationCode = await promptVerificationCode(telephoneNumber) + if (!verificationCode) return - var user = await loadingSpinner( + let user = await loadingSpinner( verifyTelephone(telephoneNumber, verificationCode.code) - ); + ) // Is the user name null? await loadingSpinner((async () => { - await checkNewUser(user); + await checkNewUser(user) - if(refCode && refCodeOwner){ + if (refCode && refCodeOwner) { await applyRefCode(refCode) } - })()); + })()) } // If an error occurs at any point stop and alert the user - catch(error) { + catch (error) { $ionicPopup.alert({ - title: "Error while trying to connect to server.", - subTitle: error && error.data && error.data.message - }); - throw error; // Allow the calling function to catch the error - }; + title: 'Error while trying to connect to server.', + subTitle: error && error.data && error.data.message, + }) + throw error // Allow the calling function to catch the error + } } // Use the referral code and apply rewards to newUser // Input: // - refCode - String: referral code - async function applyRefCode(refCode){ + async function applyRefCode (refCode) { return beelineRequest({ - method: "POST", - url: "/user/applyRefCode", + method: 'POST', + url: '/user/applyRefCode', data: { refCode: refCode, - } + }, }) } - function register(newUser) { + function register (newUser) { return beelineRequest({ method: 'POST', url: '/users', - data: newUser + data: newUser, }) - .then(function(response) { + .then(function (response) { return response.data - }); - }; + }) + } - async function checkNewUser(user) { + async function checkNewUser (user) { if (user.name || user.email) { // Not a new user - return; + return } try { - var accountResponse = await verifiedPrompt({ + let accountResponse = await verifiedPrompt({ title: 'Account Details', bodyText: 'Welcome! This looks like your first login.\ Please complete the account setup.', @@ -375,171 +373,171 @@ export default ['$http', '$ionicPopup', '$ionicLoading', '$rootScope', 'LoginDia name: 'name', pattern: VALID_USER_NAME, inputPlaceHolder: 'Name', - errorMsg: 'Please provide a name with 3 or more characters.' + errorMsg: 'Please provide a name with 3 or more characters.', }, { type: 'email', name: 'email', inputPlaceHolder: 'name@example.com', errorMsg: 'Email address does not appear to be in the correct format. \ - Please provide a valid email address.' + Please provide a valid email address.', }, ], - }); + }) if (!accountResponse) { - logOut(); - $rootScope.$digest(); - return; - } - else { - $ionicLoading.show({template: registeringWithServerTemplate}); - var updateResponse = await updateUserInfo({ + logOut() + $rootScope.$digest() + return + } else { + $ionicLoading.show({template: registeringWithServerTemplate}) + let updateResponse = await updateUserInfo({ name: accountResponse.name, email: accountResponse.email, - }); - $ionicLoading.hide(); + }) + $ionicLoading.hide() } } // If an error occurs at any point stop and alert the user - catch(error) { - $ionicLoading.hide(); + catch (error) { + $ionicLoading.hide() $ionicPopup.alert({ - title: "Error while trying to connect to server.", - subTitle: error && error.data && error.data.message - }); - }; - }; + title: 'Error while trying to connect to server.', + subTitle: error && error.data && error.data.message, + }) + } + } // Similar to prompt login // The combined prompt for phone number and subsequent prompt for verification code - var promptUpdatePhone = async function() { - try{ + let promptUpdatePhone = async function () { + try { // Start by prompting for the phone number - var telephoneResponse = await promptTelephoneNumber('Update Phone Number', - 'Please enter your new 8-digit mobile number to receive a verification code.'); - if (!telephoneResponse) return; - $ionicLoading.show({template: requestingVerificationCodeTemplate}); - var telephone = telephoneResponse.phone; - var updateToken = await requestUpdateTelephone(telephone); - $ionicLoading.hide(); - var updateCode = await promptVerificationCode(telephone); - if (!updateCode) return; - $ionicLoading.show({template: sendingVerificationCodeTemplate}); - await updateTelephone(updateToken, updateCode.code); - $ionicLoading.hide(); + let telephoneResponse = await promptTelephoneNumber('Update Phone Number', + 'Please enter your new 8-digit mobile number to receive a verification code.') + if (!telephoneResponse) return + $ionicLoading.show({template: requestingVerificationCodeTemplate}) + let telephone = telephoneResponse.phone + let updateToken = await requestUpdateTelephone(telephone) + $ionicLoading.hide() + let updateCode = await promptVerificationCode(telephone) + if (!updateCode) return + $ionicLoading.show({template: sendingVerificationCodeTemplate}) + await updateTelephone(updateToken, updateCode.code) + $ionicLoading.hide() $ionicPopup.alert({ - title: "Your phone number has been successfully updated.", - subTitle: "It is now " + telephone - }); + title: 'Your phone number has been successfully updated.', + subTitle: 'It is now ' + telephone, + }) } // If an error occurs at any point stop and alert the user - catch(error){ - $ionicLoading.hide(); + catch (error) { + $ionicLoading.hide() $ionicPopup.alert({ - title: "Error updating phone number.", - subTitle: error && error.data && error.data.message - }); - }; - }; + title: 'Error updating phone number.', + subTitle: error && error.data && error.data.message, + }) + } + } - var promptUpdateUserInfo = async function(field) { + let promptUpdateUserInfo = async function (field) { try { - var filedInput; - if (field === 'name'){ + let filedInput + if (field === 'name') { filedInput = { type: 'text', - name: 'name', + name: 'name', pattern: VALID_USER_NAME, - errorMsg: 'Please provide a name with 3 or more characters.' + errorMsg: 'Please provide a name with 3 or more characters.', } } - if (field === 'email'){ + if (field === 'email') { filedInput = { type: 'email', - name: 'email', + name: 'email', errorMsg: 'Email address doesn\'t appear to be in the correct format. \ - Please provide a valid email address.' + Please provide a valid email address.', } } - var verifiedResponse = await verifiedPrompt({ + let verifiedResponse = await verifiedPrompt({ title: 'Update '+field, bodyText: 'Enter your new '+field, - inputs: [filedInput] + inputs: [filedInput], }) - if (!verifiedResponse) return; - var update={}; - update[field] = verifiedResponse[field]; - return updateUserInfo(update); - } - catch(error){ + if (!verifiedResponse) return + let update={} + update[field] = verifiedResponse[field] + return updateUserInfo(update) + } catch (error) { $ionicPopup.alert({ title: `Error updating ${field}.`, - template: '' - }); + template: '', + }) } - }; + } // Shows a confirmation dialogue asking if the user is sure they want to log out - var promptLogOut = function() { + let promptLogOut = function () { $ionicPopup.confirm({ title: 'Are you sure you want to log out?', - subTitle: "You will not be able to make any bookings and view your tickets after you log out." - }).then(function(response) { + subTitle: 'You will not be able to make any bookings and view your tickets after you log out.', + }).then(function (response) { if (response) { - return logOut(); + return logOut() } - }); - }; + }) + } // Saves payment info to backend and update user object - var savePaymentInfo = function(stripeTokenId) { + let savePaymentInfo = function (stripeTokenId) { return beelineRequest({ method: 'POST', url: `/users/${user.id}/creditCards`, data: { - stripeToken: stripeTokenId - } + stripeToken: stripeTokenId, + }, + }) + .then(function (response) { + user.savedPaymentInfo = response.data }) - .then(function(response) { - user.savedPaymentInfo = response.data; - }); - }; + } // Update/change payment info to backend and update user object - var updatePaymentInfo = function(stripeTokenId) { + let updatePaymentInfo = function (stripeTokenId) { return beelineRequest({ method: 'POST', url: `/users/${user.id}/creditCards/replace`, data: { - stripeToken: stripeTokenId - } + stripeToken: stripeTokenId, + }, }) - .then(function(response) { - user.savedPaymentInfo = response.data; - }); - }; + .then(function (response) { + user.savedPaymentInfo = response.data + }) + } // Remove payment info from backend and update user object - var removePaymentInfo = function() { + let removePaymentInfo = function () { return beelineRequest({ method: 'DELETE', - url: `/users/${user.id}/creditCards/${user.savedPaymentInfo.sources.data[0].id}` + url: `/users/${user.id}/creditCards/${user.savedPaymentInfo.sources.data[0].id}`, }) - .then(function(response) { - user.savedPaymentInfo = response.data; - }); - }; + .then(function (response) { + user.savedPaymentInfo = response.data + }) + } // //////////////////////////////////////////////////////////////////////////// // Initialization // //////////////////////////////////////////////////////////////////////////// - verifySession(); + verifySession() // //////////////////////////////////////////////////////////////////////////// // Public external interface // //////////////////////////////////////////////////////////////////////////// return { - getUser: function() { return (user); }, + getUser: function () { + return (user) +}, beeline: beelineRequest, promptLogIn, loginIfNeeded, @@ -554,6 +552,5 @@ export default ['$http', '$ionicPopup', '$ionicLoading', '$rootScope', 'LoginDia updatePaymentInfo, removePaymentInfo, getReferralMsg, - }; - + } }] diff --git a/beeline/services/assetScopeModalService.js b/beeline/services/assetScopeModalService.js index 69503de23..cd625d4e4 100644 --- a/beeline/services/assetScopeModalService.js +++ b/beeline/services/assetScopeModalService.js @@ -1,38 +1,38 @@ -import commonmark from 'commonmark'; +import commonmark from 'commonmark' angular.module('beeline') .service('assetScopeModalService', ['$rootScope', '$ionicModal', 'UserService', 'replace', modalService]) -function modalService($rootScope, $ionicModal, UserService, replace) { - var reader = new commonmark.Parser({safe: true}); - var writer = new commonmark.HtmlRenderer({safe: true}); - let routePassTCModalTemplate = require('../templates/routepass-tc-modal.html'); +function modalService ($rootScope, $ionicModal, UserService, replace) { + let reader = new commonmark.Parser({safe: true}) + let writer = new commonmark.HtmlRenderer({safe: true}) + let routePassTCModalTemplate = require('../templates/routepass-tc-modal.html') - function showModal(template, assetName) { - var scope = $rootScope.$new(); - scope.error = scope.html = null; + function showModal (template, assetName) { + let scope = $rootScope.$new() + scope.error = scope.html = null scope.$on('modal.shown', () => { UserService.beeline({ method: 'GET', - url: replace(`/assets/${assetName}`) + url: replace(`/assets/${assetName}`), }) .then((response) => { - scope.html = writer.render(reader.parse(response.data.data)); - scope.error = false; + scope.html = writer.render(reader.parse(response.data.data)) + scope.error = false }) .catch((error) => { console.log(error) - scope.html = ""; - scope.error = error; + scope.html = '' + scope.error = error }) }) - var assetModal = $ionicModal.fromTemplate( + let assetModal = $ionicModal.fromTemplate( template, {scope: scope} - ); - assetModal.show(); + ) + assetModal.show() - scope.assetModal = assetModal; + scope.assetModal = assetModal scope.$on('modal.hidden', () => assetModal.remove()) } diff --git a/beeline/services/bookingSummaryModalService.js b/beeline/services/bookingSummaryModalService.js index ada28e109..cf53759d6 100644 --- a/beeline/services/bookingSummaryModalService.js +++ b/beeline/services/bookingSummaryModalService.js @@ -1,21 +1,21 @@ -import bookingSummaryTemplate from '../templates/booking-summary-modal.html'; -import assert from 'assert'; +import bookingSummaryTemplate from '../templates/booking-summary-modal.html' +import assert from 'assert' angular.module('beeline') .service('BookingSummaryModalService', ['$rootScope', '$ionicModal', 'RoutesService', 'loadingSpinner', 'StripeService', 'assetScopeModalService', 'PaymentService', modalService]) -function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, StripeService, assetScopeModalService, PaymentService) { +function modalService ($rootScope, $ionicModal, RoutesService, loadingSpinner, StripeService, assetScopeModalService, PaymentService) { this.show = (booking) => { - var scope = $rootScope.$new(); - var bookingSummaryModal = $ionicModal.fromTemplate( + let scope = $rootScope.$new() + let bookingSummaryModal = $ionicModal.fromTemplate( bookingSummaryTemplate, { scope: scope, animation: 'slide-in-up', - }); + }) - scope.modal = bookingSummaryModal; + scope.modal = bookingSummaryModal scope.book = booking scope.$watch('book.price', (price) => { @@ -29,13 +29,13 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, St savePaymentChecked: false, } - function cleanup() { - bookingSummaryModal.remove(); + function cleanup () { + bookingSummaryModal.remove() } - var bookingSummaryPromise = loadingSpinner(RoutesService.getRouteFeatures(parseInt(scope.book.routeId))) + let bookingSummaryPromise = loadingSpinner(RoutesService.getRouteFeatures(parseInt(scope.book.routeId))) .then((features)=>{ - scope.book.features = features; + scope.book.features = features return new Promise((resolve, reject) => { bookingSummaryModal.show() scope.payHandler = function () { @@ -44,8 +44,7 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, St PaymentService.payHandler(scope.book, scope.disp.savePaymentChecked) scope.disp.hasError = false return resolve('ticket purchased successfully') - } - catch(err) { + } catch (err) { console.log(err) scope.disp.hasError = true return reject('ticket purhchased failed') @@ -60,8 +59,8 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, St }) - bookingSummaryPromise.then(cleanup, cleanup); + bookingSummaryPromise.then(cleanup, cleanup) - return bookingSummaryPromise; + return bookingSummaryPromise } } diff --git a/beeline/services/busStopSelectorDialog.js b/beeline/services/busStopSelectorDialog.js index 7a6ee6e35..d8db9f2b2 100644 --- a/beeline/services/busStopSelectorDialog.js +++ b/beeline/services/busStopSelectorDialog.js @@ -1,37 +1,37 @@ -import busStopSelectorListTemplate from '../templates/busStopSelectorList.html'; +import busStopSelectorListTemplate from '../templates/busStopSelectorList.html' import {formatTime} from '../shared/format' -import _ from 'lodash'; +import _ from 'lodash' export default ['$rootScope', '$ionicModal', 'MapOptions', 'uiGmapGoogleMapApi', '$ionicScrollDelegate', - function($rootScope, $ionicModal, MapOptions, uiGmapGoogleMapApi, $ionicScrollDelegate) { - var scope = $rootScope.$new(); + function ($rootScope, $ionicModal, MapOptions, uiGmapGoogleMapApi, $ionicScrollDelegate) { + let scope = $rootScope.$new() - initializeScope(scope); + initializeScope(scope) scope.selectionModal = $ionicModal.fromTemplate(busStopSelectorListTemplate, { scope: scope, animation: 'slide-in-up', - }); + }) this.show = function (options) { _.assign(scope, _.pick(options, [ 'busStops', 'markerOptions', 'title', 'button', 'pinOptions', ])) - scope.data.selectedStop = options.selectedStop; + scope.data.selectedStop = options.selectedStop return new Promise((resolve, reject) => { // Initialize the selected stop scope.selectionModal.show() .then(() => { - scope.fitMap(); + scope.fitMap() // I have no idea why $getByHandle doesn't work in Ionic 1.3.1 // var scrollDelegate = $ionicScrollDelegate.$getByHandle('stopsListScroll'); - var scrollDelegate = $ionicScrollDelegate._instances.find(inst => inst.$$delegateHandle === 'stopsListScroll'); - scrollDelegate.resize(); - scrollDelegate.scrollTop(); - }); - scope.resolve = resolve; + let scrollDelegate = $ionicScrollDelegate._instances.find((inst) => inst.$$delegateHandle === 'stopsListScroll') + scrollDelegate.resize() + scrollDelegate.scrollTop() + }) + scope.resolve = resolve }) } @@ -43,38 +43,39 @@ export default ['$rootScope', '$ionicModal', 'MapOptions', @method selectStop -- fired when tapping on a stop in the list @method close -- closes the modal **/ - function initializeScope(scope) { - scope.data = {}; - scope.map = MapOptions.defaultMapOptions(); + function initializeScope (scope) { + scope.data = {} + scope.map = MapOptions.defaultMapOptions() - scope.fitMap = async () => { - await uiGmapGoogleMapApi; - MapOptions.disableMapLinks(); + scope.fitMap = async () => { + await uiGmapGoogleMapApi + MapOptions.disableMapLinks() if (!scope.map.control || !scope.busStops || - scope.busStops.length == 0) - return; + scope.busStops.length == 0) { +return +} // Pan to the bus stops - var bounds = new google.maps.LatLngBounds(); + let bounds = new google.maps.LatLngBounds() for (let bs of scope.busStops) { bounds.extend(new google.maps.LatLng( bs.coordinates.coordinates[1], - bs.coordinates.coordinates[0])); + bs.coordinates.coordinates[0])) } - scope.map.control.getGMap().fitBounds(bounds); + scope.map.control.getGMap().fitBounds(bounds) if (scope.map.control.getGMap().getZoom() > 17) { - scope.map.control.getGMap().setZoom(17); + scope.map.control.getGMap().setZoom(17) } - }; + } scope.close = () => { - scope.selectionModal.hide(); - scope.resolve(scope.data.selectedStop); + scope.selectionModal.hide() + scope.resolve(scope.data.selectedStop) } - function panToStop(stop) { + function panToStop (stop) { if (!stop) { - return; + return } if (scope.map.control.getGMap) { scope.map.control.getGMap().panTo({ @@ -86,7 +87,7 @@ export default ['$rootScope', '$ionicModal', 'MapOptions', // BECAUSE ANGULAR SCOPES ARE STUPID scope.$watch('data.selectedStop', (stop) => { - panToStop(stop); - }); + panToStop(stop) + }) } }] diff --git a/beeline/services/fastCheckoutService.js b/beeline/services/fastCheckoutService.js index 3565e4f50..984b7f25a 100644 --- a/beeline/services/fastCheckoutService.js +++ b/beeline/services/fastCheckoutService.js @@ -1,23 +1,22 @@ -import moment from 'moment'; +import moment from 'moment' import {retriveNextTrip} from '../shared/util' import assert from 'assert' angular.module('beeline') .factory('FastCheckoutService', ['RoutesService', 'UserService', 'purchaseRoutePassService', 'TicketService', '$stateParams', 'BookingSummaryModalService', '$ionicLoading', - function fastCheckoutService(RoutesService, UserService, + function fastCheckoutService (RoutesService, UserService, purchaseRoutePassService, TicketService, $stateParams, BookingSummaryModalService, $ionicLoading) { - - var user; - var hasSavedPaymentInfo; - var paymentInfo; - var ridesRemaining; - var route; - var routeId; + let user + let hasSavedPaymentInfo + let paymentInfo + let ridesRemaining + let route + let routeId // login - function userLoginPromise() { - return new Promise((resolve,reject) => { + function userLoginPromise () { + return new Promise((resolve, reject) => { if (UserService.getUser()) { return resolve(UserService.getUser()) } else { @@ -30,8 +29,8 @@ angular.module('beeline') } // ridesRemaining promise - function ridesRemainingPromise(routeId) { - return new Promise((resolve,reject) => { + function ridesRemainingPromise (routeId) { + return new Promise((resolve, reject) => { if (RoutesService.getPassCountForRoute(routeId)) { return resolve(RoutesService.getPassCountForRoute(routeId)) } else { @@ -45,19 +44,19 @@ angular.module('beeline') } // modal for purchase route pass - function purchaseRoutePass(hideOneTicket, route, routeId, hasSavedPaymentInfo, savedPaymentInfo, boardStopId, alightStopId, selectedDates) { + function purchaseRoutePass (hideOneTicket, route, routeId, hasSavedPaymentInfo, savedPaymentInfo, boardStopId, alightStopId, selectedDates) { return purchaseRoutePassService.show(hideOneTicket, route, routeId, hasSavedPaymentInfo, savedPaymentInfo, boardStopId, alightStopId, selectedDates) } - function routeQualifiedForRoutePass(route) { + function routeQualifiedForRoutePass (route) { if (route && route.tags) { - var rpList = route.tags.filter((tag) => tag.includes('rp-')) + let rpList = route.tags.filter((tag) => tag.includes('rp-')) return rpList && rpList.length === 1 && route.notes && route.notes.passSizes && route.notes.passSizes.length > 0 } } - function purchaseTicketUsingRoutePass(routeId, route, selectedDates, boardStopId, alightStopId, hasSavedPaymentInfo) { + function purchaseTicketUsingRoutePass (routeId, route, selectedDates, boardStopId, alightStopId, hasSavedPaymentInfo) { return BookingSummaryModalService.show({ routeId: routeId, price: route.trips[0].price, @@ -70,48 +69,50 @@ angular.module('beeline') }) } - function verifyPromise(routeId) { + function verifyPromise (routeId) { return new Promise(async (resolve, reject) => { route = await RoutesService.getRoute(routeId) - var nextTrip = retriveNextTrip(route) + let nextTrip = retriveNextTrip(route) if (nextTrip === null) { return reject('There is no next trip') } - var seatsAvailable = false + let seatsAvailable = false if (nextTrip && nextTrip.availability && nextTrip.availability.seatsAvailable > 0) { seatsAvailable = true } - var hasNextTripTicket = null, previouslyBookedDays = null + let hasNextTripTicket = null, previouslyBookedDays = null // user has the next trip ticket if (UserService.getUser()) { - var allTickets = TicketService.getTickets(); + let allTickets = TicketService.getTickets() if (allTickets != null) { - var ticketsByRouteId = _.groupBy(allTickets, ticket => ticket.boardStop.trip.routeId); + let ticketsByRouteId = _.groupBy(allTickets, (ticket) => ticket.boardStop.trip.routeId) if (ticketsByRouteId && ticketsByRouteId[route.id]) { - previouslyBookedDays = _.keyBy(ticketsByRouteId[route.id], t => new Date(t.boardStop.trip.date).getTime()); + previouslyBookedDays = _.keyBy(ticketsByRouteId[route.id], (t) => new Date(t.boardStop.trip.date).getTime()) } } if (previouslyBookedDays) { - var bookedDays = Object.keys(previouslyBookedDays).map(x=>{return parseInt(x)}); - //compare current date with next trip - if (nextTrip && _.includes(bookedDays,nextTrip.date.getTime())) { - hasNextTripTicket = true; + let bookedDays = Object.keys(previouslyBookedDays).map((x)=>{ +return parseInt(x) +}) + // compare current date with next trip + if (nextTrip && _.includes(bookedDays, nextTrip.date.getTime())) { + hasNextTripTicket = true } else { - hasNextTripTicket = false; + hasNextTripTicket = false } } else { - hasNextTripTicket = false; + hasNextTripTicket = false } } _.assign(nextTrip, {hasNextTripTicket, seatsAvailable}) if (hasNextTripTicket === true || seatsAvailable === false) { - nextTrip.errorMessage = "Next Trip is not available or user already purchased" + nextTrip.errorMessage = 'Next Trip is not available or user already purchased' } return resolve(nextTrip) }) } - var instance = { + let instance = { verify: function (routeId) { return verifyPromise(routeId) @@ -126,8 +127,7 @@ angular.module('beeline') route = await RoutesService.getRoute(routeId) await purchaseRoutePass(true, route, routeId, hasSavedPaymentInfo, paymentInfo) return resolve('success') - } - catch (err) { + } catch (err) { console.log(err) return reject('failed') } @@ -140,8 +140,8 @@ angular.module('beeline') user = await userLoginPromise() $ionicLoading.show({ template: `
Loading`, - hideOnStateChange: true - }); + hideOnStateChange: true, + }) let verifyNextTrip = await verifyPromise(routeId) if (verifyNextTrip.errorMessage) { return reject(verifyNextTrip.errorMessage) @@ -150,7 +150,7 @@ angular.module('beeline') paymentInfo = hasSavedPaymentInfo ? _.get(user, 'savedPaymentInfo') : null route = await RoutesService.getRoute(routeId) ridesRemaining = await ridesRemainingPromise(routeId) - $ionicLoading.hide(); + $ionicLoading.hide() if (!ridesRemaining) { if (route && routeQualifiedForRoutePass(route)) { await purchaseRoutePass(false, route, routeId, hasSavedPaymentInfo, paymentInfo, boardStopId, alightStopId, selectedDates) @@ -164,15 +164,14 @@ angular.module('beeline') selectedDates: selectedDates, boardStopId: boardStopId, alightStopId: alightStopId, - hasSavedPaymentInfo: hasSavedPaymentInfo + hasSavedPaymentInfo: hasSavedPaymentInfo, }) } } else { await purchaseTicketUsingRoutePass(routeId, route, selectedDates, boardStopId, alightStopId, hasSavedPaymentInfo) } return resolve('success') - } - catch (err) { + } catch (err) { $ionicLoading.hide() console.log(err) return reject('failed') @@ -180,9 +179,8 @@ angular.module('beeline') }) }, - routeQualifiedForRoutePass: (route) => routeQualifiedForRoutePass(route) + routeQualifiedForRoutePass: (route) => routeQualifiedForRoutePass(route), } - return instance; - + return instance }] ) diff --git a/beeline/services/legalese.js b/beeline/services/legalese.js index 6751f8820..8f1d453d8 100644 --- a/beeline/services/legalese.js +++ b/beeline/services/legalese.js @@ -1,17 +1,17 @@ export default ['$rootScope', '$ionicModal', function ($rootScope, $ionicModal) { - let privacyPolicyModalTemplate = require('../templates/'+$rootScope.o.APP.PREFIX+'privacy-policy-modal.html'); - let termsOfUseModalTemplate = require('../templates/'+$rootScope.o.APP.PREFIX+'terms-of-use-modal.html'); + let privacyPolicyModalTemplate = require('../templates/'+$rootScope.o.APP.PREFIX+'privacy-policy-modal.html') + let termsOfUseModalTemplate = require('../templates/'+$rootScope.o.APP.PREFIX+'terms-of-use-modal.html') - function showModal(template) { - var scope = $rootScope.$new(); - var modal = $ionicModal.fromTemplate( + function showModal (template) { + let scope = $rootScope.$new() + let modal = $ionicModal.fromTemplate( template, {scope: scope} - ); - modal.show(); + ) + modal.show() - scope.modal = modal; + scope.modal = modal scope.$on('modal.hidden', () => modal.remove()) } diff --git a/beeline/services/login.js b/beeline/services/login.js index 4bcb98c68..33e8d7958 100644 --- a/beeline/services/login.js +++ b/beeline/services/login.js @@ -1,55 +1,56 @@ -import loginModalTemplate from '../templates/login-modal.html'; -const VALID_PHONE_REGEX = /^[8-9]{1}[0-9]{7}$|^########$/; +import loginModalTemplate from '../templates/login-modal.html' +const VALID_PHONE_REGEX = /^[8-9]{1}[0-9]{7}$|^########$/ export default ['$rootScope', '$ionicModal', 'Legalese', function ($rootScope, $ionicModal, Legalese) { this.show = () => { - var scope = $rootScope.$new(); - var loginModal = $ionicModal.fromTemplate( + let scope = $rootScope.$new() + let loginModal = $ionicModal.fromTemplate( loginModalTemplate, {scope: scope} - ); + ) - scope.modal = loginModal; - scope.phonePattern = VALID_PHONE_REGEX; - scope.showPrivacyPolicy = () => Legalese.showPrivacyPolicy(); - scope.showTermsOfUse = () => Legalese.showTermsOfUse(); + scope.modal = loginModal + scope.phonePattern = VALID_PHONE_REGEX + scope.showPrivacyPolicy = () => Legalese.showPrivacyPolicy() + scope.showTermsOfUse = () => Legalese.showTermsOfUse() - scope.data = {}; - scope.form = {}; + scope.data = {} + scope.form = {} - function cleanup() { - loginModal.remove(); + function cleanup () { + loginModal.remove() } - var loginPromise = new Promise((resolve, reject) => { + let loginPromise = new Promise((resolve, reject) => { scope.$on('modal.hidden', () => { - if (scope.reject) - scope.reject(null); - scope.accept = scope.reject = null; + if (scope.reject) { +scope.reject(null) +} + scope.accept = scope.reject = null }) - scope.reject = resolve; + scope.reject = resolve scope.accept = () => { - scope.accept = scope.reject = null; - loginModal.hide(); + scope.accept = scope.reject = null + loginModal.hide() // returns [ telephone-number, want-telephone-verification ] - resolve([scope.data.telephone, true]); - }; + resolve([scope.data.telephone, true]) + } scope.bypass = () => { - scope.accept = scope.reject = null; - loginModal.hide(); + scope.accept = scope.reject = null + loginModal.hide() // returns [ telephone-number, want-telephone-verification ] - resolve([scope.data.telephone, false]); - }; + resolve([scope.data.telephone, false]) + } - loginModal.show(); + loginModal.show() }) - loginPromise.then(cleanup, cleanup); + loginPromise.then(cleanup, cleanup) - return loginPromise; + return loginPromise } }] diff --git a/beeline/services/paymentService.js b/beeline/services/paymentService.js index 7acfdbaa2..a40b6811c 100644 --- a/beeline/services/paymentService.js +++ b/beeline/services/paymentService.js @@ -1,43 +1,42 @@ import assert from 'assert' -import processingPaymentsTemplate from '../templates/processing-payments.html'; +import processingPaymentsTemplate from '../templates/processing-payments.html' angular.module('beeline') -.factory('PaymentService', ['UserService','RoutesService', '$ionicPopup', +.factory('PaymentService', ['UserService', 'RoutesService', '$ionicPopup', '$ionicLoading', 'BookingService', 'CreditsService', 'StripeService', 'loadingSpinner', 'TicketService', '$state', - function paymentService(UserService, RoutesService, + function paymentService (UserService, RoutesService, $ionicPopup, $ionicLoading, BookingService, CreditsService, StripeService, loadingSpinner, TicketService, $state) { - var isPaymentProcessing = false + let isPaymentProcessing = false /** After you have settled the payment mode **/ // book is booking Object - async function completePayment(paymentOptions, book) { + async function completePayment (paymentOptions, book) { try { $ionicLoading.show({ - template: processingPaymentsTemplate + template: processingPaymentsTemplate, }) - var result = await UserService.beeline({ + let result = await UserService.beeline({ method: 'POST', url: '/transactions/tickets/payment', data: _.defaults(paymentOptions, { trips: BookingService.prepareTrips(book), - promoCode: book.promoCode ? { code: book.promoCode } : { code: '' }, + promoCode: book.promoCode ? {code: book.promoCode} : {code: ''}, applyRoutePass: book.applyRoutePass ? true : false, applyCredits: book.applyCredits ? true : false, applyReferralCredits: book.applyReferralCredits ? true : false, - expectedPrice: book.price + expectedPrice: book.price, }), - }); - - assert(result.status == 200); + }) - $ionicLoading.hide(); + assert(result.status == 200) - TicketService.setShouldRefreshTickets(); - $state.go('tabs.route-confirmation'); + $ionicLoading.hide() + TicketService.setShouldRefreshTickets() + $state.go('tabs.route-confirmation') } catch (err) { - $ionicLoading.hide(); + $ionicLoading.hide() await $ionicPopup.alert({ title: 'Error processing payment', template: err.data.message, @@ -47,97 +46,97 @@ angular.module('beeline') RoutesService.fetchRoutePassCount() RoutesService.fetchRoutesWithRoutePass() - CreditsService.fetchReferralCredits(true); - CreditsService.fetchUserCredits(true); + CreditsService.fetchReferralCredits(true) + CreditsService.fetchUserCredits(true) } } - async function payZeroDollar(book) { + async function payZeroDollar (book) { if (await $ionicPopup.confirm({ title: 'Complete Purchase', - template: 'Are you sure you want to complete the purchase?' + template: 'Are you sure you want to complete the purchase?', })) { try { - isPaymentProcessing = true; + isPaymentProcessing = true await completePayment({ - stripeToken: 'this-will-not-be-used' + stripeToken: 'this-will-not-be-used', }, book) } finally { - isPaymentProcessing = false; + isPaymentProcessing = false } } } // Prompts for card and processes payment with one time stripe token. - async function payWithoutSavingCard(book) { + async function payWithoutSavingCard (book) { try { // disable the button - isPaymentProcessing = true; + isPaymentProcessing = true - var stripeToken = await loadingSpinner(StripeService.promptForToken( + let stripeToken = await loadingSpinner(StripeService.promptForToken( null, isFinite(book.price) ? book.price * 100 : '', - null)); + null)) if (!stripeToken) { - return; + return } await completePayment({ stripeToken: stripeToken.id, - }, book); + }, book) } catch (err) { await $ionicPopup.alert({ title: 'Error contacting the payment gateway', template: err.data && err.data.message || err, }) } finally { - isPaymentProcessing = false; + isPaymentProcessing = false } } // Processes payment with customer object. If customer object does not exist, // prompts for card, creates customer object, and proceeds as usual. - async function payWithSavedInfo(book) { + async function payWithSavedInfo (book) { try { // disable the button - isPaymentProcessing = true; + isPaymentProcessing = true if (!book.hasSavedPaymentInfo) { - var stripeToken = await StripeService.promptForToken( + let stripeToken = await StripeService.promptForToken( null, isFinite(book.price) ? book.price * 100 : '', - null); + null) if (!stripeToken) { - isPaymentProcessing = false; // re-enable button - return; + isPaymentProcessing = false // re-enable button + return } await loadingSpinner(UserService.savePaymentInfo(stripeToken.id)) } - var user = await UserService.getUser() + let user = await UserService.getUser() await completePayment({ customerId: user.savedPaymentInfo.id, sourceId: _.head(user.savedPaymentInfo.sources.data).id, - }, book); + }, book) } catch (err) { - isPaymentProcessing = false; // re-enable button + isPaymentProcessing = false // re-enable button await $ionicPopup.alert({ title: 'Error saving payment method', template: err.data.message, }) } finally { - isPaymentProcessing = false; + isPaymentProcessing = false } } - var instance = { - payForRoutePass: async function(route, expectedPrice, passValue, paymentOptions) { - var paymentPromise + let instance = { + payForRoutePass: async function (route, expectedPrice, passValue, paymentOptions) { + let paymentPromise try { let routePassTagList = route.tags.filter((tag) => { return tag.includes('rp-') @@ -149,15 +148,19 @@ angular.module('beeline') url: '/transactions/route_passes/payment', data: _.defaults(paymentOptions, { creditTag: routePassTagList[0], - promoCode: { code: '' }, + promoCode: {code: ''}, companyId: route.transportCompanyId, expectedPrice: expectedPrice, - value: passValue + value: passValue, }), })) - paymentPromise = new Promise((resolve, reject) => {return resolve('routePassPurchaseDone')}) + paymentPromise = new Promise((resolve, reject) => { +return resolve('routePassPurchaseDone') +}) } catch (err) { - paymentPromise = new Promise((resolve, reject) => {return resolve('routePassError')}) + paymentPromise = new Promise((resolve, reject) => { +return resolve('routePassError') +}) } finally { RoutesService.fetchRoutePasses(true) RoutesService.fetchRoutePassCount() @@ -166,19 +169,17 @@ angular.module('beeline') } }, - payHandler : function (book, savePaymentChecked) { + payHandler: function (book, savePaymentChecked) { if (book.price === 0) { - payZeroDollar(book); - } - else if (book.hasSavedPaymentInfo || savePaymentChecked) { - payWithSavedInfo(book); + payZeroDollar(book) + } else if (book.hasSavedPaymentInfo || savePaymentChecked) { + payWithSavedInfo(book) + } else { + payWithoutSavingCard(book) } - else { - payWithoutSavingCard(book); - } - } + }, } - return instance; + return instance }] ) diff --git a/beeline/services/purchaseRoutePassService.js b/beeline/services/purchaseRoutePassService.js index 3cf331b03..a9ff8f0e3 100644 --- a/beeline/services/purchaseRoutePassService.js +++ b/beeline/services/purchaseRoutePassService.js @@ -1,25 +1,25 @@ -import routePassTemplate from '../templates/route-pass-modal.html'; -import assert from 'assert'; -import commonmark from 'commonmark'; +import routePassTemplate from '../templates/route-pass-modal.html' +import assert from 'assert' +import commonmark from 'commonmark' angular.module('beeline') .service('purchaseRoutePassService', ['$rootScope', '$ionicModal', 'RoutesService', 'loadingSpinner', 'StripeService', 'assetScopeModalService', 'PaymentService', 'UserService', 'BookingSummaryModalService', '$state', modalService]) -function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, +function modalService ($rootScope, $ionicModal, RoutesService, loadingSpinner, StripeService, assetScopeModalService, PaymentService, UserService, BookingSummaryModalService, $state) { - var self = this + let self = this self.show = (hideOneTicket, route, routeId, hasSavedPaymentInfo, savedPaymentInfo, boardStopId, alightStopId, selectedDates) => { - var scope = $rootScope.$new(); - var routePassModal = $ionicModal.fromTemplate( + let scope = $rootScope.$new() + let routePassModal = $ionicModal.fromTemplate( routePassTemplate, { scope: scope, animation: 'slide-in-up', - }); + }) - scope.modal = routePassModal; + scope.modal = routePassModal scope.book = { priceSchedules: null, @@ -38,42 +38,42 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, }) // Prompts for card and processes payment with one time stripe token. - scope.payForRoutePass = async function() { + scope.payForRoutePass = async function () { try { - var paymentPromise - var quantity = scope.book.priceSchedules[scope.book.routePassChoice].quantity - var expectedPrice = scope.book.priceSchedules[scope.book.routePassChoice].totalPrice - var passValue = route.trips[0].price * scope.book.priceSchedules[scope.book.routePassChoice].quantity + let paymentPromise + let quantity = scope.book.priceSchedules[scope.book.routePassChoice].quantity + let expectedPrice = scope.book.priceSchedules[scope.book.routePassChoice].totalPrice + let passValue = route.trips[0].price * scope.book.priceSchedules[scope.book.routePassChoice].quantity // if user has credit card saved if (hasSavedPaymentInfo) { paymentPromise = PaymentService.payForRoutePass(route, expectedPrice, passValue, { customerId: savedPaymentInfo.id, sourceId: _.head(savedPaymentInfo.sources.data).id, - }); + }) } else { - var stripeToken = await loadingSpinner(StripeService.promptForToken( + let stripeToken = await loadingSpinner(StripeService.promptForToken( null, isFinite(scope.book.routePassPrice) ? scope.book.routePassPrice * 100 : '', - null)); + null)) if (!stripeToken) { - paymentPromise = new Promise((resolve, reject) => { + paymentPromise = new Promise((resolve, reject) => { return reject('no Stripe Token') }) } - //saves payment info if doesn't exist + // saves payment info if doesn't exist if (scope.book.savePaymentChecked) { await UserService.savePaymentInfo(stripeToken.id) let user = await UserService.getUser() - paymentPromise = PaymentService.payForRoutePass(route, expectedPrice, passValue, { + paymentPromise = PaymentService.payForRoutePass(route, expectedPrice, passValue, { customerId: user.savedPaymentInfo.id, - sourceId:_.head(user.savedPaymentInfo.sources.data).id, - }); + sourceId: _.head(user.savedPaymentInfo.sources.data).id, + }) } else { paymentPromise = PaymentService.payForRoutePass(route, expectedPrice, passValue, { stripeToken: stripeToken.id, - }); + }) } return paymentPromise @@ -86,12 +86,12 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, } } - function cleanup() { + function cleanup () { console.log('cleanup') - routePassModal.remove(); + routePassModal.remove() } - var purchaseRoutePassPromise = loadingSpinner(RoutesService.fetchPriceSchedule(routeId)).then((response) => { + let purchaseRoutePassPromise = loadingSpinner(RoutesService.fetchPriceSchedule(routeId)).then((response) => { return new Promise((resolve, reject) => { scope.book.priceSchedules = response scope.book.routePassChoice = 0 @@ -100,7 +100,7 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, scope.book.priceSchedules =scope.book.priceSchedules.slice(0, scope.book.priceSchedules.length-1) } routePassModal.show() - scope.proceed = async function() { + scope.proceed = async function () { routePassModal.hide() scope.book.isProcessing = true if (scope.book.priceSchedules[scope.book.routePassChoice].quantity === 1) { @@ -110,8 +110,7 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, $state.go('tabs.route-summary', {routeId: routeId, boardStop: boardStopId, alightStop: alightStopId, - selectedDates: selectedDates}); - + selectedDates: selectedDates}) } else { loadingSpinner(scope.payForRoutePass()).then(() => { scope.book.isProcessing = false @@ -125,7 +124,7 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, scope.closeModal = function () { routePassModal.hide() - //TODO + // TODO return reject('routePassError') } }) @@ -136,7 +135,7 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, const writer = new commonmark.HtmlRenderer({safe: true}) UserService.beeline({ method: 'GET', - url: '/assets/routepass-tc' + url: '/assets/routepass-tc', }) .then((response) => { scope.routePassTerms.html = writer.render(reader.parse(response.data.data)) @@ -148,8 +147,8 @@ function modalService($rootScope, $ionicModal, RoutesService, loadingSpinner, }) - purchaseRoutePassPromise.then(cleanup, cleanup); + purchaseRoutePassPromise.then(cleanup, cleanup) - return purchaseRoutePassPromise; + return purchaseRoutePassPromise } } diff --git a/beeline/shared/errors.js b/beeline/shared/errors.js index 49b6ddc60..699d85f42 100644 --- a/beeline/shared/errors.js +++ b/beeline/shared/errors.js @@ -1,6 +1,6 @@ export class NetworkError extends Error { - constructor(str) { - super(str); + constructor (str) { + super(str) } } diff --git a/beeline/shared/format.js b/beeline/shared/format.js index a48adc4f2..7001afaaf 100644 --- a/beeline/shared/format.js +++ b/beeline/shared/format.js @@ -1,109 +1,114 @@ -export function twoPad(s, len, ch) { - len = len || 2; - ch = ch || '0'; +export function twoPad (s, len, ch) { + len = len || 2 + ch = ch || '0' - s = s + ''; + s = s + '' while (s.length < len) { - s = ch + s; + s = ch + s } - return s; + return s } -export function timeSinceMidnight(date) { - if (!date) return ''; +export function timeSinceMidnight (date) { + if (!date) return '' if (typeof date == 'string' || typeof date == 'number') { - date = new Date(date); + date = new Date(date) } return date.getHours() * 3600000 + date.getMinutes() * 60000 + date.getSeconds() * 1000 + - date.getMilliseconds(); + date.getMilliseconds() } -export function formatDate(date) { - if (!date) return ''; +export function formatDate (date) { + if (!date) return '' if (typeof date == 'string' || typeof date == 'number') { - date = new Date(date); + date = new Date(date) } return twoPad(date.getDate()) + '-' + twoPad(date.getMonth() + 1) + '-' + - twoPad(date.getFullYear()); + twoPad(date.getFullYear()) } -export function formatDateMMMdd(date) { - var monthNames = 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','); +export function formatDateMMMdd (date) { + let monthNames = 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(',') - if (!date) return ''; + if (!date) return '' if (typeof date == 'string' || typeof date == 'number') { - date = new Date(date); + date = new Date(date) } - return monthNames[date.getMonth()] + ' ' + twoPad(date.getDate()); + return monthNames[date.getMonth()] + ' ' + twoPad(date.getDate()) } -export function formatUTCDate(date) { - if (!date) return ''; +export function formatUTCDate (date) { + if (!date) return '' if (typeof date == 'string') { - date = new Date(date); + date = new Date(date) } return twoPad(date.getUTCDate()) + '-' + twoPad(date.getUTCMonth() + 1) + '-' + - twoPad(date.getUTCFullYear()); + twoPad(date.getUTCFullYear()) } -export function formatTime(date, prePadding) { - if (!date) return ''; +export function formatTime (date, prePadding) { + if (!date) return '' if (typeof date == 'string' || typeof date == 'number') { - date = new Date(date); + date = new Date(date) } // Fix time zone to +0800 date = new Date(date.getTime() + 8*60*60*1000) - var hours = date.getUTCHours(); + let hours = date.getUTCHours() - var hourPart = 12 - (24 - hours) % 12; - hourPart = prePadding ? twoPad(hourPart, 2, '\u2007') : hourPart; + let hourPart = 12 - (24 - hours) % 12 + hourPart = prePadding ? twoPad(hourPart, 2, '\u2007') : hourPart /* \u2007 is a figure space */ return hourPart + ':' + twoPad(date.getUTCMinutes()) + '\u00a0' /* non-breaking space */ + (hours >= 12 ? 'pm' : 'am')/* + ':' + - twoPad(date.getSeconds()) */; + twoPad(date.getSeconds()) */ } -export function formatTimeArray(timeArray) { - if (timeArray.length ==0 )return; +export function formatTimeArray (timeArray) { + if (timeArray.length ==0 ) return else { - return timeArray.map((x)=>formatTime(x,true)).join(', '); + return timeArray.map((x)=>formatTime(x, true)).join(', ') } } // func to generate something like '14:15 pm' from JS date obj -export function formatHHMM_ampm(t) { - var h = t.getHours(), +export function formatHHMM_ampm (t) { + let h = t.getHours(), m = t.getMinutes(), - term = 'am'; + term = 'am' - if (h >= 12) - { - term = 'pm'; - if (h > 12) { h = h - 12; } - h = h.toString(); + if (h >= 12) { + term = 'pm' + if (h > 12) { + h = h - 12 +} + h = h.toString() } - if (h.toString().length == 1) { h = '0' + h.toString(); } - if (m.toString().length == 1) { m = '0' + m.toString(); } + if (h.toString().length == 1) { + h = '0' + h.toString() +} + if (m.toString().length == 1) { + m = '0' + m.toString() +} - return h + ':' + m + ' ' + term; + return h + ':' + m + ' ' + term } -export function titleCase(s) { - if (!s) return ''; +export function titleCase (s) { + if (!s) return '' - return s.replace(/\w\S*/g, function(txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); + return s.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() + }) } diff --git a/beeline/shared/imageSources.js b/beeline/shared/imageSources.js index 98fbc9dfb..7d99a6a78 100644 --- a/beeline/shared/imageSources.js +++ b/beeline/shared/imageSources.js @@ -1,11 +1,13 @@ -export function companyLogo(i) { - if (!i) - return ''; - return `${process.env.BACKEND_URL}/companies/${i}/logo`; +export function companyLogo (i) { + if (!i) { +return '' +} + return `${process.env.BACKEND_URL}/companies/${i}/logo` } -export function miniCompanyLogo(i) { - if (!i) - return ''; - return `${process.env.BACKEND_URL}/companies/${i}/logo?width=20`; +export function miniCompanyLogo (i) { + if (!i) { +return '' +} + return `${process.env.BACKEND_URL}/companies/${i}/logo?width=20` } diff --git a/beeline/shared/util.js b/beeline/shared/util.js index 6645fffe6..0b4d2c360 100644 --- a/beeline/shared/util.js +++ b/beeline/shared/util.js @@ -1,97 +1,97 @@ -import _ from 'lodash'; +import _ from 'lodash' /* Update a scope so that the child scopes also receive the $ionicView.*Enter events */ -export function setupBroadcastViewEnter($scope) { - $scope.$on('$ionicView.afterEnter', function(a, b) { +export function setupBroadcastViewEnter ($scope) { + $scope.$on('$ionicView.afterEnter', function (a, b) { // var next = $scope.$$childHead; // while (next) { // next.$broadcast('$ionicView.afterEnter', a, b); // next = next.$$nextSibling; // } - $scope.$broadcast('mapRequireResize'); - }); + $scope.$broadcast('mapRequireResize') + }) } -var lineSymbol = { +let lineSymbol = { path: 'M 0,-1 0,1', strokeOpacity: 1, - scale: 4 -}; -var lineIcons = { + scale: 4, +} +let lineIcons = { path: [{lat: 22.291, lng: 153.027}, {lat: 18.291, lng: 153.027}], strokeOpacity: 0, icons: [{ icon: lineSymbol, offset: '0', - repeat: '20px' + repeat: '20px', }], -}; -export function dashedLineIcons() { - return lineIcons; +} +export function dashedLineIcons () { + return lineIcons } -export function defaultMapOptions(options) { +export function defaultMapOptions (options) { return _.assign({ center: {latitude: 1.370244, longitude: 103.823315}, zoom: 11, bounds: { // so that autocomplete will mainly search within Singapore northeast: { latitude: 1.485152, - longitude: 104.091837 + longitude: 104.091837, }, southwest: { latitude: 1.205764, - longitude: 103.589899 - } + longitude: 103.589899, + }, }, control: {}, options: { disableDefaultUI: true, styles: [{ - featureType: "poi", + featureType: 'poi', stylers: [{ - visibility: "off" - }] + visibility: 'off', + }], }], - draggable: true + draggable: true, }, markers: [], lines: [], - }, options || {}); + }, options || {}) } -export function retriveNextTrip(route) { - //compare current date with nearest date trip's 1st board stop time - var sortedRunningTripInDates = _.sortBy(route.trips.filter(tr => tr.isRunning),'date'); - var now = Date.now(); - var nextTrip = null; +export function retriveNextTrip (route) { + // compare current date with nearest date trip's 1st board stop time + let sortedRunningTripInDates = _.sortBy(route.trips.filter((tr) => tr.isRunning), 'date') + let now = Date.now() + let nextTrip = null for (let trip of sortedRunningTripInDates) { - var sortedTripStopsInTime = _.sortBy(trip.tripStops,'time'); - var boardTime = null, lastStopTime = null; + let sortedTripStopsInTime = _.sortBy(trip.tripStops, 'time') + let boardTime = null, lastStopTime = null if (trip.bookingInfo.windowSize && trip.bookingInfo.windowType) { if (trip.bookingInfo.windowType === 'firstStop') { - boardTime = sortedTripStopsInTime[0].time.getTime() + trip.bookingInfo.windowSize; + boardTime = sortedTripStopsInTime[0].time.getTime() + trip.bookingInfo.windowSize } - //FIXME : windowType == "stop" + // FIXME : windowType == "stop" } - //if no booking window information + // if no booking window information if (boardTime == null) { - boardTime = sortedTripStopsInTime[0].time.getTime(); + boardTime = sortedTripStopsInTime[0].time.getTime() } - //the trip end time - lastStopTime = sortedTripStopsInTime[sortedTripStopsInTime.length-1].time.getTime(); - //check seat is available + // the trip end time + lastStopTime = sortedTripStopsInTime[sortedTripStopsInTime.length-1].time.getTime() + // check seat is available if (now < boardTime || (now >= boardTime && now <= lastStopTime)) { - nextTrip = trip; + nextTrip = trip // assign the boardTime to the Object nextTrip.boardTime = boardTime - break; + break } } - return nextTrip; + return nextTrip } -export function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} \ No newline at end of file +export function sleep (ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +}