DEV: Move relevant glimmer search menu logic to service (#23483)

This will allow initializing the glimmer search menu without having to pass args directly from header.js widget, to help themes and plugins with search customizations

---------

Co-authored-by: Mark VanLandingham <markvanlan@gmail.com>
This commit is contained in:
Isaac Janzen 2023-09-13 14:32:12 -05:00 committed by GitHub
parent 6b218636ab
commit 3d6b812220
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 48 deletions

View File

@ -1,6 +1,5 @@
<MenuPanel @animationClass={{@animationClass}}>
<MenuPanel @animationClass={{this.animationClass}}>
<SearchMenu::MenuPanelContents
@inTopicContext={{this.inTopicContext}}
@clearTopicContext={{this.clearTopicContext}}
@clearPMInboxContext={{this.clearPMInboxContext}}
@inPMInboxContext={{this.inPMInboxContext}}
@ -19,7 +18,6 @@
@searchTopics={{this.includesTopics}}
@typeFilter={{this.typeFilter}}
@updateTypeFilter={{this.updateTypeFilter}}
@toggleSearchMenu={{@toggleSearchMenu}}
@closeSearchMenu={{@closeSearchMenu}}
/>
</MenuPanel>

View File

@ -39,8 +39,8 @@ export default class SearchMenu extends Component {
@service currentUser;
@service siteSettings;
@service appEvents;
@service site;
@tracked inTopicContext = this.args.inTopicContext;
@tracked loading = false;
@tracked results = {};
@tracked noResults = false;
@ -53,12 +53,18 @@ export default class SearchMenu extends Component {
_debouncer = null;
_activeSearch = null;
get animationClass() {
return this.site.mobileView || this.site.narrowDesktopView
? "slide-in"
: "drop-down";
}
get includesTopics() {
return this.typeFilter !== DEFAULT_TYPE_FILTER;
}
get searchContext() {
if (this.inTopicContext || this.inPMInboxContext) {
if (this.search.inTopicContext || this.inPMInboxContext) {
return this.search.searchContext;
}
@ -102,7 +108,7 @@ export default class SearchMenu extends Component {
searchTermChanged(term, opts = {}) {
this.typeFilter = opts.searchTopics ? null : DEFAULT_TYPE_FILTER;
if (opts.setTopicContext) {
this.inTopicContext = true;
this.search.inTopicContext = true;
}
this.search.activeGlobalSearchTerm = term;
this.triggerSearch();
@ -129,7 +135,7 @@ export default class SearchMenu extends Component {
@action
clearTopicContext() {
this.inTopicContext = false;
this.search.inTopicContext = false;
}
// for cancelling debounced search
@ -286,7 +292,7 @@ export default class SearchMenu extends Component {
}
} else {
this.loading = false;
if (!this.inTopicContext) {
if (!this.search.inTopicContext) {
this._debouncer = discourseDebounce(this, this.perform, 400);
}
}

View File

@ -1,5 +1,5 @@
<div class="search-input">
{{#if @inTopicContext}}
{{#if this.search.inTopicContext}}
<DButton
@icon="times"
@label="search.in_this_topic"
@ -42,7 +42,7 @@
{{/if}}
</div>
{{#if (and @inTopicContext (not @includesTopics))}}
{{#if (and this.search.inTopicContext (not @includesTopics))}}
<SearchMenu::BrowserSearchTip />
{{else}}
{{#unless @loading}}

View File

@ -95,6 +95,7 @@ export default class AssistantItem extends Component {
} else {
updatedValue = this.prefix.trim();
}
const inTopicContext = this.search.searchContext?.type === "topic";
this.args.searchTermChanged(updatedValue, {
searchTopics: !inTopicContext || this.search.activeGlobalSearchTerm,

View File

@ -28,7 +28,7 @@ export default class InitialOptions extends Component {
this.contextTypeComponent =
SEARCH_CONTEXT_TYPE_COMPONENTS[this.search.searchContext.type];
// set attributes for the component
this.attributesForSearchContextType(this.search.searchContext.type);
this.setAttributesForSearchContextType(this.search.searchContext.type);
}
}
}
@ -39,7 +39,7 @@ export default class InitialOptions extends Component {
: false;
}
attributesForSearchContextType(type) {
setAttributesForSearchContextType(type) {
switch (type) {
case "topic":
this.topicContextType();

View File

@ -11,6 +11,8 @@ export default class Search extends Service {
@tracked activeGlobalSearchTerm = "";
@tracked searchContext;
@tracked highlightTerm;
@tracked inTopicContext = false;
@tracked visible = false;
// only relative for the widget search menu
searchContextEnabled = false; // checkbox to scope search

View File

@ -244,6 +244,7 @@ createWidget(
);
createWidget("header-icons", {
services: ["search"],
tagName: "ul.icons.d-header-icons",
html(attrs) {
@ -264,7 +265,7 @@ createWidget("header-icons", {
icon: "search",
iconId: SEARCH_BUTTON_ID,
action: "toggleSearchMenu",
active: attrs.searchVisible,
active: attrs.searchVisible || this.search.visible,
href: getURL("/search"),
classNames: ["search-dropdown"],
});
@ -421,6 +422,7 @@ createWidget("revamped-user-menu-wrapper", {
});
createWidget("glimmer-search-menu-wrapper", {
services: ["search"],
buildAttributes() {
return { "data-click-outside": true, "aria-live": "polite" };
},
@ -434,18 +436,8 @@ createWidget("glimmer-search-menu-wrapper", {
new RenderGlimmer(
this,
"div.widget-component-connector",
hbs`<SearchMenu
@inTopicContext={{@data.inTopicContext}}
@searchVisible={{@data.searchVisible}}
@animationClass={{@data.animationClass}}
@closeSearchMenu={{@data.closeSearchMenu}}
/>`,
{
closeSearchMenu: this.closeSearchMenu.bind(this),
inTopicContext: this.attrs.inTopicContext,
searchVisible: this.attrs.searchVisible,
animationClass: this.attrs.animationClass,
}
hbs`<SearchMenu @closeSearchMenu={{@data.closeSearchMenu}} />`,
{ closeSearchMenu: this.closeSearchMenu.bind(this) }
),
];
},
@ -481,8 +473,7 @@ export default createWidget("header", {
html(attrs, state) {
let inTopicRoute = false;
if (this.state.inTopicContext) {
if (this.state.inTopicContext || this.search.inTopicContext) {
inTopicRoute = this.router.currentRouteName.startsWith("topic.");
}
@ -490,7 +481,7 @@ export default createWidget("header", {
const headerIcons = this.attach("header-icons", {
hamburgerVisible: state.hamburgerVisible,
userVisible: state.userVisible,
searchVisible: state.searchVisible,
searchVisible: state.searchVisible || this.search.visible,
flagCount: attrs.flagCount,
user: this.currentUser,
sidebarEnabled: attrs.sidebarEnabled,
@ -502,15 +493,11 @@ export default createWidget("header", {
const panels = [this.attach("header-buttons", attrs), headerIcons];
if (state.searchVisible) {
if (state.searchVisible || this.search.visible) {
if (this.currentUser?.experimental_search_menu_groups_enabled) {
panels.push(
this.attach("glimmer-search-menu-wrapper", {
inTopicContext: state.inTopicContext && inTopicRoute,
searchVisible: state.searchVisible,
animationClass: this.animationClass(),
})
);
this.search.inTopicContext =
this.search.inTopicContext && inTopicRoute;
panels.push(this.attach("glimmer-search-menu-wrapper"));
} else {
panels.push(
this.attach("search-menu", {
@ -563,21 +550,16 @@ export default createWidget("header", {
},
updateHighlight() {
if (!this.state.searchVisible) {
this.search.set("highlightTerm", "");
if (!this.state.searchVisible || !this.search.visible) {
this.search.highlightTerm = "";
}
},
animationClass() {
return this.site.mobileView || this.site.narrowDesktopView
? "slide-in"
: "drop-down";
},
closeAll() {
this.state.userVisible = false;
this.state.hamburgerVisible = false;
this.state.searchVisible = false;
this.search.visible = false;
this.toggleBodyScrolling(false);
},
@ -618,12 +600,15 @@ 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;
this.search.inTopicContext = false;
}
},
@ -706,6 +691,7 @@ export default createWidget("header", {
togglePageSearch() {
const { state } = this;
this.search.inTopicContext = false;
state.inTopicContext = false;
let showSearch = this.router.currentRouteName.startsWith("topic.");
@ -721,13 +707,14 @@ export default createWidget("header", {
$(".topic-post .cooked, .small-action:not(.time-gap)").length < total;
}
if (state.searchVisible) {
if (state.searchVisible || this.search.visible) {
this.toggleSearchMenu();
return showSearch;
}
if (showSearch) {
state.inTopicContext = true;
this.search.inTopicContext = true;
this.toggleSearchMenu();
return false;
}
@ -738,7 +725,12 @@ export default createWidget("header", {
domClean() {
const { state } = this;
if (state.searchVisible || state.hamburgerVisible || state.userVisible) {
if (
state.searchVisible ||
this.search.visible ||
state.hamburgerVisible ||
state.userVisible
) {
this.closeAll();
}
},
@ -763,9 +755,8 @@ export default createWidget("header", {
}
},
// only used by the widget search-menu
focusSearchInput() {
// the glimmer search menu handles the focusing of the search
// input within the search component
if (
this.state.searchVisible &&
!this.currentUser?.experimental_search_menu_groups_enabled
@ -778,11 +769,13 @@ export default createWidget("header", {
}
},
// 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();