mirror of
https://github.com/nasa/openmct.git
synced 2025-06-15 13:48:12 +00:00
Notifications progress method (#2193)
* Added progress method to notifications so no longer dependent on reactive properties * Updated notification launch controller to use new progress method * Added progress function to Notifications API. Introduced NotificationService compatibility layer for legacy code
This commit is contained in:
committed by
Deep Tailor
parent
c3b7e7869e
commit
6f1b5b4ae3
@ -79,30 +79,34 @@ define(
|
|||||||
* periodically, tracking an ongoing process.
|
* periodically, tracking an ongoing process.
|
||||||
*/
|
*/
|
||||||
$scope.newProgress = function () {
|
$scope.newProgress = function () {
|
||||||
|
let progress = 0;
|
||||||
var notificationModel = {
|
var notificationModel = {
|
||||||
title: "Progress notification example",
|
title: "Progress notification example",
|
||||||
severity: "info",
|
severity: "info",
|
||||||
progress: 0,
|
progress: progress,
|
||||||
actionText: getExampleActionText()
|
actionText: getExampleActionText()
|
||||||
};
|
};
|
||||||
|
let notification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulate an ongoing process and update the progress bar.
|
* Simulate an ongoing process and update the progress bar.
|
||||||
* @param notification
|
* @param notification
|
||||||
*/
|
*/
|
||||||
function incrementProgress() {
|
function incrementProgress() {
|
||||||
notificationModel.progress = Math.min(100, Math.floor(notificationModel.progress + Math.random() * 30));
|
progress = Math.min(100, Math.floor(progress + Math.random() * 30))
|
||||||
notificationModel.progressText = ["Estimated time" +
|
let progressText = ["Estimated time" +
|
||||||
" remaining:" +
|
" remaining:" +
|
||||||
" about ", 60 - Math.floor((notificationModel.progress / 100) * 60), " seconds"].join(" ");
|
" about ", 60 - Math.floor((progress / 100) * 60), " seconds"].join(" ");
|
||||||
if (notificationModel.progress < 100) {
|
notification.progress(progress, progressText);
|
||||||
|
|
||||||
|
if (progress < 100) {
|
||||||
$timeout(function () {
|
$timeout(function () {
|
||||||
incrementProgress(notificationModel);
|
incrementProgress(notificationModel);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationService.notify(notificationModel);
|
notification = notificationService.notify(notificationModel);
|
||||||
incrementProgress();
|
incrementProgress();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,31 +2,14 @@
|
|||||||
ng-class="'message-severity-' + ngModel.severity">
|
ng-class="'message-severity-' + ngModel.severity">
|
||||||
<div class="w-message-contents">
|
<div class="w-message-contents">
|
||||||
<div class="top-bar">
|
<div class="top-bar">
|
||||||
<div class="title">{{ngModel.title}}</div>
|
<div class="title">{{ngModel.message}}</div>
|
||||||
</div>
|
|
||||||
<div class="hint" ng-hide="ngModel.hint === undefined">
|
|
||||||
{{ngModel.hint}}
|
|
||||||
<span ng-if="ngModel.timestamp !== undefined">[{{ngModel.timestamp}}]</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
<div class="message-action">
|
|
||||||
{{ngModel.actionText}}
|
|
||||||
</div>
|
|
||||||
<mct-include key="'progress-bar'"
|
<mct-include key="'progress-bar'"
|
||||||
ng-model="ngModel"
|
ng-model="ngModel"
|
||||||
ng-show="ngModel.progress !== undefined || ngModel.unknownProgress"></mct-include>
|
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom-bar">
|
<div class="bottom-bar">
|
||||||
<a ng-repeat="dialogOption in ngModel.options"
|
|
||||||
class="s-button"
|
|
||||||
ng-click="dialogOption.callback()">
|
|
||||||
{{dialogOption.label}}
|
|
||||||
</a>
|
|
||||||
<a class="s-button major"
|
|
||||||
ng-if="ngModel.primaryOption"
|
|
||||||
ng-click="ngModel.primaryOption.callback()">
|
|
||||||
{{ngModel.primaryOption.label}}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<span class="l-progress-bar s-progress-bar"
|
<span class="l-progress-bar s-progress-bar"
|
||||||
ng-class="{ indeterminate:ngModel.unknownProgress }">
|
ng-class="{ indeterminate:ngModel.progressPerc === 'unknown' }">
|
||||||
<span class="progress-amt-holder">
|
<span class="progress-amt-holder">
|
||||||
<span class="progress-amt" style="width: {{ngModel.progress}}%"></span>
|
<span class="progress-amt" style="width: {{ngModel.progressPerc === 'unknown' ? 100 : ngModel.progressPerc}}%"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<div class="progress-info hint" ng-hide="ngModel.progressText === undefined">
|
<div class="progress-info hint" ng-hide="ngModel.progressText === undefined">
|
||||||
<span class="progress-amt-text" ng-show="ngModel.progress > 0">{{ngModel.progress}}% complete. </span>
|
<span class="progress-amt-text" ng-show="ngModel.progressPerc !== 'unknown' && ngModel.progressPerc > 0">{{ngModel.progressPerc}}% complete. </span>
|
||||||
{{ngModel.progressText}}
|
{{ngModel.progressText}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,7 +50,7 @@ define(
|
|||||||
};
|
};
|
||||||
$scope.dismiss = function (notification, $event) {
|
$scope.dismiss = function (notification, $event) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
notification.dismissOrMinimize();
|
notification.dismiss();
|
||||||
};
|
};
|
||||||
$scope.maximize = function (notification) {
|
$scope.maximize = function (notification) {
|
||||||
if (notification.model.severity !== "info") {
|
if (notification.model.severity !== "info") {
|
||||||
|
@ -23,11 +23,13 @@
|
|||||||
define([
|
define([
|
||||||
"./src/NotificationIndicatorController",
|
"./src/NotificationIndicatorController",
|
||||||
"./src/NotificationIndicator",
|
"./src/NotificationIndicator",
|
||||||
|
"./src/NotificationService",
|
||||||
"./res/notification-indicator.html",
|
"./res/notification-indicator.html",
|
||||||
'legacyRegistry'
|
'legacyRegistry'
|
||||||
], function (
|
], function (
|
||||||
NotificationIndicatorController,
|
NotificationIndicatorController,
|
||||||
NotificationIndicator,
|
NotificationIndicator,
|
||||||
|
NotificationService,
|
||||||
notificationIndicatorTemplate,
|
notificationIndicatorTemplate,
|
||||||
legacyRegistry
|
legacyRegistry
|
||||||
) {
|
) {
|
||||||
@ -46,7 +48,7 @@ define([
|
|||||||
"implementation": NotificationIndicatorController,
|
"implementation": NotificationIndicatorController,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$scope",
|
"$scope",
|
||||||
"notificationService",
|
"openmct",
|
||||||
"dialogService"
|
"dialogService"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -61,7 +63,7 @@ define([
|
|||||||
{
|
{
|
||||||
"key": "notificationService",
|
"key": "notificationService",
|
||||||
"implementation": function (openmct) {
|
"implementation": function (openmct) {
|
||||||
return openmct.notifications;
|
return new NotificationService.default(openmct);
|
||||||
},
|
},
|
||||||
"depends": [
|
"depends": [
|
||||||
"openmct"
|
"openmct"
|
||||||
|
@ -35,9 +35,9 @@ define(
|
|||||||
* @param dialogService
|
* @param dialogService
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function NotificationIndicatorController($scope, notificationService, dialogService) {
|
function NotificationIndicatorController($scope, openmct, dialogService) {
|
||||||
$scope.notifications = notificationService.notifications;
|
$scope.notifications = openmct.notifications.notifications;
|
||||||
$scope.highest = notificationService.highest;
|
$scope.highest = openmct.notifications.highest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch a dialog showing a list of current notifications.
|
* Launch a dialog showing a list of current notifications.
|
||||||
@ -48,7 +48,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
|
messages: openmct.notifications.notifications
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
64
platform/commonUI/notification/src/NotificationService.js
Normal file
64
platform/commonUI/notification/src/NotificationService.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
export default class NotificationService {
|
||||||
|
constructor(openmct) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
}
|
||||||
|
info(message) {
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
return this.openmct.notifications.info(message);
|
||||||
|
} else {
|
||||||
|
if (message.hasOwnProperty('progress')) {
|
||||||
|
return this.openmct.notifications.progress(message.title, message.progress, message.progressText);
|
||||||
|
} else {
|
||||||
|
return this.openmct.notifications.info(message.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alert(message) {
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
return this.openmct.notifications.alert(message);
|
||||||
|
} else {
|
||||||
|
return this.openmct.notifications.alert(message.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error(message) {
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
return this.openmct.notifications.error(message);
|
||||||
|
} else {
|
||||||
|
return this.openmct.notifications.error(message.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notify(options) {
|
||||||
|
switch (options.severity) {
|
||||||
|
case 'info':
|
||||||
|
return this.info(options);
|
||||||
|
case 'alert':
|
||||||
|
return this.alert(options);
|
||||||
|
case 'error':
|
||||||
|
return this.error(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getAllNotifications() {
|
||||||
|
return this.openmct.notifications.notifications;
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
import EventEmitter from 'EventEmitter';
|
|
||||||
export default class MCTNotification extends EventEmitter {
|
|
||||||
|
|
||||||
constructor(notificationModel, notificationAPI) {
|
|
||||||
super();
|
|
||||||
this.notifications = notificationAPI;
|
|
||||||
this.model = notificationModel;
|
|
||||||
this.initializeModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
minimize() {
|
|
||||||
this.notifications.minimize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
dismiss() {
|
|
||||||
this.notifications.dismiss(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
dismissOrMinimize() {
|
|
||||||
this.notifications.dismissOrMinimize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeModel() {
|
|
||||||
this.model.minimized = this.model.minimized || false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,7 +32,6 @@
|
|||||||
*/
|
*/
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import EventEmitter from 'EventEmitter';
|
import EventEmitter from 'EventEmitter';
|
||||||
import MCTNotification from './MCTNotification.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of a banner notification. Banner notifications
|
* A representation of a banner notification. Banner notifications
|
||||||
@ -42,20 +41,11 @@ import MCTNotification from './MCTNotification.js';
|
|||||||
* and then minimized to a banner notification if needed, or vice-versa.
|
* and then minimized to a banner notification if needed, or vice-versa.
|
||||||
*
|
*
|
||||||
* @typedef {object} NotificationModel
|
* @typedef {object} NotificationModel
|
||||||
* @property {string} title The title of the message
|
* @property {string} message The message to be displayed by the notification
|
||||||
* @property {string} severity The importance of the message (one of
|
* @property {number | 'unknown'} [progress] The progres of some ongoing task. Should be a number between 0 and 100, or
|
||||||
* 'info', 'alert', or 'error' where info < alert <error)
|
* with the string literal 'unknown'.
|
||||||
* @property {number} [progress] The completion status of a task
|
* @property {string} [progressText] A message conveying progress of some ongoing task.
|
||||||
* represented numerically
|
|
||||||
* @property {boolean} [unknownProgress] a boolean indicating that the
|
|
||||||
* progress of the underlying task is unknown. This will result in a
|
|
||||||
* visually distinct progress bar.
|
|
||||||
* @property {boolean} [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 {boolean} [dismissable=true] If true, notification will
|
|
||||||
* include an option to dismiss it completely.
|
|
||||||
* @see DialogModel
|
* @see DialogModel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -65,14 +55,9 @@ const MINIMIZE_ANIMATION_TIMEOUT = 300;
|
|||||||
/**
|
/**
|
||||||
* The notification service is responsible for informing the user of
|
* The notification service is responsible for informing the user of
|
||||||
* events via the use of banner notifications.
|
* events via the use of banner notifications.
|
||||||
* @memberof platform/commonUI/notification
|
* @memberof ui/notification
|
||||||
* @constructor
|
* @constructor */
|
||||||
* @param defaultAutoDismissTimeout The period of time that an
|
|
||||||
* auto-dismissed message will be displayed for.
|
|
||||||
* @param minimizeAnimationTimeout When notifications are minimized, a brief
|
|
||||||
* animation is shown. This animation requires some time to execute,
|
|
||||||
* so a timeout is required before the notification is hidden
|
|
||||||
*/
|
|
||||||
export default class NotificationAPI extends EventEmitter {
|
export default class NotificationAPI extends EventEmitter {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -86,16 +71,72 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
this.activeNotification = undefined;
|
this.activeNotification = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info notifications are low priority informational messages for the user. They will be auto-destroy after a brief
|
||||||
|
* period of time.
|
||||||
|
* @param {string} message The message to display to the user
|
||||||
|
* @returns {InfoNotification}
|
||||||
|
*/
|
||||||
|
info(message) {
|
||||||
|
let notificationModel = {
|
||||||
|
message: message,
|
||||||
|
autoDismiss: true,
|
||||||
|
severity: "info"
|
||||||
|
}
|
||||||
|
return this._notify(notificationModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Present an alert to the user.
|
||||||
|
* @param {string} message The message to display to the user.
|
||||||
|
* @returns {Notification}
|
||||||
|
*/
|
||||||
|
alert(message) {
|
||||||
|
let notificationModel = {
|
||||||
|
message: message,
|
||||||
|
severity: "alert"
|
||||||
|
}
|
||||||
|
return this._notify(notificationModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Present an error message to the user
|
||||||
|
* @param {string} message
|
||||||
|
* @returns {Notification}
|
||||||
|
*/
|
||||||
|
error(message) {
|
||||||
|
let notificationModel = {
|
||||||
|
message: message,
|
||||||
|
severity: "error"
|
||||||
|
}
|
||||||
|
return this._notify(notificationModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress notification. These notifications will contain a progress bar.
|
||||||
|
* @param {string} message
|
||||||
|
* @param {number | 'unknown'} progressPerc A value between 0 and 100, or the string 'unknown'.
|
||||||
|
* @param {string} [progressText] Text description of progress (eg. "10 of 20 objects copied").
|
||||||
|
*/
|
||||||
|
progress(message, progressPerc, progressText) {
|
||||||
|
let notificationModel = {
|
||||||
|
message: message,
|
||||||
|
progressPerc: progressPerc,
|
||||||
|
progressText: progressText,
|
||||||
|
severity: "info"
|
||||||
|
}
|
||||||
|
return this._notify(notificationModel);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* use {@link Notification#dismissOrMinimize}
|
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
minimize(notification) {
|
_minimize(notification) {
|
||||||
//Check this is a known notification
|
//Check this is a known notification
|
||||||
let index = this.notifications.indexOf(notification);
|
let index = this.notifications.indexOf(notification);
|
||||||
|
|
||||||
@ -114,11 +155,12 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
notification.model.minimized = true;
|
notification.model.minimized = true;
|
||||||
|
notification.emit('minimized');
|
||||||
//Add a brief timeout before showing the next notification
|
//Add a brief timeout before showing the next notification
|
||||||
// in order to allow the minimize animation to run through.
|
// in order to allow the minimize animation to run through.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.emit('destroy');
|
notification.emit('destroy');
|
||||||
this.setActiveNotification(this.selectNextNotification());
|
this._setActiveNotification(this._selectNextNotification());
|
||||||
}, MINIMIZE_ANIMATION_TIMEOUT);
|
}, MINIMIZE_ANIMATION_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +175,7 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
dismiss(notification) {
|
_dismiss(notification) {
|
||||||
//Check this is a known notification
|
//Check this is a known notification
|
||||||
let index = this.notifications.indexOf(notification);
|
let index = this.notifications.indexOf(notification);
|
||||||
|
|
||||||
@ -153,8 +195,8 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this.notifications.splice(index, 1);
|
this.notifications.splice(index, 1);
|
||||||
}
|
}
|
||||||
this.setActiveNotification(this.selectNextNotification());
|
this._setActiveNotification(this._selectNextNotification());
|
||||||
this.setHighestSeverity();
|
this._setHighestSeverity();
|
||||||
notification.emit('destroy');
|
notification.emit('destroy');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,81 +206,19 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
dismissOrMinimize(notification) {
|
_dismissOrMinimize(notification) {
|
||||||
let model = notification.model;
|
let model = notification.model;
|
||||||
if (model.severity === "info") {
|
if (model.severity === "info") {
|
||||||
if (model.autoDismiss === false) {
|
this._dismiss(notification);
|
||||||
this.minimize(notification);
|
|
||||||
} else {
|
} else {
|
||||||
this.dismiss(notification);
|
this._minimize(notification);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.minimize(notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the notification that is currently visible in the banner area
|
|
||||||
* @returns {Notification}
|
|
||||||
*/
|
|
||||||
getActiveNotification() {
|
|
||||||
return this.activeNotification;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience method for info notifications. Notifications
|
|
||||||
* created via this method will be auto-destroy after a default
|
|
||||||
* wait period unless explicitly forbidden by the caller through
|
|
||||||
* the {autoDismiss} property on the {NotificationModel}, in which
|
|
||||||
* case the notification will be minimized after the wait.
|
|
||||||
* @param {NotificationModel | string} message either a string for
|
|
||||||
* the title of the notification message, or a {@link NotificationModel}
|
|
||||||
* defining the options notification to display
|
|
||||||
* @returns {Notification} the provided notification decorated with
|
|
||||||
* functions to dismiss or minimize
|
|
||||||
*/
|
|
||||||
info(message) {
|
|
||||||
let notificationModel = typeof message === "string" ? {title: message} : message;
|
|
||||||
notificationModel.severity = "info";
|
|
||||||
return this.notify(notificationModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience method for alert notifications. Notifications
|
|
||||||
* created via this method will will have severity of "alert" enforced
|
|
||||||
* @param {NotificationModel | string} message either a string for
|
|
||||||
* the title of the alert message with default options, or a
|
|
||||||
* {@link NotificationModel} defining the options notification to
|
|
||||||
* display
|
|
||||||
* @returns {Notification} the provided notification decorated with
|
|
||||||
* functions to dismiss or minimize
|
|
||||||
*/
|
|
||||||
alert(message) {
|
|
||||||
let notificationModel = typeof message === "string" ? {title: message} : message;
|
|
||||||
notificationModel.severity = "alert";
|
|
||||||
return this.notify(notificationModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience method for error notifications. Notifications
|
|
||||||
* created via this method will will have severity of "error" enforced
|
|
||||||
* @param {NotificationModel | string} message either a string for
|
|
||||||
* the title of the error message with default options, or a
|
|
||||||
* {@link NotificationModel} defining the options of the notification to
|
|
||||||
* display
|
|
||||||
* @returns {Notification} the provided notification decorated with
|
|
||||||
* functions to dismiss or minimize
|
|
||||||
*/
|
|
||||||
error(message) {
|
|
||||||
let notificationModel = typeof message === "string" ? {title: message} : message;
|
|
||||||
notificationModel.severity = "error";
|
|
||||||
return this.notify(notificationModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
setHighestSeverity() {
|
_setHighestSeverity() {
|
||||||
let severity = {
|
let severity = {
|
||||||
"info": 1,
|
"info": 1,
|
||||||
"alert": 2,
|
"alert": 2,
|
||||||
@ -263,23 +243,23 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
* @returns {Notification} the provided notification decorated with
|
* @returns {Notification} the provided notification decorated with
|
||||||
* functions to {@link Notification#dismiss} or {@link Notification#minimize}
|
* functions to {@link Notification#dismiss} or {@link Notification#minimize}
|
||||||
*/
|
*/
|
||||||
notify(notificationModel) {
|
_notify(notificationModel) {
|
||||||
let notification;
|
let notification;
|
||||||
let activeNotification = this.activeNotification;
|
let activeNotification = this.activeNotification;
|
||||||
|
|
||||||
notificationModel.severity = notificationModel.severity || "info";
|
notificationModel.severity = notificationModel.severity || "info";
|
||||||
notificationModel.timestamp = moment.utc().format('YYYY-MM-DD hh:mm:ss.ms');
|
notificationModel.timestamp = moment.utc().format('YYYY-MM-DD hh:mm:ss.ms');
|
||||||
|
|
||||||
notification = new MCTNotification(notificationModel, this);
|
notification = this._createNotification(notificationModel);
|
||||||
|
|
||||||
this.notifications.push(notification);
|
this.notifications.push(notification);
|
||||||
this.setHighestSeverity();
|
this._setHighestSeverity();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if there is already an active (ie. visible) notification
|
Check if there is already an active (ie. visible) notification
|
||||||
*/
|
*/
|
||||||
if (!this.activeNotification) {
|
if (!this.activeNotification) {
|
||||||
this.setActiveNotification(notification);
|
this._setActiveNotification(notification);
|
||||||
} else if (!this.activeTimeout) {
|
} else if (!this.activeTimeout) {
|
||||||
/*
|
/*
|
||||||
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
|
||||||
@ -292,7 +272,7 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
serviced as soon as possible.
|
serviced as soon as possible.
|
||||||
*/
|
*/
|
||||||
this.activeTimeout = setTimeout(() => {
|
this.activeTimeout = setTimeout(() => {
|
||||||
this.dismissOrMinimize(activeNotification);
|
this._dismissOrMinimize(activeNotification);
|
||||||
}, DEFAULT_AUTO_DISMISS_TIMEOUT);
|
}, DEFAULT_AUTO_DISMISS_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,11 +280,30 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally by the NotificationService
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
setActiveNotification(notification) {
|
_createNotification(notificationModel) {
|
||||||
let shouldAutoDismiss;
|
let notification = new EventEmitter();
|
||||||
|
notification.model = notificationModel;
|
||||||
|
notification.dismiss = () => {
|
||||||
|
this._dismiss(notification);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (notificationModel.hasOwnProperty('progressPerc')) {
|
||||||
|
notification.progress = (progressPerc, progressText) => {
|
||||||
|
notification.model.progressPerc = progressPerc;
|
||||||
|
notification.model.progressText = progressText;
|
||||||
|
notification.emit('progress', progressPerc, progressText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_setActiveNotification(notification) {
|
||||||
this.activeNotification = notification;
|
this.activeNotification = notification;
|
||||||
|
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
@ -313,15 +312,9 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
}
|
}
|
||||||
this.emit('notification', notification);
|
this.emit('notification', notification);
|
||||||
|
|
||||||
if (notification.model.severity === "info") {
|
if (notification.model.autoDismiss || this._selectNextNotification()) {
|
||||||
shouldAutoDismiss = true;
|
|
||||||
} else {
|
|
||||||
shouldAutoDismiss = notification.model.autoDismiss;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldAutoDismiss || this.selectNextNotification()) {
|
|
||||||
this.activeTimeout = setTimeout(() => {
|
this.activeTimeout = setTimeout(() => {
|
||||||
this.dismissOrMinimize(notification);
|
this._dismissOrMinimize(notification);
|
||||||
}, DEFAULT_AUTO_DISMISS_TIMEOUT);
|
}, DEFAULT_AUTO_DISMISS_TIMEOUT);
|
||||||
} else {
|
} else {
|
||||||
delete this.activeTimeout;
|
delete this.activeTimeout;
|
||||||
@ -333,7 +326,7 @@ export default class NotificationAPI extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
selectNextNotification() {
|
_selectNextNotification() {
|
||||||
let notification;
|
let notification;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
|
@ -24,18 +24,18 @@
|
|||||||
'minimized': activeModel.minimized,
|
'minimized': activeModel.minimized,
|
||||||
'new': !activeModel.minimized
|
'new': !activeModel.minimized
|
||||||
}]"
|
}]"
|
||||||
v-if="activeModel">
|
v-if="activeModel.message">
|
||||||
<span @click="maximize()" class="banner-elem label">{{activeModel.title}}</span>
|
<span @click="maximize()" class="banner-elem label">{{activeModel.message}}</span>
|
||||||
<span @click="maximize()" v-if="activeModel.progress !== undefined || activeModel.unknownProgress">
|
<span @click="maximize()" v-if="activeModel.progressPerc !== undefined">
|
||||||
<div class="banner-elem"><!-- was mct-include -->
|
<div class="banner-elem"><!-- was mct-include -->
|
||||||
<span class="l-progress-bar s-progress-bar"
|
<span class="l-progress-bar s-progress-bar"
|
||||||
:class="{'indeterminate': activeModel.unknownProgress }">
|
:class="{'indeterminate': activeModel.progressPerc === 'unknown' }">
|
||||||
<span class="progress-amt-holder">
|
<span class="progress-amt-holder">
|
||||||
<span class="progress-amt" :style="progressWidth"></span>
|
<span class="progress-amt" :style="progressWidth"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<div class="progress-info hint" v-if="activeModel.progressText !== undefined">
|
<div class="progress-info hint" v-if="activeModel.progressText !== undefined">
|
||||||
<span class="progress-amt-text" v-if="activeModel.progress > 0">{{activeModel.progress}}% complete. </span>
|
<span class="progress-amt-text" v-if="activeModel.progressPerc > 0">{{activeModel.progressPerc}}% complete. </span>
|
||||||
{{activeModel.progressText}}
|
{{activeModel.progressText}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -62,22 +62,59 @@
|
|||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeModel: undefined
|
activeModel: {
|
||||||
|
message: undefined,
|
||||||
|
progressPerc: undefined,
|
||||||
|
progressText: undefined,
|
||||||
|
minimized: undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showNotification(notification) {
|
showNotification(notification) {
|
||||||
activeNotification = notification;
|
if (activeNotification) {
|
||||||
this.activeModel = notification.model;
|
activeNotification.off('progress', this.updateProgress);
|
||||||
activeNotification.once('destroy', () => {
|
activeNotification.off('minimized', this.minimized);
|
||||||
if (this.activeModel === notification.model){
|
activeNotification.off('destroy', this.destroyActiveNotification);
|
||||||
this.activeModel = undefined;
|
|
||||||
activeNotification = undefined;
|
|
||||||
}
|
}
|
||||||
});
|
activeNotification = notification;
|
||||||
|
this.clearModel();
|
||||||
|
this.applyModel(notification.model);
|
||||||
|
|
||||||
|
activeNotification.once('destroy', this.destroyActiveNotification);
|
||||||
|
activeNotification.on('progress', this.updateProgress);
|
||||||
|
activeNotification.on('minimized', this.minimized);
|
||||||
|
},
|
||||||
|
isEqual(modelA, modelB) {
|
||||||
|
return modelA.message === modelB.message &&
|
||||||
|
modelA.timestamp === modelB.timestamp;
|
||||||
|
},
|
||||||
|
applyModel(model) {
|
||||||
|
Object.keys(model).forEach((key) => this.activeModel[key] = model[key]);
|
||||||
|
},
|
||||||
|
clearModel() {
|
||||||
|
Object.keys(this.activeModel).forEach((key) => this.activeModel[key] = undefined);
|
||||||
|
},
|
||||||
|
updateProgress(progressPerc, progressText) {
|
||||||
|
this.activeModel.progressPerc = progressPerc;
|
||||||
|
this.activeModel.progressText = progressText;
|
||||||
|
},
|
||||||
|
destroyActiveNotification() {
|
||||||
|
this.clearModel();
|
||||||
|
activeNotification = undefined;
|
||||||
},
|
},
|
||||||
dismiss() {
|
dismiss() {
|
||||||
activeNotification.dismissOrMinimize();
|
if (activeNotification.model.severity === 'info') {
|
||||||
|
activeNotification.dismiss();
|
||||||
|
} else {
|
||||||
|
this.openmct.notifications._minimize(activeNotification);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
minimized() {
|
||||||
|
this.activeModel.minimized = true;
|
||||||
|
activeNotification.off('progress', this.updateProgress);
|
||||||
|
activeNotification.off('minimized', this.minimized);
|
||||||
|
activeNotification.off('destroy', this.destroyActiveNotification);
|
||||||
},
|
},
|
||||||
maximize() {
|
maximize() {
|
||||||
//Not implemented yet.
|
//Not implemented yet.
|
||||||
|
Reference in New Issue
Block a user