diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index cbf157d6cbc..5ffbaff63b8 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -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); } } diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu-results.js b/app/assets/javascripts/discourse/app/widgets/search-menu-results.js index 5ef9d058c18..32457733eb5 100644 --- a/app/assets/javascripts/discourse/app/widgets/search-menu-results.js +++ b/app/assets/javascripts/discourse/app/widgets/search-menu-results.js @@ -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); }, }); diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu.js b/app/assets/javascripts/discourse/app/widgets/search-menu.js index d91628cee59..f34668e243b 100644 --- a/app/assets/javascripts/discourse/app/widgets/search-menu.js +++ b/app/assets/javascripts/discourse/app/widgets/search-menu.js @@ -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; }, }; diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-test.js index 2342d2d339c..982749a6c16 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-test.js @@ -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) { diff --git a/lib/search.rb b/lib/search.rb index 4efdbff9caf..0bf753df8fe 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -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