diff --git a/app/assets/javascripts/discourse/app/lib/search.js b/app/assets/javascripts/discourse/app/lib/search.js index 40352647edb..ac5f529a533 100644 --- a/app/assets/javascripts/discourse/app/lib/search.js +++ b/app/assets/javascripts/discourse/app/lib/search.js @@ -118,7 +118,9 @@ function translateGroupedSearchResults(results, opts) { const name = pair[1]; if (results[name].length > 0) { const componentName = - opts.searchContext && type === "topic" ? "post" : type; + opts.searchContext?.type === "topic" && type === "topic" + ? "post" + : type; const result = { results: results[name], 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 ae3d08bbe22..3a7de738027 100644 --- a/app/assets/javascripts/discourse/app/widgets/search-menu-results.js +++ b/app/assets/javascripts/discourse/app/widgets/search-menu-results.js @@ -292,7 +292,7 @@ createWidget("search-menu-results", { return h("div.no-results", I18n.t("search.no_results")); } - if (!term) { + if (!term && !attrs.inPMInboxContext) { return this.attach("search-menu-initial-options", { term }); } @@ -364,7 +364,9 @@ createWidget("search-menu-results", { const content = []; if (!searchTopics) { - content.push(this.attach("search-menu-initial-options", { term })); + if (!attrs.inPMInboxContext) { + content.push(this.attach("search-menu-initial-options", { term })); + } } else { if (mainResultsContent.length) { content.push(mainResultsContent); diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu.js b/app/assets/javascripts/discourse/app/widgets/search-menu.js index 78f16baf163..d0d0ad2229a 100644 --- a/app/assets/javascripts/discourse/app/widgets/search-menu.js +++ b/app/assets/javascripts/discourse/app/widgets/search-menu.js @@ -198,6 +198,7 @@ export default createWidget("search-menu", { defaultState(attrs) { return { inTopicContext: attrs.inTopicContext, + inPMInboxContext: this.search?.searchContext?.type === "private_messages", _lastEnterTimestamp: null, _debouncer: null, }; @@ -216,6 +217,8 @@ export default createWidget("search-menu", { if (searchContext?.type === "topic") { query += encodeURIComponent(` topic:${searchContext.id}`); + } else if (searchContext?.type === "private_messages") { + query += encodeURIComponent(` in:personal`); } if (query) { @@ -236,7 +239,6 @@ export default createWidget("search-menu", { panelContents() { let searchInput = []; - if (this.state.inTopicContext) { searchInput.push( this.attach("button", { @@ -248,6 +250,17 @@ export default createWidget("search-menu", { 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 })); @@ -302,6 +315,7 @@ export default createWidget("search-menu", { suggestionKeyword: searchData.suggestionKeyword, suggestionResults: searchData.suggestionResults, searchTopics: SearchHelper.includesTopics(), + inPMInboxContext: this.state.inPMInboxContext, }) ); } @@ -336,6 +350,11 @@ export default createWidget("search-menu", { this.sendWidgetAction("clearContext"); }, + clearPMInboxContext() { + this.state.inPMInboxContext = false; + this.sendWidgetAction("focusSearchInput"); + }, + keyDown(e) { if (e.which === 27 /* escape */) { this.sendWidgetAction("toggleSearchMenu"); @@ -446,6 +465,7 @@ export default createWidget("search-menu", { if (e.target === searchInput && e.which === 8 /* backspace */) { if (!searchInput.value) { this.clearTopicContext(); + this.clearPMInboxContext(); } } }, @@ -506,7 +526,7 @@ export default createWidget("search-menu", { }, searchContext() { - if (this.state.inTopicContext) { + if (this.state.inTopicContext || this.state.inPMInboxContext) { return this.search.searchContext; } diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-test.js index fb60cfaaecf..c27b022a60a 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-test.js @@ -247,12 +247,9 @@ acceptance("Group - Authenticated", function (needs) { await click("#search-button"); await fillIn("#search-term", "smth"); - assert.strictEqual( - query( - ".search-menu .results .search-menu-assistant-item:first-child" - ).innerText.trim(), - "smth in:personal", - "contextual search is available as first option" + assert.ok( + query(".search-menu .btn.search-context"), + "'in messages' toggle is active by default" ); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js index d9cc75bf183..557b9de6f00 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js @@ -105,7 +105,7 @@ acceptance("Search - Full Page", function (needs) { }); }); - needs.hooks.afterEach(function () { + needs.hooks.afterEach(() => { searchResultClickTracked = false; }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-test.js index 506aedc50c9..fdb3044d866 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-test.js @@ -11,6 +11,13 @@ import selectKit from "discourse/tests/helpers/select-kit-helper"; import { test } from "qunit"; import { DEFAULT_TYPE_FILTER } from "discourse/widgets/search-menu"; +const keyEnter = 13; +const keyArrowDown = 40; +const keyArrowUp = 38; +const keyEsc = 27; +const keyA = 65; +const keyBackSpace = 8; + acceptance("Search - Anonymous", function (needs) { needs.pretender((server, helper) => { server.get("/search/query", (request) => { @@ -81,7 +88,7 @@ acceptance("Search - Anonymous", function (needs) { "shows matching user results" ); - await triggerKeyEvent(".search-menu", "keydown", 40); + await triggerKeyEvent(".search-menu", "keydown", keyArrowDown); await click(document.activeElement); assert.ok( @@ -195,7 +202,7 @@ acceptance("Search - Anonymous", function (needs) { await fillIn("#search-term", "a proper"); await query("input#search-term").focus(); - await triggerKeyEvent(".search-menu", "keydown", 40); + await triggerKeyEvent(".search-menu", "keydown", keyArrowDown); await click(document.activeElement); assert.ok( @@ -225,7 +232,7 @@ acceptance("Search - Anonymous", function (needs) { await fillIn("#search-term", "dev"); await query("input#search-term").focus(); - await triggerKeyEvent(".search-menu", "keydown", 40); + await triggerKeyEvent(".search-menu", "keydown", keyArrowDown); await click(document.activeElement); assert.ok( @@ -235,7 +242,7 @@ acceptance("Search - Anonymous", function (needs) { await fillIn("#search-term", ""); await query("input#search-term").focus(); - await triggerKeyEvent("input#search-term", "keydown", 8); // backspace + await triggerKeyEvent("input#search-term", "keydown", keyBackSpace); assert.ok( !exists(".search-menu .search-context"), @@ -259,7 +266,7 @@ acceptance("Search - Anonymous", function (needs) { await fillIn("#search-term", "proper"); await query("input#search-term").focus(); - await triggerKeyEvent(".search-menu", "keydown", 40); + await triggerKeyEvent(".search-menu", "keydown", keyArrowDown); await click(document.activeElement); assert.ok( @@ -394,7 +401,7 @@ acceptance("Search - Authenticated", function (needs) { await click("#search-button"); await fillIn("#search-term", "plans"); await query("input#search-term").focus(); - await triggerKeyEvent(".search-menu", "keydown", 40); + await triggerKeyEvent(".search-menu", "keydown", keyArrowDown); await click(document.activeElement); assert.notStrictEqual(count(".search-menu .results .item"), 0); @@ -407,11 +414,6 @@ acceptance("Search - Authenticated", function (needs) { }); test("search dropdown keyboard navigation", async function (assert) { - const keyEnter = 13; - const keyArrowDown = 40; - const keyArrowUp = 38; - const keyEsc = 27; - const keyA = 65; const container = ".search-menu .results"; await visit("/"); @@ -570,6 +572,147 @@ acceptance("Search - assistant", function (needs) { needs.user(); needs.pretender((server, helper) => { + server.get("/search/query", (request) => { + if (request.queryParams["search_context[type]"] === "private_messages") { + // return only one result for PM search + return helper.response({ + posts: [ + { + id: 3833, + name: "Bill Dudney", + username: "bdudney", + avatar_template: + "/user_avatar/meta.discourse.org/bdudney/{size}/8343_1.png", + uploaded_avatar_id: 8343, + created_at: "2013-02-07T17:46:57.469Z", + cooked: + "

I've gotten vagrant up and running with a development environment but it's taking forever to load.

\n\n

For example http://192.168.10.200:3000/ takes tens of seconds to load.

\n\n

I'm running the whole stack on a new rMBP with OS X 10.8.2.

\n\n

Any ideas of what I've done wrong? Or is this just a function of being on the bleeding edge?

\n\n

Thanks,

\n\n

-bd

", + post_number: 1, + post_type: 1, + updated_at: "2013-02-07T17:46:57.469Z", + like_count: 0, + reply_count: 1, + reply_to_post_number: null, + quote_count: 0, + incoming_link_count: 4422, + reads: 327, + score: 21978.4, + yours: false, + topic_id: 2179, + topic_slug: "development-mode-super-slow", + display_username: "Bill Dudney", + primary_group_name: null, + version: 2, + can_edit: false, + can_delete: false, + can_recover: false, + user_title: null, + actions_summary: [ + { + id: 2, + count: 0, + hidden: false, + can_act: false, + }, + { + id: 3, + count: 0, + hidden: false, + can_act: false, + }, + { + id: 4, + count: 0, + hidden: false, + can_act: false, + }, + { + id: 5, + count: 0, + hidden: true, + can_act: false, + }, + { + id: 6, + count: 0, + hidden: false, + can_act: false, + }, + { + id: 7, + count: 0, + hidden: false, + can_act: false, + }, + { + id: 8, + count: 0, + hidden: false, + can_act: false, + }, + ], + moderator: false, + admin: false, + staff: false, + user_id: 1828, + hidden: false, + hidden_reason_id: null, + trust_level: 1, + deleted_at: null, + user_deleted: false, + edit_reason: null, + can_view_edit_history: true, + wiki: false, + blurb: + "I've gotten vagrant up and running with a development environment but it's taking forever to load. For example http://192.168.10.200:3000/ takes...", + }, + ], + topics: [ + { + id: 2179, + title: "Development mode super slow", + fancy_title: "Development mode super slow", + slug: "development-mode-super-slow", + posts_count: 72, + reply_count: 53, + highest_post_number: 73, + image_url: null, + created_at: "2013-02-07T17:46:57.262Z", + last_posted_at: "2015-04-17T08:08:26.671Z", + bumped: true, + bumped_at: "2015-04-17T08:08:26.671Z", + unseen: false, + pinned: false, + unpinned: null, + visible: true, + closed: false, + archived: false, + bookmarked: null, + liked: null, + views: 9538, + like_count: 45, + has_summary: true, + archetype: "regular", + last_poster_username: null, + category_id: 7, + pinned_globally: false, + posters: [], + tags: ["dev", "slow"], + tags_descriptions: { + dev: "dev description", + slow: "slow description", + }, + }, + ], + grouped_search_result: { + term: "emoji", + post_ids: [3833], + }, + }); + } + return helper.response(searchFixtures["search/query"]); + }); + server.get("/u/search/users", () => { return helper.response({ users: [ @@ -666,4 +809,34 @@ acceptance("Search - assistant", function (needs) { await click(query(firstUser)); assert.strictEqual(query("#search-term").value, `@${firstUsername}`); }); + + test("shows 'in messages' button when in an inbox", async function (assert) { + await visit("/u/charlie/messages"); + await click("#search-button"); + + assert.ok(exists(".btn.search-context"), "it shows the button"); + + await fillIn("#search-term", ""); + await query("input#search-term").focus(); + await triggerKeyEvent("input#search-term", "keydown", keyBackSpace); + + assert.notOk(exists(".btn.search-context"), "it removes the button"); + + await click(".d-header"); + await click("#search-button"); + assert.ok( + exists(".btn.search-context"), + "it shows the button when reinvoking search" + ); + + await fillIn("#search-term", "emoji"); + await query("input#search-term").focus(); + await triggerKeyEvent("#search-term", "keydown", keyEnter); + + assert.strictEqual( + count(".search-menu .search-result-topic"), + 1, + "it passes the PM search context to the search query" + ); + }); }); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 75c3b0b7e82..ca322301390 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2425,6 +2425,8 @@ en: in: "in" in_this_topic: "in this topic" in_this_topic_tooltip: "switch to searching all topics" + in_messages: "in messages" + in_messages_tooltip: "switch to searching regular topics" in_topics_posts: "in all topics and posts" enter_hint: "or press Enter" in_posts_by: "in posts by %{username}"