From ad431ab03ab2d15d0613827183937c643be0c2cd Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 15 May 2023 11:29:53 +0100 Subject: [PATCH] DEV: Refactor modal 'flash' to avoid direct DOM manipulation --- .../discourse/app/components/d-modal-body.js | 33 +------------------ .../discourse/app/components/d-modal.hbs | 13 +++++++- .../discourse/app/components/d-modal.js | 15 +++++++++ .../app/controllers/forgot-password.js | 11 ++++--- .../discourse/app/controllers/login.js | 25 +++++++++----- .../tests/acceptance/login-with-email-test.js | 4 +-- 6 files changed, 53 insertions(+), 48 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/d-modal-body.js b/app/assets/javascripts/discourse/app/components/d-modal-body.js index 38ff1e818a2..f7d6457b52c 100644 --- a/app/assets/javascripts/discourse/app/components/d-modal-body.js +++ b/app/assets/javascripts/discourse/app/components/d-modal-body.js @@ -23,10 +23,7 @@ export default class DModalBody extends Component { @action didInsert(element) { - this._modalAlertElement = document.getElementById("modal-alert"); - if (this._modalAlertElement) { - this._clearFlash(); - } + this.appEvents.trigger("modal-body:clearFlash"); const fixedParent = element.closest(".d-modal.fixed-modal"); if (fixedParent) { @@ -39,8 +36,6 @@ export default class DModalBody extends Component { @action willDestroy() { - this.appEvents.off("modal-body:flash", this, "_flash"); - this.appEvents.off("modal-body:clearFlash", this, "_clearFlash"); this.appEvents.trigger("modal:body-dismissed"); } @@ -69,30 +64,4 @@ export default class DModalBody extends Component { ]) ); } - - _clearFlash() { - if (this._modalAlertElement) { - this._modalAlertElement.innerHTML = ""; - this._modalAlertElement.classList.remove( - "alert", - "alert-error", - "alert-info", - "alert-success", - "alert-warning" - ); - } - } - - _flash(msg) { - this._clearFlash(); - if (!this._modalAlertElement) { - return; - } - - this._modalAlertElement.classList.add( - "alert", - `alert-${msg.messageClass || "success"}` - ); - this._modalAlertElement.innerHTML = msg.text || ""; - } } diff --git a/app/assets/javascripts/discourse/app/components/d-modal.hbs b/app/assets/javascripts/discourse/app/components/d-modal.hbs index 6339836b71b..8d341df8e4f 100644 --- a/app/assets/javascripts/discourse/app/components/d-modal.hbs +++ b/app/assets/javascripts/discourse/app/components/d-modal.hbs @@ -57,7 +57,18 @@ {{/if}} - + {{yield}} diff --git a/app/assets/javascripts/discourse/app/components/d-modal.js b/app/assets/javascripts/discourse/app/components/d-modal.js index 8cb5561a1d7..b40e474e654 100644 --- a/app/assets/javascripts/discourse/app/components/d-modal.js +++ b/app/assets/javascripts/discourse/app/components/d-modal.js @@ -13,6 +13,7 @@ export default class DModal extends Component { @tracked wrapperElement; @tracked modalBodyData = {}; + @tracked flash; get modalStyle() { if (this.args.modalStyle === "inline-modal") { @@ -71,6 +72,8 @@ export default class DModal extends Component { @action setupListeners(element) { this.appEvents.on("modal:body-shown", this._modalBodyShown); + this.appEvents.on("modal-body:flash", this._flash); + this.appEvents.on("modal-body:clearFlash", this._clearFlash); document.documentElement.addEventListener( "keydown", this._handleModalEvents @@ -81,6 +84,8 @@ export default class DModal extends Component { @action cleanupListeners() { this.appEvents.off("modal:body-shown", this._modalBodyShown); + this.appEvents.off("modal-body:flash", this._flash); + this.appEvents.off("modal-body:clearFlash", this._clearFlash); document.documentElement.removeEventListener( "keydown", this._handleModalEvents @@ -226,4 +231,14 @@ export default class DModal extends Component { } } } + + @bind + _clearFlash() { + this.flash = null; + } + + @bind + _flash(msg) { + this.flash = msg; + } } diff --git a/app/assets/javascripts/discourse/app/controllers/forgot-password.js b/app/assets/javascripts/discourse/app/controllers/forgot-password.js index 6ca580d7f55..0d6c67b78b2 100644 --- a/app/assets/javascripts/discourse/app/controllers/forgot-password.js +++ b/app/assets/javascripts/discourse/app/controllers/forgot-password.js @@ -8,6 +8,7 @@ import { escapeExpression } from "discourse/lib/utilities"; import { flashAjaxError } from "discourse/lib/ajax-error"; import getURL from "discourse-common/lib/get-url"; import { isEmpty } from "@ember/utils"; +import { htmlSafe } from "@ember/template"; export default Controller.extend(ModalFunctionality, { offerHelp: null, @@ -70,10 +71,12 @@ export default Controller.extend(ModalFunctionality, { key += "_not_found"; this.flash( - I18n.t(key, { - email: accountEmailOrUsername, - username: accountEmailOrUsername, - }), + htmlSafe( + I18n.t(key, { + email: accountEmailOrUsername, + username: accountEmailOrUsername, + }) + ), "error" ); } else { diff --git a/app/assets/javascripts/discourse/app/controllers/login.js b/app/assets/javascripts/discourse/app/controllers/login.js index 58d01b794ea..3a92c0c7698 100644 --- a/app/assets/javascripts/discourse/app/controllers/login.js +++ b/app/assets/javascripts/discourse/app/controllers/login.js @@ -19,6 +19,7 @@ import { setting } from "discourse/lib/computed"; import showModal from "discourse/lib/show-modal"; import { wavingHandURL } from "discourse/lib/waving-hand-url"; import { inject as service } from "@ember/service"; +import { htmlSafe } from "@ember/template"; // This is happening outside of the app via popup const AuthErrors = [ @@ -157,22 +158,28 @@ export default Controller.extend(ModalFunctionality, { .then((data) => { const loginName = escapeExpression(this.loginName); const isEmail = loginName.match(/@/); - let key = `email_login.complete_${isEmail ? "email" : "username"}`; + let key = isEmail + ? "email_login.complete_email" + : "email_login.complete_username"; if (data.user_found === false) { this.flash( - I18n.t(`${key}_not_found`, { - email: loginName, - username: loginName, - }), + htmlSafe( + I18n.t(`${key}_not_found`, { + email: loginName, + username: loginName, + }) + ), "error" ); } else { let postfix = data.hide_taken ? "" : "_found"; this.flash( - I18n.t(`${key}${postfix}`, { - email: loginName, - username: loginName, - }) + htmlSafe( + I18n.t(`${key}${postfix}`, { + email: loginName, + username: loginName, + }) + ) ); } }) diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js index 15f83901d26..540bbbb47b8 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js @@ -56,7 +56,7 @@ acceptance("Login with email", function (needs) { await click("#email-login-link"); assert.strictEqual( - query(".alert-error").innerHTML, + query(".alert-error").innerHTML.trim(), I18n.t("email_login.complete_username_not_found", { username: "someuser", }), @@ -67,7 +67,7 @@ acceptance("Login with email", function (needs) { await click("#email-login-link"); assert.strictEqual( - query(".alert-error").innerHTML, + query(".alert-error").innerHTML.trim(), I18n.t("email_login.complete_email_not_found", { email: "someuser@gmail.com", }),