From 86f82ea4d3084813c6ca70ffde5e3020c96afe39 Mon Sep 17 00:00:00 2001 From: Mark VanLandingham Date: Wed, 23 Apr 2025 00:37:15 -0500 Subject: [PATCH] FIX: Do not re-render conversations sidebar on navigation (#1274) --- .../components/ai-bot-header-icon.gjs | 32 ++++++++++++++--- .../ai-conversations-sidebar-manager.js | 7 +++- spec/system/ai_bot/homepage_spec.rb | 35 ++++++++++++++----- .../page_objects/pages/discourse_ai/header.rb | 17 +++++++++ 4 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 spec/system/page_objects/pages/discourse_ai/header.rb diff --git a/assets/javascripts/discourse/components/ai-bot-header-icon.gjs b/assets/javascripts/discourse/components/ai-bot-header-icon.gjs index 3cbda25c..70ba429c 100644 --- a/assets/javascripts/discourse/components/ai-bot-header-icon.gjs +++ b/assets/javascripts/discourse/components/ai-bot-header-icon.gjs @@ -2,14 +2,17 @@ import Component from "@glimmer/component"; import { action } from "@ember/object"; import { service } from "@ember/service"; import DButton from "discourse/components/d-button"; +import { defaultHomepage } from "discourse/lib/utilities"; import { i18n } from "discourse-i18n"; import { composeAiBotMessage } from "../lib/ai-bot-helper"; +import { AI_CONVERSATIONS_PANEL } from "../services/ai-conversations-sidebar-manager"; export default class AiBotHeaderIcon extends Component { - @service currentUser; - @service siteSettings; @service composer; + @service currentUser; @service router; + @service sidebarState; + @service siteSettings; get bots() { const availableBots = this.currentUser.ai_enabled_chat_bots @@ -23,11 +26,30 @@ export default class AiBotHeaderIcon extends Component { return this.bots.length > 0 && this.siteSettings.ai_bot_add_to_header; } + get icon() { + if (this.clickShouldRouteOutOfConversations) { + return "shuffle"; + } + return "robot"; + } + + get clickShouldRouteOutOfConversations() { + return ( + this.siteSettings.ai_enable_experimental_bot_ux && + this.sidebarState.currentPanel?.key === AI_CONVERSATIONS_PANEL + ); + } + @action - compose() { + onClick() { + if (this.clickShouldRouteOutOfConversations) { + return this.router.transitionTo(`discovery.${defaultHomepage()}`); + } + if (this.siteSettings.ai_enable_experimental_bot_ux) { return this.router.transitionTo("discourse-ai-bot-conversations"); } + composeAiBotMessage(this.bots[0], this.composer); } @@ -35,8 +57,8 @@ export default class AiBotHeaderIcon extends Component { {{#if this.showHeaderButton}}
  • diff --git a/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js b/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js index ce41d0f1..c79ffe59 100644 --- a/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js +++ b/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js @@ -10,7 +10,12 @@ export default class AiConversationsSidebarManager extends Service { @tracked newTopicForceSidebar = false; forceCustomSidebar() { - // Set the panel to your custom panel + // Return early if we already have the correct panel, so we don't + // re-render it. + if (this.sidebarState.currentPanel?.key === AI_CONVERSATIONS_PANEL) { + return; + } + this.sidebarState.setPanel(AI_CONVERSATIONS_PANEL); // Use separated mode to ensure independence from hamburger menu diff --git a/spec/system/ai_bot/homepage_spec.rb b/spec/system/ai_bot/homepage_spec.rb index 30024148..fea48518 100644 --- a/spec/system/ai_bot/homepage_spec.rb +++ b/spec/system/ai_bot/homepage_spec.rb @@ -4,6 +4,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do let(:topic_page) { PageObjects::Pages::Topic.new } let(:composer) { PageObjects::Components::Composer.new } let(:ai_pm_homepage) { PageObjects::Components::AiPmHomepage.new } + let(:header) { PageObjects::Pages::DiscourseAi::Header.new } let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new } let(:header_dropdown) { PageObjects::Components::NavigationMenu::HeaderDropdown.new } let(:dialog) { PageObjects::Components::Dialog.new } @@ -92,14 +93,14 @@ RSpec.describe "AI Bot - Homepage", type: :system do context "when `ai_enable_experimental_bot_ux` is enabled" do it "renders landing page on bot click" do visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage expect(sidebar).to be_visible end it "displays error when message is too short" do visit "/" - find(".ai-bot-button").click + header.click_bot_button ai_pm_homepage.input.fill_in(with: "a") ai_pm_homepage.submit @@ -111,7 +112,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do it "renders sidebar even when navigation menu is set to header" do SiteSetting.navigation_menu = "header dropdown" visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage expect(sidebar).to be_visible expect(header_dropdown).to be_visible @@ -119,7 +120,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do it "hides default content in the sidebar" do visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage expect(sidebar).to have_no_tags_section @@ -132,7 +133,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do it "shows the bot conversation in the sidebar" do visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage expect(sidebar).to have_section("ai-conversations-history") @@ -142,7 +143,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do it "navigates to the bot conversation when clicked" do visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage sidebar.find( @@ -151,6 +152,24 @@ RSpec.describe "AI Bot - Homepage", type: :system do expect(topic_page).to have_topic_title(pm.title) end + it "displays the shuffle icon when on homepage or bot PM" do + visit "/" + expect(header).to have_icon_in_bot_button(icon: "robot") + header.click_bot_button + + expect(header).to have_icon_in_bot_button(icon: "shuffle") + + # Go to a PM and assert that the icon is still shuffle + sidebar.find( + ".sidebar-section[data-section-name='ai-conversations-history'] a.sidebar-section-link", + ).click + expect(header).to have_icon_in_bot_button(icon: "shuffle") + + # Go back home and assert that the icon is now robot again + header.click_bot_button + expect(header).to have_icon_in_bot_button(icon: "robot") + end + it "displays sidebar and 'new question' on the topic page" do topic_page.visit_topic(pm) expect(sidebar).to be_visible @@ -193,7 +212,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do sign_in(user_2) visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_homepage expect(sidebar).to have_no_section_link(pm.title) end @@ -204,7 +223,7 @@ RSpec.describe "AI Bot - Homepage", type: :system do it "opens composer on bot click" do visit "/" - find(".ai-bot-button").click + header.click_bot_button expect(ai_pm_homepage).to have_no_homepage expect(composer).to be_opened diff --git a/spec/system/page_objects/pages/discourse_ai/header.rb b/spec/system/page_objects/pages/discourse_ai/header.rb new file mode 100644 index 00000000..9a3e956a --- /dev/null +++ b/spec/system/page_objects/pages/discourse_ai/header.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module PageObjects + module Pages + module DiscourseAi + class Header < ::PageObjects::Pages::Header + def click_bot_button + find(".ai-bot-button").click + end + + def has_icon_in_bot_button?(icon:) + page.has_css?(".ai-bot-button .d-icon-#{icon}") + end + end + end + end +end