mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 07:16:39 +00:00
[Notifications] #499 All notifications now dismissable by default.
jslint
This commit is contained in:
parent
2dd9a16bf3
commit
5292b27e7d
@ -6,7 +6,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="abs message-body">
|
<div class="abs message-body">
|
||||||
<mct-include ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'" key="'message'" ng-model="msg"></mct-include>
|
<mct-include
|
||||||
|
ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
|
||||||
|
key="'message'" ng-model="msg.model"></mct-include>
|
||||||
</div>
|
</div>
|
||||||
<div class="abs bottom-bar">
|
<div class="abs bottom-bar">
|
||||||
<a ng-repeat="dialogAction in ngModel.dialog.actions"
|
<a ng-repeat="dialogAction in ngModel.dialog.actions"
|
||||||
|
@ -60,6 +60,12 @@ define(
|
|||||||
notification.model.cancel = function(){
|
notification.model.cancel = function(){
|
||||||
dialogService.dismiss();
|
dialogService.dismiss();
|
||||||
};
|
};
|
||||||
|
//If the notification is dismissed by the user, close
|
||||||
|
// the dialog.
|
||||||
|
notification.onDismiss(function(){
|
||||||
|
dialogService.dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
dialogService.showBlockingMessage(notification.model);
|
dialogService.showBlockingMessage(notification.model);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,7 @@ define([
|
|||||||
"implementation": NotificationService,
|
"implementation": NotificationService,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$timeout",
|
"$timeout",
|
||||||
|
"topic",
|
||||||
"DEFAULT_AUTO_DISMISS",
|
"DEFAULT_AUTO_DISMISS",
|
||||||
"MINIMIZE_TIMEOUT"
|
"MINIMIZE_TIMEOUT"
|
||||||
]
|
]
|
||||||
|
@ -50,9 +50,7 @@ define(
|
|||||||
title: "Messages",
|
title: "Messages",
|
||||||
//Launch the message list dialog with the models
|
//Launch the message list dialog with the models
|
||||||
// from the notifications
|
// from the notifications
|
||||||
messages: notificationService.notifications && notificationService.notifications.map(function(notification){
|
messages: notificationService.notifications
|
||||||
return notification.model;
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
cancel: function(){
|
cancel: function(){
|
||||||
dialogService.dismiss();
|
dialogService.dismiss();
|
||||||
|
@ -58,21 +58,23 @@ define(
|
|||||||
* @property {string} title The title of the message
|
* @property {string} title The title of the message
|
||||||
* @property {string} severity The importance of the message (one of
|
* @property {string} severity The importance of the message (one of
|
||||||
* 'info', 'alert', or 'error' where info < alert <error)
|
* 'info', 'alert', or 'error' where info < alert <error)
|
||||||
* @property {number} progress The completion status of a task
|
* @property {number} [progress] The completion status of a task
|
||||||
* represented numerically
|
* represented numerically
|
||||||
* @property {boolean} unknownProgress a boolean indicating that the
|
* @property {boolean} [unknownProgress] a boolean indicating that the
|
||||||
* progress of the underlying task is unknown. This will result in a
|
* progress of the underlying task is unknown. This will result in a
|
||||||
* visually distinct progress bar.
|
* visually distinct progress bar.
|
||||||
* @property {boolean | number} autoDismiss If truthy, dialog will
|
* @property {boolean | number} [autoDismiss] If truthy, dialog will
|
||||||
* be automatically minimized or dismissed (depending on severity).
|
* be automatically minimized or dismissed (depending on severity).
|
||||||
* Additionally, if the provided value is a number, it will be used
|
* Additionally, if the provided value is a number, it will be used
|
||||||
* as the delay period before being dismissed.
|
* as the delay period before being dismissed.
|
||||||
* @property {NotificationOption} primaryOption the default user
|
* @property {boolean} [dismissable=true] If truthy, notification will
|
||||||
|
* include an option to dismiss it completely.
|
||||||
|
* @property {NotificationOption} [primaryOption] the default user
|
||||||
* response to
|
* response to
|
||||||
* this message. Will be represented as a button with the provided
|
* this message. Will be represented as a button with the provided
|
||||||
* label and action. May be used by banner notifications to display
|
* label and action. May be used by banner notifications to display
|
||||||
* only the most important option to users.
|
* only the most important option to users.
|
||||||
* @property {NotificationOption[]} options any additional
|
* @property {NotificationOption[]} [options] any additional
|
||||||
* actions the user can take. Will be represented as additional buttons
|
* actions the user can take. Will be represented as additional buttons
|
||||||
* that may or may not be available from a banner.
|
* that may or may not be available from a banner.
|
||||||
* @see DialogModel
|
* @see DialogModel
|
||||||
@ -99,6 +101,8 @@ define(
|
|||||||
* be used for dismissing a notification. If more control is
|
* be used for dismissing a notification. If more control is
|
||||||
* required, then the minimize or dismiss functions can be called
|
* required, then the minimize or dismiss functions can be called
|
||||||
* individually.
|
* individually.
|
||||||
|
* @property {function} onDismiss Allows listening for on dismiss
|
||||||
|
* events. This allows cleanup etc. when the notification is dismissed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,12 +117,13 @@ define(
|
|||||||
* animation is shown. This animation requires some time to execute,
|
* animation is shown. This animation requires some time to execute,
|
||||||
* so a timeout is required before the notification is hidden
|
* so a timeout is required before the notification is hidden
|
||||||
*/
|
*/
|
||||||
function NotificationService($timeout, DEFAULT_AUTO_DISMISS, MINIMIZE_TIMEOUT) {
|
function NotificationService($timeout, topic, DEFAULT_AUTO_DISMISS, MINIMIZE_TIMEOUT) {
|
||||||
this.notifications = [];
|
this.notifications = [];
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.highest ={ severity: "info" };
|
this.highest ={ severity: "info" };
|
||||||
this.DEFAULT_AUTO_DISMISS = DEFAULT_AUTO_DISMISS;
|
this.DEFAULT_AUTO_DISMISS = DEFAULT_AUTO_DISMISS;
|
||||||
this.MINIMIZE_TIMEOUT = MINIMIZE_TIMEOUT;
|
this.MINIMIZE_TIMEOUT = MINIMIZE_TIMEOUT;
|
||||||
|
this.topic = topic;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A context in which to hold the active notification and a
|
* A context in which to hold the active notification and a
|
||||||
@ -127,14 +132,16 @@ define(
|
|||||||
this.active = {};
|
this.active = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Minimize a notification. The notification will still be available
|
* Minimize a notification. The notification will still be available
|
||||||
* from the notification list. Typically notifications with a
|
* from the notification list. Typically notifications with a
|
||||||
* severity of 'info' should not be minimized, but rather
|
* severity of 'info' should not be minimized, but rather
|
||||||
* dismissed. If you're not sure which is appropriate,
|
* dismissed. If you're not sure which is appropriate,
|
||||||
* use {@link Notification#dismissOrMinimize}
|
* use {@link Notification#dismissOrMinimize}
|
||||||
|
*
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function minimize (service, notification) {
|
NotificationService.prototype.minimize = function (service, notification) {
|
||||||
//Check this is a known notification
|
//Check this is a known notification
|
||||||
var index = service.notifications.indexOf(notification);
|
var index = service.notifications.indexOf(notification);
|
||||||
|
|
||||||
@ -159,17 +166,19 @@ define(
|
|||||||
service.setActiveNotification(service.selectNextNotification());
|
service.setActiveNotification(service.selectNextNotification());
|
||||||
}, service.MINIMIZE_TIMEOUT);
|
}, service.MINIMIZE_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Completely removes a notification. This will dismiss it from the
|
* Completely removes a notification. This will dismiss it from the
|
||||||
* message banner and remove it from the list of notifications.
|
* message banner and remove it from the list of notifications.
|
||||||
* Typically only notifications with a severity of info should be
|
* Typically only notifications with a severity of info should be
|
||||||
* dismissed. If you're not sure whether to dismiss or minimize a
|
* dismissed. If you're not sure whether to dismiss or minimize a
|
||||||
* notification, use {@link Notification#dismissOrMinimize}.
|
* notification, use {@link Notification#dismissOrMinimize}.
|
||||||
* dismiss
|
* dismiss
|
||||||
|
*
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function dismiss (service, notification) {
|
NotificationService.prototype.dismiss = function (service, notification) {
|
||||||
//Check this is a known notification
|
//Check this is a known notification
|
||||||
var index = service.notifications.indexOf(notification);
|
var index = service.notifications.indexOf(notification);
|
||||||
|
|
||||||
@ -190,19 +199,23 @@ define(
|
|||||||
service.notifications.splice(index, 1);
|
service.notifications.splice(index, 1);
|
||||||
}
|
}
|
||||||
service.setActiveNotification(service.selectNextNotification());
|
service.setActiveNotification(service.selectNextNotification());
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
this.setHighestSeverity();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
* Depending on the severity of the notification will selectively
|
* Depending on the severity of the notification will selectively
|
||||||
* dismiss or minimize where appropriate.
|
* dismiss or minimize where appropriate.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function dismissOrMinimize (notification){
|
NotificationService.prototype.dismissOrMinimize = function (notification) {
|
||||||
|
|
||||||
//For now minimize everything, and have discussion around which
|
//For now minimize everything, and have discussion around which
|
||||||
//kind of messages should or should not be in the minimized
|
//kind of messages should or should not be in the minimized
|
||||||
//notifications list
|
//notifications list
|
||||||
notification.minimize();
|
notification.minimize();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the notification that is currently visible in the banner area
|
* Returns the notification that is currently visible in the banner area
|
||||||
@ -261,6 +274,24 @@ define(
|
|||||||
return this.notify(notificationModel);
|
return this.notify(notificationModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
NotificationService.prototype.setHighestSeverity = function () {
|
||||||
|
var severity = {
|
||||||
|
"info": 1,
|
||||||
|
"alert": 2,
|
||||||
|
"error": 3
|
||||||
|
};
|
||||||
|
this.highest.severity = this.notifications.reduce(function(previous, notification){
|
||||||
|
if (severity[notification.model.severity] > severity[previous]){
|
||||||
|
return notification.model.severity;
|
||||||
|
} else {
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
}, "info");
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the user of an event. If there is a banner notification
|
* Notifies the user of an event. If there is a banner notification
|
||||||
* already active, then it will be dismissed or minimized automatically,
|
* already active, then it will be dismissed or minimized automatically,
|
||||||
@ -274,23 +305,23 @@ define(
|
|||||||
NotificationService.prototype.notify = function (notificationModel) {
|
NotificationService.prototype.notify = function (notificationModel) {
|
||||||
var self = this,
|
var self = this,
|
||||||
notification,
|
notification,
|
||||||
ordinality = {
|
activeNotification = self.active.notification,
|
||||||
"info": 1,
|
topic = this.topic();
|
||||||
"alert": 2,
|
|
||||||
"error": 3
|
|
||||||
},
|
|
||||||
activeNotification = self.active.notification;
|
|
||||||
|
|
||||||
notification = {
|
notification = {
|
||||||
model: notificationModel,
|
model: notificationModel,
|
||||||
minimize: function() {
|
minimize: function() {
|
||||||
minimize(self, notification);
|
self.minimize(self, notification);
|
||||||
},
|
},
|
||||||
dismiss: function(){
|
dismiss: function(){
|
||||||
dismiss(self, notification);
|
self.dismiss(self, notification);
|
||||||
|
topic.notify();
|
||||||
},
|
},
|
||||||
dismissOrMinimize: function(){
|
dismissOrMinimize: function(){
|
||||||
dismissOrMinimize(notification);
|
self.dismissOrMinimize(notification);
|
||||||
|
},
|
||||||
|
onDismiss: function(callback) {
|
||||||
|
topic.listen(callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -299,12 +330,25 @@ define(
|
|||||||
notificationModel.autoDismiss = this.DEFAULT_AUTO_DISMISS;
|
notificationModel.autoDismiss = this.DEFAULT_AUTO_DISMISS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ordinality[notificationModel.severity.toLowerCase()] > ordinality[this.highest.severity.toLowerCase()]){
|
//Notifications support a 'dismissable' attribute. This is a
|
||||||
this.highest.severity = notificationModel.severity;
|
// convenience to support adding a 'dismiss' option to the
|
||||||
|
// notification for the common case of dismissing a
|
||||||
|
// notification. Could also be done manually by specifying an
|
||||||
|
// option on the model
|
||||||
|
if (notificationModel.dismissable !== false) {
|
||||||
|
notificationModel.options = notificationModel.options || [];
|
||||||
|
notificationModel.options.unshift({
|
||||||
|
label: "Dismiss",
|
||||||
|
callback: function() {
|
||||||
|
notification.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.notifications.push(notification);
|
this.notifications.push(notification);
|
||||||
|
|
||||||
|
this.setHighestSeverity();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if there is already an active (ie. visible) notification
|
Check if there is already an active (ie. visible) notification
|
||||||
*/
|
*/
|
||||||
|
@ -32,13 +32,19 @@ define(
|
|||||||
mockAutoDismiss,
|
mockAutoDismiss,
|
||||||
mockMinimizeTimeout,
|
mockMinimizeTimeout,
|
||||||
successModel,
|
successModel,
|
||||||
|
mockTopicFunction,
|
||||||
|
mockTopicObject,
|
||||||
errorModel;
|
errorModel;
|
||||||
|
|
||||||
beforeEach(function(){
|
beforeEach(function(){
|
||||||
mockTimeout = jasmine.createSpy("$timeout");
|
mockTimeout = jasmine.createSpy("$timeout");
|
||||||
|
mockTopicFunction = jasmine.createSpy("topic");
|
||||||
|
mockTopicObject = jasmine.createSpyObj("topicObject", ["listen", "notify"]);
|
||||||
|
mockTopicFunction.andReturn(mockTopicObject);
|
||||||
|
|
||||||
mockAutoDismiss = mockMinimizeTimeout = 1000;
|
mockAutoDismiss = mockMinimizeTimeout = 1000;
|
||||||
notificationService = new NotificationService(
|
notificationService = new NotificationService(
|
||||||
mockTimeout, mockAutoDismiss, mockMinimizeTimeout);
|
mockTimeout, mockTopicFunction, mockAutoDismiss, mockMinimizeTimeout);
|
||||||
successModel = {
|
successModel = {
|
||||||
title: "Mock Success Notification",
|
title: "Mock Success Notification",
|
||||||
severity: "info"
|
severity: "info"
|
||||||
@ -57,6 +63,19 @@ define(
|
|||||||
expect(activeNotification.model).toBe(successModel);
|
expect(activeNotification.model).toBe(successModel);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("notifies listeners on dismissal of notification", function() {
|
||||||
|
var notification,
|
||||||
|
dismissListener = jasmine.createSpy("ondismiss");
|
||||||
|
notification = notificationService.notify(successModel);
|
||||||
|
notification.onDismiss(dismissListener);
|
||||||
|
expect(mockTopicObject.listen).toHaveBeenCalled();
|
||||||
|
notification.dismiss();
|
||||||
|
expect(mockTopicObject.notify).toHaveBeenCalled();
|
||||||
|
mockTopicObject.listen.mostRecentCall.args[0]();
|
||||||
|
expect(dismissListener).toHaveBeenCalled();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
it("allows specification of an info notification given just a" +
|
it("allows specification of an info notification given just a" +
|
||||||
" title, making the notification active", function() {
|
" title, making the notification active", function() {
|
||||||
var activeNotification,
|
var activeNotification,
|
||||||
|
@ -104,14 +104,16 @@ define(
|
|||||||
* persistence.
|
* persistence.
|
||||||
*/
|
*/
|
||||||
function notifyOnError(error, domainObject, notificationService, $q){
|
function notifyOnError(error, domainObject, notificationService, $q){
|
||||||
var errorMessage = "Unable to persist " + domainObject.getModel().name;
|
var errorMessage = "Unable to persist " + domainObject.getModel().name,
|
||||||
|
notification;
|
||||||
if (error) {
|
if (error) {
|
||||||
errorMessage += ": " + formatError(error);
|
errorMessage += ": " + formatError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationService.error({
|
notification = notificationService.error({
|
||||||
title: "Error persisting " + domainObject.getModel().name,
|
title: "Error persisting " + domainObject.getModel().name,
|
||||||
hint: errorMessage || "Unknown error"
|
hint: errorMessage || "Unknown error",
|
||||||
|
dismissable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return $q.reject(error);
|
return $q.reject(error);
|
||||||
|
Loading…
Reference in New Issue
Block a user