You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2017/01/04 03:59:54 UTC

[1/5] incubator-guacamole-client git commit: GUACAMOLE-36: Migrate guacLogin and guacNotification to TranslatableMessage.

Repository: incubator-guacamole-client
Updated Branches:
  refs/heads/master f891f6982 -> 403c578da


GUACAMOLE-36: Migrate guacLogin and guacNotification to TranslatableMessage.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/986ea4b2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/986ea4b2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/986ea4b2

Branch: refs/heads/master
Commit: 986ea4b206ef6322cad629cecb4ec86dc7642d8a
Parents: 0671f18
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Aug 16 21:47:26 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 3 19:42:24 2017 -0800

----------------------------------------------------------------------
 .../app/client/controllers/clientController.js      | 16 ++++++++++++----
 .../webapp/app/index/controllers/indexController.js |  4 ++--
 .../src/main/webapp/app/login/directives/login.js   | 10 ++++++----
 .../src/main/webapp/app/login/templates/login.html  |  6 ++++--
 .../controllers/manageConnectionController.js       |  8 +++++---
 .../controllers/manageConnectionGroupController.js  |  8 +++++---
 .../controllers/manageSharingProfileController.js   |  8 +++++---
 .../app/manage/controllers/manageUserController.js  | 15 ++++++++++-----
 .../app/notification/services/guacNotification.js   |  4 +++-
 .../notification/templates/guacNotification.html    |  4 +++-
 .../webapp/app/notification/types/Notification.js   |  2 +-
 .../settings/directives/guacSettingsPreferences.js  | 14 ++++++++++----
 .../app/settings/directives/guacSettingsSessions.js |  6 ++++--
 13 files changed, 70 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/client/controllers/clientController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js
index b522568..9827de1 100644
--- a/guacamole/src/main/webapp/app/client/controllers/clientController.js
+++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js
@@ -578,7 +578,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
          || connectionState === ManagedClientState.ConnectionState.WAITING) {
             guacNotification.showStatus({
                 title: "CLIENT.DIALOG_HEADER_CONNECTING",
-                text: "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase()
+                text: {
+                    key : "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase()
+                }
             });
         }
 
@@ -595,7 +597,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
             notifyConnectionClosed({
                 className : "error",
                 title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR",
-                text      : "CLIENT.ERROR_CLIENT_" + errorName,
+                text      : {
+                    key : "CLIENT.ERROR_CLIENT_" + errorName
+                },
                 countdown : countdown,
                 actions   : actions
             });
@@ -615,7 +619,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
             notifyConnectionClosed({
                 className : "error",
                 title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR",
-                text      : "CLIENT.ERROR_TUNNEL_" + errorName,
+                text      : {
+                    key : "CLIENT.ERROR_TUNNEL_" + errorName
+                },
                 countdown : countdown,
                 actions   : actions
             });
@@ -626,7 +632,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
         else if (connectionState === ManagedClientState.ConnectionState.DISCONNECTED) {
             notifyConnectionClosed({
                 title   : "CLIENT.DIALOG_HEADER_DISCONNECTED",
-                text    : "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase(),
+                text    : {
+                    key : "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase()
+                },
                 actions : actions
             });
         }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/index/controllers/indexController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/controllers/indexController.js b/guacamole/src/main/webapp/app/index/controllers/indexController.js
index 25e6b61..e17ecee 100644
--- a/guacamole/src/main/webapp/app/index/controllers/indexController.js
+++ b/guacamole/src/main/webapp/app/index/controllers/indexController.js
@@ -38,7 +38,7 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
      * The message to display to the user as instructions for the login
      * process.
      *
-     * @type String
+     * @type TranslatableMessage
      */
     $scope.loginHelpText = null;
 
@@ -160,7 +160,7 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
     $scope.$on('guacInsufficientCredentials', function loginInsufficient(event, parameters, error) {
         $scope.page.title = 'APP.NAME';
         $scope.page.bodyClassName = '';
-        $scope.loginHelpText = error.message;
+        $scope.loginHelpText = error.translatableMessage;
         $scope.acceptedCredentials = parameters;
         $scope.expectedCredentials = error.expected;
     });

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/login/directives/login.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js
index aa03af2..cc820b8 100644
--- a/guacamole/src/main/webapp/app/login/directives/login.js
+++ b/guacamole/src/main/webapp/app/login/directives/login.js
@@ -36,7 +36,7 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
          * An optional instructional message to display within the login
          * dialog.
          *
-         * @type String
+         * @type TranslatableMessage
          */
         helpText : '=',
 
@@ -72,7 +72,7 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
         /**
          * A description of the error that occurred during login, if any.
          *
-         * @type String
+         * @type TranslatableMessage
          */
         $scope.loginError = null;
 
@@ -160,11 +160,13 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
 
                     // Flag generic error for invalid login
                     if (error.type === Error.Type.INVALID_CREDENTIALS)
-                        $scope.loginError = 'LOGIN.ERROR_INVALID_LOGIN';
+                        $scope.loginError = {
+                            'key' : 'LOGIN.ERROR_INVALID_LOGIN'
+                        };
 
                     // Display error if anything else goes wrong
                     else
-                        $scope.loginError = error.message;
+                        $scope.loginError = error.translatableMessage;
 
                     // Clear all visible password fields
                     angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) {

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/login/templates/login.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/login/templates/login.html b/guacamole/src/main/webapp/app/login/templates/login.html
index b9d9335..26a3f18 100644
--- a/guacamole/src/main/webapp/app/login/templates/login.html
+++ b/guacamole/src/main/webapp/app/login/templates/login.html
@@ -1,7 +1,8 @@
 <div class="login-ui" ng-class="{error: loginError, continuation: isContinuation(), initial: !isContinuation()}" >
 
     <!-- Login error message -->
-    <p class="login-error">{{loginError | translate}}</p>
+    <p class="login-error" translate="{{loginError.key}}"
+       translate-values="{{loginError.variables}}"></p>
 
     <div class="login-dialog-middle">
 
@@ -17,7 +18,8 @@
                 </div>
 
                 <!-- Login message/instructions -->
-                <p ng-show="helpText">{{helpText | translate}}</p>
+                <p ng-show="helpText" translate="{{helpText.key}}"
+                   translate-values="{{helpText.variables}}"></p>
 
                 <!-- Login fields -->
                 <div class="login-fields">

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
index a911ab2..868842e 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
@@ -380,7 +380,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_CONNECTION.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -430,7 +430,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_CONNECTION.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -446,7 +446,9 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
         // Confirm deletion request
         guacNotification.showStatus({
             'title'      : 'MANAGE_CONNECTION.DIALOG_HEADER_CONFIRM_DELETE',
-            'text'       : 'MANAGE_CONNECTION.TEXT_CONFIRM_DELETE',
+            'text'       : {
+                key : 'MANAGE_CONNECTION.TEXT_CONFIRM_DELETE'
+            },
             'actions'    : [ DELETE_ACTION, CANCEL_ACTION]
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
index 0d0af59..e4c6115 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
@@ -220,7 +220,7 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_CONNECTION_GROUP.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -270,7 +270,7 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_CONNECTION_GROUP.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -286,7 +286,9 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
         // Confirm deletion request
         guacNotification.showStatus({
             'title'      : 'MANAGE_CONNECTION_GROUP.DIALOG_HEADER_CONFIRM_DELETE',
-            'text'       : 'MANAGE_CONNECTION_GROUP.TEXT_CONFIRM_DELETE',
+            'text'       : {
+                key : 'MANAGE_CONNECTION_GROUP.TEXT_CONFIRM_DELETE'
+            },
             'actions'    : [ DELETE_ACTION, CANCEL_ACTION]
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js b/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js
index 96657d1..ca7d11e 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js
@@ -341,7 +341,7 @@ angular.module('manage').controller('manageSharingProfileController', ['$scope',
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_SHARING_PROFILE.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -379,7 +379,7 @@ angular.module('manage').controller('manageSharingProfileController', ['$scope',
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_SHARING_PROFILE.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -395,7 +395,9 @@ angular.module('manage').controller('manageSharingProfileController', ['$scope',
         // Confirm deletion request
         guacNotification.showStatus({
             'title'      : 'MANAGE_SHARING_PROFILE.DIALOG_HEADER_CONFIRM_DELETE',
-            'text'       : 'MANAGE_SHARING_PROFILE.TEXT_CONFIRM_DELETE',
+            'text'       : {
+                'key' : 'MANAGE_SHARING_PROFILE.TEXT_CONFIRM_DELETE'
+            },
             'actions'    : [ DELETE_ACTION, CANCEL_ACTION]
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
index 7a4db92..5337caf 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
@@ -1012,7 +1012,9 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_USER.DIALOG_HEADER_ERROR',
-                'text'       : 'MANAGE_USER.ERROR_PASSWORD_MISMATCH',
+                'text'       : {
+                    key : 'MANAGE_USER.ERROR_PASSWORD_MISMATCH'
+                },
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
             return;
@@ -1055,7 +1057,8 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
                 guacNotification.showStatus({
                     'className'  : 'error',
                     'title'      : 'MANAGE_USER.DIALOG_HEADER_ERROR',
-                    'text'       : error.message,
+                    'text'       : error.translatableMessage,
+                    'values'     : error.translationValues,
                     'actions'    : [ ACKNOWLEDGE_ACTION ]
                 });
             });
@@ -1067,7 +1070,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_USER.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -1117,7 +1120,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
             guacNotification.showStatus({
                 'className'  : 'error',
                 'title'      : 'MANAGE_USER.DIALOG_HEADER_ERROR',
-                'text'       : error.message,
+                'text'       : error.translatableMessage,
                 'actions'    : [ ACKNOWLEDGE_ACTION ]
             });
         });
@@ -1133,7 +1136,9 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
         // Confirm deletion request
         guacNotification.showStatus({
             'title'      : 'MANAGE_USER.DIALOG_HEADER_CONFIRM_DELETE',
-            'text'       : 'MANAGE_USER.TEXT_CONFIRM_DELETE',
+            'text'       : {
+                key : 'MANAGE_USER.TEXT_CONFIRM_DELETE'
+            },
             'actions'    : [ DELETE_ACTION, CANCEL_ACTION]
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/notification/services/guacNotification.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/notification/services/guacNotification.js b/guacamole/src/main/webapp/app/notification/services/guacNotification.js
index 8273eb7..c3d4a2b 100644
--- a/guacamole/src/main/webapp/app/notification/services/guacNotification.js
+++ b/guacamole/src/main/webapp/app/notification/services/guacNotification.js
@@ -60,7 +60,9 @@ angular.module('notification').factory('guacNotification', ['$injector',
      * // To show a status message with actions
      * guacNotification.showStatus({
      *     'title'      : 'Disconnected',
-     *     'text'       : 'You have been disconnected!',
+     *     'text'       : {
+     *         'key' : 'NAMESPACE.SOME_TRANSLATION_KEY'
+     *     },
      *     'actions'    : {
      *         'name'       : 'reconnect',
      *         'callback'   : function () {

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/notification/templates/guacNotification.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/notification/templates/guacNotification.html b/guacamole/src/main/webapp/app/notification/templates/guacNotification.html
index db3360a..6c1cc00 100644
--- a/guacamole/src/main/webapp/app/notification/templates/guacNotification.html
+++ b/guacamole/src/main/webapp/app/notification/templates/guacNotification.html
@@ -8,7 +8,9 @@
     <div class="body">
 
         <!-- Notification text -->
-        <p ng-show="notification.text" class="text">{{notification.text | translate}}</p>
+        <p ng-show="notification.text" class="text"
+           translate="{{notification.text.key}}"
+           translate-values="{{notification.text.variables}}"></p>
 
         <!-- Current progress -->
         <div class="progress" ng-show="notification.progress"><div class="bar" ng-show="progressPercent" ng-style="{'width': progressPercent + '%'}"></div><div

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/notification/types/Notification.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/notification/types/Notification.js b/guacamole/src/main/webapp/app/notification/types/Notification.js
index 3a28401..921fa40 100644
--- a/guacamole/src/main/webapp/app/notification/types/Notification.js
+++ b/guacamole/src/main/webapp/app/notification/types/Notification.js
@@ -53,7 +53,7 @@ angular.module('notification').factory('Notification', [function defineNotificat
         /**
          * The body text of the notification.
          *
-         * @type String
+         * @type TranslatableMessage
          */
         this.text = template.text;
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/settings/directives/guacSettingsPreferences.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/settings/directives/guacSettingsPreferences.js b/guacamole/src/main/webapp/app/settings/directives/guacSettingsPreferences.js
index 934056b..0a3ed6e 100644
--- a/guacamole/src/main/webapp/app/settings/directives/guacSettingsPreferences.js
+++ b/guacamole/src/main/webapp/app/settings/directives/guacSettingsPreferences.js
@@ -127,7 +127,9 @@ angular.module('settings').directive('guacSettingsPreferences', [function guacSe
                     guacNotification.showStatus({
                         className  : 'error',
                         title      : 'SETTINGS_PREFERENCES.DIALOG_HEADER_ERROR',
-                        text       : 'SETTINGS_PREFERENCES.ERROR_PASSWORD_MISMATCH',
+                        text       : {
+                            key : 'SETTINGS_PREFERENCES.ERROR_PASSWORD_MISMATCH'
+                        },
                         actions    : [ ACKNOWLEDGE_ACTION ]
                     });
                     return;
@@ -138,7 +140,9 @@ angular.module('settings').directive('guacSettingsPreferences', [function guacSe
                     guacNotification.showStatus({
                         className  : 'error',
                         title      : 'SETTINGS_PREFERENCES.DIALOG_HEADER_ERROR',
-                        text       : 'SETTINGS_PREFERENCES.ERROR_PASSWORD_BLANK',
+                        text       : {
+                            key : 'SETTINGS_PREFERENCES.ERROR_PASSWORD_BLANK'
+                        },
                         actions    : [ ACKNOWLEDGE_ACTION ]
                     });
                     return;
@@ -155,7 +159,9 @@ angular.module('settings').directive('guacSettingsPreferences', [function guacSe
 
                     // Indicate that the password has been changed
                     guacNotification.showStatus({
-                        text    : 'SETTINGS_PREFERENCES.INFO_PASSWORD_CHANGED',
+                        text    : {
+                            key : 'SETTINGS_PREFERENCES.INFO_PASSWORD_CHANGED'
+                        },
                         actions : [ ACKNOWLEDGE_ACTION ]
                     });
                 })
@@ -165,7 +171,7 @@ angular.module('settings').directive('guacSettingsPreferences', [function guacSe
                     guacNotification.showStatus({
                         className  : 'error',
                         title      : 'SETTINGS_PREFERENCES.DIALOG_HEADER_ERROR',
-                        'text'       : error.message,
+                        text       : error.translatableMessage,
                         actions    : [ ACKNOWLEDGE_ACTION ]
                     });
                 });

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/986ea4b2/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js b/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
index 0b1d806..a8c13c4 100644
--- a/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
+++ b/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
@@ -334,7 +334,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
                     guacNotification.showStatus({
                         'className'  : 'error',
                         'title'      : 'SETTINGS_SESSIONS.DIALOG_HEADER_ERROR',
-                        'text'       : error.message,
+                        'text'       : error.translatableMessage,
                         'actions'    : [ ACKNOWLEDGE_ACTION ]
                     });
                 });
@@ -349,7 +349,9 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
                 // Confirm deletion request
                 guacNotification.showStatus({
                     'title'      : 'SETTINGS_SESSIONS.DIALOG_HEADER_CONFIRM_DELETE',
-                    'text'       : 'SETTINGS_SESSIONS.TEXT_CONFIRM_DELETE',
+                    'text'       : {
+                        'key' : 'SETTINGS_SESSIONS.TEXT_CONFIRM_DELETE'
+                    },
                     'actions'    : [ DELETE_ACTION, CANCEL_ACTION]
                 });
             };


[3/5] incubator-guacamole-client git commit: GUACAMOLE-36: Generalize and simplify handling of REST API errors.

Posted by jm...@apache.org.
GUACAMOLE-36: Generalize and simplify handling of REST API errors.

Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/30179c40
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/30179c40
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/30179c40

Branch: refs/heads/master
Commit: 30179c405fe2dc856c608df8226e53d81702b6eb
Parents: f891f69
Author: Michael Jumper <mj...@apache.org>
Authored: Mon Aug 15 22:24:04 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 3 19:42:24 2017 -0800

----------------------------------------------------------------------
 .../org/apache/guacamole/rest/APIError.java     | 152 +++++++++----------
 .../org/apache/guacamole/rest/APIException.java | 100 ++----------
 .../guacamole/rest/RESTExceptionWrapper.java    | 116 ++------------
 .../APIConnectionRecordSortPredicate.java       |   7 +-
 4 files changed, 111 insertions(+), 264 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/30179c40/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java b/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
index c6a2c63..7727b85 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
@@ -20,8 +20,15 @@
 package org.apache.guacamole.rest;
 
 import java.util.Collection;
-import javax.ws.rs.core.Response;
+import org.apache.guacamole.GuacamoleClientException;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleResourceNotFoundException;
+import org.apache.guacamole.GuacamoleSecurityException;
 import org.apache.guacamole.form.Field;
+import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
+import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
+import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
+import org.apache.guacamole.tunnel.GuacamoleStreamException;
 
 /**
  * Describes an error that occurred within a REST endpoint.
@@ -60,124 +67,115 @@ public class APIError {
          * The requested operation could not be performed because the request
          * itself was malformed.
          */
-        BAD_REQUEST(Response.Status.BAD_REQUEST),
+        BAD_REQUEST,
 
         /**
          * The credentials provided were invalid.
          */
-        INVALID_CREDENTIALS(Response.Status.FORBIDDEN),
+        INVALID_CREDENTIALS,
 
         /**
          * The credentials provided were not necessarily invalid, but were not
          * sufficient to determine validity.
          */
-        INSUFFICIENT_CREDENTIALS(Response.Status.FORBIDDEN),
+        INSUFFICIENT_CREDENTIALS,
 
         /**
          * An internal server error has occurred.
          */
-        INTERNAL_ERROR(Response.Status.INTERNAL_SERVER_ERROR),
+        INTERNAL_ERROR,
 
         /**
          * An object related to the request does not exist.
          */
-        NOT_FOUND(Response.Status.NOT_FOUND),
+        NOT_FOUND,
 
         /**
          * Permission was denied to perform the requested operation.
          */
-        PERMISSION_DENIED(Response.Status.FORBIDDEN),
+        PERMISSION_DENIED,
 
         /**
          * An error occurred within an intercepted stream, terminating that
          * stream. The Guacamole protocol status code of that error can be
          * retrieved with getStatusCode().
          */
-        STREAM_ERROR(Response.Status.BAD_REQUEST);
+        STREAM_ERROR;
 
         /**
-         * The HTTP status associated with this error type.
-         */
-        private final Response.Status status;
-
-        /**
-         * Defines a new error type associated with the given HTTP status.
+         * Returns the REST API error type which corresponds to the type of the
+         * given exception.
          *
-         * @param status
-         *     The HTTP status to associate with the error type.
-         */
-        Type(Response.Status status) {
-            this.status = status;
-        }
-
-        /**
-         * Returns the HTTP status associated with this error type.
+         * @param exception
+         *     The exception to use to derive the API error type.
          *
          * @return
-         *     The HTTP status associated with this error type.
+         *     The API error type which corresponds to the type of the given
+         *     exception.
          */
-        public Response.Status getStatus() {
-            return status;
+        public static Type fromGuacamoleException(GuacamoleException exception) {
+
+            // Additional credentials are needed
+            if (exception instanceof GuacamoleInsufficientCredentialsException)
+                return INSUFFICIENT_CREDENTIALS;
+
+            // The provided credentials are wrong
+            if (exception instanceof GuacamoleInvalidCredentialsException)
+                return INVALID_CREDENTIALS;
+
+            // Generic permission denied
+            if (exception instanceof GuacamoleSecurityException)
+                return PERMISSION_DENIED;
+
+            // Arbitrary resource not found
+            if (exception instanceof GuacamoleResourceNotFoundException)
+                return NOT_FOUND;
+
+            // Arbitrary bad requests
+            if (exception instanceof GuacamoleClientException)
+                return BAD_REQUEST;
+
+            // Errors from intercepted streams
+            if (exception instanceof GuacamoleStreamException)
+                return STREAM_ERROR;
+
+            // All other errors
+            return INTERNAL_ERROR;
+
         }
 
     }
 
     /**
-     * Creates a new APIError of type STREAM_ERROR and having the given
-     * Guacamole protocol status code and human-readable message. The status
-     * code and message should be taken directly from the "ack" instruction
-     * causing the error.
+     * Creates a new APIError which exposes the details of the given
+     * GuacamoleException.
      *
-     * @param statusCode
-     *     The Guacamole protocol status code describing the error that
-     *     occurred within the intercepted stream.
-     *
-     * @param message
-     *     An arbitrary human-readable message describing the error that
-     *     occurred.
+     * @param exception
+     *     The GuacamoleException from which the details of the new APIError
+     *     should be derived.
      */
-    public APIError(int statusCode, String message) {
-        this.type       = Type.STREAM_ERROR;
-        this.message    = message;
-        this.statusCode = statusCode;
-        this.expected   = null;
-    }
+    public APIError(GuacamoleException exception) {
 
-    /**
-     * Create a new APIError with the specified error message.
-     *
-     * @param type
-     *     The type of error that occurred.
-     *
-     * @param message
-     *     The error message.
-     */
-    public APIError(Type type, String message) {
-        this.type       = type;
-        this.message    = message;
-        this.statusCode = null;
-        this.expected   = null;
-    }
+        // Build base REST service error
+        this.type = Type.fromGuacamoleException(exception);
+        this.message = exception.getMessage();
+
+        // Add expected credentials if applicable
+        if (exception instanceof GuacamoleCredentialsException) {
+            GuacamoleCredentialsException credentialsException = (GuacamoleCredentialsException) exception;
+            this.expected = credentialsException.getCredentialsInfo().getFields();
+        }
+        else
+            this.expected = null;
+
+        // Add stream status code if applicable
+        if (exception instanceof GuacamoleStreamException) {
+            GuacamoleStreamException streamException = (GuacamoleStreamException) exception;
+            this.statusCode = streamException.getStatus().getGuacamoleStatusCode();
+        }
+        else
+            this.statusCode = null;
 
-    /**
-     * Create a new APIError with the specified error message and parameter
-     * information.
-     *
-     * @param type
-     *     The type of error that occurred.
-     *
-     * @param message
-     *     The error message.
-     *
-     * @param expected
-     *     All parameters expected in the original request, or now required as
-     *     a result of the original request, as a collection of fields.
-     */
-    public APIError(Type type, String message, Collection<Field> expected) {
-        this.type       = type;
-        this.message    = message;
-        this.statusCode = null;
-        this.expected   = expected;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/30179c40/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java b/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
index ea4cf5d..0e1a4f5 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
@@ -19,17 +19,16 @@
 
 package org.apache.guacamole.rest;
 
-import java.util.Collection;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import org.apache.guacamole.form.Field;
-import org.apache.guacamole.protocol.GuacamoleStatus;
+import org.apache.guacamole.GuacamoleException;
 
 /**
- * An exception that will result in the given error error information being
- * returned from the API layer. All error messages have the same format which
- * is defined by APIError.
+ * An exception which exposes a given error within the API layer. When thrown
+ * within the context of the REST API, an appropriate HTTP status code will be
+ * set for the failing response, and the details of the error will be exposed in
+ * the body of the response as an APIError structure.
  *
  * @author James Muehlner
  * @author Michael Jumper
@@ -37,88 +36,21 @@ import org.apache.guacamole.protocol.GuacamoleStatus;
 public class APIException extends WebApplicationException {
 
     /**
-     * Construct a new APIException with the given error. All information
-     * associated with this new exception will be extracted from the given
-     * APIError.
-     *
-     * @param error
-     *     The error that occurred.
-     */
-    public APIException(APIError error) {
-        super(Response.status(error.getType().getStatus())
-                .type(MediaType.APPLICATION_JSON)
-                .entity(error)
-                .build());
-    }
-
-    /**
-     * Creates a new APIException with the given type and message. The
-     * corresponding APIError will be created from the provided information.
-     *
-     * @param type
-     *     The type of error that occurred.
-     *
-     * @param message
-     *     A human-readable message describing the error.
-     */
-    public APIException(APIError.Type type, String message) {
-        this(new APIError(type, message));
-    }
-
-    /**
-     * Creates a new APIException which represents an error that occurred within
-     * an intercepted Guacamole stream. The nature of that error will be
-     * described by a given status code, which should be the status code
-     * provided by the "ack" instruction that reported the error.
+     * Construct a new APIException based on the given GuacamoleException and
+     * HTTP status. The details of the GuacamoleException relevant to the REST
+     * API will be exposed via an APIError.
      *
      * @param status
-     *     The Guacamole protocol status code describing the error that
-     *     occurred within the intercepted stream.
+     *     The HTTP status which corresponds to the GuacamoleException.
      *
-     * @param message
-     *     An arbitrary human-readable message describing the error that
-     *     occurred.
+     * @param exception
+     *     The GuacamoleException that occurred.
      */
-    public APIException(int status, String message) {
-        this(new APIError(status, message));
-    }
-
-    /**
-     * Creates a new APIException which represents an error that occurred within
-     * an intercepted Guacamole stream. The nature of that error will be
-     * described by a given Guacamole protocol status, which should be the
-     * status associated with the code provided by the "ack" instruction that
-     * reported the error.
-     *
-     * @param status
-     *     The Guacamole protocol status describing the error that occurred
-     *     within the intercepted stream.
-     *
-     * @param message
-     *     An arbitrary human-readable message describing the error that
-     *     occurred.
-     */
-    public APIException(GuacamoleStatus status, String message) {
-        this(status.getGuacamoleStatusCode(), message);
-    }
-
-    /**
-     * Creates a new APIException with the given type, message, and parameter
-     * information. The corresponding APIError will be created from the
-     * provided information.
-     *
-     * @param type
-     *     The type of error that occurred.
-     *
-     * @param message
-     *     A human-readable message describing the error.
-     *
-     * @param expected
-     *     All parameters expected in the original request, or now required as
-     *     a result of the original request, as a collection of fields.
-     */
-    public APIException(APIError.Type type, String message, Collection<Field> expected) {
-        this(new APIError(type, message, expected));
+    public APIException(Response.Status status, GuacamoleException exception) {
+        super(Response.status(status)
+                .type(MediaType.APPLICATION_JSON)
+                .entity(new APIError(exception))
+                .build());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/30179c40/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
index f4de406..8d6839f 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
@@ -24,6 +24,8 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import javax.ws.rs.FormParam;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 import org.apache.guacamole.GuacamoleClientException;
@@ -31,10 +33,7 @@ import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleResourceNotFoundException;
 import org.apache.guacamole.GuacamoleSecurityException;
 import org.apache.guacamole.GuacamoleUnauthorizedException;
-import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
-import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
 import org.apache.guacamole.rest.auth.AuthenticationService;
-import org.apache.guacamole.tunnel.GuacamoleStreamException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -148,7 +147,7 @@ public class RESTExceptionWrapper implements MethodInterceptor {
     }
 
     @Override
-    public Object invoke(MethodInvocation invocation) throws Throwable {
+    public Object invoke(MethodInvocation invocation) throws WebApplicationException {
 
         try {
 
@@ -172,108 +171,27 @@ public class RESTExceptionWrapper implements MethodInterceptor {
 
             }
 
-            // Rethrow unchecked exceptions such that they are properly wrapped
-            catch (RuntimeException e) {
-                throw new GuacamoleException(e.getMessage(), e);
-            }
-
         }
 
-        // Additional credentials are needed
-        catch (GuacamoleInsufficientCredentialsException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Permission denied.";
-
-            throw new APIException(
-                APIError.Type.INSUFFICIENT_CREDENTIALS,
-                message,
-                e.getCredentialsInfo().getFields()
-            );
-        }
-
-        // The provided credentials are wrong
-        catch (GuacamoleInvalidCredentialsException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Permission denied.";
-
-            throw new APIException(
-                APIError.Type.INVALID_CREDENTIALS,
-                message,
-                e.getCredentialsInfo().getFields()
-            );
-        }
-
-        // Generic permission denied
+        // Translate GuacamoleException subclasses to HTTP error codes
         catch (GuacamoleSecurityException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Permission denied.";
-
-            throw new APIException(
-                APIError.Type.PERMISSION_DENIED,
-                message
-            );
-
+            throw new APIException(Response.Status.FORBIDDEN, e);
         }
-
-        // Arbitrary resource not found
         catch (GuacamoleResourceNotFoundException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Not found.";
-
-            throw new APIException(
-                APIError.Type.NOT_FOUND,
-                message
-            );
-
+            throw new APIException(Response.Status.NOT_FOUND, e);
         }
-        
-        // Arbitrary bad requests
         catch (GuacamoleClientException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Invalid request.";
-
-            throw new APIException(
-                APIError.Type.BAD_REQUEST,
-                message
-            );
-
+            throw new APIException(Response.Status.BAD_REQUEST, e);
         }
-
-        // Errors from intercepted streams
-        catch (GuacamoleStreamException e) {
-
-            // Generate default message
-            String message = e.getMessage();
-            if (message == null)
-                message = "Error reported by stream.";
-
-            throw new APIException(
-                e.getStatus(),
-                message
-            );
-
+        catch (GuacamoleException e) {
+            throw new APIException(Response.Status.INTERNAL_SERVER_ERROR, e);
         }
 
-        // All other errors
-        catch (GuacamoleException e) {
+        // Rethrow unchecked exceptions such that they are properly wrapped
+        catch (Throwable t) {
 
-            // Log all reasonable details of exception
-            String message = e.getMessage();
+            // Log all reasonable details of error
+            String message = t.getMessage();
             if (message != null)
                 logger.error("Unexpected internal error: {}", message);
             else
@@ -282,12 +200,10 @@ public class RESTExceptionWrapper implements MethodInterceptor {
                            + "details.");
 
             // Ensure internal errors are fully logged at the debug level
-            logger.debug("Unexpected exception in REST endpoint.", e);
+            logger.debug("Unexpected error in REST endpoint.", t);
 
-            throw new APIException(
-                APIError.Type.INTERNAL_ERROR,
-                "Unexpected server error."
-            );
+            throw new APIException(Response.Status.INTERNAL_SERVER_ERROR,
+                    new GuacamoleException("Unexpected internal error.", t));
 
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/30179c40/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
index b685087..a881f60 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
@@ -19,8 +19,9 @@
 
 package org.apache.guacamole.rest.history;
 
+import javax.ws.rs.core.Response;
+import org.apache.guacamole.GuacamoleClientException;
 import org.apache.guacamole.net.auth.ConnectionRecordSet;
-import org.apache.guacamole.rest.APIError;
 import org.apache.guacamole.rest.APIException;
 
 /**
@@ -111,8 +112,8 @@ public class APIConnectionRecordSortPredicate {
         // Bail out if sort property is not valid
         catch (IllegalArgumentException e) {
             throw new APIException(
-                APIError.Type.BAD_REQUEST,
-                String.format("Invalid sort property: \"%s\"", value)
+                Response.Status.BAD_REQUEST,
+                new GuacamoleClientException(String.format("Invalid sort property: \"%s\"", value))
             );
         }
 


[4/5] incubator-guacamole-client git commit: GUACAMOLE-36: Clarify description/use of Translatable interface.

Posted by jm...@apache.org.
GUACAMOLE-36: Clarify description/use of Translatable interface.

Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/89d3ba44
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/89d3ba44
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/89d3ba44

Branch: refs/heads/master
Commit: 89d3ba44a7c11586c32de68f9e684fac4d8b87ca
Parents: 986ea4b
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Jan 3 19:28:54 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 3 19:42:25 2017 -0800

----------------------------------------------------------------------
 .../main/java/org/apache/guacamole/language/Translatable.java  | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/89d3ba44/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java b/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
index 0b43814..034d985 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
@@ -20,9 +20,9 @@
 package org.apache.guacamole.language;
 
 /**
- * An interface which requires the definition of a translatable message that
- * can be passed through an arbitrary translation service, producing a
- * human-readable message in the user's native language.
+ * An object which is associated with a translatable message that can be passed
+ * through an arbitrary translation service, producing a human-readable message
+ * in the user's native language.
  *
  * @author Michael Jumper
  */


[5/5] incubator-guacamole-client git commit: GUACAMOLE-36: Merge new system for fully translatable error messages.

Posted by jm...@apache.org.
GUACAMOLE-36: Merge new system for fully translatable error messages.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/403c578d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/403c578d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/403c578d

Branch: refs/heads/master
Commit: 403c578da91099aa802833e36ef623bcfd5b6147
Parents: f891f69 89d3ba4
Author: James Muehlner <ja...@guac-dev.org>
Authored: Tue Jan 3 19:57:42 2017 -0800
Committer: James Muehlner <ja...@guac-dev.org>
Committed: Tue Jan 3 19:57:42 2017 -0800

----------------------------------------------------------------------
 .../apache/guacamole/language/Translatable.java |  41 +++++
 .../guacamole/language/TranslatableMessage.java |  96 ++++++++++
 .../org/apache/guacamole/rest/APIError.java     | 183 +++++++++++--------
 .../org/apache/guacamole/rest/APIException.java | 100 ++--------
 .../guacamole/rest/RESTExceptionWrapper.java    | 116 ++----------
 .../APIConnectionRecordSortPredicate.java       |   7 +-
 .../app/client/controllers/clientController.js  |  16 +-
 .../app/index/controllers/indexController.js    |   4 +-
 .../main/webapp/app/login/directives/login.js   |  10 +-
 .../main/webapp/app/login/templates/login.html  |   6 +-
 .../controllers/manageConnectionController.js   |   8 +-
 .../manageConnectionGroupController.js          |   8 +-
 .../manageSharingProfileController.js           |   8 +-
 .../manage/controllers/manageUserController.js  |  15 +-
 .../notification/services/guacNotification.js   |   4 +-
 .../templates/guacNotification.html             |   4 +-
 .../app/notification/types/Notification.js      |   2 +-
 .../src/main/webapp/app/rest/types/Error.js     |   9 +
 .../app/rest/types/TranslatableMessage.js       |  63 +++++++
 .../directives/guacSettingsPreferences.js       |  14 +-
 .../settings/directives/guacSettingsSessions.js |   6 +-
 21 files changed, 420 insertions(+), 300 deletions(-)
----------------------------------------------------------------------



[2/5] incubator-guacamole-client git commit: GUACAMOLE-36: Define REST API transfer mechanism for translatable messages.

Posted by jm...@apache.org.
GUACAMOLE-36: Define REST API transfer mechanism for translatable messages.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/0671f18d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/0671f18d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/0671f18d

Branch: refs/heads/master
Commit: 0671f18d400a1adba977ec345baa966a0b88435d
Parents: 30179c4
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Aug 16 19:31:48 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 3 19:42:24 2017 -0800

----------------------------------------------------------------------
 .../apache/guacamole/language/Translatable.java | 41 +++++++++
 .../guacamole/language/TranslatableMessage.java | 96 ++++++++++++++++++++
 .../org/apache/guacamole/rest/APIError.java     | 33 ++++++-
 .../src/main/webapp/app/rest/types/Error.js     |  9 ++
 .../app/rest/types/TranslatableMessage.js       | 63 +++++++++++++
 5 files changed, 240 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/0671f18d/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java b/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
new file mode 100644
index 0000000..0b43814
--- /dev/null
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/language/Translatable.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.guacamole.language;
+
+/**
+ * An interface which requires the definition of a translatable message that
+ * can be passed through an arbitrary translation service, producing a
+ * human-readable message in the user's native language.
+ *
+ * @author Michael Jumper
+ */
+public interface Translatable {
+
+    /**
+     * Returns a message which can be translated using a translation service,
+     * consisting of a translation key and optional set of substitution
+     * variables.
+     *
+     * @return
+     *     A message which can be translated using a translation service.
+     */
+    TranslatableMessage getTranslatableMessage();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/0671f18d/guacamole-ext/src/main/java/org/apache/guacamole/language/TranslatableMessage.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/language/TranslatableMessage.java b/guacamole-ext/src/main/java/org/apache/guacamole/language/TranslatableMessage.java
new file mode 100644
index 0000000..4aeba9a
--- /dev/null
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/language/TranslatableMessage.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.guacamole.language;
+
+/**
+ * A message which can be translated using a translation service, providing a
+ * translation key and optional set of values to be substituted into the
+ * translation string associated with that key.
+ *
+ * @author Michael Jumper
+ */
+public class TranslatableMessage {
+
+    /**
+     * The arbitrary key which can be used to look up the message to be
+     * displayed in the user's native language.
+     */
+    private final String key;
+
+    /**
+     * An arbitrary object whose properties should be substituted for the
+     * corresponding placeholders within the string associated with the key.
+     */
+    private final Object variables;
+
+    /**
+     * Creates a new TranslatableMessage associated with the given translation
+     * key, without any associated variables.
+     *
+     * @param key
+     *     The translation key to associate with the TranslatableMessage.
+     */
+    public TranslatableMessage(String key) {
+        this(key, null);
+    }
+
+    /**
+     * Creates a new TranslatableMessage associated with the given translation
+     * key and associated variables.
+     *
+     * @param key
+     *     The translation key to associate with the TranslatableMessage.
+     *
+     * @param variables
+     *     An arbitrary object whose properties should be substituted for the
+     *     corresponding placeholders within the string associated with the
+     *     given translation key.
+     */
+    public TranslatableMessage(String key, Object variables) {
+        this.key = key;
+        this.variables = variables;
+    }
+
+    /**
+     * Returns the arbitrary key which can be used to look up the message to be
+     * displayed in the user's native language.
+     *
+     * @return
+     *     The arbitrary key associated with the human-readable message.
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * Returns an arbitrary object whose properties should be substituted for
+     * the corresponding placeholders within the string associated with the key.
+     * If not applicable, null is returned.
+     *
+     * @return
+     *     An arbitrary object whose properties should be substituted for the
+     *     corresponding placeholders within the string associated with the key,
+     *     or null if not applicable.
+     */
+    public Object getVariables() {
+        return variables;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/0671f18d/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java b/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
index 7727b85..2bec055 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/APIError.java
@@ -25,6 +25,8 @@ import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleResourceNotFoundException;
 import org.apache.guacamole.GuacamoleSecurityException;
 import org.apache.guacamole.form.Field;
+import org.apache.guacamole.language.Translatable;
+import org.apache.guacamole.language.TranslatableMessage;
 import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
 import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
 import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
@@ -39,11 +41,16 @@ import org.apache.guacamole.tunnel.GuacamoleStreamException;
 public class APIError {
 
     /**
-     * The error message.
+     * The human-readable error message.
      */
     private final String message;
 
     /**
+     * A translatable message representing the error that occurred.
+     */
+    private final TranslatableMessage translatableMessage;
+
+    /**
      * The associated Guacamole protocol status code.
      */
     private final Integer statusCode;
@@ -148,7 +155,9 @@ public class APIError {
 
     /**
      * Creates a new APIError which exposes the details of the given
-     * GuacamoleException.
+     * GuacamoleException. If the given GuacamoleException implements
+     * Translatable, then its translation string and values will be exposed as
+     * well.
      *
      * @param exception
      *     The GuacamoleException from which the details of the new APIError
@@ -176,6 +185,14 @@ public class APIError {
         else
             this.statusCode = null;
 
+        // Pull translatable message and values if available
+        if (exception instanceof Translatable) {
+            Translatable translatable = (Translatable) exception;
+            this.translatableMessage = translatable.getTranslatableMessage();
+        }
+        else
+            this.translatableMessage = new TranslatableMessage(this.message);
+
     }
 
     /**
@@ -223,4 +240,16 @@ public class APIError {
         return message;
     }
 
+    /**
+     * Returns a translatable message describing the error that occurred. If no
+     * translatable message is associated with the error, this will be null.
+     *
+     * @return
+     *     A translatable message describing the error that occurred, or null
+     *     if there is no such message defined.
+     */
+    public TranslatableMessage getTranslatableMessage() {
+        return translatableMessage;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/0671f18d/guacamole/src/main/webapp/app/rest/types/Error.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/types/Error.js b/guacamole/src/main/webapp/app/rest/types/Error.js
index 43fdc96..47f9cf7 100644
--- a/guacamole/src/main/webapp/app/rest/types/Error.js
+++ b/guacamole/src/main/webapp/app/rest/types/Error.js
@@ -43,6 +43,15 @@ angular.module('rest').factory('Error', [function defineError() {
         this.message = template.message;
 
         /**
+         * A message which can be translated using the translation service,
+         * consisting of a translation key and optional set of substitution
+         * variables.
+         *
+         * @type TranslatableMessage
+         */
+        this.translatableMessage = template.translatableMessage;
+
+        /**
          * The Guacamole protocol status code associated with the error that
          * occurred. This is only valid for errors of type STREAM_ERROR.
          *

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/0671f18d/guacamole/src/main/webapp/app/rest/types/TranslatableMessage.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/types/TranslatableMessage.js b/guacamole/src/main/webapp/app/rest/types/TranslatableMessage.js
new file mode 100644
index 0000000..4542248
--- /dev/null
+++ b/guacamole/src/main/webapp/app/rest/types/TranslatableMessage.js
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * Service which defines the TranslatableMessage class.
+ */
+angular.module('rest').factory('TranslatableMessage', [function defineTranslatableMessage() {
+
+    /**
+     * The object returned by REST API calls when representing a message which
+     * can be translated using the translation service, providing a translation
+     * key and optional set of values to be substituted into the translation
+     * string associated with that key.
+     *
+     * @constructor
+     * @param {TranslatableMessage|Object} [template={}]
+     *     The object whose properties should be copied within the new
+     *     TranslatableMessage.
+     */
+    var TranslatableMessage = function TranslatableMessage(template) {
+
+        // Use empty object by default
+        template = template || {};
+
+        /**
+         * The key associated with the translation string that used when
+         * displaying this message.
+         *
+         * @type String
+         */
+        this.key = template.key;
+
+        /**
+         * The object which should be passed through to the translation service
+         * for the sake of variable substitution. Each property of the provided
+         * object will be substituted for the variable of the same name within
+         * the translation string.
+         *
+         * @type Object
+         */
+        this.variables = template.variables;
+
+    };
+
+    return TranslatableMessage;
+
+}]);
\ No newline at end of file