diff --git a/app/assets/javascripts/discourse/app/components/search-advanced-options.js b/app/assets/javascripts/discourse/app/components/search-advanced-options.js
index b2ddfc879d1..b4c40f833a9 100644
--- a/app/assets/javascripts/discourse/app/components/search-advanced-options.js
+++ b/app/assets/javascripts/discourse/app/components/search-advanced-options.js
@@ -12,6 +12,7 @@ const REGEXP_TAGS_PREFIX = /^(tags?:|#(?=[a-z0-9\-]+::tag))/gi;
const REGEXP_IN_PREFIX = /^(in|with):/gi;
const REGEXP_STATUS_PREFIX = /^status:/gi;
const REGEXP_MIN_POSTS_PREFIX = /^min_posts:/gi;
+const REGEXP_MAX_POSTS_PREFIX = /^max_posts:/gi;
const REGEXP_MIN_VIEWS_PREFIX = /^min_views:/gi;
const REGEXP_MAX_VIEWS_PREFIX = /^max_views:/gi;
const REGEXP_POST_TIME_PREFIX = /^(before|after):/gi;
@@ -95,6 +96,7 @@ export default Component.extend({
},
status: null,
min_posts: null,
+ max_posts: null,
min_views: null,
max_views: null,
time: {
@@ -166,6 +168,11 @@ export default Component.extend({
REGEXP_MIN_POSTS_PREFIX
);
+ this.setSearchedTermValue(
+ "searchedTerms.max_posts",
+ REGEXP_MAX_POSTS_PREFIX
+ );
+
this.setSearchedTermValue(
"searchedTerms.min_views",
REGEXP_MIN_VIEWS_PREFIX
@@ -359,6 +366,12 @@ export default Component.extend({
this._updateSearchTermForMinPostCount();
},
+ @action
+ onChangeSearchTermMaxPostCount(value) {
+ this.set("searchedTerms.max_posts", value.length ? value : null);
+ this._updateSearchTermForMaxPostCount();
+ },
+
@action
onChangeSearchTermMinViews(value) {
this.set("searchedTerms.min_views", value.length ? value : null);
@@ -653,6 +666,28 @@ export default Component.extend({
}
},
+ _updateSearchTermForMaxPostCount() {
+ const match = this.filterBlocks(REGEXP_MAX_POSTS_PREFIX);
+ const postsCountFilter = this.get("searchedTerms.max_posts");
+ let searchTerm = this.searchTerm || "";
+
+ if (postsCountFilter) {
+ if (match.length !== 0) {
+ searchTerm = searchTerm.replace(
+ match[0],
+ `max_posts:${postsCountFilter}`
+ );
+ } else {
+ searchTerm += ` max_posts:${postsCountFilter}`;
+ }
+
+ this._updateSearchTerm(searchTerm);
+ } else if (match.length !== 0) {
+ searchTerm = searchTerm.replace(match[0], "");
+ this._updateSearchTerm(searchTerm);
+ }
+ },
+
_updateSearchTermForMinViews() {
const match = this.filterBlocks(REGEXP_MIN_VIEWS_PREFIX);
const viewsCountFilter = this.get("searchedTerms.min_views");
diff --git a/app/assets/javascripts/discourse/app/templates/components/search-advanced-options.hbs b/app/assets/javascripts/discourse/app/templates/components/search-advanced-options.hbs
index 82a474440d3..c717b704d2a 100644
--- a/app/assets/javascripts/discourse/app/templates/components/search-advanced-options.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/search-advanced-options.hbs
@@ -148,22 +148,39 @@
}}
-
+
+
-
- {{input
- type="number"
- value=(readonly searchedTerms.min_posts)
- class="input-small"
- id="search-min-post-count"
- input=(action "onChangeSearchTermMinPostCount" value="target.value")
- }}
+
+
+ {{input
+ type="number"
+ value=(readonly searchedTerms.min_posts)
+ class="input-small"
+ id="search-min-post-count"
+ input=(action "onChangeSearchTermMinPostCount" value="target.value")
+ placeholder=(i18n "search.advanced.post.min.placeholder")
+ }}
+
+
+
—
+
+
+ {{input
+ type="number"
+ value=(readonly searchedTerms.max_posts)
+ class="input-small"
+ id="search-max-post-count"
+ input=(action "onChangeSearchTermMaxPostCount" value="target.value")
+ placeholder=(i18n "search.advanced.post.max.placeholder")
+ }}
+
-
+
-
+
{{input
type="number"
@@ -175,8 +192,8 @@
}}
-
–
-
+
—
+
{{input
type="number"
diff --git a/app/assets/stylesheets/common/base/search.scss b/app/assets/stylesheets/common/base/search.scss
index 729c6179f11..2cbab66792a 100644
--- a/app/assets/stylesheets/common/base/search.scss
+++ b/app/assets/stylesheets/common/base/search.scss
@@ -164,13 +164,13 @@
}
}
- .views {
- .views-count {
+ .count-group {
+ .count {
margin-bottom: 15px;
width: 45%;
}
- .views-count-dash {
- padding-left: 10px;
+ .count-dash {
+ padding-left: 6px;
vertical-align: middle;
}
}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 595f456d2ed..2396307e2bb 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2119,7 +2119,11 @@ en:
single_user: contain a single user
post:
count:
- label: Minimum Posts
+ label: Posts
+ min:
+ placeholder: minimum
+ max:
+ placeholder: maximum
time:
label: Posted
before: before
diff --git a/lib/search.rb b/lib/search.rb
index 9284ac95c59..1ea88a44ce9 100644
--- a/lib/search.rb
+++ b/lib/search.rb
@@ -369,12 +369,16 @@ class Search
posts.where("topics.posts_count = ?", match.to_i)
end
+ advanced_filter(/^min_post_count:(\d+)$/i) do |posts, match|
+ posts.where("topics.posts_count >= ?", match.to_i)
+ end
+
advanced_filter(/^min_posts:(\d+)$/i) do |posts, match|
posts.where("topics.posts_count >= ?", match.to_i)
end
- advanced_filter(/^min_post_count:(\d+)$/i) do |posts, match|
- posts.where("topics.posts_count >= ?", match.to_i)
+ advanced_filter(/^max_posts:(\d+)$/i) do |posts, match|
+ posts.where("topics.posts_count <= ?", match.to_i)
end
advanced_filter(/^in:first|^f$/i) do |posts|
diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb
index 113276085fd..5f05a2b28c5 100644
--- a/spec/components/search_spec.rb
+++ b/spec/components/search_spec.rb
@@ -1279,6 +1279,7 @@ describe Search do
expect(Search.execute('test posts_count:1').posts.length).to eq(1)
expect(Search.execute('test min_post_count:1').posts.length).to eq(1)
expect(Search.execute('test min_posts:1').posts.length).to eq(1)
+ expect(Search.execute('test max_posts:2').posts.length).to eq(1)
topic.update(closed: true)
second_topic.update(category: public_category)
diff --git a/test/javascripts/acceptance/search-full-test.js b/test/javascripts/acceptance/search-full-test.js
index 9c2f2ed43ba..964296d6a15 100644
--- a/test/javascripts/acceptance/search-full-test.js
+++ b/test/javascripts/acceptance/search-full-test.js
@@ -396,6 +396,26 @@ QUnit.test(
}
);
+QUnit.test(
+ "update max post count through advanced search ui",
+ async (assert) => {
+ await visit("/search");
+ await fillIn(".search-query", "none");
+ await fillIn("#search-max-post-count", "5");
+
+ assert.equal(
+ find(".search-advanced-options #search-max-post-count").val(),
+ "5",
+ 'has "5" populated'
+ );
+ assert.equal(
+ find(".search-query").val(),
+ "none max_posts:5",
+ 'has updated search term to "none max_posts:5"'
+ );
+ }
+);
+
QUnit.test("validate advanced search when initially empty", async (assert) => {
await visit("/search?expanded=true");
await click(".search-advanced-options .in-likes");