This commit is contained in:
Henry
2015-10-09 15:27:40 -07:00
parent 82ae9e72c1
commit 60dda8a7a4
10 changed files with 101 additions and 53 deletions

View File

@ -12,7 +12,7 @@
</div> </div>
<div class="message-body"> <div class="message-body">
<div class="message-action"> <div class="message-action">
{{ngModel.actionText}} message-severity-{{ngModel.severity}} {{ngModel.actionText}}
</div> </div>
<mct-include key="'progress-bar'" <mct-include key="'progress-bar'"
ng-model="ngModel" ng-model="ngModel"
@ -24,6 +24,13 @@
ng-click="dialogAction.action()"> ng-click="dialogAction.action()">
{{dialogAction.label}} {{dialogAction.label}}
</a> </a>
<a class="s-btn major"
ng-if="ngModel.primaryAction"
ng-click="ngModel.primaryAction.action()">
{{ngModel.primaryAction.label}}
</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -202,7 +202,9 @@ define(
/** /**
* A description of the model options that may be passed to the * A description of the model options that may be passed to the
* showBlockingMessage method * showBlockingMessage method. Note that the DialogModel desribed
* here is shared with the Notifications framework.
* @see NotificationService
* *
* @typedef DialogModel * @typedef DialogModel
* @property {string} severity the severity level of this message. * @property {string} severity the severity level of this message.
@ -220,8 +222,13 @@ define(
* impossible to provide an estimate for. Providing a true value for * impossible to provide an estimate for. Providing a true value for
* this attribute will indicate to the user that the progress and * this attribute will indicate to the user that the progress and
* duration cannot be estimated. * duration cannot be estimated.
* @property {DialogAction} primaryAction an action that will
* be added to the dialog as a button. The primary action can be
* used as the suggested course of action for the user. Making it
* distinct from other actions allows it to be styled differently,
* and treated preferentially in banner mode.
* @property {DialogAction[]} actions a list of actions that will * @property {DialogAction[]} actions a list of actions that will
* be added to the dialog as buttons. These buttons are * be added to the dialog as buttons.
*/ */
/** /**
@ -235,8 +242,17 @@ define(
* @returns {boolean} * @returns {boolean}
*/ */
DialogService.prototype.showBlockingMessage = function(dialogModel) { DialogService.prototype.showBlockingMessage = function(dialogModel) {
if (this.canShowDialog) { if (this.canShowDialog(dialogModel)) {
this.getDialogResponse("overlay-blocking-message", dialogModel, undefined, "t-dialog-sm"); // Add the overlay using the OverlayService, which
// will handle actual insertion into the DOM
this.overlay = this.overlayService.createOverlay(
"overlay-blocking-message",
dialogModel,
"t-dialog-sm"
);
// Track that a dialog is already visible, to
// avoid spawning multiple dialogs at once.
this.dialogVisible = true;
return true; return true;
} else { } else {
return false; return false;

View File

@ -104,7 +104,7 @@
{ {
"key": "BannerController", "key": "BannerController",
"implementation": "controllers/BannerController.js", "implementation": "controllers/BannerController.js",
"depends": ["$scope", "notificationService"] "depends": ["$scope", "notificationService", "dialogService"]
} }
], ],
"directives": [ "directives": [

View File

@ -1,20 +1,18 @@
<div ng-controller="BannerController"> <div ng-controller="BannerController" ng-show="active.notification"
<div ng-show="active.notification" class="l-message-banner s-message-banner" ng-click="maximize(active.notification)">
class="l-message-banner s-message-banner"> <span class="banner-elem label">
<span class="banner-elem label"> {{active.notification.title}}
{{active.notification.title}} </span>
</span> <span ng-hide="active.notification.progress === undefined">
<span ng-hide="active.notification.progress === undefined"> <mct-include key="'progress-bar'" class="banner-elem"
<mct-include key="'progress-bar'" class="banner-elem" ng-model="active.notification">
ng-model="ngModel"> </mct-include>
</mct-include> </span>
</span> <a ng-hide="active.notification.primaryAction === undefined"
<a ng-hide="active.notification.primaryAction === undefined" class="banner-elem l-action s-action"
class="banner-elem l-action s-action" ng-click="active.notification.primaryAction.action()">
ng-click="active.notification.primaryAction.action"> {{active.notification.primaryAction.label}}
{{active.notification.primaryAction.label}} </a>
</a> <a class="banner-elem ui-symbol close" ng-click="dismiss(active.notification)">
<a class="banner-elem ui-symbol close" ng-click="dismiss(active.notification)"> &#x78;</a>
&#x78;</a>
</div>
</div> </div>

View File

@ -25,10 +25,16 @@ define(
[], [],
function () { function () {
"use strict"; "use strict";
function BannerController($scope, notificationService){ function BannerController($scope, notificationService, dialogService) {
$scope.active = notificationService.active; $scope.active = notificationService.active;
$scope.dismiss = function(notification){ $scope.dismiss = function(notification) {
notificationService.dismissOrMinimize(notification); notificationService.dismissOrMinimize(notification);
};
$scope.maximize = function(notification) {
notification.cancel = function(){
dialogService.dismiss();
}
dialogService.showBlockingMessage(notification);
} }
} }
return BannerController; return BannerController;

View File

@ -4,6 +4,10 @@
{ {
"key": "DEFAULT_AUTO_DISMISS", "key": "DEFAULT_AUTO_DISMISS",
"value": 3000 "value": 3000
},
{
"key": "FORCE_AUTO_DISMISS",
"value": 1000
} }
], ],
"controllers": [ "controllers": [
@ -17,7 +21,8 @@
{ {
"key": "notificationService", "key": "notificationService",
"implementation": "NotificationService.js", "implementation": "NotificationService.js",
"depends": [ "$timeout", "DEFAULT_AUTO_DISMISS" ] "depends": [ "$timeout", "DEFAULT_AUTO_DISMISS",
"FORCE_AUTO_DISMISS" ]
} }
] ]
} }

View File

@ -59,7 +59,7 @@ define(
* @property {number} progress The completion status of a task * @property {number} progress The completion status of a task
* represented numerically * represented numerically
* @property {MessageSeverity} messageSeverity The importance of the * @property {MessageSeverity} messageSeverity The importance of the
* message (eg. error, success) * message (eg. error, info)
* @property {boolean} unknownProgress a boolean indicating self the * @property {boolean} unknownProgress a boolean indicating self 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.
@ -84,10 +84,11 @@ define(
* @memberof platform/commonUI/notification * @memberof platform/commonUI/notification
* @constructor * @constructor
*/ */
function NotificationService($timeout, DEFAULT_AUTO_DISMISS) { function NotificationService($timeout, DEFAULT_AUTO_DISMISS, FORCE_AUTO_DISMISS) {
this.notifications = []; this.notifications = [];
this.$timeout = $timeout; this.$timeout = $timeout;
this.DEFAULT_AUTO_DISMISS = DEFAULT_AUTO_DISMISS; this.DEFAULT_AUTO_DISMISS = DEFAULT_AUTO_DISMISS;
this.FORCE_AUTO_DISMISS = FORCE_AUTO_DISMISS;
/* /*
* A context in which to hold the active notification and a * A context in which to hold the active notification and a
@ -105,12 +106,12 @@ define(
}; };
/** /**
* A convenience method for success notifications. Notifications * A convenience method for info notifications. Notifications
* created via this method will be auto-dismissed after a default * created via this method will be auto-dismissed after a default
* wait period * wait period
* @param {Notification} notification The notification to display * @param {Notification} notification The notification to display
*/ */
NotificationService.prototype.success = function (notification) { NotificationService.prototype.info = function (notification) {
notification.autoDismiss = notification.autoDismiss || true; notification.autoDismiss = notification.autoDismiss || true;
notification.severity = MessageSeverity.INFO; notification.severity = MessageSeverity.INFO;
this.notify(notification); this.notify(notification);
@ -145,17 +146,15 @@ define(
If there is already an active notification, time it out. If it's If there is already an active notification, time it out. If it's
already got a timeout in progress (either because it has had already got a timeout in progress (either because it has had
timeout forced because of a queue of messages, or it had an timeout forced because of a queue of messages, or it had an
autodismiss specified), leave it to run. autodismiss specified), leave it to run. Otherwise force a
timeout.
This notifcation has been added to queue and will be This notifcation has been added to queue and will be
serviced as soon as possible. serviced as soon as possible.
*/ */
timeout = notification.autoDismiss ?
notification.autoDismiss :
this.DEFAULT_AUTO_DISMISS;
this.active.timeout = this.$timeout(function () { this.active.timeout = this.$timeout(function () {
self.dismissOrMinimize(self.active.notification); self.dismissOrMinimize(self.active.notification);
}, timeout); }, this.FORCE_AUTO_DISMISS);
} }
}; };
@ -217,7 +216,7 @@ define(
/** /**
* 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 'success' 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 NotificationService#dismissOrMinimize} * use {@link NotificationService#dismissOrMinimize}
* @see dismiss * @see dismiss
@ -236,7 +235,7 @@ define(
/** /**
* 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 success 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 NotificationService#dismissOrMinimize}. * notification, use {@link NotificationService#dismissOrMinimize}.
* dismiss * dismiss

View File

@ -43,7 +43,7 @@ define(
* 3) Calling .notify with autoDismiss results in an ERROR notification * 3) Calling .notify with autoDismiss results in an ERROR notification
* being MINIMIZED after a timeout has elapsed DONE * being MINIMIZED after a timeout has elapsed DONE
* *
* 4) Calling .notify with an active success notification results in that * 4) Calling .notify with an active info notification results in that
* notification being auto-dismissed, and the new notification becoming * notification being auto-dismissed, and the new notification becoming
* active. DONE * active. DONE
* *
@ -80,7 +80,7 @@ define(
mockTimeout, mockAutoDismiss); mockTimeout, mockAutoDismiss);
successModel = { successModel = {
title: "Mock Success Notification", title: "Mock Success Notification",
severity: MessageSeverity.SUCCESS severity: MessageSeverity.INFO
}; };
errorModel = { errorModel = {
title: "Mock Error Notification", title: "Mock Error Notification",
@ -124,11 +124,11 @@ define(
it("auto-dismisses the previously active notification, making" + it("auto-dismisses the previously active notification, making" +
" the new notification active", function() { " the new notification active", function() {
var activeNotification; var activeNotification;
//First pre-load with a success message //First pre-load with a info message
notificationService.notify(successModel); notificationService.notify(successModel);
activeNotification = activeNotification =
notificationService.getActiveNotification(); notificationService.getActiveNotification();
//Initially expect the active notification to be success //Initially expect the active notification to be info
expect(activeNotification).toBe(successModel); expect(activeNotification).toBe(successModel);
//Then notify of an error //Then notify of an error
notificationService.notify(errorModel); notificationService.notify(errorModel);
@ -140,20 +140,20 @@ define(
}); });
it("auto-dismisses an active success notification, removing" + it("auto-dismisses an active success notification, removing" +
" it completely", function() { " it completely", function() {
//First pre-load with a success message //First pre-load with a info message
notificationService.notify(successModel); notificationService.notify(successModel);
//Then notify of an error //Then notify of an error
notificationService.notify(errorModel); notificationService.notify(errorModel);
expect(notificationService.notifications.length).toEqual(2); expect(notificationService.notifications.length).toEqual(2);
mockTimeout.mostRecentCall.args[0](); mockTimeout.mostRecentCall.args[0]();
//Previous success message should be completely dismissed //Previous info message should be completely dismissed
expect(notificationService.notifications.length).toEqual(1); expect(notificationService.notifications.length).toEqual(1);
}); });
it("auto-minimizes an active error notification", function() { it("auto-minimizes an active error notification", function() {
var activeNotification; var activeNotification;
//First pre-load with an error message //First pre-load with an error message
notificationService.notify(errorModel); notificationService.notify(errorModel);
//Then notify of success //Then notify of info
notificationService.notify(successModel); notificationService.notify(successModel);
expect(notificationService.notifications.length).toEqual(2); expect(notificationService.notifications.length).toEqual(2);
//Mock the auto-minimize //Mock the auto-minimize
@ -178,7 +178,7 @@ define(
severity: MessageSeverity.ERROR severity: MessageSeverity.ERROR
}; };
//First pre-load with a success message //First pre-load with a info message
notificationService.notify(errorModel); notificationService.notify(errorModel);
//Then notify of a third error //Then notify of a third error
notificationService.notify(error2); notificationService.notify(error2);

View File

@ -27,6 +27,7 @@
"implementation": "NotificationLaunchController.js", "implementation": "NotificationLaunchController.js",
"depends": [ "depends": [
"$scope", "$scope",
"$timeout",
"notificationService" "notificationService"
] ]
} }

View File

@ -26,10 +26,11 @@ define(
function (MessageSeverity) { function (MessageSeverity) {
"use strict"; "use strict";
function NotificationLaunchController($scope, notificationService) { function NotificationLaunchController($scope, $timeout, notificationService) {
var messageCounter = 1;
$scope.newSuccess = function(){ $scope.newSuccess = function(){
notificationService.success({ notificationService.info({
title: "Success notification!" title: "Success notification!"
}) })
}; };
@ -37,9 +38,14 @@ define(
$scope.newError = function(){ $scope.newError = function(){
notificationService.notify({ notificationService.notify({
title: "Error notification!", title: "Error notification " + messageCounter++ + "!",
severity: MessageSeverity.ERROR severity: MessageSeverity.ERROR,
}) primaryAction: {
label: 'Retry',
action: function() {
console.log('Retry clicked');
}
}});
}; };
$scope.newProgress = function(){ $scope.newProgress = function(){
@ -52,7 +58,17 @@ define(
}; };
notificationService.notify(notification) function incrementProgress(notification) {
notification.progress = Math.min(100, Math.floor(notification.progress + Math.random() * 30));
notification.progressText = ["Estimated time remaining:" +
" about ", 60 - Math.floor((notification.progress / 100) * 60), " seconds"].join(" ");
if (notification.progress < 100) {
$timeout(function(){incrementProgress(notification)}, 1000);
}
}
notificationService.notify(notification);
incrementProgress(notification);
}; };
} }