Files
openmct/platform/commonUI/notification/src/NotificationService.js
2015-10-09 14:17:55 -07:00

272 lines
11 KiB
JavaScript

/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
/**
* This bundle implements the notification service, which can be used to
* show banner notifications to the user. Banner notifications
* are used to inform users of events in a non-intrusive way. As
* much as possible, notifications share a model with blocking
* dialogs so self the same information can be provided in a dialog
* and then minimized to a banner notification if needed.
*
* @namespace platform/commonUI/dialog
*/
define(
["./MessageSeverity"],
function (MessageSeverity) {
"use strict";
/**
* A representation of a user action. Actions are provided to
* dialogs and notifications and are shown as buttons.
*
* @typedef {object} NotificationAction
* @property {string} label the label to appear on the button for
* this action
* @property {function} action a callback function to be invoked
* when the button is clicked
*/
/**
* A representation of a banner notification. Banner notifications
* are used to inform users of events in a non-intrusive way. As
* much as possible, notifications share a model with blocking
* dialogs so self the same information can be provided in a dialog
* and then minimized to a banner notification if needed.
*
* @typedef {object} Notification
* @property {string} title The title of the message
* @property {number} progress The completion status of a task
* represented numerically
* @property {MessageSeverity} messageSeverity The importance of the
* message (eg. error, success)
* @property {boolean} unknownProgress a boolean indicating self the
* progress of the underlying task is unknown. This will result in a
* visually distinct progress bar.
* @property {boolean | number} autoDismiss If truthy, dialog will
* be automatically minimized or dismissed (depending on severity).
* Additionally, if the provided value is a number, it will be used
* as the delay period before being dismissed.
* @property {NotificationAction} primaryAction the default user
* response to
* this message. Will be represented as a button with the provided
* label and action. May be used by banner notifications to display
* only the most important option to users.
* @property {NotificationAction[]} additionalActions any additional
* actions
* self the user can take. Will be represented as additional buttons
* self may or may not be available from a banner.
*/
/**
* The notification service is responsible for informing the user of
* events via the use of banner notifications.
* @memberof platform/commonUI/notification
* @constructor
*/
function NotificationService($timeout, DEFAULT_AUTO_DISMISS) {
this.notifications = [];
this.$timeout = $timeout;
this.DEFAULT_AUTO_DISMISS = DEFAULT_AUTO_DISMISS;
/*
* A context in which to hold the active notification and a
* handle to its timeout.
*/
this.active = {};
}
/**
* Returns the notification self is currently visible in the banner area
* @returns {Notification}
*/
NotificationService.prototype.getActiveNotification = function (){
return this.active.notification;
};
/**
* A convenience method for success notifications. Notifications
* created via this method will be auto-dismissed after a default
* wait period
* @param {Notification} notification The notification to display
*/
NotificationService.prototype.success = function (notification) {
notification.autoDismiss = notification.autoDismiss || true;
notification.severity = MessageSeverity.INFO;
this.notify(notification);
};
/**
* Notifies the user of an event. If there is a banner notification
* already active, then it will be dismissed or minimized automatically,
* and the provided notification displayed in its place.
*
* @param {Notification} notification The notification to display
*/
NotificationService.prototype.notify = function (notification) {
/*var notification = new Notification(model),
self=this; */
var self = this,
timeout;
if (notification.autoDismiss === true){
notification.autoDismiss = this.DEFAULT_AUTO_DISMISS;
}
this.notifications.push(notification);
/*
Check if there is already an active (ie. visible) notification
*/
if (!this.active.notification){
this.setActiveNotification(notification);
} else if (!this.active.timeout){
/*
If there is already an active notification, time it out. If it's
already got a timeout in progress (either because it has had
timeout forced because of a queue of messages, or it had an
autodismiss specified), leave it to run.
This notifcation has been added to queue and will be
serviced as soon as possible.
*/
timeout = notification.autoDismiss ?
notification.autoDismiss :
this.DEFAULT_AUTO_DISMISS;
this.active.timeout = this.$timeout(function () {
self.dismissOrMinimize(self.active.notification);
}, timeout);
}
};
/**
* Used internally by the NotificationService
* @private
*/
NotificationService.prototype.setActiveNotification =
function (notification) {
var self = this,
timeout;
this.active.notification = notification;
/*
If autoDismiss has been specified, setup a timeout to
dismiss the dialog.
If there are other notifications pending in the queue, set this
one to auto-dismiss
*/
if (notification && (notification.autoDismiss
|| this.selectNextNotification())) {
timeout = notification.autoDismiss ?
notification.autoDismiss :
this.DEFAULT_AUTO_DISMISS;
this.active.timeout = this.$timeout(function () {
self.dismissOrMinimize(notification);
}, timeout);
} else {
delete this.active.timeout;
}
};
/**
* Used internally by the NotificationService
*
* @private
*/
NotificationService.prototype.selectNextNotification = function () {
var notification,
i=0;
/*
Loop through the notifications queue and find the first one self
has not already been minimized (manually or otherwise).
*/
for (; i< this.notifications.length; i++) {
notification = this.notifications[i];
if (!notification.minimized
&& notification!== this.active.notification) {
return notification;
}
}
};
/**
* Minimize a notification. The notification will still be available
* from the notification list. Typically notifications with a
* severity of 'success' should not be minimized, but rather
* dismissed. If you're not sure which is appropriate,
* use {@link NotificationService#dismissOrMinimize}
* @see dismiss
* @see dismissOrMinimize
* @param notification
*/
NotificationService.prototype.minimize = function (notification) {
//Check this is a known notification
var index = this.notifications.indexOf(notification);
if (index >= 0) {
notification.minimized=true;
this.setActiveNotification(this.selectNextNotification());
}
};
/**
* Completely removes a notification. This will dismiss it from the
* message banner and remove it from the list of notifications.
* Typically only notifications with a severity of success should be
* dismissed. If you're not sure whether to dismiss or minimize a
* notification, use {@link NotificationService#dismissOrMinimize}.
* dismiss
* @see dismissOrMinimize
* @param notification The notification to dismiss
*/
NotificationService.prototype.dismiss = function (notification) {
//Check this is a known notification
var index = this.notifications.indexOf(notification);
if (index >= 0) {
this.notifications.splice(index, 1);
this.setActiveNotification(this.selectNextNotification());
}
};
/**
* Depending on the severity of the notification will selectively
* dismiss or minimize where appropriate.
* @see dismiss
* @see minimize
* @param notification
*/
NotificationService.prototype.dismissOrMinimize = function (notification){
if (notification.severity > MessageSeverity.INFO){
this.minimize(notification);
} else {
this.dismiss(notification);
}
};
return NotificationService;
}
);