- {{#if hasResults}}
- {{create-topic-button canCreateTopic=canCreateTopic action=(action "createTopic" searchTerm)}}
- {{/if}}
+ {{#if usingDefaultSearchType}}
+
+ {{/if}}
{{/if}}
{{plugin-outlet name="full-page-search-below-search-info" args=(hash search=searchTerm)}}
@@ -79,99 +102,113 @@
{{else}}
{{#load-more selector=".fps-result" action=(action "loadMore")}}
- {{search-result-entries posts=model.posts bulkSelectEnabled=bulkSelectEnabled selected=selected}}
+ {{#if usingDefaultSearchType}}
+ {{search-result-entries
+ posts=model.posts
+ bulkSelectEnabled=bulkSelectEnabled
+ selected=selected
+ highlightQuery=highlightQuery
+ }}
- {{#conditional-loading-spinner condition=loading }}
- {{#unless hasResults}}
- {{#if searchActive}}
-
{{i18n "search.no_results"}}
+ {{#conditional-loading-spinner condition=loading }}
+ {{#unless hasResults}}
+ {{#if searchActive}}
+
{{i18n "search.no_results"}}
- {{#if model.grouped_search_result.error}}
-
- {{model.grouped_search_result.error}}
+ {{#if model.grouped_search_result.error}}
+
+ {{model.grouped_search_result.error}}
+
+ {{/if}}
+
+ {{#if showSuggestion}}
+
+ {{i18n "search.cant_find"}}
+ {{#if canCreateTopic}}
+
{{i18n "search.start_new_topic"}}
+ {{#unless siteSettings.login_required}}
+ {{i18n "search.or_search_google"}}
+ {{/unless}}
+ {{else}}
+ {{i18n "search.search_google"}}
+ {{/if}}
+
+
+ {{google-search searchTerm=searchTerm}}
+ {{/if}}
+ {{/if}}
+ {{/unless}}
+
+ {{#if hasResults}}
+ {{#unless loading}}
+
+ {{/unless}}
+ {{/if}}
+ {{/conditional-loading-spinner}}
+ {{else}}
+ {{#conditional-loading-spinner condition=loading }}
+ {{#if hasResults}}
+ {{#if model.categories.length}}
+
+ {{i18n "search.categories"}}
+
+
+ {{#each model.categories as |category|}}
+ {{category-link category extraClasses="fps-category-item"}}
+ {{/each}}
{{/if}}
- {{#if showSuggestion}}
-
- {{i18n "search.cant_find"}}
- {{#if canCreateTopic}}
-
{{i18n "search.start_new_topic"}}
- {{#unless siteSettings.login_required}}
- {{i18n "search.or_search_google"}}
- {{/unless}}
- {{else}}
- {{i18n "search.search_google"}}
- {{/if}}
+ {{#if model.tags.length}}
+
+ {{i18n "search.tags"}}
+
+
+ {{#each model.tags as |tag|}}
+
+ {{/each}}
+ {{/if}}
- {{google-search searchTerm=searchTerm}}
+ {{#if model.users}}
+ {{#each model.users as |user|}}
+ {{#user-link user=user class="fps-user-item"}}
+ {{avatar user imageSize="large"}}
+
+ {{#if user.name}}
+
+ {{user.name}}
+
+ {{/if}}
+
+ {{user.username}}
+
+
+ {{/user-link}}
+ {{/each}}
+ {{/if}}
+ {{else}}
+ {{#if searchActive}}
+
{{i18n "search.no_results"}}
{{/if}}
{{/if}}
- {{/unless}}
- {{#if hasResults}}
- {{#unless loading}}
-
- {{/unless}}
- {{/if}}
- {{/conditional-loading-spinner}}
+ {{/conditional-loading-spinner}}
+ {{/if}}
{{/load-more}}
{{/if}}
-
-
{{/d-section}}
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 483f01cae0..ae114f360f 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js
@@ -9,6 +9,11 @@ import {
} from "discourse/tests/helpers/qunit-helpers";
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
import { skip, test } from "qunit";
+import {
+ SEARCH_TYPE_CATS_TAGS,
+ SEARCH_TYPE_DEFAULT,
+ SEARCH_TYPE_USERS,
+} from "discourse/controllers/full-page-search";
import selectKit from "discourse/tests/helpers/select-kit-helper";
acceptance("Search - Full Page", function (needs) {
@@ -16,7 +21,12 @@ acceptance("Search - Full Page", function (needs) {
needs.settings({ tagging_enabled: true });
needs.pretender((server, helper) => {
server.get("/tags/filter/search", () => {
- return helper.response({ results: [{ text: "monkey", count: 1 }] });
+ return helper.response({
+ results: [
+ { text: "monkey", count: 1 },
+ { text: "gazelle", count: 2 },
+ ],
+ });
});
server.get("/u/search/users", () => {
@@ -126,6 +136,8 @@ acceptance("Search - Full Page", function (needs) {
1,
"shows the right icon"
);
+
+ assert.equal(count(".search-highlight"), 1, "search highlights work");
});
test("escape search term", async function (assert) {
@@ -419,7 +431,9 @@ acceptance("Search - Full Page", function (needs) {
await fillIn("#search-min-post-count", "5");
assert.equal(
- queryAll(".search-advanced-options #search-min-post-count").val(),
+ queryAll(
+ ".search-advanced-additional-options #search-min-post-count"
+ ).val(),
"5",
'has "5" populated'
);
@@ -436,7 +450,9 @@ acceptance("Search - Full Page", function (needs) {
await fillIn("#search-max-post-count", "5");
assert.equal(
- queryAll(".search-advanced-options #search-max-post-count").val(),
+ queryAll(
+ ".search-advanced-additional-options #search-max-post-count"
+ ).val(),
"5",
'has "5" populated'
);
@@ -469,4 +485,100 @@ acceptance("Search - Full Page", function (needs) {
"does not populate the likes checkbox"
);
});
+
+ test("all tags checkbox only visible for two or more tags", async function (assert) {
+ await visit("/search?expanded=true");
+
+ const tagSelector = selectKit("#search-with-tags");
+
+ await tagSelector.expand();
+ await tagSelector.selectRowByValue("monkey");
+
+ assert.ok(!visible("input.all-tags"), "all tags checkbox not visible");
+
+ await tagSelector.selectRowByValue("gazelle");
+ assert.ok(visible("input.all-tags"), "all tags checkbox is visible");
+ });
+
+ test("search for users", async function (assert) {
+ await visit("/search");
+
+ const typeSelector = selectKit(".search-bar .select-kit#search-type");
+
+ await fillIn(".search-query", "admin");
+ assert.ok(!exists(".fps-user-item"), "has no user results");
+
+ await typeSelector.expand();
+ await typeSelector.selectRowByValue(SEARCH_TYPE_USERS);
+
+ assert.ok(!exists(".search-filters"), "has no filters");
+
+ await click(".search-cta");
+
+ assert.equal(count(".fps-user-item"), 1, "has one user result");
+
+ await typeSelector.expand();
+ await typeSelector.selectRowByValue(SEARCH_TYPE_DEFAULT);
+
+ assert.ok(
+ exists(".search-filters"),
+ "returning to topic/posts shows filters"
+ );
+ assert.ok(!exists(".fps-user-item"), "has no user results");
+ });
+
+ test("search for categories/tags", async function (assert) {
+ await visit("/search");
+
+ await fillIn(".search-query", "monk");
+ const typeSelector = selectKit(".search-bar .select-kit#search-type");
+
+ assert.ok(!exists(".fps-tag-item"), "has no category/tag results");
+
+ await typeSelector.expand();
+ await typeSelector.selectRowByValue(SEARCH_TYPE_CATS_TAGS);
+ await click(".search-cta");
+
+ assert.ok(!exists(".search-filters"), "has no filters");
+ assert.equal(count(".fps-tag-item"), 2, "has two tag results");
+
+ await typeSelector.expand();
+ await typeSelector.selectRowByValue(SEARCH_TYPE_DEFAULT);
+
+ assert.ok(
+ exists(".search-filters"),
+ "returning to topic/posts shows filters"
+ );
+ assert.ok(!exists(".user-item"), "has no user results");
+ });
+
+ test("filters expand/collapse as expected", async function (assert) {
+ await visit("/search?expanded=true");
+
+ assert.ok(
+ visible(".search-advanced-options"),
+ "advanced filters are expanded when url query param is included"
+ );
+
+ await fillIn(".search-query", "none");
+ await click(".search-cta");
+
+ assert.ok(
+ !visible(".search-advanced-options"),
+ "launching a search collapses advanced filters"
+ );
+
+ await visit("/search");
+
+ assert.ok(
+ !visible(".search-advanced-options"),
+ "filters are collapsed when query param is not present"
+ );
+
+ await click(".advanced-filters > summary");
+ assert.ok(
+ visible(".search-advanced-options"),
+ "clicking on element expands filters"
+ );
+ });
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js
index c32647550e..14063d5750 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js
@@ -3,6 +3,7 @@ import {
count,
exists,
queryAll,
+ visible,
} from "discourse/tests/helpers/qunit-helpers";
import { click, fillIn, visit } from "@ember/test-helpers";
import { test } from "qunit";
@@ -22,11 +23,10 @@ acceptance("Search - Mobile", function (needs) {
assert.ok(!exists(".search-results .fps-topic"), "no results by default");
- await click(".search-advanced-title");
+ await click(".advanced-filters summary");
- assert.equal(
- count(".search-advanced-filters"),
- 1,
+ assert.ok(
+ visible(".search-advanced-filters"),
"it should expand advanced search filters"
);
@@ -36,7 +36,7 @@ acceptance("Search - Mobile", function (needs) {
assert.equal(count(".fps-topic"), 1, "has one post");
assert.ok(
- !exists(".search-advanced-filters"),
+ !visible(".search-advanced-filters"),
"it should collapse advanced search filters"
);
diff --git a/app/assets/stylesheets/common/base/search.scss b/app/assets/stylesheets/common/base/search.scss
index d7e425e14d..1d36792eba 100644
--- a/app/assets/stylesheets/common/base/search.scss
+++ b/app/assets/stylesheets/common/base/search.scss
@@ -1,182 +1,179 @@
+@mixin search-page-spacing {
+ padding: 1rem 10%;
+ @include breakpoint(medium) {
+ padding: 1rem;
+ }
+}
.search-highlight {
font-weight: bold;
}
.search-container {
- display: flex;
- justify-content: space-between;
-
+ .search-header {
+ @include search-page-spacing();
+ background: var(--primary-very-low);
+ }
.warning {
background-color: var(--danger-medium);
padding: 5px 8px;
color: var(--secondary);
}
+ .search-page-heading {
+ font-size: var(--font-up-3);
+
+ // spans can be in different orders depending of locale
+ span + span {
+ margin-left: 0.25em;
+ }
+
+ span.term {
+ background: var(--tertiary-low);
+ }
+ }
+
.search-bar {
display: flex;
justify-content: space-between;
align-items: stretch;
- margin-bottom: 1em;
+ background: var(--primary-very-low);
- .search-query {
- flex: 1 0 0px;
- margin: 0 0.5em 0 0;
+ input.search-query {
+ flex: 1 0 60%;
+ margin: 0 1em 0 0;
}
- .search-cta {
- padding-bottom: 6.5px;
- padding-top: 6.5px;
+ .select-kit {
+ margin-right: 1em;
+ flex: 1 0 20%;
+ }
+
+ @include breakpoint(mobile-extra-large) {
+ flex-direction: column;
+
+ input.search-query,
+ .select-kit {
+ margin-right: 0;
+ margin-bottom: 0.5em;
+ }
}
}
.search-advanced {
- width: 70%;
- @include breakpoint(medium) {
- width: 65%;
- }
-
+ position: relative;
.search-actions,
- .search-notice,
- .search-results,
.search-title,
.search-bar {
margin-bottom: 1em;
}
+ .search-results {
+ @include search-page-spacing();
+ padding-bottom: 3em;
+ }
+
.search-info {
display: flex;
+ @include search-page-spacing();
flex-wrap: wrap;
border-bottom: 1px solid var(--primary-low);
- padding-bottom: 1em;
- margin-bottom: 1.5em;
+ padding-top: 2em;
+ margin-bottom: 2em;
flex-direction: row;
- align-items: center;
+ align-items: flex-start;
+ justify-content: flex-start;
- .result-count {
- display: flex;
-
- .term {
- font-weight: bold;
- }
-
- // spans can be in different orders depending of locale
- span + span {
- margin-left: 0.25em;
- }
+ &.bulk-select-visible {
+ @include sticky;
+ top: 60px;
+ background-color: var(--secondary);
+ z-index: 10;
}
.sort-by {
- display: flex;
margin-left: auto;
- align-items: center;
-
- .desc {
- margin-right: 0.5em;
- }
-
- .combo-box {
- min-width: 150px;
- }
}
- }
- .search-title {
- display: flex;
- justify-content: flex-start;
- align-items: stretch;
- flex-wrap: wrap;
- padding-right: 2.6em; // placeholder for fixed position bulk search button
button {
margin: 0 0.5em 0.5em 0;
}
- .bulk-select-container {
- order: 2; // last button
- margin-left: auto;
- z-index: z("dropdown"); // below composer
- }
-
#bulk-select {
- position: fixed;
+ position: relative;
right: unset;
margin: 0;
+ padding: 0;
+ display: inline;
button {
- margin: 0;
- box-shadow: 0 0 0.4em 0.45em var(--secondary); // slight fade behind the button, because it can overlay content
+ margin-right: 0.5em;
}
}
}
-
- .search-notice {
- .fps-invalid {
- padding: 0.5em;
- background-color: var(--danger-low);
- border: 1px solid var(--danger-medium);
- color: var(--danger);
- }
- }
}
- .search-advanced-sidebar {
- width: 30%;
- @include breakpoint(medium) {
- width: 35%;
- }
- margin-left: 1em;
+ .search-notice .fps-invalid {
+ padding: 0.5em;
+ background-color: var(--danger-low);
+ border: 1px solid var(--danger-medium);
+ color: var(--danger);
+ }
+
+ .search-context {
+ margin-top: 1em;
+ }
+
+ .search-filters {
+ background: var(--primary-very-low);
display: flex;
flex-direction: column;
- .input-small,
- .combo-box,
- .ac-wrap,
+ details.advanced-filters,
+ details.search-advanced-additional-options {
+ margin-top: 1em;
+
+ > summary {
+ color: var(--tertiary);
+ cursor: pointer;
+ }
+ &[open] > summary {
+ color: var(--primary);
+ margin-bottom: 1em;
+ }
+ }
+
+ details.search-advanced-additional-options {
+ > summary {
+ font-size: var(--font-down-1);
+ }
+ }
+
+ .combo-box:not(#postTime),
.control-group,
- .multi-select,
- .search-advanced-category-chooser {
- box-sizing: border-box;
+ .multi-select {
width: 100%;
min-width: 100%;
- margin: 0;
-
- input,
- .item {
- padding-left: 4px; // temporarily normalizing input padding for this section
- }
- }
-
- .d-date-input {
- margin-top: 0.5em;
- width: 100%;
- }
-
- .search-advanced-title {
- font-size: $font-up-1;
- background: var(--primary-low);
- padding: 0.358em 1em;
- margin-bottom: 0;
- @include breakpoint(medium) {
- padding: 0.358em 0.5em;
- }
- font-weight: 700;
- text-align: left;
- cursor: pointer;
-
- .d-icon {
- margin: 0;
- }
}
.search-advanced-filters {
background: var(--primary-very-low);
- padding: 1em;
- .control-group {
- margin-bottom: 15px;
+
+ @include breakpoint(mobile-extra-large, min-width) {
+ .search-advanced-options {
+ column-count: 2;
+ column-gap: 2em;
+ .control-group {
+ break-inside: avoid;
+ }
+ }
}
- section.field {
- margin-top: 5px;
+
+ @include breakpoint(medium, min-width) {
+ .search-advanced-options {
+ column-gap: 5em;
+ }
}
+
@include breakpoint(medium) {
- padding: 0.75em 0.5em;
- .ac-wrap,
.choices,
.select-kit.multi-select {
// overriding inline width from JS
@@ -187,13 +184,18 @@
}
}
+ .control-group {
+ margin-bottom: 1em;
+ }
+
.count-group {
- .count {
- width: 45%;
+ input[type="number"] {
+ width: 8em;
}
- .count-dash {
- padding-left: 6px;
- vertical-align: middle;
+
+ .d-icon {
+ margin-left: 0.25em;
+ margin-right: 0.25em;
}
}
}
@@ -201,15 +203,21 @@
}
.fps-invalid {
+ margin-top: 1em;
margin-bottom: 1em;
}
.fps-result {
display: flex;
padding: 0 0.5em;
- margin-bottom: 28px;
- max-width: 780px;
+ margin-bottom: 2em;
+ max-width: 100%;
word-break: break-word;
+ position: relative;
+
+ &.bulk-select-enabled {
+ padding-left: 3em;
+ }
.author {
display: inline-block;
@@ -229,7 +237,14 @@
grid-template-columns: auto 1fr;
align-items: baseline;
.bulk-select {
- grid-area: bulk-select;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ padding: 0.5em;
+ background: var(--tertiary-very-low);
+ input[type="checkbox"] {
+ margin: 0;
+ }
}
.search-link {
grid-area: title;
@@ -260,19 +275,9 @@
}
}
- input[type="checkbox"] {
- margin-top: 0;
- margin-left: 0;
- // cross-browser alignment below
- position: relative;
- vertical-align: bottom;
- margin-bottom: 0.39em;
- }
-
.blurb {
font-size: $font-0;
line-height: $line-height-large;
- max-width: 640px;
color: var(--primary-medium);
.date {
color: var(--primary-high);
@@ -319,18 +324,48 @@
}
}
-.no-results-suggestion {
- margin-top: 30px;
-}
-
-.search-footer {
- margin-bottom: 30px;
-}
-
-.panel-body-contents .search-context label {
- float: left;
-}
-
+.no-results-suggestion,
.google-search-form {
- margin-top: 2em;
+ margin-top: 1em;
+}
+
+// temporary
+
+.search-results {
+ .fps-user-item {
+ margin-bottom: 1.5em;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ .avatar {
+ margin-right: 0.5em;
+ min-width: 25px;
+ }
+ .user-titles {
+ display: flex;
+ flex-direction: column;
+ max-width: 300px;
+ .name {
+ color: var(--primary-high-or-secondary-low);
+ font-size: var(--font-0);
+ font-weight: 700;
+ @include ellipsis;
+ }
+ .username {
+ color: var(--primary-high-or-secondary-low);
+ font-size: var(--font-down-1);
+ @include ellipsis;
+ }
+ }
+ }
+
+ .category-items,
+ .tag-items {
+ margin-bottom: 1.5em;
+ .fps-category-item,
+ .fps-tag-item {
+ margin-bottom: 1.5em;
+ display: block;
+ }
+ }
}
diff --git a/app/assets/stylesheets/common/foundation/base.scss b/app/assets/stylesheets/common/foundation/base.scss
index 97ff00ae51..4c2863c4aa 100644
--- a/app/assets/stylesheets/common/foundation/base.scss
+++ b/app/assets/stylesheets/common/foundation/base.scss
@@ -174,7 +174,8 @@ input[type="submit"] {
> .select-kit,
> input[type="text"],
> label,
- > .btn {
+ > .btn,
+ > .d-date-input {
margin-bottom: 0.5em; // for when items wrap (mobile, narrow windows)
margin-right: 0.5em;
&:last-child {
diff --git a/app/assets/stylesheets/mobile/search.scss b/app/assets/stylesheets/mobile/search.scss
index 8ea2333d5c..af11a99581 100644
--- a/app/assets/stylesheets/mobile/search.scss
+++ b/app/assets/stylesheets/mobile/search.scss
@@ -1,48 +1,6 @@
.search-container {
- flex-direction: column;
- margin: 0;
-
- .search-advanced {
- order: 1;
- width: 100%;
-
- .search-info {
- flex-direction: column;
- align-items: left;
- justify-content: center;
-
- .sort-by {
- display: flex;
- align-items: center;
- margin-top: 0.5em;
- margin-left: 0;
- width: 100%;
-
- .select-kit {
- flex: 1 1 auto;
- }
- }
- }
- }
-
- .search-notice {
- margin-top: 1em;
- }
-
- .search-advanced-sidebar {
- order: 0;
- width: 100%;
- margin: 0;
-
- .tag-chooser,
- .user-chooser {
- width: 100%;
- }
- }
-}
-
-.fps-result {
- input[type="checkbox"] {
- vertical-align: baseline;
+ .search-advanced .search-info {
+ padding-left: 0;
+ padding-right: 0;
}
}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 01d08fc3b3..b806ce9519 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2338,7 +2338,7 @@ en:
one: "
%{count} result for%{term}"
other: "
%{count}%{plus} results for%{term}"
title: "search topics, posts, users, or categories"
- full_page_title: "search topics or posts"
+ full_page_title: "Search"
no_results: "No results found."
no_more_results: "No more results found."
post_format: "#%{post_number} by %{username}"
@@ -2350,6 +2350,14 @@ en:
search_google: "Try searching with Google instead:"
search_google_button: "Google"
search_button: "Search"
+ search_term_label: "enter search keyword"
+ categories: "Categories"
+ tags: "Tags"
+
+ type:
+ default: "Topics/posts"
+ users: "Users"
+ categories_and_tags: "Categories/tags"
context:
user: "Search posts by @%{username}"
@@ -2359,7 +2367,7 @@ en:
private_messages: "Search messages"
advanced:
- title: Advanced Search
+ title: Advanced filters
posted_by:
label: Posted by
in_category:
@@ -2412,6 +2420,8 @@ en:
placeholder: minimum
max_views:
placeholder: maximum
+ additional_options:
+ label: "Filter by post count and topic views"
hamburger_menu: "go to another topic list or category"
new_item: "new"