Use angular events to broadcast status updates

This commit is contained in:
Tankred Hase 2014-11-26 21:12:40 +01:00
parent 32d3ea1801
commit 2f25557747
6 changed files with 41 additions and 87 deletions

View File

@ -11,7 +11,7 @@ var INIT_DISPLAY_LEN = 20,
FOLDER_TYPE_INBOX = 'Inbox', FOLDER_TYPE_INBOX = 'Inbox',
NOTIFICATION_INBOX_TIMEOUT = 5000; NOTIFICATION_INBOX_TIMEOUT = 5000;
var MailListCtrl = function($scope, $routeParams, statusDisplay, notification, email, keychain, dialog, search, dummy) { var MailListCtrl = function($scope, $timeout, $routeParams, statusDisplay, notification, email, keychain, dialog, search, dummy) {
// //
// Init // Init
@ -197,12 +197,15 @@ var MailListCtrl = function($scope, $routeParams, statusDisplay, notification, e
* Sync current folder when client comes back online * Sync current folder when client comes back online
*/ */
$scope.watchOnline = $scope.$watch('account.online', function(isOnline) { $scope.watchOnline = $scope.$watch('account.online', function(isOnline) {
if (isOnline) { // wait one cycle for the status display controllers to init
statusDisplay.update('Online'); $timeout(function() {
openCurrentFolder(); if (isOnline) {
} else { statusDisplay.update('Online');
statusDisplay.update('Offline mode'); openCurrentFolder();
} } else {
statusDisplay.update('Offline mode');
}
});
}, true); }, true);
// //

View File

@ -1,26 +1,15 @@
'use strict'; 'use strict';
var StatusDisplayCtrl = function($scope, $timeout, statusDisplay) { var StatusDisplayCtrl = function($scope) {
$scope.state.statusDisplay = { $scope.$on('status', function(e, text, time) {
text: '', $scope.text = text;
time: undefined, $scope.time = (time) ? time : '';
searching: false });
};
// set the show functions $scope.$on('searching', function(e, state) {
statusDisplay.showStatus = function(lbl, time) { $scope.searching = state;
return $timeout(function() { });
$scope.state.statusDisplay.text = lbl;
$scope.state.statusDisplay.time = (time) ? time : '';
});
};
statusDisplay.showSearching = function(state) {
return $timeout(function() {
$scope.state.statusDisplay.searching = state;
});
};
}; };

View File

@ -7,26 +7,19 @@ module.exports = StatusDisplay;
/** /**
* A central service to display status updates to the user * A central service to display status updates to the user
*/ */
function StatusDisplay($q, axe) { function StatusDisplay($rootScope, axe) {
this._q = $q; this._rootScope = $rootScope;
this._axe = axe; this._axe = axe;
} }
/** /**
* Update the status disply in the lower left of the screen * Update the status disply in the lower left of the screen
* @param {String} msg The status message that is to be displayed to the user * @param {String} text The status message that is to be displayed to the user
* @param {Date} time The time of the last update * @param {Date} time The time of the last update
*/ */
StatusDisplay.prototype.update = function(msg, time) { StatusDisplay.prototype.update = function(text, time) {
var self = this; this._axe.info('status display', text);
self._axe.info('status display', msg); this._rootScope.$broadcast('status', text, time);
return self._q(function(resolve, reject) {
if (self.showStatus) {
return resolve(self.showStatus(msg, time));
} else {
reject(new Error('Status display service showStatus not set!'));
}
});
}; };
/** /**
@ -34,12 +27,5 @@ StatusDisplay.prototype.update = function(msg, time) {
* @param {Boolean} state If the spinner should be displayed or not * @param {Boolean} state If the spinner should be displayed or not
*/ */
StatusDisplay.prototype.setSearching = function(state) { StatusDisplay.prototype.setSearching = function(state) {
var self = this; this._rootScope.$broadcast('searching', state);
return self._q(function(resolve, reject) {
if (self.showSearching) {
return resolve(self.showSearching(state));
} else {
reject(new Error('Status display service showSearching not set!'));
}
});
}; };

View File

@ -69,5 +69,5 @@
</li> </li>
</ul><!--/nav__secondary--> </ul><!--/nav__secondary-->
<footer ng-include="'tpl/status-display.html'" ng-controller="StatusDisplayCtrl"></footer> <footer ng-include="'tpl/status-display.html'"></footer>
</nav> </nav>

View File

@ -1,9 +1,9 @@
<div> <div ng-controller="StatusDisplayCtrl">
<span class="spinner" ng-show="account.loggingIn || account.busy || state.statusDisplay.searching"></span> <span class="spinner" ng-show="account.loggingIn || account.busy || searching"></span>
<span class="text" ng-switch="account.online"> <span class="text" ng-switch="account.online">
<span ng-switch-when="false"> <span ng-switch-when="false">
<svg><use xlink:href="#icon-offline" /></svg> <svg><use xlink:href="#icon-offline" /></svg>
</span> </span>
{{state.statusDisplay.text}} {{state.statusDisplay.time | date:'shortTime'}} {{text}} {{time | date:'shortTime'}}
</span> </span>
</div> </div>

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
describe('Status Display Service unit test', function() { describe('Status Display Service unit test', function() {
var statusDisplay, logInfoStub; var statusDisplay, logInfoStub, rootScope, broadcastSpy;
beforeEach(function() { beforeEach(function() {
angular.module('statusDisplay-test', ['woUtil']); angular.module('statusDisplay-test', ['woUtil']);
@ -9,6 +9,8 @@ describe('Status Display Service unit test', function() {
angular.mock.inject(function($injector, axe) { angular.mock.inject(function($injector, axe) {
logInfoStub = sinon.stub(axe, 'info'); logInfoStub = sinon.stub(axe, 'info');
statusDisplay = $injector.get('statusDisplay'); statusDisplay = $injector.get('statusDisplay');
rootScope = $injector.get('$rootScope');
broadcastSpy = sinon.spy(rootScope, '$broadcast');
}); });
}); });
@ -17,49 +19,23 @@ describe('Status Display Service unit test', function() {
}); });
describe('update', function() { describe('update', function() {
it('should work', inject(function($rootScope) { it('should work', function() {
var message = 'Tada!', var message = 'Tada!',
time = new Date(); time = new Date();
statusDisplay.showStatus = function() {};
var showStatusStub = sinon.stub(statusDisplay, 'showStatus');
statusDisplay.update(message, time).then(function(result) { statusDisplay.update(message, time);
expect(result).to.not.exist;
});
expect(logInfoStub.calledOnce).to.be.true; expect(broadcastSpy.withArgs('status', message, time).calledOnce).to.be.true;
$rootScope.$apply(); expect(logInfoStub.withArgs('status display', message).calledOnce).to.be.true;
expect(showStatusStub.withArgs(message, time).calledOnce).to.be.true; });
}));
it('should fail for no display function', inject(function($rootScope) {
statusDisplay.update().catch(function(err) {
expect(err.message).to.match(/showStatus/);
});
expect(logInfoStub.calledOnce).to.be.true;
$rootScope.$apply();
}));
}); });
describe('setSearching', function() { describe('setSearching', function() {
it('should work', inject(function($rootScope) { it('should work', function() {
statusDisplay.showSearching = function() {}; statusDisplay.setSearching(true);
var showSearchingStub = sinon.stub(statusDisplay, 'showSearching');
statusDisplay.setSearching(true).then(function(result) { expect(broadcastSpy.withArgs('searching', true).calledOnce).to.be.true;
expect(result).to.not.exist; });
});
$rootScope.$apply();
expect(showSearchingStub.withArgs(true).calledOnce).to.be.true;
}));
it('should fail for no display function', inject(function($rootScope) {
statusDisplay.setSearching().catch(function(err) {
expect(err.message).to.match(/showSearching/);
});
$rootScope.$apply();
}));
}); });
}); });