diff --git a/app/assets/javascripts/discourse/app/components/user-menu/menu.hbs b/app/assets/javascripts/discourse/app/components/user-menu/menu.hbs index d3e23b3cb46..25efaa7a1cc 100644 --- a/app/assets/javascripts/discourse/app/components/user-menu/menu.hbs +++ b/app/assets/javascripts/discourse/app/components/user-menu/menu.hbs @@ -35,12 +35,11 @@ class="quick-access-panel" tabindex="-1" > - {{component - this.currentPanelComponent - closeUserMenu=@closeUserMenu - filterByTypes=this.currentNotificationTypes - ariaLabelledby=(concat "user-menu-button-" this.currentTabId) - }} + diff --git a/app/assets/javascripts/discourse/app/components/user-menu/menu.js b/app/assets/javascripts/discourse/app/components/user-menu/menu.js index 743d9f7feec..1b4abeecb2d 100644 --- a/app/assets/javascripts/discourse/app/components/user-menu/menu.js +++ b/app/assets/javascripts/discourse/app/components/user-menu/menu.js @@ -6,25 +6,27 @@ import UserMenuTab, { CUSTOM_TABS_CLASSES } from "discourse/lib/user-menu/tab"; import { inject as service } from "@ember/service"; import getUrl from "discourse-common/lib/get-url"; import { wantsNewWindow } from "discourse/lib/intercept-click"; +import UserMenuNotificationsList from "./notifications-list"; +import UserMenuRepliesNotificationsList from "./replies-notifications-list"; +import UserMenuLikesNotificationsList from "./likes-notifications-list"; +import UserMenuMessagesList from "./messages-list"; +import UserMenuBookmarksList from "./bookmarks-list"; +import UserMenuReviewablesList from "./reviewables-list"; +import UserMenuProfileTabContent from "./profile-tab-content"; +import UserMenuOtherNotificationsList from "./other-notifications-list"; +import deprecated from "discourse-common/lib/deprecated"; +import { getOwner } from "discourse-common/lib/get-owner"; const DEFAULT_TAB_ID = "all-notifications"; -const DEFAULT_PANEL_COMPONENT = "user-menu/notifications-list"; +const DEFAULT_PANEL_COMPONENT = UserMenuNotificationsList; const REVIEW_QUEUE_TAB_ID = "review-queue"; const CORE_TOP_TABS = [ class extends UserMenuTab { - get id() { - return DEFAULT_TAB_ID; - } - - get icon() { - return "bell"; - } - - get panelComponent() { - return DEFAULT_PANEL_COMPONENT; - } + id = DEFAULT_TAB_ID; + icon = "bell"; + panelComponent = DEFAULT_PANEL_COMPONENT; get linkWhenActive() { return `${this.currentUser.path}/notifications`; @@ -32,17 +34,10 @@ const CORE_TOP_TABS = [ }, class extends UserMenuTab { - get id() { - return "replies"; - } - - get icon() { - return "reply"; - } - - get panelComponent() { - return "user-menu/replies-notifications-list"; - } + id = "replies"; + icon = "reply"; + panelComponent = UserMenuRepliesNotificationsList; + notificationTypes = ["mentioned", "posted", "quoted", "replied"]; get count() { return ( @@ -53,27 +48,15 @@ const CORE_TOP_TABS = [ ); } - get notificationTypes() { - return ["mentioned", "posted", "quoted", "replied"]; - } - get linkWhenActive() { return `${this.currentUser.path}/notifications/responses`; } }, class extends UserMenuTab { - get id() { - return "likes"; - } - - get icon() { - return "heart"; - } - - get panelComponent() { - return "user-menu/likes-notifications-list"; - } + id = "likes"; + icon = "heart"; + panelComponent = UserMenuLikesNotificationsList; get shouldDisplay() { return !this.currentUser.user_option.likes_notifications_disabled; @@ -96,17 +79,10 @@ const CORE_TOP_TABS = [ }, class extends UserMenuTab { - get id() { - return "messages"; - } - - get icon() { - return "notification.private_message"; - } - - get panelComponent() { - return "user-menu/messages-list"; - } + id = "messages"; + icon = "notification.private_message"; + panelComponent = UserMenuMessagesList; + notificationTypes = ["private_message", "group_message_summary"]; get count() { return this.getUnreadCountForType("private_message"); @@ -116,53 +92,31 @@ const CORE_TOP_TABS = [ return this.currentUser?.can_send_private_messages; } - get notificationTypes() { - return ["private_message", "group_message_summary"]; - } - get linkWhenActive() { return `${this.currentUser.path}/messages`; } }, class extends UserMenuTab { - get id() { - return "bookmarks"; - } - - get icon() { - return NO_REMINDER_ICON; - } - - get panelComponent() { - return "user-menu/bookmarks-list"; - } + id = "bookmarks"; + icon = NO_REMINDER_ICON; + panelComponent = UserMenuBookmarksList; + notificationTypes = ["bookmark_reminder"]; get count() { return this.getUnreadCountForType("bookmark_reminder"); } - get notificationTypes() { - return ["bookmark_reminder"]; - } - get linkWhenActive() { return `${this.currentUser.path}/activity/bookmarks`; } }, class extends UserMenuTab { - get id() { - return REVIEW_QUEUE_TAB_ID; - } - - get icon() { - return "flag"; - } - - get panelComponent() { - return "user-menu/reviewables-list"; - } + id = REVIEW_QUEUE_TAB_ID; + icon = "flag"; + panelComponent = UserMenuReviewablesList; + linkWhenActive = getUrl("/review"); get shouldDisplay() { return ( @@ -173,26 +127,14 @@ const CORE_TOP_TABS = [ get count() { return this.currentUser.get("reviewable_count"); } - - get linkWhenActive() { - return getUrl("/review"); - } }, ]; const CORE_BOTTOM_TABS = [ class extends UserMenuTab { - get id() { - return "profile"; - } - - get icon() { - return "user"; - } - - get panelComponent() { - return "user-menu/profile-tab-content"; - } + id = "profile"; + icon = "user"; + panelComponent = UserMenuProfileTabContent; get linkWhenActive() { return `${this.currentUser.path}/summary`; @@ -201,23 +143,15 @@ const CORE_BOTTOM_TABS = [ ]; const CORE_OTHER_NOTIFICATIONS_TAB = class extends UserMenuTab { + id = "other-notifications"; + icon = "discourse-other-tab"; + panelComponent = UserMenuOtherNotificationsList; + constructor(currentUser, siteSettings, site, otherNotificationTypes) { super(...arguments); this.otherNotificationTypes = otherNotificationTypes; } - get id() { - return "other-notifications"; - } - - get icon() { - return "discourse-other-tab"; - } - - get panelComponent() { - return "user-menu/other-notifications-list"; - } - get count() { return this.otherNotificationTypes.reduce((sum, notificationType) => { return sum + this.getUnreadCountForType(notificationType); @@ -229,6 +163,18 @@ const CORE_OTHER_NOTIFICATIONS_TAB = class extends UserMenuTab { } }; +function resolvePanelComponent(owner, panelComponent) { + if (typeof panelComponent === "string") { + const nameForConsole = JSON.stringify(panelComponent); + deprecated( + `user-menu tab panelComponent must be passed as a component class (passed ${nameForConsole})`, + { id: "discourse.user-menu.panel-component-class" } + ); + return owner.resolveRegistration(`component:${panelComponent}`); + } + return panelComponent; +} + export default class UserMenu extends Component { @service currentUser; @service siteSettings; @@ -323,7 +269,10 @@ export default class UserMenu extends Component { event.preventDefault(); this.currentTabId = tab.id; - this.currentPanelComponent = tab.panelComponent; + this.currentPanelComponent = resolvePanelComponent( + getOwner(this), + tab.panelComponent + ); this.currentNotificationTypes = tab.notificationTypes; } diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 0822df4fbe3..95f4da95eee 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -2056,9 +2056,9 @@ class PluginApi { * ``` * api.registerUserMenuTab((UserMenuTab) => { * return class extends UserMenuTab { - * get id() { - * return "custom-tab-id"; - * } + * id = "custom-tab-id"; + * panelComponent = MyCustomPanelGlimmerComponent; + * icon = "some-fa5-icon"; * * get shouldDisplay() { * return this.siteSettings.enable_custom_tab && this.currentUser.admin; @@ -2067,14 +2067,6 @@ class PluginApi { * get count() { * return this.currentUser.my_custom_notification_count; * } - * - * get panelComponent() { - * return "your-custom-glimmer-component"; - * } - * - * get icon() { - * return "some-fa5-icon"; - * } * } * }); * ``` diff --git a/app/assets/javascripts/discourse/app/lib/user-menu/tab.js b/app/assets/javascripts/discourse/app/lib/user-menu/tab.js index 356b7f8ec1d..76cfbe9aa5c 100644 --- a/app/assets/javascripts/discourse/app/lib/user-menu/tab.js +++ b/app/assets/javascripts/discourse/app/lib/user-menu/tab.js @@ -45,7 +45,7 @@ export default class UserMenuTab { } /** - * @returns {string} Dasherized version of the component name that should be rendered in the panel area when the tab is active. + * @returns {Component} Component class that should be rendered in the panel area when the tab is active. */ get panelComponent() { throw new Error("not implemented"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-menu-test.js index 020ba419e08..be891bb7a14 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-menu-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-menu-test.js @@ -17,6 +17,7 @@ import TopicFixtures from "discourse/tests/fixtures/topic"; import { Promise } from "rsvp"; import { later } from "@ember/runloop"; import I18n from "I18n"; +import DButton from "discourse/components/d-button"; acceptance("User menu", function (needs) { needs.user({ @@ -178,7 +179,7 @@ acceptance("User menu", function (needs) { } get panelComponent() { - return "d-button"; + return DButton; } get title() { @@ -246,7 +247,7 @@ acceptance("User menu", function (needs) { } get panelComponent() { - return "d-button"; + return DButton; } }; }); @@ -266,7 +267,7 @@ acceptance("User menu", function (needs) { } get panelComponent() { - return "d-button"; + return DButton; } }; }); @@ -680,7 +681,7 @@ acceptance("User menu", function (needs) { } get panelComponent() { - return "d-button"; + return DButton; } get linkWhenActive() { @@ -700,7 +701,7 @@ acceptance("User menu", function (needs) { } get panelComponent() { - return "d-button"; + return DButton; } }; });