UX: don't disable "create account" button & display error message for required fields. (#9643)

This commit is contained in:
Vinoth Kannan
2020-05-14 12:15:33 +05:30
committed by GitHub
parent 3d050bdaa3
commit c014b93854
10 changed files with 162 additions and 112 deletions

View File

@@ -6,6 +6,16 @@ export default Component.extend({
classNameBindings: [":user-field", "field.field_type", "customFieldClass"],
layoutName: fmt("field.field_type", "components/user-fields/%@"),
didInsertElement() {
this._super(...arguments);
let element = this.element.querySelector(
".user-field.dropdown .select-kit-header"
);
element = element || this.element.querySelector("input");
this.field.element = element;
},
@discourseComputed
noneLabel() {
return "user_fields.none";

View File

@@ -61,27 +61,9 @@ export default Controller.extend(
this._createUserFields();
},
@discourseComputed(
"passwordRequired",
"nameValidation.failed",
"emailValidation.failed",
"usernameValidation.failed",
"passwordValidation.failed",
"userFieldsValidation.failed",
"formSubmitted",
"inviteCode"
)
@discourseComputed("formSubmitted")
submitDisabled() {
if (this.formSubmitted) return true;
if (this.get("nameValidation.failed")) return true;
if (this.get("emailValidation.failed")) return true;
if (this.get("usernameValidation.failed") && this.usernameRequired)
return true;
if (this.get("passwordValidation.failed") && this.passwordRequired)
return true;
if (this.get("userFieldsValidation.failed")) return true;
if (this.requireInviteCode && !this.inviteCode) return true;
return false;
},
@@ -114,18 +96,26 @@ export default Controller.extend(
// Check the email address
@discourseComputed("accountEmail", "rejectedEmails.[]")
emailValidation(email, rejectedEmails) {
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-email")
};
// If blank, fail without a reason
if (isEmpty(email)) {
return EmberObject.create({
failed: true
});
return EmberObject.create(
Object.assign(failedAttrs, {
message: I18n.t("user.email.required")
})
);
}
if (rejectedEmails.includes(email)) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.email.invalid")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.email.invalid")
})
);
}
if (
@@ -149,10 +139,11 @@ export default Controller.extend(
});
}
return EmberObject.create({
failed: true,
reason: I18n.t("user.email.invalid")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.email.invalid")
})
);
},
@discourseComputed(
@@ -312,6 +303,34 @@ export default Controller.extend(
},
createAccount() {
this.clearFlash();
const validation = [
this.emailValidation,
this.usernameValidation,
this.nameValidation,
this.passwordValidation,
this.userFieldsValidation
].find(v => v.failed);
if (validation) {
if (validation.message) {
this.flash(validation.message, "error");
}
const element = validation.element;
if (element.tagName === "DIV") {
if (element.scrollIntoView) {
element.scrollIntoView();
}
element.click();
} else {
element.focus();
}
return;
}
if (new Date() - this._challengeDate > 1000 * this._challengeExpiry) {
this.fetchConfirmationValue().then(() =>
this.performAccountCreation()

View File

@@ -18,7 +18,11 @@ export default Mixin.create({
@discourseComputed("accountName")
nameValidation() {
if (this.siteSettings.full_name_required && isEmpty(this.accountName)) {
return EmberObject.create({ failed: true });
return EmberObject.create({
failed: true,
message: I18n.t("user.name.required"),
element: document.querySelector("#new-account-name")
});
}
return EmberObject.create({ ok: true });

View File

@@ -43,44 +43,57 @@ export default Mixin.create({
accountEmail,
passwordMinLength
) {
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-password")
};
if (!passwordRequired) {
return EmberObject.create({ ok: true });
}
if (rejectedPasswords.includes(password)) {
return EmberObject.create({
failed: true,
reason:
this.rejectedPasswordsMessages.get(password) ||
I18n.t("user.password.common")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason:
this.rejectedPasswordsMessages.get(password) ||
I18n.t("user.password.common")
})
);
}
// If blank, fail without a reason
if (isEmpty(password)) {
return EmberObject.create({ failed: true });
return EmberObject.create(
Object.assign(failedAttrs, {
message: I18n.t("user.password.required")
})
);
}
// If too short
if (password.length < passwordMinLength) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.password.too_short")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.password.too_short")
})
);
}
if (!isEmpty(accountUsername) && password === accountUsername) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.password.same_as_username")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.password.same_as_username")
})
);
}
if (!isEmpty(accountEmail) && password === accountEmail) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.password.same_as_email")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.password.same_as_email")
})
);
}
// Looks good!

View File

@@ -27,12 +27,17 @@ export default Mixin.create({
userFields = userFields.filterBy("field.required");
}
if (!isEmpty(userFields)) {
const anyEmpty = userFields.any(uf => {
const emptyUserField = userFields.find(uf => {
const val = uf.get("value");
return !val || isEmpty(val);
});
if (anyEmpty) {
return EmberObject.create({ failed: true });
if (emptyUserField) {
const userField = emptyUserField.field;
return EmberObject.create({
failed: true,
message: I18n.t("user_fields.required", { name: userField.name }),
element: userField.element
});
}
}
return EmberObject.create({ ok: true });

View File

@@ -31,6 +31,10 @@ export default Mixin.create({
@discourseComputed("accountUsername")
basicUsernameValidation(accountUsername) {
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-username")
};
this.set("uniqueUsernameValidation", null);
if (accountUsername && accountUsername === this.prefilledUsername) {
@@ -42,31 +46,38 @@ export default Mixin.create({
// If blank, fail without a reason
if (isEmpty(accountUsername)) {
return EmberObject.create({ failed: true });
return EmberObject.create(
Object.assign(failedAttrs, {
message: I18n.t("user.username.required")
})
);
}
// If too short
if (accountUsername.length < this.siteSettings.min_username_length) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.username.too_short")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.too_short")
})
);
}
// If too long
if (accountUsername.length > this.maxUsernameLength) {
return EmberObject.create({
failed: true,
reason: I18n.t("user.username.too_long")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.too_long")
})
);
}
this.checkUsernameAvailability();
// Let's check it out asynchronously
return EmberObject.create({
failed: true,
reason: I18n.t("user.username.checking")
});
return EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.checking")
})
);
},
shouldCheckUsernameAvailability() {
@@ -93,23 +104,30 @@ export default Mixin.create({
})
);
} else {
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-username")
};
if (result.suggestion) {
return this.set(
"uniqueUsernameValidation",
EmberObject.create({
failed: true,
reason: I18n.t("user.username.not_available", result)
})
EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.not_available", result)
})
)
);
} else {
return this.set(
"uniqueUsernameValidation",
EmberObject.create({
failed: true,
reason: result.errors
? result.errors.join(" ")
: I18n.t("user.username.not_available_no_suggestion")
})
EmberObject.create(
Object.assign(failedAttrs, {
reason: result.errors
? result.errors.join(" ")
: I18n.t("user.username.not_available_no_suggestion")
})
)
);
}
}