UX: Improve quick search suggestions (#13813)

This commit is contained in:
Penar Musaraj 2021-07-21 14:00:27 -04:00 committed by GitHub
parent 4f328089d6
commit 8a470e508e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 85 deletions

View File

@ -73,10 +73,10 @@ import { replaceFormatter } from "discourse/lib/utilities";
import { replaceTagRenderer } from "discourse/lib/render-tag";
import { setNewCategoryDefaultColors } from "discourse/routes/new-category";
import { addSearchResultsCallback } from "discourse/lib/search";
import { addInSearchShortcut } from "discourse/widgets/search-menu-results";
import { addSearchSuggestion } from "discourse/widgets/search-menu-results";
// If you add any methods to the API ensure you bump up this number
const PLUGIN_API_VERSION = "0.11.6";
const PLUGIN_API_VERSION = "0.11.7";
class PluginApi {
constructor(version, container) {
@ -1298,15 +1298,15 @@ class PluginApi {
}
/**
* Add a in: shortcut to search menu panel.
* Add a suggestion shortcut to search menu panel.
*
* ```
* addInSearchShortcut("in:assigned");
* addSearchSuggestion("in:assigned");
* ```
*
*/
addInSearchShortcut(value) {
addInSearchShortcut(value);
addSearchSuggestion(value) {
addSearchSuggestion(value);
}
}

View File

@ -10,30 +10,22 @@ import highlightSearch from "discourse/lib/highlight-search";
import { iconNode } from "discourse-common/lib/icon-library";
import renderTag from "discourse/lib/render-tag";
const inSearchShortcuts = [
const suggestionShortcuts = [
"in:title",
"in:personal",
"in:seen",
"in:likes",
"in:bookmarks",
"in:created",
];
const statusSearchShortcuts = [
"in:pinned",
"status:open",
"status:closed",
"status:public",
"status:noreplies",
];
const orderSearchShortcuts = [
"order:latest",
"order:views",
"order:likes",
"order:latest_topic",
];
export function addInSearchShortcut(value) {
if (inSearchShortcuts.indexOf(value) === -1) {
inSearchShortcuts.push(value);
export function addSearchSuggestion(value) {
if (suggestionShortcuts.indexOf(value) === -1) {
suggestionShortcuts.push(value);
}
}
@ -360,8 +352,19 @@ createWidget("search-menu-assistant", {
tagName: "ul.search-menu-assistant",
html(attrs) {
if (this.currentUser) {
addSearchSuggestion("in:likes");
addSearchSuggestion("in:bookmarks");
addSearchSuggestion("in:mine");
addSearchSuggestion("in:personal");
addSearchSuggestion("in:seen");
addSearchSuggestion("in:tracking");
addSearchSuggestion("in:unseen");
addSearchSuggestion("in:watching");
}
if (this.siteSettings.tagging_enabled) {
addInSearchShortcut("in:tagged");
addSearchSuggestion("in:tagged");
addSearchSuggestion("in:untagged");
}
const content = [];
@ -370,7 +373,7 @@ createWidget("search-menu-assistant", {
switch (suggestionKeyword) {
case "#":
attrs.results.map((category) => {
attrs.results.forEach((category) => {
const slug = prefix
? `${prefix} #${category.slug} `
: `#${category.slug} `;
@ -385,7 +388,7 @@ createWidget("search-menu-assistant", {
});
break;
case "@":
attrs.results.map((user) => {
attrs.results.forEach((user) => {
const slug = prefix
? `${prefix} @${user.username} `
: `@${user.username} `;
@ -399,27 +402,17 @@ createWidget("search-menu-assistant", {
);
});
break;
case "in:":
inSearchShortcuts.map((item) => {
const slug = prefix ? `${prefix} ${item} ` : item;
content.push(this.attach("search-menu-assistant-item", { slug }));
});
break;
case "status:":
statusSearchShortcuts.map((item) => {
const slug = prefix ? `${prefix} ${item} ` : item;
content.push(this.attach("search-menu-assistant-item", { slug }));
});
break;
case "order:":
orderSearchShortcuts.map((item) => {
const slug = prefix ? `${prefix} ${item} ` : item;
content.push(this.attach("search-menu-assistant-item", { slug }));
default:
suggestionShortcuts.forEach((item) => {
if (item.includes(suggestionKeyword)) {
const slug = prefix ? `${prefix} ${item} ` : `${item} `;
content.push(this.attach("search-menu-assistant-item", { slug }));
}
});
break;
}
return content;
return content.filter((c, i) => i <= 8);
},
});

View File

@ -11,9 +11,9 @@ import userSearch from "discourse/lib/user-search";
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 searchData = {};
const suggestionTriggers = ["in:", "status:", "order:"];
export function initSearchData() {
searchData.loading = false;
@ -53,47 +53,42 @@ const SearchHelper = {
searchData.results = [];
searchData.loading = false;
if (typeof matchSuggestions === "string") {
searchData.suggestionKeyword = matchSuggestions;
if (matchSuggestions.type === "category") {
const categorySearchTerm = matchSuggestions.categoriesMatch[0].replace(
"#",
""
);
searchData.suggestionResults = Category.search(categorySearchTerm);
searchData.suggestionKeyword = "#";
widget.scheduleRerender();
return;
} else {
if (matchSuggestions.type === "category") {
const categorySearchTerm = matchSuggestions.categoriesMatch[0].replace(
"#",
""
);
searchData.suggestionResults = Category.search(categorySearchTerm);
searchData.suggestionKeyword = "#";
widget.scheduleRerender();
return;
} 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;
}
if (matchSuggestions.type === "username") {
const userSearchTerm = matchSuggestions.usernamesMatch[0].replace(
"@",
""
);
const opts = { includeGroups: true, limit: 6 };
if (userSearchTerm.length > 0) {
opts.term = userSearchTerm;
userSearch(opts).then((result) => {
if (result?.users?.length > 0) {
searchData.suggestionResults = result.users;
searchData.suggestionKeyword = "@";
} else {
opts.lastSeenUsers = true;
searchData.noResults = true;
searchData.suggestionKeyword = false;
}
userSearch(opts).then((result) => {
if (result?.users?.length > 0) {
searchData.suggestionResults = result.users;
searchData.suggestionKeyword = "@";
} else {
searchData.noResults = true;
searchData.suggestionKeyword = false;
}
widget.scheduleRerender();
});
return;
}
widget.scheduleRerender();
});
} else {
searchData.suggestionKeyword = matchSuggestions[0];
widget.scheduleRerender();
}
return;
}
searchData.suggestionKeyword = false;
@ -142,14 +137,6 @@ const SearchHelper = {
return false;
}
const simpleSuggestion = suggestionTriggers.find(
(mod) => searchData.term === mod || searchData.term.endsWith(` ${mod}`)
);
if (simpleSuggestion) {
return simpleSuggestion;
}
const categoriesMatch = searchData.term.match(CATEGORY_SLUG_REGEXP);
if (categoriesMatch) {
@ -161,6 +148,11 @@ const SearchHelper = {
return { type: "username", usernamesMatch };
}
const suggestionsMatch = searchData.term.match(SUGGESTIONS_REGEXP);
if (suggestionsMatch) {
return suggestionsMatch;
}
return false;
},
};

View File

@ -343,6 +343,10 @@ acceptance("Search - assistant", function (needs) {
await fillIn("#search-term", "sam in:");
await triggerKeyEvent("#search-term", "keyup", 51);
assert.equal(query(firstTarget).innerText, "sam in:title");
await fillIn("#search-term", "in:pers");
await triggerKeyEvent("#search-term", "keyup", 51);
assert.equal(query(firstTarget).innerText, "in:personal");
});
test("shows users when typing @", async function (assert) {

View File

@ -452,7 +452,7 @@ class Search
posts.where("posts.user_id = #{@guardian.user.id}") if @guardian.user
end
advanced_filter(/^in:created$/i) do |posts|
advanced_filter(/^in:(created|mine)$/i) do |posts|
posts.where(user_id: @guardian.user.id, post_number: 1) if @guardian.user
end