From 023236d600a1c9cdc7c1de8f70ef816ea51b747a Mon Sep 17 00:00:00 2001 From: David Taylor Date: Tue, 3 Sep 2024 22:51:40 +0100 Subject: [PATCH] DEV: Convert card-contents-base from mixin to base class (#28709) * DEV: Convert card-contents-base from mixin to base class This allows us to convert it to native class syntax Mixins are essentially deprecated, and will not be receiving native class syntax support. In this case, there is no real need for it to be a mixin, so a base class makes sense. --- .../card-contents-base.js | 74 +++++++++---------- .../app/components/group-card-contents.js | 6 +- .../app/components/user-card-contents.js | 6 +- .../discourse/app/lib/plugin-api.gjs | 2 +- .../discourse/tests/helpers/qunit-helpers.js | 2 +- 5 files changed, 43 insertions(+), 47 deletions(-) rename app/assets/javascripts/discourse/app/{mixins => components}/card-contents-base.js (91%) diff --git a/app/assets/javascripts/discourse/app/mixins/card-contents-base.js b/app/assets/javascripts/discourse/app/components/card-contents-base.js similarity index 91% rename from app/assets/javascripts/discourse/app/mixins/card-contents-base.js rename to app/assets/javascripts/discourse/app/components/card-contents-base.js index 74a93bbf432..57ab85aaf73 100644 --- a/app/assets/javascripts/discourse/app/mixins/card-contents-base.js +++ b/app/assets/javascripts/discourse/app/components/card-contents-base.js @@ -1,5 +1,5 @@ +import Component from "@ember/component"; import { alias, match } from "@ember/object/computed"; -import Mixin from "@ember/object/mixin"; import { next, schedule, throttle } from "@ember/runloop"; import { service } from "@ember/service"; import { wantsNewWindow } from "discourse/lib/intercept-click"; @@ -23,27 +23,27 @@ export function resetCardClickListenerSelector() { _cardClickListenerSelectors = [DEFAULT_SELECTOR]; } -export default Mixin.create({ - appEvents: service(), - currentUser: service(), - menu: service(), - router: service(), - site: service(), - siteSettings: service(), +export default class CardContentsBase extends Component { + @service appEvents; + @service currentUser; + @service menu; + @service router; + @service site; + @service siteSettings; - elementId: null, //click detection added for data-{elementId} - _showCallback: null, //username - load up data for when show is called + elementId = null; //click detection added for data-{elementId} - visible: false, - username: null, - loading: null, - cardTarget: null, - post: null, - isDocked: false, - _menuInstance: null, + visible = false; + username = null; + loading = null; + cardTarget = null; + post = null; + isDocked = false; - postStream: alias("topic.postStream"), - viewingTopic: match("router.currentRouteName", /^topic\./), + @alias("topic.postStream") postStream; + @match("router.currentRouteName", /^topic\./) viewingTopic; + + _menuInstance = null; _show(username, target, event) { // No user card for anon @@ -100,10 +100,10 @@ export default Mixin.create({ } return false; - }, + } didInsertElement() { - this._super(...arguments); + super.didInsertElement(...arguments); document.addEventListener("mousedown", this._clickOutsideHandler); document.addEventListener("keyup", this._escListener); @@ -127,7 +127,7 @@ export default Mixin.create({ ); this.appEvents.on("card:close", this, "_close"); - }, + } @bind _cardClickHandler(event) { @@ -147,7 +147,7 @@ export default Mixin.create({ this._showCardOnClick(event, this.mentionSelector, (el) => el.innerText.replace(/^@/, "") ); - }, + } _showCardOnClick(event, selector, transformText) { const matchingEl = event.target.closest(selector); @@ -169,29 +169,29 @@ export default Mixin.create({ } return false; - }, + } _topicHeaderTrigger(username, target, event) { this.set("isDocked", true); return this._show(username, target, event); - }, + } @bind _onScroll() { throttle(this, this._close, 1000); - }, + } _bindMobileScroll() { window.addEventListener(MOBILE_SCROLL_EVENT, this._onScroll); - }, + } _unbindMobileScroll() { window.removeEventListener(MOBILE_SCROLL_EVENT, this._onScroll); - }, + } _previewClick(target, event) { return this._show(target.innerText.replace(/^@/, ""), target, event); - }, + } _positionCard(target, event) { schedule("afterRender", async () => { @@ -234,7 +234,7 @@ export default Mixin.create({ }, 350); } }); - }, + } @bind _hide() { @@ -243,7 +243,7 @@ export default Mixin.create({ } this._menuInstance?.destroy(); - }, + } _close() { this.setProperties({ @@ -262,10 +262,10 @@ export default Mixin.create({ this._hide(); this.appEvents.trigger("card:hide"); - }, + } willDestroyElement() { - this._super(...arguments); + super.willDestroyElement(...arguments); document.removeEventListener("mousedown", this._clickOutsideHandler); document.removeEventListener("keyup", this._escListener); @@ -290,7 +290,7 @@ export default Mixin.create({ this.appEvents.off("card:close", this, "_close"); this._hide(); - }, + } @bind _clickOutsideHandler(event) { @@ -306,7 +306,7 @@ export default Mixin.create({ } this._close(); - }, + } @bind _escListener(event) { @@ -314,5 +314,5 @@ export default Mixin.create({ this.cardTarget?.focus(); this._close(); } - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/group-card-contents.js b/app/assets/javascripts/discourse/app/components/group-card-contents.js index cbb3ae4ba88..82ef2b5e201 100644 --- a/app/assets/javascripts/discourse/app/components/group-card-contents.js +++ b/app/assets/javascripts/discourse/app/components/group-card-contents.js @@ -1,12 +1,11 @@ -import Component from "@ember/component"; import { action } from "@ember/object"; import { alias, gt } from "@ember/object/computed"; import { service } from "@ember/service"; import { classNameBindings, classNames } from "@ember-decorators/component"; +import CardContentsBase from "discourse/components/card-contents-base"; import { setting } from "discourse/lib/computed"; import { wantsNewWindow } from "discourse/lib/intercept-click"; import { groupPath } from "discourse/lib/url"; -import CardContentsBase from "discourse/mixins/card-contents-base"; import CleansUp from "discourse/mixins/cleans-up"; import discourseComputed from "discourse-common/utils/decorators"; @@ -20,8 +19,7 @@ const maxMembersToDisplay = 10; "isFixed:fixed", "groupClass" ) -export default class GroupCardContents extends Component.extend( - CardContentsBase, +export default class GroupCardContents extends CardContentsBase.extend( CleansUp ) { @service composer; diff --git a/app/assets/javascripts/discourse/app/components/user-card-contents.js b/app/assets/javascripts/discourse/app/components/user-card-contents.js index 9dfd00ad89e..e5680b651cd 100644 --- a/app/assets/javascripts/discourse/app/components/user-card-contents.js +++ b/app/assets/javascripts/discourse/app/components/user-card-contents.js @@ -1,4 +1,3 @@ -import Component from "@ember/component"; import EmberObject, { action, computed, set } from "@ember/object"; import { alias, and, gt, gte, not, or } from "@ember/object/computed"; import { dasherize } from "@ember/string"; @@ -9,6 +8,7 @@ import { classNames, } from "@ember-decorators/component"; import { observes } from "@ember-decorators/object"; +import CardContentsBase from "discourse/components/card-contents-base"; import { setting } from "discourse/lib/computed"; import { durationTiny } from "discourse/lib/formatter"; import { wantsNewWindow } from "discourse/lib/intercept-click"; @@ -16,7 +16,6 @@ import { prioritizeNameInUx } from "discourse/lib/settings"; import { emojiUnescape } from "discourse/lib/text"; import { escapeExpression } from "discourse/lib/utilities"; import CanCheckEmails from "discourse/mixins/can-check-emails"; -import CardContentsBase from "discourse/mixins/card-contents-base"; import CleansUp from "discourse/mixins/cleans-up"; import User from "discourse/models/user"; import { getURLWithCDN } from "discourse-common/lib/get-url"; @@ -33,8 +32,7 @@ import I18n from "discourse-i18n"; "primaryGroup" ) @attributeBindings("labelledBy:aria-labelledby") -export default class UserCardContents extends Component.extend( - CardContentsBase, +export default class UserCardContents extends CardContentsBase.extend( CanCheckEmails, CleansUp ) { diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs index d7728765963..84c1e6cbc65 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs @@ -9,6 +9,7 @@ import $ from "jquery"; import { h } from "virtual-dom"; import { addAboutPageActivity } from "discourse/components/about-page"; import { addBulkDropdownButton } from "discourse/components/bulk-select-topics-dropdown"; +import { addCardClickListenerSelector } from "discourse/components/card-contents-base"; import { addApiImageWrapperButtonClickEvent, addComposerUploadHandler, @@ -112,7 +113,6 @@ import { } from "discourse/lib/transformer"; import { registerUserMenuTab } from "discourse/lib/user-menu/tab"; import { replaceFormatter } from "discourse/lib/utilities"; -import { addCardClickListenerSelector } from "discourse/mixins/card-contents-base"; import { addCustomUserFieldValidationCallback } from "discourse/mixins/user-fields-validation"; import Composer, { registerCustomizationCallback, diff --git a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js index ee1ebae4c16..5c24b18ca61 100644 --- a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js +++ b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js @@ -13,6 +13,7 @@ import { resetCache as resetOneboxCache } from "pretty-text/oneboxer"; import QUnit, { module, skip, test } from "qunit"; import sinon from "sinon"; import { clearAboutPageActivities } from "discourse/components/about-page"; +import { resetCardClickListenerSelector } from "discourse/components/card-contents-base"; import { cleanUpComposerUploadHandler, cleanUpComposerUploadMarkdownResolver, @@ -75,7 +76,6 @@ import { setTestPresence, } from "discourse/lib/user-presence"; import { resetUserSearchCache } from "discourse/lib/user-search"; -import { resetCardClickListenerSelector } from "discourse/mixins/card-contents-base"; import { resetComposerCustomizations } from "discourse/models/composer"; import { clearAuthMethods } from "discourse/models/login-method"; import { clearNavItems } from "discourse/models/nav-item";