diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 06afcdd3e83..ca592cb76f3 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -17,7 +17,7 @@ import { registerReviewableActionModal, } from "discourse/components/reviewable-item"; import { addAdvancedSearchOptions } from "discourse/components/search-advanced-options"; -import { addSearchSuggestion as addGlimmerSearchSuggestion } from "discourse/components/search-menu/results/assistant"; +import { addSearchSuggestion } from "discourse/components/search-menu/results/assistant"; import { addItemSelectCallback as addSearchMenuAssistantSelectCallback } from "discourse/components/search-menu/results/assistant-item"; import { addQuickSearchRandomTip, @@ -117,12 +117,6 @@ import { preventCloak, } from "discourse/widgets/post-stream"; import { disableNameSuppression } from "discourse/widgets/poster-name"; -import { addOnKeyDownCallback } from "discourse/widgets/search-menu"; -import { - addQuickSearchRandomTip as addWidgetQuickSearchRandomTip, - addSearchSuggestion, - removeDefaultQuickSearchRandomTips as removeWidgetDefaultQuickSearchRandomTips, -} from "discourse/widgets/search-menu-results"; import { changeSetting, createWidget, @@ -1867,7 +1861,6 @@ class PluginApi { */ addSearchSuggestion(value) { addSearchSuggestion(value); - addGlimmerSearchSuggestion(value); } /** @@ -1941,7 +1934,6 @@ class PluginApi { * */ addSearchMenuOnKeyDownCallback(fn) { - addOnKeyDownCallback(fn); addOnKeyUpCallback(fn); } @@ -1962,7 +1954,6 @@ class PluginApi { */ addQuickSearchRandomTip(tip) { addQuickSearchRandomTip(tip); - addWidgetQuickSearchRandomTip(tip); } /** @@ -1976,7 +1967,6 @@ class PluginApi { */ removeDefaultQuickSearchRandomTips() { removeDefaultQuickSearchRandomTips(); - removeWidgetDefaultQuickSearchRandomTips(); } /** diff --git a/app/assets/javascripts/discourse/app/widgets/header.js b/app/assets/javascripts/discourse/app/widgets/header.js index 96b1c01f085..6ba2d2b15cc 100644 --- a/app/assets/javascripts/discourse/app/widgets/header.js +++ b/app/assets/javascripts/discourse/app/widgets/header.js @@ -249,7 +249,7 @@ createWidget("header-icons", { icon: "search", iconId: SEARCH_BUTTON_ID, action: "toggleSearchMenu", - active: attrs.searchVisible || this.search.visible, + active: this.search.visible, href: getURL("/search"), classNames: ["search-dropdown"], }); @@ -447,14 +447,14 @@ createWidget("revamped-user-menu-wrapper", { }, }); -createWidget("glimmer-search-menu-wrapper", { +createWidget("search-menu-wrapper", { services: ["search"], buildAttributes() { - return { "data-click-outside": true, "aria-live": "polite" }; + return { "aria-live": "polite" }; }, buildClasses() { - return ["search-menu glimmer-search-menu"]; + return ["search-menu"]; }, html() { @@ -502,7 +502,7 @@ export default createWidget("header", { html(attrs, state) { let inTopicRoute = false; - if (this.state.inTopicContext || this.search.inTopicContext) { + if (this.search.inTopicContext) { inTopicRoute = this.router.currentRouteName.startsWith("topic."); } @@ -510,7 +510,7 @@ export default createWidget("header", { const headerIcons = this.attach("header-icons", { hamburgerVisible: state.hamburgerVisible, userVisible: state.userVisible, - searchVisible: state.searchVisible || this.search.visible, + searchVisible: this.search.visible, flagCount: attrs.flagCount, user: this.currentUser, sidebarEnabled: attrs.sidebarEnabled, @@ -522,18 +522,9 @@ export default createWidget("header", { const panels = [this.attach("header-buttons", attrs), headerIcons]; - if (state.searchVisible || this.search.visible) { - if (this.siteSettings.experimental_search_menu) { - this.search.inTopicContext = - this.search.inTopicContext && inTopicRoute; - panels.push(this.attach("glimmer-search-menu-wrapper")); - } else { - panels.push( - this.attach("search-menu", { - inTopicContext: state.inTopicContext && inTopicRoute, - }) - ); - } + if (this.search.visible) { + this.search.inTopicContext = this.search.inTopicContext && inTopicRoute; + panels.push(this.attach("search-menu-wrapper")); } else if (state.hamburgerVisible) { panels.push(this.attach("hamburger-dropdown-wrapper", {})); } else if (state.userVisible) { @@ -570,7 +561,7 @@ export default createWidget("header", { }, updateHighlight() { - if (!this.state.searchVisible || !this.search.visible) { + if (!this.search.visible) { this.search.highlightTerm = ""; } }, @@ -578,7 +569,6 @@ export default createWidget("header", { closeAll() { this.state.userVisible = false; this.state.hamburgerVisible = false; - this.state.searchVisible = false; this.search.visible = false; this.toggleBodyScrolling(false); }, @@ -619,15 +609,10 @@ export default createWidget("header", { } } - this.state.searchVisible = !this.state.searchVisible; this.search.visible = !this.search.visible; this.updateHighlight(); - if (this.state.searchVisible) { - // only used by the widget search-menu - this.focusSearchInput(); - } else { - this.state.inTopicContext = false; + if (!this.search.searchVisible) { this.search.inTopicContext = false; } }, @@ -664,10 +649,7 @@ export default createWidget("header", { }, togglePageSearch() { - const { state } = this; this.search.inTopicContext = false; - state.inTopicContext = false; - let showSearch = this.router.currentRouteName.startsWith("topic."); // If we're viewing a topic, only intercept search if there are cloaked posts @@ -681,13 +663,12 @@ export default createWidget("header", { $(".topic-post .cooked, .small-action:not(.time-gap)").length < total; } - if (state.searchVisible || this.search.visible) { + if (this.search.visible) { this.toggleSearchMenu(); return showSearch; } if (showSearch) { - state.inTopicContext = true; this.search.inTopicContext = true; this.toggleSearchMenu(); return false; @@ -699,12 +680,7 @@ export default createWidget("header", { domClean() { const { state } = this; - if ( - state.searchVisible || - this.search.visible || - state.hamburgerVisible || - state.userVisible - ) { + if (this.search.visible || state.hamburgerVisible || state.userVisible) { this.closeAll(); } }, @@ -728,30 +704,4 @@ export default createWidget("header", { break; } }, - - // only used by the widget search-menu - focusSearchInput() { - if ( - this.state.searchVisible && - !this.siteSettings.experimental_search_menu - ) { - schedule("afterRender", () => { - const searchInput = document.querySelector("#search-term"); - searchInput.focus(); - searchInput.select(); - }); - } - }, - - // only used by the widget search-menu - setTopicContext() { - this.state.inTopicContext = true; - this.focusSearchInput(); - }, - - // only used by the widget search-menu - clearContext() { - this.state.inTopicContext = false; - this.focusSearchInput(); - }, }); diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu-controls.js b/app/assets/javascripts/discourse/app/widgets/search-menu-controls.js deleted file mode 100644 index 8fb489b8c99..00000000000 --- a/app/assets/javascripts/discourse/app/widgets/search-menu-controls.js +++ /dev/null @@ -1,36 +0,0 @@ -import { createWidget } from "discourse/widgets/widget"; -import I18n from "discourse-i18n"; - -createWidget("search-term", { - tagName: "input", - buildId: () => "search-term", - buildKey: () => "search-term", - - buildAttributes(attrs) { - return { - type: "text", - value: attrs.value || "", - autocomplete: "off", - placeholder: I18n.t("search.title"), - "aria-label": I18n.t("search.title"), - }; - }, - - input(e) { - const val = this.attrs.value; - - // remove zero-width chars - const newVal = e.target.value.replace(/[\u200B-\u200D\uFEFF]/, ""); - - if (newVal !== val) { - this.sendWidgetAction("searchTermChanged", newVal); - } - }, -}); - -// TODO: No longer used, remove in December 2021 -createWidget("search-context", { - html() { - return false; - }, -}); diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu-results.js b/app/assets/javascripts/discourse/app/widgets/search-menu-results.js deleted file mode 100644 index cc143658718..00000000000 --- a/app/assets/javascripts/discourse/app/widgets/search-menu-results.js +++ /dev/null @@ -1,901 +0,0 @@ -import { hbs } from "ember-cli-htmlbars"; -import { h } from "virtual-dom"; -import { dateNode } from "discourse/helpers/node"; -import highlightSearch from "discourse/lib/highlight-search"; -import renderTag from "discourse/lib/render-tag"; -import { emojiUnescape } from "discourse/lib/text"; -import { escapeExpression, formatUsername } from "discourse/lib/utilities"; -import User from "discourse/models/user"; -import widgetHbs from "discourse/widgets/hbs-compiler"; -import { avatarImg } from "discourse/widgets/post"; -import RawHtml from "discourse/widgets/raw-html"; -import RenderGlimmer from "discourse/widgets/render-glimmer"; -import { MODIFIER_REGEXP } from "discourse/widgets/search-menu"; -import { createWidget } from "discourse/widgets/widget"; -import getURL from "discourse-common/lib/get-url"; -import { iconNode } from "discourse-common/lib/icon-library"; -import { deepMerge } from "discourse-common/lib/object"; -import I18n from "discourse-i18n"; - -const suggestionShortcuts = [ - "in:title", - "in:pinned", - "status:open", - "status:closed", - "status:public", - "status:noreplies", - "order:latest", - "order:views", - "order:likes", - "order:latest_topic", -]; - -const DEFAULT_QUICK_TIPS = [ - { - label: "#", - description: I18n.t("search.tips.category_tag"), - clickable: true, - }, - { - label: "@", - description: I18n.t("search.tips.author"), - clickable: true, - }, - { - label: "in:", - description: I18n.t("search.tips.in"), - clickable: true, - }, - { - label: "status:", - description: I18n.t("search.tips.status"), - clickable: true, - }, - { - label: I18n.t("search.tips.full_search_key", { modifier: "Ctrl" }), - description: I18n.t("search.tips.full_search"), - }, - { - label: "@me", - description: I18n.t("search.tips.me"), - }, -]; - -let QUICK_TIPS = []; - -export function addSearchSuggestion(value) { - if (!suggestionShortcuts.includes(value)) { - suggestionShortcuts.push(value); - } -} - -export function addQuickSearchRandomTip(tip) { - if (!QUICK_TIPS.includes(tip)) { - QUICK_TIPS.push(tip); - } -} - -export function removeDefaultQuickSearchRandomTips() { - QUICK_TIPS = QUICK_TIPS.filter((tip) => !DEFAULT_QUICK_TIPS.includes(tip)); -} - -export function resetQuickSearchRandomTips() { - QUICK_TIPS = [].concat(DEFAULT_QUICK_TIPS); -} - -resetQuickSearchRandomTips(); - -class Highlighted extends RawHtml { - constructor(html, term) { - super({ html: `${html}` }); - this.term = term; - } - - decorate($html) { - highlightSearch($html[0], this.term); - } -} - -function createSearchResult({ type, linkField, builder }) { - return createWidget(`search-result-${type}`, { - tagName: "ul.list", - - buildAttributes() { - return { - "aria-label": `${type} ${I18n.t("search.results")}`, - }; - }, - - html(attrs) { - return attrs.results.map((r) => { - let searchResultId; - - if (type === "topic") { - searchResultId = r.topic_id; - } else { - searchResultId = r.id; - } - - return h( - "li.item", - this.attach("link", { - href: r[linkField], - contents: () => builder.call(this, r, attrs.term), - className: "search-link", - searchResultId, - searchResultType: type, - searchLogId: attrs.searchLogId, - }) - ); - }); - }, - }); -} - -function postResult(result, link, term) { - const html = [link]; - - if (!this.site.mobileView) { - html.push( - h("span.blurb", [ - dateNode(result.created_at), - h("span", " - "), - this.siteSettings.use_pg_headlines_for_excerpt - ? new RawHtml({ html: `${result.blurb}` }) - : new Highlighted(result.blurb, term), - ]) - ); - } - - return html; -} - -createSearchResult({ - type: "tag", - linkField: "url", - builder(t) { - const tag = escapeExpression(t.id); - return [ - iconNode("tag"), - new RawHtml({ html: renderTag(tag, { tagName: "span" }) }), - ]; - }, -}); - -createSearchResult({ - type: "category", - linkField: "url", - builder(c) { - return this.attach("category-link", { category: c, link: false }); - }, -}); - -createSearchResult({ - type: "group", - linkField: "url", - builder(group) { - const fullName = escapeExpression(group.fullName); - const name = escapeExpression(group.name); - const groupNames = [h("span.name", fullName || name)]; - - if (fullName) { - groupNames.push(h("span.slug", name)); - } - - let avatarFlair; - if (group.flairUrl) { - avatarFlair = this.attach("avatar-flair", { - flair_name: name, - flair_url: group.flairUrl, - flair_bg_color: group.flairBgColor, - flair_color: group.flairColor, - }); - } else { - avatarFlair = iconNode("users"); - } - - const groupResultContents = [avatarFlair, h("div.group-names", groupNames)]; - - return h("div.group-result", groupResultContents); - }, -}); - -createSearchResult({ - type: "user", - linkField: "path", - builder(u) { - const userTitles = []; - - if (u.name) { - userTitles.push(h("span.name", u.name)); - } - - userTitles.push(h("span.username", formatUsername(u.username))); - - if (u.custom_data) { - u.custom_data.forEach((row) => - userTitles.push(h("span.custom-field", `${row.name}: ${row.value}`)) - ); - } - - const userResultContents = [ - avatarImg("small", { - template: u.avatar_template, - username: u.username, - }), - h("div.user-titles", userTitles), - ]; - - return h("div.user-result", userResultContents); - }, -}); - -createSearchResult({ - type: "topic", - linkField: "url", - builder(result, term) { - const topic = result.topic; - - const firstLine = [ - this.attach("topic-status", { topic, disableActions: true }), - h( - "span.topic-title", - { attributes: { "data-topic-id": topic.id } }, - this.siteSettings.use_pg_headlines_for_excerpt && - result.topic_title_headline - ? new RawHtml({ - html: `${emojiUnescape( - result.topic_title_headline - )}`, - }) - : new Highlighted(topic.fancyTitle, term) - ), - ]; - - const secondLine = [ - this.attach("category-link", { - category: topic.category, - link: false, - }), - ]; - if (this.siteSettings.tagging_enabled) { - secondLine.push( - this.attach("discourse-tags", { topic, tagName: "span" }) - ); - } - - const link = h("span.topic", [ - h("span.first-line", firstLine), - h("span.second-line", secondLine), - ]); - - return postResult.call(this, result, link, term); - }, -}); - -createSearchResult({ - type: "post", - linkField: "url", - builder(result, term) { - return postResult.call( - this, - result, - I18n.t("search.post_format", result), - term - ); - }, -}); - -createWidget("search-menu-results", { - tagName: "div.results", - - html(attrs) { - const { - term, - suggestionKeyword, - inTopicContext, - results, - searchTopics, - onLinkClicked, - } = attrs; - - if (suggestionKeyword) { - return this.attach("search-menu-assistant", { - term, - suggestionKeyword, - results: attrs.suggestionResults || [], - }); - } - - if (searchTopics && attrs.invalidTerm) { - return h("div.no-results", I18n.t("search.too_short")); - } - - if (searchTopics && attrs.noResults) { - return h("div.no-results", I18n.t("search.no_results")); - } - - if (!term && !attrs.inPMInboxContext) { - return this.attach("search-menu-initial-options", { term }); - } - - const resultTypes = results.resultTypes || []; - - const mainResultsContent = []; - const usersAndGroups = []; - const categoriesAndTags = []; - - const buildMoreNode = (result) => { - const moreArgs = { - className: "filter search-link", - contents: () => [I18n.t("more"), "..."], - }; - - if (result.moreUrl) { - return this.attach( - "link", - deepMerge(moreArgs, { - href: result.moreUrl, - }) - ); - } else if (result.more) { - return this.attach( - "link", - deepMerge(moreArgs, { - action: "moreOfType", - actionParam: result.type, - }) - ); - } - }; - - const assignContainer = (result, node) => { - if (searchTopics) { - if (["topic"].includes(result.type)) { - mainResultsContent.push(node); - } - } else { - if (["user", "group"].includes(result.type)) { - usersAndGroups.push(node); - } - - if (["category", "tag"].includes(result.type)) { - categoriesAndTags.push(node); - } - } - }; - - resultTypes.forEach((rt) => { - const resultNodeContents = [ - this.attach(rt.componentName, { - searchLogId: attrs.results.grouped_search_result.search_log_id, - results: rt.results, - term, - }), - ]; - - if (["topic"].includes(rt.type)) { - const more = buildMoreNode(rt); - if (more) { - resultNodeContents.push(h("div.search-menu__show-more", more)); - } - } - - assignContainer(rt, h(`div.${rt.componentName}`, resultNodeContents)); - }); - - const content = []; - - if (!searchTopics) { - if (!attrs.inPMInboxContext) { - content.push(this.attach("search-menu-initial-options", { term })); - } - } else { - if (mainResultsContent.length) { - content.push(mainResultsContent); - } else { - return h("div.no-results", I18n.t("search.no_results")); - } - } - - content.push( - new RenderGlimmer( - this, - "div", - hbs``, - { - outletArgs: { - searchTerm: term, - inTopicContext, - onLinkClicked, - searchTopics, - }, - } - ) - ); - - content.push(categoriesAndTags); - content.push(usersAndGroups); - - content.push( - new RenderGlimmer( - this, - "div", - hbs``, - { - outletArgs: { - searchTerm: term, - inTopicContext, - onLinkClicked, - searchTopics, - }, - } - ) - ); - - return content; - }, -}); - -createWidget("search-menu-assistant", { - tagName: "ul.search-menu-assistant", - buildKey: () => `search-menu-assistant`, - services: ["router"], - - html(attrs) { - if (this.currentUser) { - addSearchSuggestion("in:likes"); - addSearchSuggestion("in:bookmarks"); - addSearchSuggestion("in:mine"); - addSearchSuggestion("in:messages"); - addSearchSuggestion("in:seen"); - addSearchSuggestion("in:tracking"); - addSearchSuggestion("in:unseen"); - addSearchSuggestion("in:watching"); - } - if (this.siteSettings.tagging_enabled) { - addSearchSuggestion("in:tagged"); - addSearchSuggestion("in:untagged"); - } - - const content = []; - const { suggestionKeyword, term } = attrs; - - let prefix; - if (suggestionKeyword !== "+") { - prefix = term?.split(suggestionKeyword)[0].trim() || ""; - - if (prefix.length) { - prefix = `${prefix} `; - } - } - - switch (suggestionKeyword) { - case "+": - attrs.results.forEach((item) => { - if (item.additionalTags) { - prefix = term?.split(" ").slice(0, -1).join(" ").trim() || ""; - } else { - prefix = term?.split("#")[0].trim() || ""; - } - - if (prefix.length) { - prefix = `${prefix} `; - } - - content.push( - this.attach("search-menu-assistant-item", { - prefix, - tag: item.tagName, - additionalTags: item.additionalTags, - category: item.category, - slug: term, - withInLabel: attrs.withInLabel, - isIntersection: true, - }) - ); - }); - break; - case "#": - attrs.results.forEach((item) => { - if (item.model) { - const fullSlug = item.model.parentCategory - ? `#${item.model.parentCategory.slug}:${item.model.slug}` - : `#${item.model.slug}`; - - content.push( - this.attach("search-menu-assistant-item", { - prefix, - category: item.model, - slug: `${prefix}${fullSlug}`, - withInLabel: attrs.withInLabel, - }) - ); - } else { - content.push( - this.attach("search-menu-assistant-item", { - prefix, - tag: item.name, - slug: `${prefix}#${item.name}`, - withInLabel: attrs.withInLabel, - }) - ); - } - }); - break; - case "@": - // when only one user matches while in topic - // quick suggest user search in the topic or globally - if ( - attrs.results.length === 1 && - this.router.currentRouteName.startsWith("topic.") - ) { - const user = attrs.results[0]; - content.push( - this.attach("search-menu-assistant-item", { - extraHint: I18n.t("search.enter_hint"), - prefix, - user, - slug: `${prefix}@${user.username}`, - suffix: h( - "span.label-suffix", - ` ${I18n.t("search.in_topics_posts")}` - ), - }) - ); - content.push( - this.attach("search-menu-assistant-item", { - prefix, - user, - setTopicContext: true, - slug: `${prefix}@${user.username}`, - suffix: h( - "span.label-suffix", - ` ${I18n.t("search.in_this_topic")}` - ), - }) - ); - } else { - attrs.results.forEach((user) => { - content.push( - this.attach("search-menu-assistant-item", { - prefix, - user, - slug: `${prefix}@${user.username}`, - }) - ); - }); - } - break; - default: - suggestionShortcuts.forEach((item) => { - if (item.includes(suggestionKeyword) || !suggestionKeyword) { - content.push( - this.attach("search-menu-assistant-item", { - slug: `${prefix}${item}`, - }) - ); - } - }); - break; - } - - return content.filter((c, i) => i <= 8); - }, -}); - -createWidget("search-menu-initial-options", { - tagName: "ul.search-menu-initial-options", - services: ["search"], - - html(attrs) { - if (attrs.term?.match(MODIFIER_REGEXP)) { - return this.defaultRow(attrs.term); - } - - const ctx = this.search.searchContext; - const content = []; - - if (attrs.term || ctx) { - if (attrs.term) { - content.push(this.defaultRow(attrs.term, { withLabel: true })); - } - - if (ctx) { - const term = attrs.term || ""; - switch (ctx.type) { - case "topic": - content.push( - this.attach("search-menu-assistant-item", { - slug: term, - setTopicContext: true, - label: [ - h("span", `${term} `), - h("span.label-suffix", I18n.t("search.in_this_topic")), - ], - }) - ); - break; - - case "private_messages": - content.push( - this.attach("search-menu-assistant-item", { - slug: `${term} in:messages`, - }) - ); - break; - - case "category": - const fullSlug = ctx.category.parentCategory - ? `#${ctx.category.parentCategory.slug}:${ctx.category.slug}` - : `#${ctx.category.slug}`; - - content.push( - this.attach("search-menu-assistant", { - term: `${term} ${fullSlug}`, - suggestionKeyword: "#", - results: [{ model: ctx.category }], - withInLabel: true, - }) - ); - - break; - case "tag": - content.push( - this.attach("search-menu-assistant", { - term: `${term} #${ctx.name}`, - suggestionKeyword: "#", - results: [{ name: ctx.name }], - withInLabel: true, - }) - ); - break; - case "tagIntersection": - let tagTerm; - if (ctx.additionalTags) { - const tags = [ctx.tagId, ...ctx.additionalTags]; - tagTerm = `${term} tags:${tags.join("+")}`; - } else { - tagTerm = `${term} #${ctx.tagId}`; - } - let suggestionOptions = { - tagName: ctx.tagId, - additionalTags: ctx.additionalTags, - }; - if (ctx.category) { - const categorySlug = ctx.category.parentCategory - ? `#${ctx.category.parentCategory.slug}:${ctx.category.slug}` - : `#${ctx.category.slug}`; - suggestionOptions.categoryName = categorySlug; - suggestionOptions.category = ctx.category; - tagTerm = tagTerm + ` ${categorySlug}`; - } - - content.push( - this.attach("search-menu-assistant", { - term: tagTerm, - suggestionKeyword: "+", - results: [suggestionOptions], - withInLabel: true, - }) - ); - break; - case "user": - content.push( - this.attach("search-menu-assistant-item", { - slug: `${term} @${ctx.user.username}`, - label: [ - h("span", `${term} `), - h( - "span.label-suffix", - I18n.t("search.in_posts_by", { - username: ctx.user.username, - }) - ), - ], - }) - ); - break; - } - } - - return content; - } - - if (content.length === 0) { - content.push(this.attach("random-quick-tip")); - - if (this.currentUser && this.siteSettings.log_search_queries) { - if (this.currentUser.recent_searches?.length) { - content.push(this.attach("search-menu-recent-searches")); - } else { - this.loadRecentSearches(); - } - } - } - - return content; - }, - - defaultRow(term, opts = { withLabel: false }) { - return this.attach("search-menu-assistant-item", { - slug: term, - extraHint: I18n.t("search.enter_hint"), - label: [ - h("span.keyword", `${term}`), - opts.withLabel - ? h("span.label-suffix", I18n.t("search.in_topics_posts")) - : null, - ], - }); - }, - - refreshSearchMenuResults() { - this.scheduleRerender(); - }, - - loadRecentSearches() { - User.loadRecentSearches().then((result) => { - if (result.success && result.recent_searches?.length) { - this.currentUser.set( - "recent_searches", - Object.assign(result.recent_searches) - ); - this.scheduleRerender(); - } - }); - }, -}); - -createWidget("search-menu-assistant-item", { - tagName: "li.search-menu-assistant-item", - - html(attrs) { - const prefix = attrs.prefix?.trim(); - const attributes = {}; - attributes.href = "#"; - - let content = [ - h( - "span", - { attributes: { "aria-label": I18n.t("search.title") } }, - iconNode(attrs.icon || "search") - ), - ]; - - if (prefix) { - content.push(h("span.search-item-prefix", `${prefix} `)); - } - - if (attrs.withInLabel) { - content.push(h("span.label-suffix", `${I18n.t("search.in")} `)); - } - - if (attrs.category) { - attributes.href = attrs.category.url; - - content.push( - this.attach("category-link", { - category: attrs.category, - allowUncategorized: true, - recursive: true, - link: false, - }) - ); - - // category and tag combination - if (attrs.tag && attrs.isIntersection) { - attributes.href = getURL(`/tag/${attrs.tag}`); - content.push(h("span.search-item-tag", [iconNode("tag"), attrs.tag])); - } - } else if (attrs.tag) { - if (attrs.isIntersection && attrs.additionalTags?.length) { - const tags = [attrs.tag, ...attrs.additionalTags]; - content.push(h("span.search-item-tag", `tags:${tags.join("+")}`)); - } else { - attributes.href = getURL(`/tag/${attrs.tag}`); - content.push(h("span.search-item-tag", [iconNode("tag"), attrs.tag])); - } - } else if (attrs.user) { - const userResult = [ - avatarImg("small", { - template: attrs.user.avatar_template, - username: attrs.user.username, - }), - h("span.username", formatUsername(attrs.user.username)), - attrs.suffix, - ]; - content.push(h("span.search-item-user", userResult)); - } else { - content.push(h("span.search-item-slug", attrs.label || attrs.slug)); - } - if (attrs.extraHint) { - content.push(h("span.extra-hint", attrs.extraHint)); - } - return h("a.widget-link.search-link", { attributes }, content); - }, - - click(e) { - const searchInput = document.querySelector("#search-term"); - searchInput.value = this.attrs.slug; - searchInput.focus(); - this.sendWidgetAction("triggerAutocomplete", { - value: this.attrs.slug, - searchTopics: true, - setTopicContext: this.attrs.setTopicContext, - origin: this.attrs.origin, - }); - e.preventDefault(); - return false; - }, -}); - -createWidget("random-quick-tip", { - tagName: "li.search-random-quick-tip", - - buildKey: () => "random-quick-tip", - - defaultState() { - return QUICK_TIPS.length - ? QUICK_TIPS[Math.floor(Math.random() * QUICK_TIPS.length)] - : {}; - }, - - html(attrs, state) { - if (!Object.keys(state).length) { - return; - } - - return [ - h( - `span.tip-label${state.clickable ? ".tip-clickable" : ""}`, - state.label - ), - h("span.tip-description", state.description), - ]; - }, - - click(e) { - if (e.target.classList.contains("tip-clickable")) { - const searchInput = document.querySelector("#search-term"); - searchInput.value = this.state.label; - searchInput.focus(); - this.sendWidgetAction("triggerAutocomplete", { - value: this.state.label, - searchTopics: this.state.searchTopics, - }); - } - }, -}); - -createWidget("search-menu-recent-searches", { - tagName: "div.search-menu-recent", - - template: widgetHbs` -
-

{{i18n "search.recent"}}

- {{flat-button - className="clear-recent-searches" - title="search.clear_recent" - icon="times" - action="clearRecent" - }} -
- - {{#each this.currentUser.recent_searches as |slug|}} - {{attach - widget="search-menu-assistant-item" - attrs=(hash slug=slug icon="history" origin="recent-search") - }} - {{/each}} - `, - - clearRecent() { - return User.resetRecentSearches().then((result) => { - if (result.success) { - this.currentUser.recent_searches.clear(); - this.sendWidgetAction("refreshSearchMenuResults"); - } - }); - }, -}); diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu.js b/app/assets/javascripts/discourse/app/widgets/search-menu.js deleted file mode 100644 index ced31e6dcbb..00000000000 --- a/app/assets/javascripts/discourse/app/widgets/search-menu.js +++ /dev/null @@ -1,595 +0,0 @@ -import { cancel } from "@ember/runloop"; -import { Promise } from "rsvp"; -import { h } from "virtual-dom"; -import { popupAjaxError } from "discourse/lib/ajax-error"; -import { CANCELLED_STATUS } from "discourse/lib/autocomplete"; -import { search as searchCategoryTag } from "discourse/lib/category-tag-search"; -import { - isValidSearchTerm, - searchForTerm, - updateRecentSearches, -} from "discourse/lib/search"; -import DiscourseURL from "discourse/lib/url"; -import userSearch from "discourse/lib/user-search"; -import { isiPad, translateModKey } from "discourse/lib/utilities"; -import { createWidget } from "discourse/widgets/widget"; -import discourseDebounce from "discourse-common/lib/debounce"; -import getURL from "discourse-common/lib/get-url"; -import { iconNode } from "discourse-common/lib/icon-library"; -import I18n from "discourse-i18n"; - -const CATEGORY_SLUG_REGEXP = /(\#[a-zA-Z0-9\-:]*)$/gi; -const USERNAME_REGEXP = /(\@[a-zA-Z0-9\-\_]*)$/gi; -const SUGGESTIONS_REGEXP = /(in:|status:|order:|:)([a-zA-Z]*)$/gi; -const SECOND_ENTER_MAX_DELAY = 15000; -export const MODIFIER_REGEXP = /.*(\#|\@|:).*$/gi; -export const DEFAULT_TYPE_FILTER = "exclude_topics"; - -const searchData = {}; - -const onKeyDownCallbacks = []; - -export function addOnKeyDownCallback(fn) { - onKeyDownCallbacks.push(fn); -} -export function resetOnKeyDownCallbacks() { - onKeyDownCallbacks.clear(); -} - -export function initSearchData() { - searchData.loading = false; - searchData.results = {}; - searchData.noResults = false; - searchData.term = undefined; - searchData.typeFilter = DEFAULT_TYPE_FILTER; - searchData.invalidTerm = false; - searchData.suggestionResults = []; - searchData.suggestionKeyword = false; -} - -initSearchData(); - -// Helps with debouncing and cancelling promises -const SearchHelper = { - _activeSearch: null, - - // for cancelling debounced search - cancel() { - if (this._activeSearch) { - this._activeSearch.abort(); - this._activeSearch = null; - } - }, - - perform(widget) { - this.cancel(); - - const { term, typeFilter } = searchData; - const searchContext = widget.searchContext(); - - const fullSearchUrl = widget.fullSearchUrl(); - const matchSuggestions = this.matchesSuggestions(); - - if (matchSuggestions) { - searchData.noResults = true; - searchData.results = {}; - searchData.loading = false; - searchData.suggestionResults = []; - - if (matchSuggestions.type === "category") { - const categorySearchTerm = matchSuggestions.categoriesMatch[0].replace( - "#", - "" - ); - - const categoryTagSearch = searchCategoryTag( - categorySearchTerm, - widget.siteSettings - ); - Promise.resolve(categoryTagSearch).then((results) => { - if (results !== CANCELLED_STATUS) { - searchData.suggestionResults = results; - searchData.suggestionKeyword = "#"; - } - widget.scheduleRerender(); - }); - } else if (matchSuggestions.type === "username") { - const userSearchTerm = matchSuggestions.usernamesMatch[0].replace( - "@", - "" - ); - const opts = { includeGroups: true, limit: 6 }; - if (userSearchTerm.length > 0) { - opts.term = userSearchTerm; - } else { - opts.lastSeenUsers = true; - } - - userSearch(opts).then((result) => { - if (result?.users?.length > 0) { - searchData.suggestionResults = result.users; - searchData.suggestionKeyword = "@"; - } else { - searchData.noResults = true; - searchData.suggestionKeyword = false; - } - widget.scheduleRerender(); - }); - } else { - searchData.suggestionKeyword = matchSuggestions[0]; - widget.scheduleRerender(); - } - return; - } - - searchData.suggestionKeyword = false; - - if (!term) { - searchData.noResults = false; - searchData.results = {}; - searchData.loading = false; - searchData.invalidTerm = false; - - widget.scheduleRerender(); - } else if (!isValidSearchTerm(term, widget.siteSettings)) { - searchData.noResults = true; - searchData.results = {}; - searchData.loading = false; - searchData.invalidTerm = true; - - widget.scheduleRerender(); - } else { - searchData.invalidTerm = false; - - this._activeSearch = searchForTerm(term, { - typeFilter, - fullSearchUrl, - searchContext, - }); - this._activeSearch - .then((results) => { - // we ensure the current search term is the one used - // when starting the query - if (results && term === searchData.term) { - if (searchContext) { - widget.appEvents.trigger("post-stream:refresh", { force: true }); - } - - searchData.noResults = results.resultTypes.length === 0; - searchData.results = results; - } - }) - .catch(popupAjaxError) - .finally(() => { - searchData.loading = false; - widget.scheduleRerender(); - }); - } - }, - - matchesSuggestions() { - if (searchData.term === undefined || this.includesTopics()) { - return false; - } - - const term = searchData.term.trim(); - const categoriesMatch = term.match(CATEGORY_SLUG_REGEXP); - - if (categoriesMatch) { - return { type: "category", categoriesMatch }; - } - - const usernamesMatch = term.match(USERNAME_REGEXP); - if (usernamesMatch) { - return { type: "username", usernamesMatch }; - } - - const suggestionsMatch = term.match(SUGGESTIONS_REGEXP); - if (suggestionsMatch) { - return suggestionsMatch; - } - - return false; - }, - - includesTopics() { - return searchData.typeFilter !== DEFAULT_TYPE_FILTER; - }, -}; - -export default createWidget("search-menu", { - tagName: "div.search-menu", - services: ["search"], - searchData, - - buildAttributes() { - return { - "aria-live": "polite", - }; - }, - - buildKey: () => "search-menu", - - defaultState(attrs) { - return { - inTopicContext: attrs.inTopicContext, - inPMInboxContext: this.search?.searchContext?.type === "private_messages", - _lastEnterTimestamp: null, - _debouncer: null, - }; - }, - - fullSearchUrl(opts) { - let url = "/search"; - const params = []; - - if (searchData.term) { - let query = ""; - - query += `q=${encodeURIComponent(searchData.term)}`; - - const searchContext = this.searchContext(); - - if (searchContext?.type === "topic") { - query += encodeURIComponent(` topic:${searchContext.id}`); - } else if (searchContext?.type === "private_messages") { - query += encodeURIComponent(` in:messages`); - } - - if (query) { - params.push(query); - } - } - - if (opts && opts.expanded) { - params.push("expanded=true"); - } - - if (params.length > 0) { - url = `${url}?${params.join("&")}`; - } - - return getURL(url); - }, - - panelContents() { - let searchInput = []; - if (this.state.inTopicContext) { - searchInput.push( - this.attach("button", { - icon: "times", - label: "search.in_this_topic", - title: "search.in_this_topic_tooltip", - className: "btn btn-small search-context", - action: "clearTopicContext", - iconRight: true, - }) - ); - } else if (this.state.inPMInboxContext) { - searchInput.push( - this.attach("button", { - icon: "times", - label: "search.in_messages", - title: "search.in_messages_tooltip", - className: "btn btn-small search-context", - action: "clearPMInboxContext", - iconRight: true, - }) - ); - } - - searchInput.push(this.attach("search-term", { value: searchData.term })); - - if (searchData.loading) { - searchInput.push(h("div.searching", h("div.spinner"))); - } else { - const clearButton = this.attach("link", { - title: "search.clear_search", - action: "clearSearch", - className: "clear-search", - contents: () => iconNode("times"), - }); - - const advancedSearchButton = this.attach("link", { - href: this.fullSearchUrl({ expanded: true }), - contents: () => iconNode("sliders-h"), - className: "show-advanced-search", - title: "search.open_advanced", - }); - - if (searchData.term) { - searchInput.push( - h("div.searching", [clearButton, advancedSearchButton]) - ); - } else { - searchInput.push(h("div.searching", advancedSearchButton)); - } - } - - const results = [h("div.search-input", searchInput)]; - - if ( - this.state.inTopicContext && - (!SearchHelper.includesTopics() || !searchData.term) - ) { - const isMobileDevice = this.site.isMobileDevice; - - if (!isMobileDevice) { - results.push(this.attach("browser-search-tip")); - } - return results; - } - - if (!searchData.loading) { - results.push( - this.attach("search-menu-results", { - term: searchData.term, - noResults: searchData.noResults, - results: searchData.results, - invalidTerm: searchData.invalidTerm, - suggestionKeyword: searchData.suggestionKeyword, - suggestionResults: searchData.suggestionResults, - searchTopics: SearchHelper.includesTopics(), - inPMInboxContext: this.state.inPMInboxContext, - inTopicContext: this.state.inTopicContext, - onLinkClicked: this.onLinkClicked.bind(this), - }) - ); - } - - return results; - }, - - clearSearch() { - searchData.term = ""; - const searchInput = document.getElementById("search-term"); - searchInput.value = ""; - searchInput.focus(); - this.triggerSearch(); - }, - - html(attrs, state) { - if (attrs.inTopicContext === false) { - state.inTopicContext = false; - } - - return this.attach("menu-panel", { - maxWidth: 500, - contents: () => this.panelContents(), - }); - }, - - onLinkClicked() { - return this.sendWidgetAction("linkClickedEvent"); - }, - - mouseDown(e) { - if (e.target === document.querySelector("input#search-term")) { - this.state.inputSelectionEvent = true; - } - }, - - clickOutside() { - if (this.key === "search-menu" && !this.state.inputSelectionEvent) { - this.sendWidgetAction("toggleSearchMenu"); - } - this.state.inputSelectionEvent = false; - }, - - clearTopicContext() { - this.sendWidgetAction("clearContext"); - }, - - clearPMInboxContext() { - this.state.inPMInboxContext = false; - this.sendWidgetAction("focusSearchInput"); - }, - - keyDown(e) { - if ( - onKeyDownCallbacks.length && - !onKeyDownCallbacks.some((fn) => fn(this, e)) - ) { - // Return early if any callbacks return false - return; - } - - this.handleKeyDown(e); - }, - - handleKeyDown(e) { - if (e.key === "Escape") { - this.sendWidgetAction("toggleSearchMenu"); - document.querySelector("#search-button").focus(); - e.preventDefault(); - return false; - } - - if (searchData.loading) { - return; - } - - if (e.which === 65 /* a */) { - if (document.activeElement?.classList.contains("search-link")) { - if (document.querySelector("#reply-control.open")) { - // add a link and focus composer - - this.appEvents.trigger( - "composer:insert-text", - document.activeElement.href, - { - ensureSpace: true, - } - ); - this.appEvents.trigger("header:keyboard-trigger", { type: "search" }); - - e.preventDefault(); - document.querySelector("#reply-control.open textarea").focus(); - return false; - } - } - } - - const up = e.key === "ArrowUp"; - const down = e.key === "ArrowDown"; - if (up || down) { - let focused = document.activeElement.closest(".search-menu") - ? document.activeElement - : null; - - if (!focused) { - return; - } - - let links = document.querySelectorAll(".search-menu .results a"); - let results = document.querySelectorAll( - ".search-menu .results .search-link" - ); - - if (!results.length) { - return; - } - - let prevResult; - let result; - - links.forEach((item) => { - if (item.classList.contains("search-link")) { - prevResult = item; - } - - if (item === focused) { - result = prevResult; - } - }); - - let index = -1; - - if (result) { - index = Array.prototype.indexOf.call(results, result); - } - - if (index === -1 && down) { - document.querySelector(".search-menu .results .search-link").focus(); - } else if (index === 0 && up) { - document.querySelector(".search-menu input#search-term").focus(); - } else if (index > -1) { - index += down ? 1 : -1; - if (index >= 0 && index < results.length) { - results[index].focus(); - } - } - - e.preventDefault(); - return false; - } - - const searchInput = document.querySelector("#search-term"); - if (e.key === "Enter" && e.target === searchInput) { - const recentEnterHit = - this.state._lastEnterTimestamp && - Date.now() - this.state._lastEnterTimestamp < SECOND_ENTER_MAX_DELAY; - - // same combination as key-enter-escape mixin - if ( - e.ctrlKey || - e.metaKey || - (isiPad() && e.altKey) || - (searchData.typeFilter !== DEFAULT_TYPE_FILTER && recentEnterHit) - ) { - this.fullSearch(); - } else { - searchData.typeFilter = null; - this.triggerSearch(); - } - this.state._lastEnterTimestamp = Date.now(); - } - - if (e.target === searchInput && e.key === "Backspace") { - if (!searchInput.value) { - this.clearTopicContext(); - this.clearPMInboxContext(); - } - } - }, - - triggerSearch() { - searchData.noResults = false; - if (SearchHelper.includesTopics()) { - if (this.state.inTopicContext) { - this.search.set("highlightTerm", searchData.term); - } - - searchData.loading = true; - cancel(this.state._debouncer); - SearchHelper.perform(this); - if (this.currentUser) { - updateRecentSearches(this.currentUser, searchData.term); - } - } else { - searchData.loading = false; - if (!this.state.inTopicContext) { - this.state._debouncer = discourseDebounce( - SearchHelper, - SearchHelper.perform, - this, - 400 - ); - } - } - }, - - moreOfType(type) { - searchData.typeFilter = type; - this.triggerSearch(); - }, - - searchTermChanged(term, opts = {}) { - searchData.typeFilter = opts.searchTopics ? null : DEFAULT_TYPE_FILTER; - searchData.term = term; - this.triggerSearch(); - }, - - triggerAutocomplete(opts = {}) { - if (opts.setTopicContext) { - this.sendWidgetAction("setTopicContext"); - this.state.inTopicContext = true; - } - this.searchTermChanged(opts.value, { searchTopics: opts.searchTopics }); - }, - - fullSearch() { - searchData.loading = false; - SearchHelper.cancel(); - const url = this.fullSearchUrl(); - if (url) { - this.sendWidgetEvent("linkClicked"); - DiscourseURL.routeTo(url); - } - }, - - searchContext() { - if (this.state.inTopicContext || this.state.inPMInboxContext) { - return this.search.searchContext; - } - - return false; - }, -}); - -createWidget("browser-search-tip", { - buildKey: () => "browser-search-tip", - tagName: "div.browser-search-tip", - - html() { - return [ - h( - "span.tip-label", - I18n.t("search.browser_tip", { - modifier: translateModKey("Meta"), - }) - ), - h("span.tip-description", I18n.t("search.browser_tip_description")), - ]; - }, -}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/glimmer-search-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/glimmer-search-mobile-test.js deleted file mode 100644 index 4ea36862363..00000000000 --- a/app/assets/javascripts/discourse/tests/acceptance/glimmer-search-mobile-test.js +++ /dev/null @@ -1,50 +0,0 @@ -import { click, fillIn, visit } from "@ember/test-helpers"; -import { test } from "qunit"; -import { - acceptance, - count, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; - -acceptance("Search - Glimmer - Mobile", function (needs) { - needs.mobileView(); - - test("search", async function (assert) { - await visit("/"); - - await click("#search-button"); - - assert.ok( - exists("input.full-page-search"), - "it shows the full page search form" - ); - - assert.ok(!exists(".search-results .fps-topic"), "no results by default"); - - await click(".advanced-filters summary"); - - assert.ok( - exists(".advanced-filters[open]"), - "it should expand advanced search filters" - ); - - await fillIn(".search-query", "discourse"); - await click(".search-cta"); - - assert.strictEqual(count(".fps-topic"), 1, "has one post"); - - assert.notOk( - exists(".advanced-filters[open]"), - "it should collapse advanced search filters" - ); - - await click("#search-button"); - - assert.strictEqual( - query("input.full-page-search").value, - "discourse", - "it does not reset input when hitting search icon again" - ); - }); -}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js index aeaf436342b..767b36ef7e0 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js @@ -47,24 +47,4 @@ acceptance("Search - Mobile", function (needs) { "it does not reset input when hitting search icon again" ); }); - - test("Search context in full page search", async function (assert) { - await visit("/search?context=tag&context_id=dev&skip_context=true"); - - assert.ok(exists(".search-header .search-context")); - - assert.strictEqual( - query(".search-header .search-context input[type='checkbox']").checked, - false, - "checkbox matches query parameter" - ); - - await click(".search-header .search-context label"); - - assert.strictEqual( - query(".search-header .search-context input[type='checkbox']").checked, - true, - "checkbox toggling works" - ); - }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/glimmer-search-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-test.js similarity index 99% rename from app/assets/javascripts/discourse/tests/acceptance/glimmer-search-test.js rename to app/assets/javascripts/discourse/tests/acceptance/search-test.js index 9cd352d6744..b754c1a83f4 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/glimmer-search-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-test.js @@ -19,7 +19,7 @@ import { import selectKit from "discourse/tests/helpers/select-kit-helper"; import I18n from "discourse-i18n"; -acceptance("Search - Glimmer - Anonymous", function (needs) { +acceptance("Search - Anonymous", function (needs) { needs.pretender((server, helper) => { server.get("/search/query", (request) => { if (request.queryParams.type_filter === DEFAULT_TYPE_FILTER) { @@ -431,7 +431,7 @@ acceptance("Search - Glimmer - Anonymous", function (needs) { }); }); -acceptance("Search - Glimmer - Authenticated", function (needs) { +acceptance("Search - Authenticated", function (needs) { needs.user(); needs.settings({ log_search_queries: true, @@ -741,7 +741,7 @@ acceptance("Search - Glimmer - Authenticated", function (needs) { }); }); -acceptance("Search - Glimmer - with tagging enabled", function (needs) { +acceptance("Search - with tagging enabled", function (needs) { needs.user(); needs.settings({ tagging_enabled: true }); needs.pretender((server, helper) => { @@ -923,7 +923,7 @@ acceptance("Search - Glimmer - with tagging enabled", function (needs) { }); }); -acceptance("Search - Glimmer - assistant", function (needs) { +acceptance("Search - assistant", function (needs) { needs.user(); needs.pretender((server, helper) => { server.get("/t/2179.json", () => { diff --git a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js index 8beee715bd8..aeb00a200b0 100644 --- a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js +++ b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js @@ -22,6 +22,7 @@ import { clearBulkButtons } from "discourse/components/modal/topic-bulk-actions" import { resetWidgetCleanCallbacks } from "discourse/components/mount-widget"; import { resetDecorators as resetPluginOutletDecorators } from "discourse/components/plugin-connector"; import { resetItemSelectCallbacks } from "discourse/components/search-menu/results/assistant-item"; +import { resetQuickSearchRandomTips } from "discourse/components/search-menu/results/random-quick-tip"; import { resetOnKeyUpCallbacks } from "discourse/components/search-menu/search-term"; import { resetTopicTitleDecorators } from "discourse/components/topic-title"; import { resetUserMenuProfileTabItems } from "discourse/components/user-menu/profile-tab-content"; @@ -84,11 +85,6 @@ import { import { clearExtraHeaderIcons } from "discourse/widgets/header"; import { resetDecorators as resetPostCookedDecorators } from "discourse/widgets/post-cooked"; import { resetPostMenuExtraButtons } from "discourse/widgets/post-menu"; -import { - initSearchData, - resetOnKeyDownCallbacks, -} from "discourse/widgets/search-menu"; -import { resetQuickSearchRandomTips } from "discourse/widgets/search-menu-results"; import { resetDecorators } from "discourse/widgets/widget"; import deprecated from "discourse-common/lib/deprecated"; import { getOwnerWithFallback } from "discourse-common/lib/get-owner"; @@ -188,7 +184,6 @@ export function testCleanup(container, app) { clearOutletCache(); clearHTMLCache(); clearRewrites(); - initSearchData(); resetDecorators(); resetPostCookedDecorators(); resetPluginOutletDecorators(); @@ -229,7 +224,6 @@ export function testCleanup(container, app) { resetNotificationTypeRenderers(); resetSidebarPanels(); clearExtraHeaderIcons(); - resetOnKeyDownCallbacks(); resetOnKeyUpCallbacks(); resetItemSelectCallbacks(); resetUserMenuTabs(); diff --git a/app/assets/javascripts/discourse/tests/integration/components/search-menu-test.gjs b/app/assets/javascripts/discourse/tests/integration/components/search-menu-test.gjs index b03c92fb9f3..f8f5fc34346 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/search-menu-test.gjs +++ b/app/assets/javascripts/discourse/tests/integration/components/search-menu-test.gjs @@ -10,7 +10,7 @@ import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import I18n from "discourse-i18n"; // Note this isn't a full-fledge test of the search menu. Those tests are in -// acceptance/glimmer-search-test.js. This is simply about the rendering of the +// acceptance/search-test.js. This is simply about the rendering of the // menu panel separate from the search input. module("Integration | Component | search-menu", function (hooks) { setupRenderingTest(hooks); diff --git a/app/assets/stylesheets/common/base/search-menu.scss b/app/assets/stylesheets/common/base/search-menu.scss index 48bfffa8657..0e0f0747d39 100644 --- a/app/assets/stylesheets/common/base/search-menu.scss +++ b/app/assets/stylesheets/common/base/search-menu.scss @@ -130,11 +130,40 @@ $search-pad-horizontal: 0.5em; } .search-result-group .group-result, - .search-result-user .user-result { - display: flex; - align-items: center; - font-size: var(--font-down-1); + .search-result-user { + .search-link { + display: flex; + align-items: center; + + img.avatar { + margin-right: 10px; + } + } + + .user-titles { + @include user-item-flex; + + .name { + font-weight: 700; + } + + .username, + .name, + .custom-field { + color: var(--primary-high-or-secondary-low); + } + + .custom-field { + font-size: var(--font-down-2); + } + } + .user-result { + display: flex; + align-items: center; + font-size: var(--font-down-1); + } } + .search-result-group .group-result { .d-icon, .avatar-flair { @@ -171,31 +200,6 @@ $search-pad-horizontal: 0.5em; } } - .search-result-user .user-result { - .user-titles { - @include user-item-flex; - - .username, - .name { - @include ellipsis; - } - - .name { - font-weight: 700; - } - - .username, - .name, - .custom-field { - color: var(--primary-high-or-secondary-low); - } - - .custom-field { - font-size: var(--font-down-2); - } - } - } - .search-result-category, .search-result-tag { + .search-result-user, @@ -205,10 +209,18 @@ $search-pad-horizontal: 0.5em; } .search-result-user .user-result img.avatar, - .search-item-user img.avatar { - width: 20px; - height: 20px; - margin-right: 0.5em; + .search-item-user { + display: flex; + align-self: center; + + img.avatar { + width: 20px; + height: 20px; + margin-right: 0.5em; + } + .username { + margin-right: 0.33em; + } } .label-suffix { @@ -218,6 +230,10 @@ $search-pad-horizontal: 0.5em; .search-item-tag { color: var(--primary-high); + + .d-icon { + margin-right: 0 !important; + } } .extra-hint { @@ -377,55 +393,3 @@ $search-pad-horizontal: 0.5em; } } } - -// these styles will become the default once the glimmer search menu -// is enabled for all users, and the old search menu is removed -// we can then drop any '!important' rules -.search-menu.glimmer-search-menu { - .search-item-tag .d-icon { - margin-right: 0 !important; - } - - .search-item-user { - display: flex; - align-self: center; - - .username { - margin-right: 0.33em; - } - } - - .search-result-user { - .search-link { - display: flex; - align-items: center; - - img.avatar { - margin-right: 10px; - } - } - - .user-titles { - @include user-item-flex; - - .username, - .name { - @include ellipsis; - } - - .name { - font-weight: 700; - } - - .username, - .name, - .custom-field { - color: var(--primary-high-or-secondary-low); - } - - .custom-field { - font-size: var(--font-down-2); - } - } - } -} diff --git a/config/site_settings.yml b/config/site_settings.yml index 83ea3c6eae4..e32ff60b5aa 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -2323,10 +2323,6 @@ developer: experimental_topics_filter: client: true default: false - experimental_search_menu: - client: true - hidden: true - default: true max_sidebar_section_links: default: 50 hidden: true