DEV: refactor components dependent on UsernameValidation to use related tracked properties and native inputs (#30946)

This will update properties that are used by the UsernameValidation
mixin to autotracking and also updates the use of Input component in
these templates to native inputs. This will help the refactor of the
mixin to a helper class that uses the modern Ember reactivity system.
This commit is contained in:
Kelv 2025-01-24 13:57:16 +08:00 committed by GitHub
parent 8be16c997e
commit 084ed7a457
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 55 additions and 32 deletions

View File

@ -70,9 +70,11 @@
</div> </div>
<div class="input-group create-account__username"> <div class="input-group create-account__username">
<Input <input
{{on "focusin" this.scrollInputIntoView}} {{on "focusin" this.scrollInputIntoView}}
@value={{this.model.accountUsername}} {{on "input" this.setAccountUsername}}
type="text"
value={{this.accountUsername}}
disabled={{this.usernameDisabled}} disabled={{this.usernameDisabled}}
maxlength={{this.maxUsernameLength}} maxlength={{this.maxUsernameLength}}
aria-describedby="username-validation username-validation-more-info" aria-describedby="username-validation username-validation-more-info"
@ -80,7 +82,7 @@
autocomplete="off" autocomplete="off"
name="username" name="username"
id="new-account-username" id="new-account-username"
class={{value-entered this.model.accountUsername}} class={{value-entered this.accountUsername}}
/> />
<label class="alt-placeholder" for="new-account-username"> <label class="alt-placeholder" for="new-account-username">
{{i18n "user.username.title"}} {{i18n "user.username.title"}}
@ -114,7 +116,7 @@
@name="create-account-before-password" @name="create-account-before-password"
@outletArgs={{hash @outletArgs={{hash
accountName=this.model.accountName accountName=this.model.accountName
accountUsername=this.model.accountUsername accountUsername=this.accountUsername
accountPassword=this.accountPassword accountPassword=this.accountPassword
userFields=this.userFields userFields=this.userFields
authOptions=this.model.authOptions authOptions=this.model.authOptions
@ -206,7 +208,7 @@
@name="create-account-after-password" @name="create-account-after-password"
@outletArgs={{hash @outletArgs={{hash
accountName=this.model.accountName accountName=this.model.accountName
accountUsername=this.model.accountUsername accountUsername=this.accountUsername
accountPassword=this.accountPassword accountPassword=this.accountPassword
userFields=this.userFields userFields=this.userFields
}} }}
@ -243,7 +245,7 @@
@name="create-account-after-user-fields" @name="create-account-after-user-fields"
@outletArgs={{hash @outletArgs={{hash
accountName=this.model.accountName accountName=this.model.accountName
accountUsername=this.model.accountUsername accountUsername=this.accountUsername
accountPassword=this.accountPassword accountPassword=this.accountPassword
userFields=this.userFields userFields=this.userFields
}} }}

View File

@ -1,3 +1,4 @@
import { tracked } from "@glimmer/tracking";
import { A } from "@ember/array"; import { A } from "@ember/array";
import Component from "@ember/component"; import Component from "@ember/component";
import EmberObject, { action } from "@ember/object"; import EmberObject, { action } from "@ember/object";
@ -31,13 +32,14 @@ export default class CreateAccount extends Component.extend(
@service siteSettings; @service siteSettings;
@service login; @service login;
@tracked isDeveloper = false;
@tracked accountUsername = this.model.accountUsername;
accountChallenge = 0; accountChallenge = 0;
accountHoneypot = 0; accountHoneypot = 0;
formSubmitted = false; formSubmitted = false;
rejectedEmails = A(); rejectedEmails = A();
prefilledUsername = null; prefilledUsername = null;
userFields = null; userFields = null;
isDeveloper = false;
maskPassword = true; maskPassword = true;
passwordValidationVisible = false; passwordValidationVisible = false;
emailValidationVisible = false; emailValidationVisible = false;
@ -46,13 +48,11 @@ export default class CreateAccount extends Component.extend(
@notEmpty("model.authOptions") hasAuthOptions; @notEmpty("model.authOptions") hasAuthOptions;
@setting("enable_local_logins") canCreateLocal; @setting("enable_local_logins") canCreateLocal;
@setting("require_invite_code") requireInviteCode; @setting("require_invite_code") requireInviteCode;
// For NameValidation mixin
@alias("model.accountName") accountName;
// For UsernameValidation mixin // For UsernameValidation mixin
@alias("model.authOptions") authOptions; @alias("model.authOptions") authOptions;
@alias("model.accountEmail") accountEmail; @alias("model.accountEmail") accountEmail;
@alias("model.accountUsername") accountUsername;
// For NameValidation mixin
@alias("model.accountName") accountName;
init() { init() {
super.init(...arguments); super.init(...arguments);
@ -70,6 +70,11 @@ export default class CreateAccount extends Component.extend(
} }
} }
@action
setAccountUsername(event) {
this.accountUsername = event.target.value;
}
get nameTitle() { get nameTitle() {
return this.nameValidationHelper.nameTitle; return this.nameValidationHelper.nameTitle;
} }
@ -349,15 +354,14 @@ export default class CreateAccount extends Component.extend(
if (this.prefilledUsername) { if (this.prefilledUsername) {
// If username field has been filled automatically, and email field just changed, // If username field has been filled automatically, and email field just changed,
// then remove the username. // then remove the username.
if (this.model.accountUsername === this.prefilledUsername) { if (this.accountUsername === this.prefilledUsername) {
this.set("model.accountUsername", ""); this.accountUsername = "";
} }
this.set("prefilledUsername", null); this.set("prefilledUsername", null);
} }
if ( if (
this.get("emailValidation.ok") && this.get("emailValidation.ok") &&
(isEmpty(this.model.accountUsername) || (isEmpty(this.accountUsername) || this.get("model.authOptions.email"))
this.get("model.authOptions.email"))
) { ) {
// If email is valid and username has not been entered yet, // If email is valid and username has not been entered yet,
// or email and username were filled automatically by 3rd party auth, // or email and username were filled automatically by 3rd party auth,
@ -416,7 +420,7 @@ export default class CreateAccount extends Component.extend(
accountName: this.model.accountName, accountName: this.model.accountName,
accountEmail: this.model.accountEmail, accountEmail: this.model.accountEmail,
accountPassword: this.accountPassword, accountPassword: this.accountPassword,
accountUsername: this.model.accountUsername, accountUsername: this.accountUsername,
accountChallenge: this.accountChallenge, accountChallenge: this.accountChallenge,
inviteCode: this.inviteCode, inviteCode: this.inviteCode,
accountPasswordConfirm: this.accountHoneypot, accountPasswordConfirm: this.accountHoneypot,
@ -443,7 +447,7 @@ export default class CreateAccount extends Component.extend(
return; return;
} }
this.set("isDeveloper", false); this.isDeveloper = false;
if (result.success) { if (result.success) {
// invalidate honeypot // invalidate honeypot
this._challengeExpiry = 1; this._challengeExpiry = 1;
@ -463,7 +467,7 @@ export default class CreateAccount extends Component.extend(
} else { } else {
this.set("flash", result.message || i18n("create_account.failed")); this.set("flash", result.message || i18n("create_account.failed"));
if (result.is_developer) { if (result.is_developer) {
this.set("isDeveloper", true); this.isDeveloper = true;
} }
if ( if (
result.errors && result.errors &&

View File

@ -1,3 +1,4 @@
import { tracked } from "@glimmer/tracking";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import EmberObject, { action } from "@ember/object"; import EmberObject, { action } from "@ember/object";
import { dependentKeyCompat } from "@ember/object/compat"; import { dependentKeyCompat } from "@ember/object/compat";
@ -21,9 +22,12 @@ export default class InvitesShowController extends Controller.extend(
UsernameValidation, UsernameValidation,
UserFieldsValidation UserFieldsValidation
) { ) {
@tracked accountUsername;
@tracked isDeveloper;
queryParams = ["t"]; queryParams = ["t"];
nameValidationHelper = new NameValidationHelper(this); nameValidationHelper = new NameValidationHelper(this);
successMessage = null;
@readOnly("model.is_invite_link") isInviteLink;
@readOnly("model.invited_by") invitedBy; @readOnly("model.invited_by") invitedBy;
@alias("model.email") email; @alias("model.email") email;
@alias("email") accountEmail; @alias("email") accountEmail;
@ -34,17 +38,18 @@ export default class InvitesShowController extends Controller.extend(
@alias("model.hidden_email") hiddenEmail; @alias("model.hidden_email") hiddenEmail;
@alias("model.email_verified_by_link") emailVerifiedByLink; @alias("model.email_verified_by_link") emailVerifiedByLink;
@alias("model.different_external_email") differentExternalEmail; @alias("model.different_external_email") differentExternalEmail;
@alias("model.username") accountUsername;
@not("externalAuthsOnly") passwordRequired; @not("externalAuthsOnly") passwordRequired;
@readOnly("model.is_invite_link") isInviteLink;
successMessage = null;
errorMessage = null; errorMessage = null;
userFields = null; userFields = null;
authOptions = null; authOptions = null;
rejectedEmails = []; rejectedEmails = [];
maskPassword = true; maskPassword = true;
@action
setAccountUsername(event) {
this.accountUsername = event.target.value;
}
get nameTitle() { get nameTitle() {
return this.nameValidationHelper.nameTitle; return this.nameValidationHelper.nameTitle;
} }

View File

@ -1,3 +1,4 @@
import { tracked } from "@glimmer/tracking";
import { A } from "@ember/array"; import { A } from "@ember/array";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import EmberObject, { action } from "@ember/object"; import EmberObject, { action } from "@ember/object";
@ -31,13 +32,14 @@ export default class SignupPageController extends Controller.extend(
@service siteSettings; @service siteSettings;
@service login; @service login;
@tracked accountUsername;
@tracked isDeveloper = false;
accountChallenge = 0; accountChallenge = 0;
accountHoneypot = 0; accountHoneypot = 0;
formSubmitted = false; formSubmitted = false;
rejectedEmails = A(); rejectedEmails = A();
prefilledUsername = null; prefilledUsername = null;
userFields = null; userFields = null;
isDeveloper = false;
maskPassword = true; maskPassword = true;
passwordValidationVisible = false; passwordValidationVisible = false;
emailValidationVisible = false; emailValidationVisible = false;
@ -256,6 +258,11 @@ export default class SignupPageController extends Controller.extend(
}); });
} }
@action
setAccountUsername(event) {
this.accountUsername = event.target.value;
}
@action @action
togglePasswordValidation() { togglePasswordValidation() {
if (this.passwordValidation.reason) { if (this.passwordValidation.reason) {
@ -338,7 +345,7 @@ export default class SignupPageController extends Controller.extend(
// If username field has been filled automatically, and email field just changed, // If username field has been filled automatically, and email field just changed,
// then remove the username. // then remove the username.
if (this.accountUsername === this.prefilledUsername) { if (this.accountUsername === this.prefilledUsername) {
this.set("accountUsername", ""); this.accountUsername = "";
} }
this.set("prefilledUsername", null); this.set("prefilledUsername", null);
} }
@ -438,7 +445,7 @@ export default class SignupPageController extends Controller.extend(
return; return;
} }
this.set("isDeveloper", false); this.isDeveloper = false;
if (result.success) { if (result.success) {
// invalidate honeypot // invalidate honeypot
this._challengeExpiry = 1; this._challengeExpiry = 1;
@ -458,7 +465,7 @@ export default class SignupPageController extends Controller.extend(
} else { } else {
this.set("flash", result.message || i18n("create_account.failed")); this.set("flash", result.message || i18n("create_account.failed"));
if (result.is_developer) { if (result.is_developer) {
this.set("isDeveloper", true); this.isDeveloper = true;
} }
if ( if (
result.errors && result.errors &&

View File

@ -103,7 +103,7 @@ export default Mixin.create({
} }
this.set("checkedUsername", this.accountUsername); this.set("checkedUsername", this.accountUsername);
this.set("isDeveloper", !!result.is_developer); this.isDeveloper = !!result.is_developer;
if (result.available) { if (result.available) {
this.set( this.set(

View File

@ -46,6 +46,7 @@ export default class InvitesShow extends DiscourseRoute {
setupController(controller, model) { setupController(controller, model) {
super.setupController(...arguments); super.setupController(...arguments);
controller.accountUsername = model.username;
if (model.user_fields) { if (model.user_fields) {
controller.userFields.forEach((userField) => { controller.userFields.forEach((userField) => {

View File

@ -93,9 +93,11 @@
{{/if}} {{/if}}
<div class="input username-input input-group"> <div class="input username-input input-group">
<Input <input
{{on "focusin" this.scrollInputIntoView}} {{on "focusin" this.scrollInputIntoView}}
@value={{this.accountUsername}} {{on "input" this.setAccountUsername}}
type="text"
value={{this.accountUsername}}
class={{value-entered this.accountUsername}} class={{value-entered this.accountUsername}}
id="new-account-username" id="new-account-username"
name="username" name="username"

View File

@ -66,9 +66,11 @@
</div> </div>
<div class="input-group create-account__username"> <div class="input-group create-account__username">
<Input <input
{{on "focusin" this.scrollInputIntoView}} {{on "focusin" this.scrollInputIntoView}}
@value={{this.accountUsername}} {{on "input" this.setAccountUsername}}
type="text"
value={{this.accountUsername}}
disabled={{this.usernameDisabled}} disabled={{this.usernameDisabled}}
maxlength={{this.maxUsernameLength}} maxlength={{this.maxUsernameLength}}
aria-describedby="username-validation username-validation-more-info" aria-describedby="username-validation username-validation-more-info"