From 6713aaae02296d486c3a9fcaf6cebc5f3c3f9b60 Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Sat, 16 Sep 2017 12:40:23 +0200 Subject: [PATCH 1/6] scores: Enable automatic refreshing (every 30s for now) of scores.json. --- spec/mocks/scoresMock.js | 2 ++ spec/services/ng-scoresSpec.js | 56 ++++++++++++++++++++++++++++++---- src/js/services/ng-scores.js | 56 ++++++++++++++++++++++++++++++++-- src/js/views/ranking.js | 8 ++++- src/js/views/scores.js | 6 ++++ 5 files changed, 119 insertions(+), 9 deletions(-) diff --git a/spec/mocks/scoresMock.js b/spec/mocks/scoresMock.js index c9002e76..9ed7cb1c 100644 --- a/spec/mocks/scoresMock.js +++ b/spec/mocks/scoresMock.js @@ -15,6 +15,8 @@ function createScoresMock($q,scoreboard) { update: jasmine.createSpy('scoreUpdateSpy'), _update: jasmine.createSpy('score_UpdateSpy'), save: jasmine.createSpy('scoreSaveSpy'), + enableAutoRefresh: jasmine.createSpy('enableAutoRefresh'), + disableAutoRefresh: jasmine.createSpy('disableAutoRefresh'), getRankings: jasmine.createSpy('getRankings').and.returnValue({ scoreboard: scoreboard }) diff --git a/spec/services/ng-scoresSpec.js b/spec/services/ng-scoresSpec.js index 1ffa2729..5c4e13a4 100644 --- a/spec/services/ng-scoresSpec.js +++ b/spec/services/ng-scoresSpec.js @@ -10,6 +10,7 @@ describe('ng-scores',function() { var $stages; var $teams; var $q; + var $interval; var dummyTeam = { number: 123, name: 'foo' @@ -41,12 +42,16 @@ describe('ng-scores',function() { angular.mock.module(function($provide) { $provide.value('$fs', fsMock); }); - angular.mock.inject(["$scores", "$stages", "$teams", "$q", function(_$scores_, _$stages_, _$teams_,_$q_) { - $scores = _$scores_; - $stages = _$stages_; - $teams = _$teams_; - $q = _$q_; - }]); + angular.mock.inject([ + "$scores", "$stages", "$teams", "$q", "$interval", + function(_$scores_, _$stages_, _$teams_, _$q_, $_interval_) { + $scores = _$scores_; + $stages = _$stages_; + $teams = _$teams_; + $q = _$q_; + $interval = $_interval_; + } + ]); return $stages.init().then(function() { mockStage = $stages.get(rawMockStage.id); @@ -534,4 +539,43 @@ describe('ng-scores',function() { }); }); + describe('autoRefresh', function() { + it('should not be started when no-one is interested', function () { + fsMock.read.calls.reset(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).not.toHaveBeenCalled(); + }); + it('should be started when someone is interested', function () { + fsMock.read.calls.reset(); + $scores.enableAutoRefresh(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).toHaveBeenCalled(); + }); + it('should keep refreshing when someone is interested', function () { + fsMock.read.calls.reset(); + $scores.enableAutoRefresh(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).toHaveBeenCalled(); + fsMock.read.calls.reset(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).toHaveBeenCalled(); + }); + it('should be stopped when everyone unregistered', function () { + $scores.enableAutoRefresh(); + $interval.flush($scores._autoRefreshTimeout + 1); + $scores.disableAutoRefresh(); + + fsMock.read.calls.reset(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).not.toHaveBeenCalled(); + }); + it('should skip refresh when busy', function () { + fsMock.read.calls.reset(); + $scores.enableAutoRefresh(); + $scores.beginupdate(); + $interval.flush($scores._autoRefreshTimeout + 1); + expect(fsMock.read).not.toHaveBeenCalled(); + }); + }); + }); diff --git a/src/js/services/ng-scores.js b/src/js/services/ng-scores.js index 0bea8f7e..a5cdd4da 100644 --- a/src/js/services/ng-scores.js +++ b/src/js/services/ng-scores.js @@ -15,8 +15,8 @@ define('services/ng-scores',[ var SCORES_VERSION = 2; return module.service('$scores', - ['$rootScope', '$fs', '$stages', '$q', '$teams', - function($rootScope, $fs, $stages, $q, $teams) { + ['$rootScope', '$fs', '$stages', '$q', '$teams', '$interval', + function($rootScope, $fs, $stages, $q, $teams, $interval) { // Replace placeholders in format string. // Example: format("Frobnicate {0} {1} {2}", "foo", "bar") @@ -130,6 +130,9 @@ define('services/ng-scores',[ this._updating = 0; this._initialized = null; // Promise this._pollingSheets = null; // Promise + this._autoRefreshUsers = 0; + this._autoRefreshInterval = undefined; // $interval handle + this._autoRefreshTimeout = 30 * 1000; // ms before reloading scores.json this.init(); } @@ -177,6 +180,7 @@ define('services/ng-scores',[ Scores.prototype.load = function() { var self = this; + this._updateAutoRefreshTimer(); return $fs.read('scores.json').then(function(res) { self.beginupdate(); try { @@ -327,6 +331,54 @@ define('services/ng-scores',[ } }; + /** + * Enable automatic refresh of scores if no e.g. manual + * refresh happened for a while. This is mostly used as + * a backup scenario in case we e.g. missed an (MHub) event, + * or when MHub is not available. + * Use disableAutoRefresh() when no longer needed (e.g. on + * controller destruction). + */ + Scores.prototype.enableAutoRefresh = function() { + this._autoRefreshUsers++; + this._updateAutoRefreshTimer(); + }; + + /** + * Unregister interest in auto-refresh. See enableAutoRefresh(). + */ + Scores.prototype.disableAutoRefresh = function () { + if (this._autoRefreshUsers <= 0) { + throw new Error("enableAutoRefresh()/disableAutoRefresh() calls mismatched"); + } + this._autoRefreshUsers--; + if (this._autoRefreshUsers === 0) { + // Only stop the timer when needed, otherwise + // we unnecessarily restart it + this._updateAutoRefreshTimer(); + } + }; + + /** + * Restart refresh timer, if anyone is interested in auto-refreshing. + */ + Scores.prototype._updateAutoRefreshTimer = function() { + var self = this; + if (this._autoRefreshInterval !== undefined) { + $interval.cancel(this._autoRefreshInterval); + this._autoRefreshInterval = undefined; + } + if (this._autoRefreshUsers > 0) { + this._autoRefreshInterval = $interval(function() { + // Reload scores from server (if we're not already + // in the middle of something). + if (self._updating <= 0) { + self.load(); + } + }, this._autoRefreshTimeout); + } + }; + /** * Poll storage for any new score sheets. * Ignore already processed sheets, add a new score entry for each diff --git a/src/js/views/ranking.js b/src/js/views/ranking.js index 479a6055..3cb5c7b1 100644 --- a/src/js/views/ranking.js +++ b/src/js/views/ranking.js @@ -156,10 +156,16 @@ define('views/ranking',[ $scope.stages = $stages.stages; $scope.scoreboard = $scores.scoreboard; + // Ensure periodic updates of scores view + $scores.enableAutoRefresh(); + $scope.$on("$destroy", function () { + $scores.disableAutoRefresh(); + }); + $scope.getRoundLabel = function(round){ return "Round " + round; }; - + } ]); diff --git a/src/js/views/scores.js b/src/js/views/scores.js index 574ab79c..411240b8 100644 --- a/src/js/views/scores.js +++ b/src/js/views/scores.js @@ -16,6 +16,12 @@ define('views/scores',[ $scope.scores = $scores.scores; $scope.stages = $stages.stages; + // Ensure periodic updates of scores view + $scores.enableAutoRefresh(); + $scope.$on("$destroy", function () { + $scores.disableAutoRefresh(); + }); + $scope.doSort = function(col, defaultSort) { $scope.rev = (String($scope.sort) === String(col)) ? !$scope.rev : !!defaultSort; $scope.sort = col; From 9e79588d0e4c7c5cecc41969b0bf97279a67d2c0 Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Sun, 8 Oct 2017 10:39:28 +0200 Subject: [PATCH 2/6] factories/poller: Add Poller: ref-counted $interval. --- karma.conf.js | 1 + spec/factories/pollerSpec.js | 103 +++++++++++++++++++++++++++++++ src/js/factories/ng-factories.js | 3 + src/js/factories/poller.js | 79 ++++++++++++++++++++++++ src/js/main.js | 6 +- 5 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 spec/factories/pollerSpec.js create mode 100644 src/js/factories/ng-factories.js create mode 100644 src/js/factories/poller.js diff --git a/karma.conf.js b/karma.conf.js index f6d4a0bc..c17c80ac 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -20,6 +20,7 @@ module.exports = function(config) { 'src/components/q/q.js', 'src/components/idbwrapper/idbstore.js', 'spec/helpers/*.js', + 'src/js/factories/*.js', 'src/js/directives/*.js', 'src/js/services/*.js', 'src/js/views/*.js', diff --git a/spec/factories/pollerSpec.js b/spec/factories/pollerSpec.js new file mode 100644 index 00000000..a82abfcd --- /dev/null +++ b/spec/factories/pollerSpec.js @@ -0,0 +1,103 @@ +describe('poller', function () { + "use strict"; + + var ngFactories = factory('factories/ng-factories'); + var module = factory('factories/poller', { + 'factories/ng-factories': ngFactories + }); + + var Poller; + var $interval; + var poller; + var callback; + var INTERVAL = 1000; + + beforeEach(function () { + angular.mock.module(module.name); + angular.mock.inject(["Poller", "$interval", function (_Poller_, _$interval_) { + Poller = _Poller_; + $interval = _$interval_; + callback = jasmine.createSpy("callback"); + poller = new Poller(INTERVAL, callback); + }]); + + }); + + describe('constructor', function () { + it('should not start poller', function () { + $interval.flush(1001); + expect(callback).not.toHaveBeenCalled(); + }); + }); + + describe('start', function () { + it('should be started when someone is interested', function () { + poller.start(); + $interval.flush(INTERVAL + 1); + expect(callback).toHaveBeenCalledTimes(1); + }); + it('should keep running when someone is interested', function () { + poller.start(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(2); + }); + }); + + describe('stop', function () { + it('should stop when no-one is interested, case 1', function () { + poller.start(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + poller.stop(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + }); + it('should stop when no-one is interested, case 2', function () { + poller.start(); + poller.start(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + poller.stop(); + poller.stop(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + }); + it('should not stop when at least one user is interested', function () { + poller.start(); + poller.start(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(1); + poller.stop(); + $interval.flush(INTERVAL); + expect(callback).toHaveBeenCalledTimes(2); + }); + it('should throw when stopping more then starting', function () { + poller.start(); + poller.stop(); + expect(function () { + poller.stop(); + }).toThrowError(); + }) + }); + + describe('reset', function () { + it('should not start timer when no-one interested', function () { + $interval.flush(INTERVAL / 2); + poller.reset(); + $interval.flush(2 * INTERVAL); + expect(callback).not.toHaveBeenCalled(); + }); + it('should restart timer when someone interested', function () { + poller.start(); + $interval.flush(INTERVAL / 2); + expect(callback).not.toHaveBeenCalled(); + poller.reset(); + $interval.flush(INTERVAL / 2); + expect(callback).not.toHaveBeenCalled(); + $interval.flush(INTERVAL / 2); + expect(callback).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/src/js/factories/ng-factories.js b/src/js/factories/ng-factories.js new file mode 100644 index 00000000..a1affc2b --- /dev/null +++ b/src/js/factories/ng-factories.js @@ -0,0 +1,3 @@ +define('factories/ng-factories', ['angular'], function () { + return angular.module('factories', []); +}); diff --git a/src/js/factories/poller.js b/src/js/factories/poller.js new file mode 100644 index 00000000..f069199a --- /dev/null +++ b/src/js/factories/poller.js @@ -0,0 +1,79 @@ +/** + * Variant of $interval() which only starts the interval + * when at least one user is interested. + */ +define('factories/poller', [ + 'factories/ng-factories', +], function (module) { + "use strict"; + + return module.factory('Poller', [ + '$interval', + function($interval) { + + /** + * Ref-counted $interval. + * Starts calling `callback` every `interval` milliseconds when + * number of calls to `start()` is bigger than number of calls to `stop()`. + * + * Usage example: + * const p = new Poller(10000, () => { console.log("tick"); }); + * // when instantiating controller: + * p.start(); + * // when destroying controller: + * p.stop(); + */ + function Poller(interval, callback) { + this._interval = interval; + this._callback = callback; + this._refs = 0; + this._handle = undefined; // $interval handle + } + + /** + * Enable polling. + * Multiple calls to start() can be made. As long as the number of + * stop() calls is smaller than the number of start() calls, the + * poller keeps running. + */ + Poller.prototype.start = function () { + this._refs++; + this.reset(); + }; + + /** + * Disable polling when the number of stop calls is equal to + * the number of start calls. + * It is an error to call stop more often than start. + */ + Poller.prototype.stop = function () { + if (this._refs <= 0) { + throw new Error("start/stop calls mismatched"); + } + this._refs--; + if (this._refs === 0) { + // Keep timer running if others are still interested + this.reset(); + } + }; + + /** + * Restart poller, if it is currently running. + */ + Poller.prototype.reset = function() { + var self = this; + if (this._handle !== undefined) { + $interval.cancel(this._handle); + this._handle = undefined; + } + if (this._refs > 0) { + this._handle = $interval(function () { + self._callback(); + }, this._interval); + } + }; + + return Poller; + } + ]); +}); diff --git a/src/js/main.js b/src/js/main.js index 1b9e7cb9..7bdff802 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -6,6 +6,7 @@ define([ 'views/scoresheet', 'views/scores', 'views/ranking', + 'factories/ng-factories', 'services/ng-services', 'directives/ng-directives', 'directives/size', @@ -17,7 +18,7 @@ define([ 'angular-touch', 'angular-sanitize', 'angular' -],function(log,session,settings,teams,scoresheet,scores,ranking,services,directives,size,filters,indexFilter,fsTest,dbTest) { +],function(log,session,settings,teams,scoresheet,scores,ranking,factories,services,directives,size,filters,indexFilter,fsTest,dbTest) { log('device ready'); @@ -107,6 +108,7 @@ define([ ranking.name, filters.name, services.name, - directives.name + directives.name, + factories.name, ]); }); From ab6967141414b6b9fc4bc8be962a88fae8bd3a37 Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Sun, 8 Oct 2017 10:50:39 +0200 Subject: [PATCH 3/6] scores: Use Poller: - Functionality works (in browser) - Tests currently fail because ng-scores can't find Poller (only in tests) --- spec/services/ng-scoresSpec.js | 14 +++++----- src/js/services/ng-scores.js | 49 ++++++++++------------------------ 2 files changed, 21 insertions(+), 42 deletions(-) diff --git a/spec/services/ng-scoresSpec.js b/spec/services/ng-scoresSpec.js index 5c4e13a4..f0960f63 100644 --- a/spec/services/ng-scoresSpec.js +++ b/spec/services/ng-scoresSpec.js @@ -542,38 +542,38 @@ describe('ng-scores',function() { describe('autoRefresh', function() { it('should not be started when no-one is interested', function () { fsMock.read.calls.reset(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).not.toHaveBeenCalled(); }); it('should be started when someone is interested', function () { fsMock.read.calls.reset(); $scores.enableAutoRefresh(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).toHaveBeenCalled(); }); it('should keep refreshing when someone is interested', function () { fsMock.read.calls.reset(); $scores.enableAutoRefresh(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).toHaveBeenCalled(); fsMock.read.calls.reset(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).toHaveBeenCalled(); }); it('should be stopped when everyone unregistered', function () { $scores.enableAutoRefresh(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); $scores.disableAutoRefresh(); fsMock.read.calls.reset(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).not.toHaveBeenCalled(); }); it('should skip refresh when busy', function () { fsMock.read.calls.reset(); $scores.enableAutoRefresh(); $scores.beginupdate(); - $interval.flush($scores._autoRefreshTimeout + 1); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).not.toHaveBeenCalled(); }); }); diff --git a/src/js/services/ng-scores.js b/src/js/services/ng-scores.js index a5cdd4da..ea9b000b 100644 --- a/src/js/services/ng-scores.js +++ b/src/js/services/ng-scores.js @@ -6,7 +6,8 @@ define('services/ng-scores',[ 'services/ng-services', 'services/log', 'services/ng-fs', - 'services/ng-stages' + 'services/ng-stages', + 'factories/poller', ],function(module,log) { "use strict"; @@ -15,8 +16,8 @@ define('services/ng-scores',[ var SCORES_VERSION = 2; return module.service('$scores', - ['$rootScope', '$fs', '$stages', '$q', '$teams', '$interval', - function($rootScope, $fs, $stages, $q, $teams, $interval) { + ['$rootScope', '$fs', '$stages', '$q', '$teams', 'Poller', + function($rootScope, $fs, $stages, $q, $teams, Poller) { // Replace placeholders in format string. // Example: format("Frobnicate {0} {1} {2}", "foo", "bar") @@ -130,9 +131,8 @@ define('services/ng-scores',[ this._updating = 0; this._initialized = null; // Promise this._pollingSheets = null; // Promise - this._autoRefreshUsers = 0; - this._autoRefreshInterval = undefined; // $interval handle - this._autoRefreshTimeout = 30 * 1000; // ms before reloading scores.json + this.AUTO_REFRESH_INTERVAL = 30 * 1000; // milliseconds + this._autoRefreshPoller = new Poller(this.AUTO_REFRESH_INTERVAL, function() { self._onAutoRefresh(); }); this.init(); } @@ -180,7 +180,7 @@ define('services/ng-scores',[ Scores.prototype.load = function() { var self = this; - this._updateAutoRefreshTimer(); + this._autoRefreshPoller.reset(); return $fs.read('scores.json').then(function(res) { self.beginupdate(); try { @@ -340,42 +340,21 @@ define('services/ng-scores',[ * controller destruction). */ Scores.prototype.enableAutoRefresh = function() { - this._autoRefreshUsers++; - this._updateAutoRefreshTimer(); + this._autoRefreshPoller.start(); }; /** * Unregister interest in auto-refresh. See enableAutoRefresh(). */ Scores.prototype.disableAutoRefresh = function () { - if (this._autoRefreshUsers <= 0) { - throw new Error("enableAutoRefresh()/disableAutoRefresh() calls mismatched"); - } - this._autoRefreshUsers--; - if (this._autoRefreshUsers === 0) { - // Only stop the timer when needed, otherwise - // we unnecessarily restart it - this._updateAutoRefreshTimer(); - } + this._autoRefreshPoller.stop(); }; - /** - * Restart refresh timer, if anyone is interested in auto-refreshing. - */ - Scores.prototype._updateAutoRefreshTimer = function() { - var self = this; - if (this._autoRefreshInterval !== undefined) { - $interval.cancel(this._autoRefreshInterval); - this._autoRefreshInterval = undefined; - } - if (this._autoRefreshUsers > 0) { - this._autoRefreshInterval = $interval(function() { - // Reload scores from server (if we're not already - // in the middle of something). - if (self._updating <= 0) { - self.load(); - } - }, this._autoRefreshTimeout); + Scores.prototype._onAutoRefresh = function () { + // Reload scores from server (if we're not already + // in the middle of something). + if (this._updating <= 0) { + this.load(); } }; From 8aee5c0fe439da60cbcccfe3e10cc7f9c0e96968 Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Sun, 8 Oct 2017 10:51:23 +0200 Subject: [PATCH 4/6] scores: Add test to assert that polls continue after it was busy last poll. --- spec/services/ng-scoresSpec.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/services/ng-scoresSpec.js b/spec/services/ng-scoresSpec.js index f0960f63..c6870fa8 100644 --- a/spec/services/ng-scoresSpec.js +++ b/spec/services/ng-scoresSpec.js @@ -576,6 +576,16 @@ describe('ng-scores',function() { $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); expect(fsMock.read).not.toHaveBeenCalled(); }); + it('should continue refresh after it was busy before', function () { + fsMock.read.calls.reset(); + $scores.enableAutoRefresh(); + $scores.beginupdate(); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); + expect(fsMock.read).not.toHaveBeenCalled(); + $scores.endupdate(); + $interval.flush($scores.AUTO_REFRESH_INTERVAL + 1); + expect(fsMock.read).toHaveBeenCalled(); + }); }); }); From 6bbe45770eb5a36e2068f84e8043c13d675294fe Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Sun, 8 Oct 2017 10:57:53 +0200 Subject: [PATCH 5/6] scores: Extract isUpdating(). --- src/js/services/ng-scores.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/js/services/ng-scores.js b/src/js/services/ng-scores.js index ea9b000b..28aa31d8 100644 --- a/src/js/services/ng-scores.js +++ b/src/js/services/ng-scores.js @@ -326,11 +326,15 @@ define('services/ng-scores',[ throw new Error("beginupdate()/endupdate() calls mismatched"); } this._updating--; - if (this._updating === 0) { + if (!this.isUpdating()) { this._update(); } }; + Scores.prototype.isUpdating = function () { + return this._updating > 0; + }; + /** * Enable automatic refresh of scores if no e.g. manual * refresh happened for a while. This is mostly used as @@ -353,7 +357,7 @@ define('services/ng-scores',[ Scores.prototype._onAutoRefresh = function () { // Reload scores from server (if we're not already // in the middle of something). - if (this._updating <= 0) { + if (!this.isUpdating()) { this.load(); } }; @@ -438,7 +442,7 @@ define('services/ng-scores',[ }; Scores.prototype._update = function() { - if (this._updating > 0) { + if (this.isUpdating()) { return; } From 341efe048c79f8f3000d72810a28756a55af586c Mon Sep 17 00:00:00 2001 From: Martin Poelstra Date: Mon, 23 Oct 2017 20:41:57 +0200 Subject: [PATCH 6/6] ng-services: Now depends on factories (for Poller in ng-scores). --- src/js/services/ng-services.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/services/ng-services.js b/src/js/services/ng-services.js index 8374a32b..5485ba5f 100644 --- a/src/js/services/ng-services.js +++ b/src/js/services/ng-services.js @@ -1,3 +1,3 @@ define('services/ng-services',['angular'],function() { - return angular.module('services',[]); + return angular.module('services',['factories']); });