DEV: Remove widget search menu (#25545)

This commit is contained in:
Isaac Janzen 2024-02-06 08:52:24 -07:00 committed by GitHub
parent 2caaadea4a
commit 5c43fd5054
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 69 additions and 1777 deletions

View File

@ -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();
}
/**

View File

@ -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();
},
});

View File

@ -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;
},
});

View File

@ -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: `<span>${html}</span>` });
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: `<span>${result.blurb}</span>` })
: 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: `<span>${emojiUnescape(
result.topic_title_headline
)}</span>`,
})
: 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`<PluginOutlet @name="search-menu-results-top" @outletArgs={{@data.outletArgs}}/>`,
{
outletArgs: {
searchTerm: term,
inTopicContext,
onLinkClicked,
searchTopics,
},
}
)
);
content.push(categoriesAndTags);
content.push(usersAndGroups);
content.push(
new RenderGlimmer(
this,
"div",
hbs`<PluginOutlet @name="search-menu-results-bottom" @outletArgs={{@data.outletArgs}}/>`,
{
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`
<div class="heading">
<h4>{{i18n "search.recent"}}</h4>
{{flat-button
className="clear-recent-searches"
title="search.clear_recent"
icon="times"
action="clearRecent"
}}
</div>
{{#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");
}
});
},
});

View File

@ -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")),
];
},
});

View File

@ -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"
);
});
});

View File

@ -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"
);
});
});

View File

@ -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", () => {

View File

@ -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();

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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