UX: refactor password reset page (#30323)

This commit is contained in:
Jordan Vidrine 2024-12-17 12:11:02 -06:00 committed by GitHub
parent af8c98217a
commit 8f26ae7b7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 128 additions and 108 deletions

View File

@ -29,6 +29,7 @@ export default class PasswordResetController extends Controller.extend(
requiresApproval = false; requiresApproval = false;
redirected = false; redirected = false;
maskPassword = true; maskPassword = true;
passwordValidationVisible = false;
lockImageUrl = getURL("/images/lock.svg"); lockImageUrl = getURL("/images/lock.svg");
@ -65,6 +66,30 @@ export default class PasswordResetController extends Controller.extend(
return getURL(redirectTo || "/"); return getURL(redirectTo || "/");
} }
@discourseComputed(
"passwordValidation.ok",
"passwordValidation.reason",
"passwordValidationVisible"
)
showPasswordValidation(
passwordValidationOk,
passwordValidationReason,
passwordValidationVisible
) {
return (
passwordValidationOk ||
(passwordValidationReason && passwordValidationVisible)
);
}
@action
togglePasswordValidation() {
this.set(
"passwordValidationVisible",
Boolean(this.passwordValidation.reason)
);
}
@action @action
done(event) { done(event) {
if (wantsNewWindow(event)) { if (wantsNewWindow(event)) {

View File

@ -2,11 +2,7 @@
{{hide-application-sidebar}} {{hide-application-sidebar}}
{{hide-application-header-buttons "search" "login" "signup" "menu"}} {{hide-application-header-buttons "search" "login" "signup" "menu"}}
<div class="container password-reset clearfix"> <div class="container password-reset clearfix">
<div class="pull-left col-image"> <form class="change-password-form login-left-side">
<img src={{this.lockImageUrl}} class="password-reset-img" alt="" />
</div>
<div class="pull-left col-form">
{{#if this.successMessage}} {{#if this.successMessage}}
<p>{{this.successMessage}}</p> <p>{{this.successMessage}}</p>
@ -22,7 +18,6 @@
{{/unless}} {{/unless}}
{{/if}} {{/if}}
{{else}} {{else}}
<form class="change-password-form">
{{#if this.securityKeyOrSecondFactorRequired}} {{#if this.securityKeyOrSecondFactorRequired}}
<h2>{{i18n "user.change_password.title"}}</h2> <h2>{{i18n "user.change_password.title"}}</h2>
<p> <p>
@ -35,9 +30,7 @@
{{#if this.displaySecurityKeyForm}} {{#if this.displaySecurityKeyForm}}
<SecurityKeyForm <SecurityKeyForm
@setSecondFactorMethod={{fn @setSecondFactorMethod={{fn (mut this.selectedSecondFactorMethod)}}
(mut this.selectedSecondFactorMethod)
}}
@backupEnabled={{this.backupEnabled}} @backupEnabled={{this.backupEnabled}}
@totpEnabled={{this.secondFactorRequired}} @totpEnabled={{this.secondFactorRequired}}
@otherMethodAllowed={{this.otherMethodAllowed}} @otherMethodAllowed={{this.otherMethodAllowed}}
@ -72,7 +65,7 @@
/> />
{{/unless}} {{/unless}}
{{else}} {{else}}
<h2>{{i18n "user.change_password.choose"}}</h2> <h2>{{i18n "user.change_password.choose_new"}}</h2>
{{#if this.errorMessage}} {{#if this.errorMessage}}
<div class="alert alert-error">{{this.errorMessage}}</div> <div class="alert alert-error">{{this.errorMessage}}</div>
<br /> <br />
@ -81,24 +74,31 @@
<div class="input"> <div class="input">
<PasswordField <PasswordField
@value={{this.accountPassword}} @value={{this.accountPassword}}
{{on "focusout" this.togglePasswordValidation}}
@capsLockOn={{this.capsLockOn}} @capsLockOn={{this.capsLockOn}}
type={{if this.maskPassword "password" "text"}} type={{if this.maskPassword "password" "text"}}
autofocus="autofocus" autofocus="autofocus"
autocomplete="new-password" autocomplete="new-password"
id="new-account-password" id="new-account-password"
/> />
<TogglePasswordMask <div class="change-password__password-info">
@maskPassword={{this.maskPassword}} <div class="change-password_tip-validation">
@togglePasswordMask={{this.togglePasswordMask}} {{#if this.showPasswordValidation}}
/> <InputTip @validation={{this.passwordValidation}} />
{{/if}}
<div class="caps-lock-warning {{unless this.capsLockOn 'hidden'}}"> <div
class="caps-lock-warning {{unless this.capsLockOn 'hidden'}}"
>
{{d-icon "triangle-exclamation"}} {{d-icon "triangle-exclamation"}}
{{i18n "login.caps_lock_warning"}} {{i18n "login.caps_lock_warning"}}
</div> </div>
</div> </div>
<TogglePasswordMask
<InputTip @validation={{this.passwordValidation}} /> @maskPassword={{this.maskPassword}}
@togglePasswordMask={{this.togglePasswordMask}}
/>
</div>
</div>
<DButton <DButton
@action={{action "submit"}} @action={{action "submit"}}
@ -107,7 +107,6 @@
class="btn-primary" class="btn-primary"
/> />
{{/if}} {{/if}}
</form>
{{/if}} {{/if}}
</div> </form>
</div> </div>

View File

@ -1,4 +1,4 @@
import { click, fillIn, visit } from "@ember/test-helpers"; import { blur, click, fillIn, visit } from "@ember/test-helpers";
import { test } from "qunit"; import { test } from "qunit";
import sinon from "sinon"; import sinon from "sinon";
import PreloadStore from "discourse/lib/preload-store"; import PreloadStore from "discourse/lib/preload-store";
@ -71,6 +71,8 @@ acceptance("Password Reset", function (needs) {
assert.dom(".password-reset .tip.good").exists("input looks good"); assert.dom(".password-reset .tip.good").exists("input looks good");
await fillIn(".password-reset input", "123"); await fillIn(".password-reset input", "123");
await blur(".password-reset input");
assert.dom(".password-reset .tip.bad").exists("input is not valid"); assert.dom(".password-reset .tip.bad").exists("input is not valid");
assert.dom(".password-reset .tip.bad").includesHtml( assert.dom(".password-reset .tip.bad").includesHtml(
i18n("user.password.too_short", { i18n("user.password.too_short", {

View File

@ -11,7 +11,8 @@
body.login-page, body.login-page,
body.signup-page, body.signup-page,
body.invite-page { body.invite-page,
body.password-reset-page {
& ~ .powered-by-discourse, & ~ .powered-by-discourse,
.above-main-container-outlet { .above-main-container-outlet {
display: none; display: none;
@ -25,7 +26,8 @@ body.signup-page {
.login-fullpage, .login-fullpage,
.signup-fullpage, .signup-fullpage,
.invites-show { .invites-show,
.password-reset-page {
.signup-body, .signup-body,
.login-body { .login-body {
display: flex; display: flex;
@ -241,8 +243,6 @@ body.signup-page {
.caps-lock-warning { .caps-lock-warning {
color: var(--danger); color: var(--danger);
font-size: var(--font-down-1); font-size: var(--font-down-1);
font-weight: bold;
margin-top: 0.5em;
} }
.create-account__password-info { .create-account__password-info {

View File

@ -33,28 +33,22 @@ body.invite-page {
// the second button can wrap in some locales, and this helps alignment // the second button can wrap in some locales, and this helps alignment
} }
.password-reset {
.instructions {
label {
color: var(--primary-medium);
}
}
#new-account-password {
width: 15em;
}
.tip {
margin: 0 0 0.5em;
}
.toggle-password-mask {
margin-left: 0.25em;
}
}
.password-reset-page { .password-reset-page {
.caps-lock-warning {
display: inline;
}
.change-password-form { .change-password-form {
margin: 0 auto;
display: flex;
flex-direction: column;
width: 400px;
input {
padding: 0.75em 0.77em;
min-width: 250px;
margin-bottom: 0.25em;
width: 100%;
}
.input {
position: relative;
margin-bottom: 1em;
}
.tip { .tip {
display: block; display: block;
} }