mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Added HTML5 form.reportValidity() to login screens
This improves browser feedback on form errors
This commit is contained in:
parent
612aff4b27
commit
cca0fc15da
5 changed files with 74 additions and 105 deletions
|
|
@ -58,10 +58,10 @@ class RemoteUserFetch extends AbstractFetchRemote {
|
||||||
* @param {string=} sAdditionalCode
|
* @param {string=} sAdditionalCode
|
||||||
* @param {boolean=} bAdditionalCodeSignMe
|
* @param {boolean=} bAdditionalCodeSignMe
|
||||||
*/
|
*/
|
||||||
login(fCallback, sEmail, sLogin, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe) {
|
login(fCallback, sEmail, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe) {
|
||||||
this.defaultRequest(fCallback, 'Login', {
|
this.defaultRequest(fCallback, 'Login', {
|
||||||
Email: sEmail,
|
Email: sEmail,
|
||||||
Login: sLogin,
|
Login: '',
|
||||||
Password: sPassword,
|
Password: sPassword,
|
||||||
Language: sLanguage || '',
|
Language: sLanguage || '',
|
||||||
AdditionalCode: sAdditionalCode || '',
|
AdditionalCode: sAdditionalCode || '',
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,7 @@ class LoginAdminView extends AbstractViewCenter {
|
||||||
|
|
||||||
this.addSubscribables({
|
this.addSubscribables({
|
||||||
login: () => this.loginError(false),
|
login: () => this.loginError(false),
|
||||||
|
password: () => this.passwordError(false)
|
||||||
password: () => this.passwordError(false),
|
|
||||||
|
|
||||||
loginError: v => this.formError(!!v),
|
|
||||||
|
|
||||||
passwordError: v => this.formError(!!v)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
decorateKoCommands(this, {
|
decorateKoCommands(this, {
|
||||||
|
|
@ -44,33 +39,33 @@ class LoginAdminView extends AbstractViewCenter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
submitCommand() {
|
submitCommand(self, event) {
|
||||||
this.loginError(false);
|
const valid = event.target.form.reportValidity(),
|
||||||
this.passwordError(false);
|
name = this.login().trim(),
|
||||||
|
pass = this.password();
|
||||||
|
|
||||||
this.loginError(!this.login().trim());
|
this.loginError(!name);
|
||||||
this.passwordError(!this.password().trim());
|
this.passwordError(!pass);
|
||||||
|
this.formError(!valid);
|
||||||
if (this.loginError() || this.passwordError()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
this.submitRequest(true);
|
this.submitRequest(true);
|
||||||
|
|
||||||
Remote.adminLogin(
|
Remote.adminLogin(
|
||||||
(iError) => {
|
iError => {
|
||||||
this.submitRequest(false);
|
|
||||||
if (iError) {
|
if (iError) {
|
||||||
|
this.submitRequest(false);
|
||||||
this.submitError(getNotification(iError));
|
this.submitError(getNotification(iError));
|
||||||
} else {
|
} else {
|
||||||
rl.route.reload();
|
rl.route.reload();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
this.login(),
|
name,
|
||||||
this.password()
|
pass
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|
@ -78,7 +73,7 @@ class LoginAdminView extends AbstractViewCenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.submitCommand();
|
// return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,13 +95,8 @@ class LoginUserView extends AbstractViewCenter {
|
||||||
password: () => this.passwordError(false),
|
password: () => this.passwordError(false),
|
||||||
|
|
||||||
additionalCode: () => this.additionalCodeError(false),
|
additionalCode: () => this.additionalCodeError(false),
|
||||||
additionalCodeError: bV => this.formError(!!bV),
|
|
||||||
additionalCodeVisibility: () => this.additionalCodeError(false),
|
additionalCodeVisibility: () => this.additionalCodeError(false),
|
||||||
|
|
||||||
emailError: bV => this.formError(!!bV),
|
|
||||||
|
|
||||||
passwordError: bV => this.formError(!!bV),
|
|
||||||
|
|
||||||
submitError: value => value || this.submitErrorAddidional(''),
|
submitError: value => value || this.submitErrorAddidional(''),
|
||||||
|
|
||||||
signMeType: iValue => this.signMe(LoginSignMeType.DefaultOn === iValue)
|
signMeType: iValue => this.signMe(LoginSignMeType.DefaultOn === iValue)
|
||||||
|
|
@ -116,72 +111,53 @@ class LoginUserView extends AbstractViewCenter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
windowOpenFeatures(wh) {
|
submitCommand(self, event) {
|
||||||
return `left=200,top=100,width=${wh},height=${wh},menubar=no,status=no,resizable=yes,scrollbars=yes`;
|
let email = this.email().trim(),
|
||||||
}
|
valid = event.target.form.reportValidity() && email,
|
||||||
|
pass = this.password(),
|
||||||
|
totp = this.additionalCodeVisibility(),
|
||||||
|
code = totp ? this.additionalCode() : '';
|
||||||
|
|
||||||
submitCommand() {
|
this.emailError(!email);
|
||||||
this.emailError(false);
|
this.passwordError(!pass);
|
||||||
this.passwordError(false);
|
this.formError(!valid);
|
||||||
|
this.additionalCodeError(totp && !code);
|
||||||
let error;
|
|
||||||
if (this.additionalCodeVisibility()) {
|
|
||||||
this.additionalCodeError(false);
|
|
||||||
if (!this.additionalCode().trim()) {
|
|
||||||
this.additionalCodeError(true);
|
|
||||||
error = '.inputAdditionalCode';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this.password().trim()) {
|
|
||||||
this.passwordError(true);
|
|
||||||
error = '#RainLoopPassword';
|
|
||||||
}
|
|
||||||
if (!this.email().trim()) {
|
|
||||||
this.emailError(true);
|
|
||||||
error = '#RainLoopEmail';
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
this.querySelector(error).focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
this.submitRequest(true);
|
this.submitRequest(true);
|
||||||
|
|
||||||
const fLoginRequest = (sLoginPassword) => {
|
|
||||||
Remote.login(
|
Remote.login(
|
||||||
(iError, oData) => {
|
(iError, oData) => {
|
||||||
this.submitRequest(false);
|
|
||||||
if (iError) {
|
if (iError) {
|
||||||
|
this.submitRequest(false);
|
||||||
if (Notification.InvalidInputArgument == iError) {
|
if (Notification.InvalidInputArgument == iError) {
|
||||||
iError = Notification.AuthError;
|
iError = Notification.AuthError;
|
||||||
}
|
}
|
||||||
this.submitError(getNotification(iError, oData.ErrorMessage, Notification.UnknownNotification));
|
this.submitError(getNotification(iError, oData.ErrorMessage, Notification.UnknownNotification));
|
||||||
this.submitErrorAddidional((oData && oData.ErrorMessageAdditional) || '');
|
this.submitErrorAddidional((oData && oData.ErrorMessageAdditional) || '');
|
||||||
} else {
|
} else if (oData.TwoFactorAuth) {
|
||||||
if (oData.TwoFactorAuth) {
|
this.submitRequest(false);
|
||||||
this.additionalCode('');
|
this.additionalCode('');
|
||||||
this.additionalCodeVisibility(true);
|
this.additionalCodeVisibility(true);
|
||||||
setTimeout(() => this.querySelector('.inputAdditionalCode').focus(), 100);
|
let input = this.querySelector('.inputAdditionalCode');
|
||||||
|
input.required = true;
|
||||||
|
setTimeout(() => input.focus(), 100);
|
||||||
} else {
|
} else {
|
||||||
rl.route.reload();
|
rl.route.reload();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
this.email(),
|
email,
|
||||||
'',
|
pass,
|
||||||
sLoginPassword,
|
|
||||||
!!this.signMe(),
|
!!this.signMe(),
|
||||||
this.bSendLanguage ? this.language() : '',
|
this.bSendLanguage ? this.language() : '',
|
||||||
this.additionalCodeVisibility() ? this.additionalCode() : '',
|
code,
|
||||||
this.additionalCodeVisibility() ? !!this.additionalCodeSignMe() : false
|
!!(totp && this.additionalCodeSignMe())
|
||||||
);
|
);
|
||||||
|
|
||||||
Local.set(ClientSideKeyName.LastSignMe, this.signMe() ? '-1-' : '-0-');
|
Local.set(ClientSideKeyName.LastSignMe, this.signMe() ? '-1-' : '-0-');
|
||||||
};
|
}
|
||||||
|
|
||||||
fLoginRequest(this.password());
|
return valid;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|
@ -234,7 +210,7 @@ class LoginUserView extends AbstractViewCenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.submitCommand();
|
// return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectLanguage() {
|
selectLanguage() {
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,9 @@
|
||||||
<form class="wrapper submitting-pane loginForm" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'submitting': submitRequest()}">
|
<form class="wrapper submitting-pane loginForm" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'submitting': submitRequest()}">
|
||||||
<div class="controls" data-bind="css: {'error': loginError}">
|
<div class="controls" data-bind="css: {'error': loginError}">
|
||||||
<div class="input-append">
|
<div class="input-append">
|
||||||
<input type="text" class="input-block-level inputLogin"
|
<input required="" type="text" class="input-block-level inputLogin"
|
||||||
name="RainLoopAdminLogin" id="RainLoopAdminLogin"
|
autofocus="" autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
autofocus=""
|
data-i18n="[placeholder]LOGIN/LABEL_LOGIN"
|
||||||
autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_LOGIN"
|
|
||||||
data-bind="textInput: login, disable: submitRequest" />
|
data-bind="textInput: login, disable: submitRequest" />
|
||||||
<span class="add-on">
|
<span class="add-on">
|
||||||
<i class="fontastic">👤</i>
|
<i class="fontastic">👤</i>
|
||||||
|
|
@ -20,9 +19,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="controls" data-bind="css: {'error': passwordError}">
|
<div class="controls" data-bind="css: {'error': passwordError}">
|
||||||
<div class="input-append">
|
<div class="input-append">
|
||||||
<input type="password" class="input-block-level inputPassword"
|
<input required="" type="password" class="input-block-level inputPassword"
|
||||||
placeholder="Password" name="RainLoopAdminPassword" id="RainLoopAdminPassword"
|
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD"
|
data-i18n="[placeholder]LOGIN/LABEL_PASSWORD"
|
||||||
data-bind="textInput: password, disable: submitRequest" />
|
data-bind="textInput: password, disable: submitRequest" />
|
||||||
<span class="add-on" tabindex="-1" data-bind="command: submitCommand, tooltip: 'LOGIN/BUTTON_LOGIN'">
|
<span class="add-on" tabindex="-1" data-bind="command: submitCommand, tooltip: 'LOGIN/BUTTON_LOGIN'">
|
||||||
<i class="fontastic" data-bind="visible: '' === password()">🔑</i>
|
<i class="fontastic" data-bind="visible: '' === password()">🔑</i>
|
||||||
|
|
@ -30,13 +29,13 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls controls-submit-wrp" data-bind="hidden: hideSubmitButton">
|
<div class="controls" data-bind="hidden: hideSubmitButton">
|
||||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand">
|
<button type="submit" class="btn btn-large btn-block buttonLogin"
|
||||||
<span data-i18n="LOGIN/BUTTON_LOGIN"></span>
|
data-bind="command: submitCommand"
|
||||||
|
data-i18n="LOGIN/BUTTON_LOGIN">
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,9 @@
|
||||||
<div class="controls plugin-mark-Login-TopControlGroup"
|
<div class="controls plugin-mark-Login-TopControlGroup"
|
||||||
data-bind="css: {'error': emailError}">
|
data-bind="css: {'error': emailError}">
|
||||||
<div class="input-append">
|
<div class="input-append">
|
||||||
<input type="email" class="input-block-level inputEmail"
|
<input required="" type="text" class="input-block-level inputEmail"
|
||||||
name="RainLoopEmail" id="RainLoopEmail"
|
pattern="[^@\s]+(@[^\s]+)?" inputmode="email"
|
||||||
autofocus=""
|
autofocus="" autocomplete="email" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
autocomplete="email" autocorrect="off" autocapitalize="off" spellcheck="false"
|
|
||||||
data-bind="textInput: email, disable: submitRequest"
|
data-bind="textInput: email, disable: submitRequest"
|
||||||
data-i18n="[placeholder]GLOBAL/EMAIL" />
|
data-i18n="[placeholder]GLOBAL/EMAIL" />
|
||||||
<span class="add-on">
|
<span class="add-on">
|
||||||
|
|
@ -31,8 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="controls" data-bind="css: {'error': passwordError}">
|
<div class="controls" data-bind="css: {'error': passwordError}">
|
||||||
<div class="input-append">
|
<div class="input-append">
|
||||||
<input type="password" class="input-block-level inputPassword"
|
<input required="" type="password" class="input-block-level inputPassword"
|
||||||
name="RainLoopPassword" id="RainLoopPassword"
|
|
||||||
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
data-bind="textInput: password, disable: submitRequest"
|
data-bind="textInput: password, disable: submitRequest"
|
||||||
data-i18n="[placeholder]GLOBAL/PASSWORD" />
|
data-i18n="[placeholder]GLOBAL/PASSWORD" />
|
||||||
|
|
@ -46,11 +44,12 @@
|
||||||
<div class="controls"
|
<div class="controls"
|
||||||
data-bind="visible: additionalCodeVisibility(), css: {'error': additionalCodeError}">
|
data-bind="visible: additionalCodeVisibility(), css: {'error': additionalCodeError}">
|
||||||
<div class="input-append">
|
<div class="input-append">
|
||||||
<input type="text" class="input-block-level inputAdditionalCode" autocomplete="off"
|
<input type="text" class="input-block-level inputAdditionalCode"
|
||||||
autocorrect="off" autocapitalize="off" spellcheck="false" style="padding-right: 35px;"
|
inputmode="numeric"
|
||||||
|
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="padding-right: 35px;"
|
||||||
data-bind="textInput: additionalCode, disable: submitRequest"
|
data-bind="textInput: additionalCode, disable: submitRequest"
|
||||||
data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
|
data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
|
||||||
<span class="add-on fontastic">🔑</span>
|
<span class="add-on"><i class="fontastic">🔑</i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls plugin-mark-Login-BottomControlGroup"
|
<div class="controls plugin-mark-Login-BottomControlGroup"
|
||||||
|
|
@ -63,7 +62,7 @@
|
||||||
}
|
}
|
||||||
}"></div>
|
}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls controls-submit-wrp" data-bind="hidden: hideSubmitButton">
|
<div class="controls" data-bind="hidden: hideSubmitButton">
|
||||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand">
|
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand">
|
||||||
<span class="i18n-animation" data-i18n="LOGIN/BUTTON_SIGN_IN"></span>
|
<span class="i18n-animation" data-i18n="LOGIN/BUTTON_SIGN_IN"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue