diff --git a/bundles.json b/bundles.json index a0f7edd7a8..498718fa58 100644 --- a/bundles.json +++ b/bundles.json @@ -29,5 +29,7 @@ "example/imagery", "example/eventGenerator", - "example/generator" + "example/generator", + + "testing/dialogTest" ] diff --git a/platform/commonUI/dialog/bundle.json b/platform/commonUI/dialog/bundle.json index 9a2d541419..eab8fb000a 100644 --- a/platform/commonUI/dialog/bundle.json +++ b/platform/commonUI/dialog/bundle.json @@ -1,5 +1,15 @@ { "extensions": { + "constants": [ + { + "key": "messageSeverity", + "value": { + "ERROR": "error", + "INFO": "info", + "SUCCESS": "success" + } + } + ], "services": [ { "key": "dialogService", @@ -24,6 +34,10 @@ { "key": "form-dialog", "templateUrl": "templates/dialog.html" + }, + { + "key": "blocking-message", + "templateUrl": "templates/blocking-message.html" } ], "containers": [ diff --git a/platform/commonUI/dialog/res/templates/blocking-message.html b/platform/commonUI/dialog/res/templates/blocking-message.html new file mode 100644 index 0000000000..81a183eb13 --- /dev/null +++ b/platform/commonUI/dialog/res/templates/blocking-message.html @@ -0,0 +1,30 @@ + + +
+
{{ngModel.dialog.title}}
+
+
+
+
{{ngModel.dialog.hint}}
+
+
{{ngModel.dialog.progress}} %
+
{{ngModel.dialog.progressText}}
+
+
+
+ +
+
\ No newline at end of file diff --git a/platform/commonUI/dialog/src/DialogService.js b/platform/commonUI/dialog/src/DialogService.js index 25e8943c06..94c8e24844 100644 --- a/platform/commonUI/dialog/src/DialogService.js +++ b/platform/commonUI/dialog/src/DialogService.js @@ -84,17 +84,7 @@ define( model.confirm = confirm; model.cancel = cancel; - if (this.dialogVisible) { - // Only one dialog should be shown at a time. - // The application design should be such that - // we never even try to do this. - this.$log.warn([ - "Dialog already showing; ", - "unable to show ", - model.name - ].join("")); - deferred.reject(); - } else { + if (this.canShowDialog(model)) { // Add the overlay using the OverlayService, which // will handle actual insertion into the DOM this.overlay = this.overlayService.createOverlay( @@ -105,6 +95,8 @@ define( // Track that a dialog is already visible, to // avoid spawning multiple dialogs at once. this.dialogVisible = true; + } else { + deferred.reject(); } return deferred.promise; @@ -157,6 +149,104 @@ define( ); }; + /** + * Tests if a dialog can be displayed. A modal dialog may only be + * displayed if one is not already visible. + * Will log a warning message if it can't display a dialog. + * @returns {boolean} true if dialog is currently visible, false + * otherwise + */ + DialogService.prototype.canShowDialog = function(dialogModel){ + if (this.dialogVisible){ + // Only one dialog should be shown at a time. + // The application design should be such that + // we never even try to do this. + this.$log.warn([ + "Dialog already showing; ", + "unable to show ", + dialogModel.title + ].join("")); + + return false; + } else { + return true; + } + }; + + /** + * dialogModel: { + * severity: string "error" | "info", + * title: string, + * hint: string, + * progress: int, + * progressText: string, + * unknownProgress: boolean, + * actions: [{ + * label: String, + * action: function + * }] + */ + + /** + * A user action that can be performed from a blocking dialog. These + * actions will be rendered as buttons within a blocking dialog. + * + * @typedef DialogAction + * @property {string} label a label to be displayed as the button + * text for this action + * @property {function} action a function to be called when the + * button is clicked + */ + + /** + * A description of the model options that may be passed to the + * showBlockingMessage method + * + * @typedef DialogModel + * @property {string} severity the severity level of this message. + * These are defined in a bundle constant with key 'dialogSeverity' + * @property {string} title the title to use for the dialog + * @property {string} hint the 'hint' message to show below the title + * @property {number} progress a percentage value (1-100) + * indicating the completion of the blocking task + * @property {string} progressText the message to show below a + * progress bar to indicate progress. For example, this might be + * used to indicate time remaining, or items still to process. + * @property {boolean} unknownProgress some tasks may be + * impossible to provide an estimate for. Providing a true value for + * this attribute will indicate to the user that the progress and + * duration cannot be estimated. + * @property {DialogAction[]} actions a list of actions that will + * be added to the dialog as buttons. These buttons are + */ + + /** + * Displays a blocking (modal) dialog. This dialog can be used for + * displaying messages that require the user's + * immediate attention. The message may include an indication of + * progress, as well as a series of actions that + * the user can take if necessary + * @param {DialogModel} dialogModel defines options for the dialog + * @returns {boolean} + */ + DialogService.prototype.showBlockingMessage = function(dialogModel) { + if (this.canShowDialog(dialogModel)) { + // Add the overlay using the OverlayService, which + // will handle actual insertion into the DOM + this.overlay = this.overlayService.createOverlay( + "blocking-message", + {dialog: dialogModel} + ); + this.dialogVisible = true; + return true; + } else { + //Could not show a dialog, so return indication of this to + //client code. + return false; + } + + }; + return DialogService; } diff --git a/testing/dialogTest/bundle.json b/testing/dialogTest/bundle.json new file mode 100644 index 0000000000..36ec16e048 --- /dev/null +++ b/testing/dialogTest/bundle.json @@ -0,0 +1,28 @@ +{ + "extensions": { + "templates": [ + { + "key": "dialogLaunchTemplate", + "templateUrl": "dialog-launch.html" + } + ], + "controllers": [ + { + "key": "DialogLaunchController", + "implementation": "DialogLaunchController.js", + "depends": [ + "$scope", + "dialogService", + "$timeout", + "$log", + "messageSeverity" + ] + } + ], + "indicators": [ + { + "implementation": "DialogLaunchIndicator.js" + } + ] + } +} diff --git a/testing/dialogTest/res/dialog-launch.html b/testing/dialogTest/res/dialog-launch.html new file mode 100644 index 0000000000..b9d0d525ea --- /dev/null +++ b/testing/dialogTest/res/dialog-launch.html @@ -0,0 +1 @@ +   \ No newline at end of file diff --git a/testing/dialogTest/src/DialogLaunchController.js b/testing/dialogTest/src/DialogLaunchController.js new file mode 100644 index 0000000000..bc088274e9 --- /dev/null +++ b/testing/dialogTest/src/DialogLaunchController.js @@ -0,0 +1,94 @@ +/***************************************************************************** + * 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*/ + +define( + [], + function () { + "use strict"; + + function DialogLaunchController($scope, dialogService, $timeout, $log, messageSeverity) { + $scope.launchProgress = function () { + var model = { + title: "Progress dialog example", + progress: 0, + hint: "Calculating...", + unknownDuration: false, + severity: messageSeverity.INFO, + actions: [ + { + label: "Cancel Operation", + action: function () { + $log.debug("Operation cancelled"); + dialogService.dismiss(); + } + }, + { + label: "Do something else...", + action: function () { + $log.debug("Something else pressed"); + } + } + ] + }; + + function incrementProgress() { + model.progress = Math.min(100, Math.floor(model.progress + Math.random() * 30)); + model.progressText = ["Estimated time remaining: about ", 60 - Math.floor((model.progress / 100) * 60), " seconds"].join(" "); + if (model.progress < 100) { + $timeout(incrementProgress, 1000); + } + } + + if (dialogService.showBlockingMessage(model)) { + //Do processing here + model.hint = "Processing 100 objects..."; + $timeout(incrementProgress, 1000); + } else { + $log.error("Could not display modal dialog"); + } + }; + + $scope.launchError = function () { + var model = { + title: "Error Message Title", + hint: "Something happened. It was not so good.", + severity: messageSeverity.ERROR, + actions: [ + { + label: "OK", + action: function () { + $log.debug("OK Pressed"); + dialogService.dismiss(); + } + } + ] + }; + + if (!dialogService.showBlockingMessage(model)) { + $log.error("Could not display modal dialog"); + } + }; + } + return DialogLaunchController; + } +); diff --git a/testing/dialogTest/src/DialogLaunchIndicator.js b/testing/dialogTest/src/DialogLaunchIndicator.js new file mode 100644 index 0000000000..47c516fc70 --- /dev/null +++ b/testing/dialogTest/src/DialogLaunchIndicator.js @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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,window*/ + +define( + [], + function () { + "use strict"; + + function DialogLaunchIndicator() { + + } + + DialogLaunchIndicator.template = 'dialogLaunchTemplate'; + + DialogLaunchIndicator.prototype.getGlyph = function () { + return "i"; + }; + DialogLaunchIndicator.prototype.getGlyphClass = function () { + return 'caution'; + }; + DialogLaunchIndicator.prototype.getText = function () { + return "Launch test dialog"; + }; + DialogLaunchIndicator.prototype.getDescription = function () { + return "Launch test dialog"; + }; + + return DialogLaunchIndicator; + } +);