diff --git a/guacamole/src/main/webapp/app/index/controllers/indexController.js b/guacamole/src/main/webapp/app/index/controllers/indexController.js index 4a5b26ce3..5854cf7ff 100644 --- a/guacamole/src/main/webapp/app/index/controllers/indexController.js +++ b/guacamole/src/main/webapp/app/index/controllers/indexController.js @@ -50,6 +50,21 @@ angular.module('index').controller('indexController', ['$scope', '$injector', } }; + /** + * The current status notification, or false if no status is currently + * shown. + * + * @type Notification|Boolean + */ + $scope.status = false; + + /** + * All currently-visible notifications. + * + * @type Notification[] + */ + $scope.notifications = []; + // Put some useful variables in the top level scope $scope.page = { title: '', @@ -59,7 +74,6 @@ angular.module('index').controller('indexController', ['$scope', '$injector', $scope.currentUserIsAdmin = false; $scope.currentUserHasUpdate = false; $scope.currentUserPermissions = null; - $scope.notifications = []; var notificationUniqueID = 0; // A promise to be fulfilled when all basic user permissions are loaded. @@ -77,41 +91,8 @@ angular.module('index').controller('indexController', ['$scope', '$injector', * notification is currently shown, no further statuses will be shown * until the current status is hidden. * - * @param {Object} status The status notification to show. - * @param {String} [status.title] The title of the notification. - * @param {String} [status.text] The body text of the notification. - * @param {String} [status.className] The CSS class name to apply. - * - * @param {String} [status.countdown.text] - * In the case that a countdown applies to the notification, the text to - * display while the countdown is active. - * - * @param {Function} [status.countdown.callback] - * The callback to call when the countdown expires. - * - * @param {String} [status.countdown.remaining] - * The number of seconds remaining before the countdown callback is - * called. - * - * @param {String} [status.progress.text] - * If this notification has associated progress, the text to display - * while the operation is occurring. - * - * @param {String} [status.progress.value] - * The current state of operation progress, as an arbitrary number - * which increases as the operation continues. - * - * @param {String} [status.progress.unit] - * The unit of the arbitrary status.progress.value, if that value has - * an associated unit. - * - * @param {String} [status.progress.ratio] - * If known, the current status of the operation as a value between - * 0 and 1 inclusive, where 0 is not yet started, and 1 is complete. - * - * @param {Object[]} [status.actions] - * Array of action objects which contain an action name and callback to - * be executed when that action is invoked. + * @param {Notification|Boolean|Object} status + * The status notification to show. * * @example * @@ -138,43 +119,10 @@ angular.module('index').controller('indexController', ['$scope', '$injector', /** * Adds a notification to the the list of notifications shown. * - * @param {Object} notification The notification to add. - * @param {String} [notification.title] The title of the notification. - * @param {String} [notification.text] The body text of the notification. - * @param {String} [notification.className] The CSS class name to apply. + * @param {Notification|Object} notification The notification to add. * - * @param {String} [notification.countdown.text] - * In the case that a countdown applies to the notification, the text to - * display while the countdown is active. - * - * @param {Function} [notification.countdown.callback] - * The callback to call when the countdown expires. - * - * @param {String} [notification.countdown.remaining] - * The number of seconds remaining before the countdown callback is - * called. - * - * @param {String} [notification.progress.text] - * If this notification has associated progress, the text to display - * while the operation is occurring. - * - * @param {String} [notification.progress.value] - * The current state of operation progress, as an arbitrary number - * which increases as the operation continues. - * - * @param {String} [notification.progress.unit] - * The unit of the arbitrary notification.progress.value, if that value - * has an associated unit. - * - * @param {String} [notification.progress.ratio] - * If known, the current status of the operation as a value between - * 0 and 1 inclusive, where 0 is not yet started, and 1 is complete. - * - * @param {Object[]} [notification.actions] - * Array of action objects which contain an action name and callback to - * be executed when that action is invoked. - * - * @returns {Number} A unique ID for the notification that's just been added. + * @returns {Number} + * A unique ID for the notification that's just been added. * * @example * diff --git a/guacamole/src/main/webapp/app/notification/directives/guacNotification.js b/guacamole/src/main/webapp/app/notification/directives/guacNotification.js index f8fb8334b..e6c36ef58 100644 --- a/guacamole/src/main/webapp/app/notification/directives/guacNotification.js +++ b/guacamole/src/main/webapp/app/notification/directives/guacNotification.js @@ -31,110 +31,11 @@ angular.module('notification').directive('guacNotification', [function guacNotif scope: { /** - * The CSS class to apply to the notification. + * The notification to display. * - * @type String + * @type Notification|Object */ - className : '=', - - /** - * The title of the notification. - * - * @type String - */ - title : '=', - - /** - * The body text of the notification. - * - * @type String - */ - text : '=', - - /** - * The text to use for displaying the countdown. For the sake of - * i18n, the variable REMAINING will be applied within the - * translation string for formatting plurals, etc. - * - * @type String - * @example - * "Only {REMAINING} {REMAINING, plural, one{second} other{seconds}} remain." - */ - countdownText : '=', - - /** - * The number of seconds to wait before automatically calling the - * default callback. - * - * @type Number - */ - countdown : '=', - - /** - * The function to call when timeRemaining expires. If timeRemaining - * is not set, this does not apply. - * - * @type Function - */ - defaultCallback : '=', - - /** - * The text to use for displaying the progress. For the sake of - * i18n, the variable PROGRESS will be applied within the - * translation string for formatting plurals, etc., while the - * variable UNIT will be applied, if needed, for whatever units - * are applicable to the progress display. - * - * @type String - * @example - * "{PROGRESS} {UNIT, select, b{B} kb{KB}} uploaded." - */ - progressText : '=', - - /** - * The unit which applies to the progress indicator, if any. This - * will be substituted in the progressText string with the UNIT - * variable. - * - * @type String - */ - progressUnit : '=', - - /** - * Arbitrary value denoting how much progress has been made - * in some ongoing task that this notification represents. - * - * @type Number - */ - progress : '=', - - /** - * Value between 0 and 1 denoting what proportion of the operation - * has completed. If known, this value should be 0 if the operation - * has not started, and 1 if the operation is complete. - * - * @type Number - */ - progressRatio : '=', - - /** - * Array of name/callback pairs for each action the user is allowed - * to take once the notification is shown. - * - * @type Array - * @example - * [ - * { - * name : "Action 1 name", - * callback : actionCallback1 - * }, - * { - * name : "Action 2 text", - * callback : actionCallback2 - * } - * ] - */ - actions : '=' + notification : '=' }, @@ -142,21 +43,22 @@ angular.module('notification').directive('guacNotification', [function guacNotif controller: ['$scope', '$interval', function guacNotificationController($scope, $interval) { // Update progress bar if end known - $scope.$watch("progressRatio", function updateProgress(ratio) { + $scope.$watch("notification.progress.ratio", function updateProgress(ratio) { $scope.progressPercent = ratio * 100; }); - // Set countdown interval when associated property is set - $scope.$watch("countdown", function resetTimeRemaining(countdown) { + $scope.$watch("notification", function resetTimeRemaining(notification) { - $scope.timeRemaining = countdown; + var countdown = notification.countdown; // Clean up any existing interval if ($scope.interval) $interval.cancel($scope.interval); // Update and handle countdown, if provided - if ($scope.timeRemaining) { + if (countdown) { + + $scope.timeRemaining = countdown.remaining; $scope.interval = $interval(function updateTimeRemaining() { @@ -164,8 +66,8 @@ angular.module('notification').directive('guacNotification', [function guacNotif $scope.timeRemaining--; // Call countdown callback when time remaining expires - if ($scope.timeRemaining === 0 && $scope.defaultCallback) - $scope.defaultCallback(); + if ($scope.timeRemaining === 0) + countdown.performAction(); }, 1000, $scope.timeRemaining); @@ -184,4 +86,4 @@ angular.module('notification').directive('guacNotification', [function guacNotif }] }; -}]); \ No newline at end of file +}]); diff --git a/guacamole/src/main/webapp/app/notification/templates/guacNotification.html b/guacamole/src/main/webapp/app/notification/templates/guacNotification.html index 0691f663e..50d484fb2 100644 --- a/guacamole/src/main/webapp/app/notification/templates/guacNotification.html +++ b/guacamole/src/main/webapp/app/notification/templates/guacNotification.html @@ -1,4 +1,4 @@ -
+
-
-
{{title | translate}}
+
+
{{notification.title | translate}}
-

{{text | translate}}

+

{{notification.text | translate}}

-
{{progressText | translate:"{ PROGRESS: progress, UNIT: progressUnit }"}}
+
{{notification.progress.text | translate:"{ PROGRESS: notification.progress.value, UNIT: notification.progress.unit}"}}
-

{{countdownText | translate:"{ REMAINING: timeRemaining }"}}

+

{{notification.countdown.text | translate:"{ REMAINING: timeRemaining}"}}

-
- +
+
-
\ No newline at end of file +
diff --git a/guacamole/src/main/webapp/app/notification/types/Notification.js b/guacamole/src/main/webapp/app/notification/types/Notification.js new file mode 100644 index 000000000..dfb5ef9fa --- /dev/null +++ b/guacamole/src/main/webapp/app/notification/types/Notification.js @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Provides the Notification class definition. + */ +angular.module('notification').factory('Notification', [function defineNotification() { + + /** + * Creates a new Notification, initializing the properties of that + * Notification with the corresponding properties of the given template. + * + * @constructor + * @param {Notification|Object} [template={}] + * The object whose properties should be copied within the new + * Notification. + */ + var Notification = function Notification(template) { + + // Use empty object by default + template = template || {}; + + /** + * The CSS class to associate with the notification, if any. + * + * @type String + */ + this.className = template.className; + + /** + * The title of the notification. + * + * @type String + */ + this.title = template.title; + + /** + * The body text of the notification. + * + * @type String + */ + this.text = template.text; + + /** + * An array of all actions available to the user in response to this + * notification. + * + * @type NotificationAction[] + */ + this.actions = template.actions || []; + + /** + * The current progress state of the ongoing action associated with this + * notification. + * + * @type NotificationProgress + */ + this.progress = template.progress; + + /** + * The countdown and corresponding default action which applies to + * this notification, if any. + * + * @type NotificationCountdown + */ + this.countdown = template.countdown; + + }; + + return Notification; + +}]); diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationAction.js b/guacamole/src/main/webapp/app/notification/types/NotificationAction.js new file mode 100644 index 000000000..d0e75cb6d --- /dev/null +++ b/guacamole/src/main/webapp/app/notification/types/NotificationAction.js @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Provides the NotificationAction class definition. + */ +angular.module('notification').factory('NotificationAction', [function defineNotificationAction() { + + /** + * Creates a new NotificationAction, which pairs an arbitrary callback with + * an action name. The name of this action will ultimately be presented to + * the user when the user is prompted to choose among available actions. + * + * @constructor + * @param {String} name The name of this action. + * + * @param {Function} callback + * The callback to call when the user elects to perform this action. + */ + var NotificationAction = function NotificationAction(name, callback) { + + /** + * Reference to this NotificationAction. + * + * @type NotificationAction + */ + var action = this; + + /** + * The name of this action. + * + * @type String + */ + this.name = name; + + /** + * The callback to call when this action is performed. + * + * @type Function + */ + this.callback = callback; + + /** + * Calls the callback associated with this NotificationAction, if any. + * If no callback is associated with this NotificationAction, this + * function has no effect. + */ + this.performAction = function performAction() { + if (action.callback) + action.callback(); + }; + + }; + + return NotificationAction; + +}]); diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js b/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js new file mode 100644 index 000000000..1f834508e --- /dev/null +++ b/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Provides the NotificationCountdown class definition. + */ +angular.module('notification').factory('NotificationCountdown', [function defineNotificationCountdown() { + + /** + * Creates a new NotificationCountdown which describes an action that + * should be performed after a specific number of seconds has elapsed. + * + * @constructor + * @param {String} text The body text of the notification countdown. + * + * @param {Number} remaining + * The number of seconds remaining in the countdown. + * + * @param {Function} [callback] + * The callback to call when the countdown elapses. + */ + var NotificationCountdown = function NotificationCountdown(text, remaining, callback) { + + /** + * Reference to this NotificationCountdown. + * + * @type NotificationCountdown + */ + var countdown = this; + + /** + * The body text of the notification countdown. For the sake of i18n, + * the variable REMAINING should be applied within the translation + * string for formatting plurals, etc. + * + * @type String + */ + this.text = text; + + /** + * The number of seconds remaining in the countdown. After this number + * of seconds elapses, the callback associated with this + * NotificationCountdown will be called. + * + * @type Number + */ + this.remaining = remaining; + + /** + * The callback to call when this countdown expires. + * + * @type Function + */ + this.callback = callback; + + /** + * Calls the callback associated with this NotificationCountdown, if any. + * If no callback is associated with this NotificationCountdown, this + * function has no effect. + */ + this.performAction = function performAction() { + if (countdown.callback) + countdown.callback(); + }; + + }; + + return NotificationCountdown; + +}]); diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js b/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js new file mode 100644 index 000000000..5c3a45c0c --- /dev/null +++ b/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Provides the NotificationProgress class definition. + */ +angular.module('notification').factory('NotificationProgress', [function defineNotificationProgress() { + + /** + * Creates a new NotificationProgress which describes the current status + * of an operation, and how much of that operation remains to be performed. + * + * @constructor + * @param {String} text The text describing the operation progress. + * + * @param {Number} value + * The current state of operation progress, as an arbitrary number + * which increases as the operation continues. + * + * @param {String} [unit] + * The unit of the arbitrary value, if that value has an associated + * unit. + * + * @param {Number} [ratio] + * If known, the current status of the operation as a value between 0 + * and 1 inclusive, where 0 is not yet started, and 1 is complete. + */ + var NotificationProgress = function NotificationProgress(text, value, unit, ratio) { + + /** + * The text describing the operation progress. For the sake of i18n, + * the variable PROGRESS should be applied within the translation + * string for formatting plurals, etc., while UNIT should be used + * for the progress unit, if any. + * + * @type String + */ + this.text = text; + + /** + * The current state of operation progress, as an arbitrary number which + * increases as the operation continues. + * + * @type Number + */ + this.value = value; + + /** + * The unit of the arbitrary value, if that value has an associated + * unit. + * + * @type String + */ + this.unit = unit; + + /** + * If known, the current status of the operation as a value between 0 + * and 1 inclusive, where 0 is not yet started, and 1 is complete. + * + * @type String + */ + this.ratio = ratio; + + }; + + return NotificationProgress; + +}]); diff --git a/guacamole/src/main/webapp/index.html b/guacamole/src/main/webapp/index.html index 8206371ad..472e18ca6 100644 --- a/guacamole/src/main/webapp/index.html +++ b/guacamole/src/main/webapp/index.html @@ -37,20 +37,7 @@ THE SOFTWARE.
- - - +
@@ -60,20 +47,7 @@ THE SOFTWARE.
- - - +