mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUACAMOLE-742: Merge provide feedback while login is in progress.
This commit is contained in:
@@ -64,7 +64,15 @@ angular.module('form').directive('guacForm', [function form() {
|
|||||||
*
|
*
|
||||||
* @type Boolean
|
* @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',
|
templateUrl: 'app/form/templates/form.html',
|
||||||
|
@@ -53,7 +53,15 @@ angular.module('form').directive('guacFormField', [function formField() {
|
|||||||
*
|
*
|
||||||
* @type String
|
* @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',
|
templateUrl: 'app/form/templates/formField.html',
|
||||||
|
@@ -213,6 +213,10 @@ angular.module('form').provider('formService', function formServiceProvider() {
|
|||||||
* model:
|
* model:
|
||||||
* The current String value of the field, if any.
|
* 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
|
* @param {Element} fieldContainer
|
||||||
* The DOM Element whose contents should be replaced with the
|
* The DOM Element whose contents should be replaced with the
|
||||||
* compiled field template.
|
* compiled field template.
|
||||||
|
@@ -1 +1 @@
|
|||||||
<input type="checkbox" ng-model="typedValue" autocorrect="off" autocapitalize="off"/>
|
<input type="checkbox" ng-disabled="disabled" ng-model="typedValue" autocorrect="off" autocapitalize="off"/>
|
@@ -1,5 +1,6 @@
|
|||||||
<div class="date-field">
|
<div class="date-field">
|
||||||
<input type="date"
|
<input type="date"
|
||||||
|
ng-disabled="disabled"
|
||||||
ng-model="typedValue"
|
ng-model="typedValue"
|
||||||
ng-model-options="modelOptions"
|
ng-model-options="modelOptions"
|
||||||
guac-lenient-date
|
guac-lenient-date
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<div class="email-field">
|
<div class="email-field">
|
||||||
<input type="email"
|
<input type="email"
|
||||||
|
ng-disabled="disabled"
|
||||||
ng-model="model"
|
ng-model="model"
|
||||||
ng-hide="readOnly"
|
ng-hide="readOnly"
|
||||||
autocorrect="off"
|
autocorrect="off"
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
<div class="fields">
|
<div class="fields">
|
||||||
<guac-form-field ng-repeat="field in form.fields" namespace="namespace"
|
<guac-form-field ng-repeat="field in form.fields" namespace="namespace"
|
||||||
ng-if="isVisible(field)"
|
ng-if="isVisible(field)"
|
||||||
|
disabled="disabled"
|
||||||
field="field" model="values[field.name]"></guac-form-field>
|
field="field" model="values[field.name]"></guac-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
<input type="number" ng-model="typedValue" autocorrect="off" autocapitalize="off"/>
|
<input type="number" ng-disabled="disabled" ng-model="typedValue" autocorrect="off" autocapitalize="off"/>
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="password-field">
|
<div class="password-field">
|
||||||
<input type="{{passwordInputType}}" ng-model="model" ng-trim="false" autocorrect="off" autocapitalize="off"/>
|
<input type="{{passwordInputType}}" ng-disabled="disabled" ng-model="model" ng-trim="false" autocorrect="off" autocapitalize="off"/>
|
||||||
<div class="icon toggle-password" ng-click="togglePassword()" title="{{getTogglePasswordHelpText() | translate}}"></div>
|
<div class="icon toggle-password" ng-click="togglePassword()" title="{{getTogglePasswordHelpText() | translate}}"></div>
|
||||||
</div>
|
</div>
|
@@ -1 +1,2 @@
|
|||||||
<select ng-model="model" ng-options="option as getFieldOption(option) | translate for option in field.options | orderBy: value"></select>
|
<select ng-model="model" ng-disabled="disabled"
|
||||||
|
ng-options="option as getFieldOption(option) | translate for option in field.options | orderBy: value"></select>
|
@@ -1 +1 @@
|
|||||||
<textarea ng-model="model" autocorrect="off" autocapitalize="off"></textarea>
|
<textarea ng-model="model" autocorrect="off" autocapitalize="off" ng-disabled="disabled"></textarea>
|
@@ -1,5 +1,6 @@
|
|||||||
<div class="text-field">
|
<div class="text-field">
|
||||||
<input type="text" ng-model="model" autocorrect="off" autocapitalize="off" ng-attr-list="{{ dataListId }}"/>
|
<input type="text" ng-model="model" autocorrect="off" autocapitalize="off"
|
||||||
|
ng-disabled="disabled" ng-attr-list="{{ dataListId }}"/>
|
||||||
<datalist ng-if="dataListId" id="{{ dataListId }}">
|
<datalist ng-if="dataListId" id="{{ dataListId }}">
|
||||||
<option ng-repeat="option in field.options | orderBy: option"
|
<option ng-repeat="option in field.options | orderBy: option"
|
||||||
value="{{ option }}">{{ getFieldOption(option) | translate }}</option>
|
value="{{ option }}">{{ getFieldOption(option) | translate }}</option>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<div class="time-field">
|
<div class="time-field">
|
||||||
<input type="time"
|
<input type="time"
|
||||||
|
ng-disabled="disabled"
|
||||||
ng-model="typedValue"
|
ng-model="typedValue"
|
||||||
ng-model-options="modelOptions"
|
ng-model-options="modelOptions"
|
||||||
guac-lenient-time
|
guac-lenient-time
|
||||||
|
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
<!-- Available time zone regions -->
|
<!-- Available time zone regions -->
|
||||||
<select class="time-zone-region"
|
<select class="time-zone-region"
|
||||||
|
ng-disabled="disabled"
|
||||||
ng-model="region"
|
ng-model="region"
|
||||||
ng-options="name for name in regions | orderBy: name"></select>
|
ng-options="name for name in regions | orderBy: name"></select>
|
||||||
|
|
||||||
<!-- Time zones within selected region -->
|
<!-- Time zones within selected region -->
|
||||||
<select class="time-zone"
|
<select class="time-zone"
|
||||||
ng-disabled="!region"
|
ng-disabled="disabled || !region"
|
||||||
ng-model="model"
|
ng-model="model"
|
||||||
ng-options="timeZone.value as timeZone.key for timeZone in timeZones[region] | toArray | orderBy: key"></select>
|
ng-options="timeZone.value as timeZone.key for timeZone in timeZones[region] | toArray | orderBy: key"></select>
|
||||||
|
|
||||||
|
@@ -66,6 +66,7 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
|
|||||||
var Field = $injector.get('Field');
|
var Field = $injector.get('Field');
|
||||||
|
|
||||||
// Required services
|
// Required services
|
||||||
|
var $rootScope = $injector.get('$rootScope');
|
||||||
var $route = $injector.get('$route');
|
var $route = $injector.get('$route');
|
||||||
var authenticationService = $injector.get('authenticationService');
|
var authenticationService = $injector.get('authenticationService');
|
||||||
var requestService = $injector.get('requestService');
|
var requestService = $injector.get('requestService');
|
||||||
@@ -91,6 +92,16 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
|
|||||||
*/
|
*/
|
||||||
$scope.remainingFields = [];
|
$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.
|
* Returns whether a previous login attempt is continuing.
|
||||||
*
|
*
|
||||||
@@ -141,21 +152,27 @@ angular.module('login').directive('guacLogin', [function guacLogin() {
|
|||||||
*/
|
*/
|
||||||
$scope.login = function login() {
|
$scope.login = function login() {
|
||||||
|
|
||||||
|
// Authentication is now in progress
|
||||||
|
$scope.submitted = true;
|
||||||
|
|
||||||
// Start with cleared status
|
// Start with cleared status
|
||||||
$scope.loginError = null;
|
$scope.loginError = null;
|
||||||
|
|
||||||
// Attempt login once existing session is destroyed
|
// Attempt login once existing session is destroyed
|
||||||
authenticationService.authenticate($scope.enteredValues)
|
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() {
|
.then(function loginSuccessful() {
|
||||||
$scope.enteredValues = {};
|
|
||||||
$route.reload();
|
$route.reload();
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reset upon failure
|
// Reset upon failure
|
||||||
['catch'](requestService.createErrorCallback(function loginFailed(error) {
|
['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
|
// Clear out passwords if the credentials were rejected for any reason
|
||||||
if (error.type !== Error.Type.INSUFFICIENT_CREDENTIALS) {
|
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;
|
return directive;
|
||||||
|
@@ -17,27 +17,20 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.login-ui.error .login-dialog {
|
.login-ui {
|
||||||
animation-name: shake-head;
|
animation: fadein 0.125s linear;
|
||||||
animation-duration: 0.25s;
|
-moz-animation: fadein 0.125s linear;
|
||||||
animation-timing-function: linear;
|
-webkit-animation: fadein 0.125s linear;
|
||||||
-webkit-animation-name: shake-head;
|
|
||||||
-webkit-animation-duration: 0.25s;
|
|
||||||
-webkit-animation-timing-function: linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-ui div.login-dialog-middle {
|
.login-ui .login-dialog-middle {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-ui div.login-dialog {
|
.login-ui .login-dialog {
|
||||||
|
|
||||||
animation: fadein 0.125s linear;
|
|
||||||
-moz-animation: fadein 0.125s linear;
|
|
||||||
-webkit-animation: fadein 0.125s linear;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 3in;
|
max-width: 3in;
|
||||||
@@ -115,7 +108,7 @@
|
|||||||
background-image: url("images/guac-tricolor.png");
|
background-image: url("images/guac-tricolor.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-ui.continuation div.login-dialog {
|
.login-ui.continuation .login-dialog {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@@ -126,3 +119,12 @@
|
|||||||
.login-ui.continuation .login-dialog .version {
|
.login-ui.continuation .login-dialog .version {
|
||||||
display: none;
|
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;
|
||||||
|
}
|
||||||
|
@@ -23,13 +23,24 @@
|
|||||||
|
|
||||||
<!-- Login fields -->
|
<!-- Login fields -->
|
||||||
<div class="login-fields">
|
<div class="login-fields">
|
||||||
<guac-form namespace="'LOGIN'" content="remainingFields" model="enteredValues"></guac-form>
|
<guac-form
|
||||||
|
namespace="'LOGIN'"
|
||||||
|
content="remainingFields"
|
||||||
|
model="enteredValues"
|
||||||
|
disabled="submitted"></guac-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Submit button -->
|
<!-- Login/continue button -->
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<input type="submit" name="login" class="login" value="{{'LOGIN.ACTION_LOGIN' | translate}}"/>
|
|
||||||
<input type="submit" name="login" class="continue-login" value="{{'LOGIN.ACTION_CONTINUE' | translate}}"/>
|
<input type="submit" name="login" class="login"
|
||||||
|
ng-disabled="submitted"
|
||||||
|
value="{{'LOGIN.ACTION_LOGIN' | translate}}"/>
|
||||||
|
|
||||||
|
<input type="submit" name="login" class="continue-login"
|
||||||
|
ng-disabled="submitted"
|
||||||
|
value="{{'LOGIN.ACTION_CONTINUE' | translate}}"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
Reference in New Issue
Block a user