diff --git a/guacamole/src/main/webapp/app/form/directives/form.js b/guacamole/src/main/webapp/app/form/directives/form.js index 518db7dba..be2f3b176 100644 --- a/guacamole/src/main/webapp/app/form/directives/form.js +++ b/guacamole/src/main/webapp/app/form/directives/form.js @@ -64,7 +64,15 @@ angular.module('form').directive('guacForm', [function form() { * * @type Boolean */ - modelOnly : '=' + modelOnly : '=', + + /** + * Whether the contents of the form should be rendered as disabled. + * By default, form fields are enabled. + * + * @type Boolean + */ + disabled : '=' }, templateUrl: 'app/form/templates/form.html', diff --git a/guacamole/src/main/webapp/app/form/directives/formField.js b/guacamole/src/main/webapp/app/form/directives/formField.js index ea0f35fd7..15adc29e4 100644 --- a/guacamole/src/main/webapp/app/form/directives/formField.js +++ b/guacamole/src/main/webapp/app/form/directives/formField.js @@ -53,7 +53,15 @@ angular.module('form').directive('guacFormField', [function formField() { * * @type String */ - model : '=' + model : '=', + + /** + * Whether this field should be rendered as disabled. By default, + * form fields are enabled. + * + * @type Boolean + */ + disabled : '=' }, templateUrl: 'app/form/templates/formField.html', diff --git a/guacamole/src/main/webapp/app/form/services/formService.js b/guacamole/src/main/webapp/app/form/services/formService.js index 168a1efa7..21bfb4742 100644 --- a/guacamole/src/main/webapp/app/form/services/formService.js +++ b/guacamole/src/main/webapp/app/form/services/formService.js @@ -213,6 +213,10 @@ angular.module('form').provider('formService', function formServiceProvider() { * model: * The current String value of the field, if any. * + * disabled: + * A boolean value which is true if the field should be disabled. + * If false or undefined, the field should be enabled. + * * @param {Element} fieldContainer * The DOM Element whose contents should be replaced with the * compiled field template. diff --git a/guacamole/src/main/webapp/app/form/templates/checkboxField.html b/guacamole/src/main/webapp/app/form/templates/checkboxField.html index ad9d8e006..b76368afe 100644 --- a/guacamole/src/main/webapp/app/form/templates/checkboxField.html +++ b/guacamole/src/main/webapp/app/form/templates/checkboxField.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/form/templates/dateField.html b/guacamole/src/main/webapp/app/form/templates/dateField.html index a186e19a5..b6af5463c 100644 --- a/guacamole/src/main/webapp/app/form/templates/dateField.html +++ b/guacamole/src/main/webapp/app/form/templates/dateField.html @@ -1,5 +1,6 @@
diff --git a/guacamole/src/main/webapp/app/form/templates/numberField.html b/guacamole/src/main/webapp/app/form/templates/numberField.html index 3d6312e20..007297365 100644 --- a/guacamole/src/main/webapp/app/form/templates/numberField.html +++ b/guacamole/src/main/webapp/app/form/templates/numberField.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/form/templates/passwordField.html b/guacamole/src/main/webapp/app/form/templates/passwordField.html index 506d8b6b2..56472ef4e 100644 --- a/guacamole/src/main/webapp/app/form/templates/passwordField.html +++ b/guacamole/src/main/webapp/app/form/templates/passwordField.html @@ -1,4 +1,4 @@
- +
\ No newline at end of file diff --git a/guacamole/src/main/webapp/app/form/templates/selectField.html b/guacamole/src/main/webapp/app/form/templates/selectField.html index 3bd2bb876..2f2b9d5ee 100644 --- a/guacamole/src/main/webapp/app/form/templates/selectField.html +++ b/guacamole/src/main/webapp/app/form/templates/selectField.html @@ -1 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/form/templates/textAreaField.html b/guacamole/src/main/webapp/app/form/templates/textAreaField.html index 082476f14..e049df60d 100644 --- a/guacamole/src/main/webapp/app/form/templates/textAreaField.html +++ b/guacamole/src/main/webapp/app/form/templates/textAreaField.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/form/templates/textField.html b/guacamole/src/main/webapp/app/form/templates/textField.html index a338db4cd..819ae038a 100644 --- a/guacamole/src/main/webapp/app/form/templates/textField.html +++ b/guacamole/src/main/webapp/app/form/templates/textField.html @@ -1,5 +1,6 @@
- + diff --git a/guacamole/src/main/webapp/app/form/templates/timeField.html b/guacamole/src/main/webapp/app/form/templates/timeField.html index 24ae968b0..d45f54c91 100644 --- a/guacamole/src/main/webapp/app/form/templates/timeField.html +++ b/guacamole/src/main/webapp/app/form/templates/timeField.html @@ -1,5 +1,6 @@
diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js index 562e3972e..aad7020b9 100644 --- a/guacamole/src/main/webapp/app/login/directives/login.js +++ b/guacamole/src/main/webapp/app/login/directives/login.js @@ -66,6 +66,7 @@ angular.module('login').directive('guacLogin', [function guacLogin() { var Field = $injector.get('Field'); // Required services + var $rootScope = $injector.get('$rootScope'); var $route = $injector.get('$route'); var authenticationService = $injector.get('authenticationService'); var requestService = $injector.get('requestService'); @@ -91,6 +92,16 @@ angular.module('login').directive('guacLogin', [function guacLogin() { */ $scope.remainingFields = []; + /** + * Whether an authentication attempt has been submitted. This will be + * set to true once credentials have been submitted and will only be + * reset to false once the attempt has been fully processed, including + * rerouting the user to the requested page if the attempt succeeded. + * + * @type Boolean + */ + $scope.submitted = false; + /** * Returns whether a previous login attempt is continuing. * @@ -141,21 +152,27 @@ angular.module('login').directive('guacLogin', [function guacLogin() { */ $scope.login = function login() { + // Authentication is now in progress + $scope.submitted = true; + // Start with cleared status - $scope.loginError = null; + $scope.loginError = null; // Attempt login once existing session is destroyed authenticationService.authenticate($scope.enteredValues) - // Clear and reload upon success + // Retry route upon success (entered values will be cleared only + // after route change has succeeded as this can take time) .then(function loginSuccessful() { - $scope.enteredValues = {}; $route.reload(); }) // Reset upon failure ['catch'](requestService.createErrorCallback(function loginFailed(error) { + // Initial submission is complete and has failed + $scope.submitted = false; + // Clear out passwords if the credentials were rejected for any reason if (error.type !== Error.Type.INSUFFICIENT_CREDENTIALS) { @@ -183,6 +200,12 @@ angular.module('login').directive('guacLogin', [function guacLogin() { }; + // Reset state after authentication and routing have succeeded + $rootScope.$on('$routeChangeSuccess', function routeChanged() { + $scope.enteredValues = {}; + $scope.submitted = false; + }); + }]; return directive; diff --git a/guacamole/src/main/webapp/app/login/styles/dialog.css b/guacamole/src/main/webapp/app/login/styles/dialog.css index c9c6a4af6..e83353331 100644 --- a/guacamole/src/main/webapp/app/login/styles/dialog.css +++ b/guacamole/src/main/webapp/app/login/styles/dialog.css @@ -17,27 +17,20 @@ * under the License. */ -.login-ui.error .login-dialog { - animation-name: shake-head; - animation-duration: 0.25s; - animation-timing-function: linear; - -webkit-animation-name: shake-head; - -webkit-animation-duration: 0.25s; - -webkit-animation-timing-function: linear; +.login-ui { + animation: fadein 0.125s linear; + -moz-animation: fadein 0.125s linear; + -webkit-animation: fadein 0.125s linear; } -.login-ui div.login-dialog-middle { +.login-ui .login-dialog-middle { width: 100%; display: table-cell; vertical-align: middle; text-align: center; } -.login-ui div.login-dialog { - - animation: fadein 0.125s linear; - -moz-animation: fadein 0.125s linear; - -webkit-animation: fadein 0.125s linear; +.login-ui .login-dialog { width: 100%; max-width: 3in; @@ -115,7 +108,7 @@ background-image: url("images/guac-tricolor.png"); } -.login-ui.continuation div.login-dialog { +.login-ui.continuation .login-dialog { border-right: none; border-left: none; box-shadow: none; @@ -126,3 +119,12 @@ .login-ui.continuation .login-dialog .version { display: none; } + +.login-ui.error .login-dialog { + animation-name: shake-head; + animation-duration: 0.25s; + animation-timing-function: linear; + -webkit-animation-name: shake-head; + -webkit-animation-duration: 0.25s; + -webkit-animation-timing-function: linear; +} diff --git a/guacamole/src/main/webapp/app/login/templates/login.html b/guacamole/src/main/webapp/app/login/templates/login.html index 26a3f1889..833fef61b 100644 --- a/guacamole/src/main/webapp/app/login/templates/login.html +++ b/guacamole/src/main/webapp/app/login/templates/login.html @@ -23,13 +23,24 @@ - +
- - + + + + +