diff --git a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 index b45f54b5306..6d78fb2b6a6 100644 --- a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 +++ b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 @@ -1,16 +1,16 @@ import { observes } from 'ember-addons/ember-computed-decorators'; -const REGEXP_BLOCKS = /(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/g; +const REGEXP_BLOCKS = /(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/g; -const REGEXP_USERNAME_PREFIX = /(user:|@)/ig; -const REGEXP_CATEGORY_PREFIX = /(category:|#)/ig; -const REGEXP_GROUP_PREFIX = /group:/ig; -const REGEXP_BADGE_PREFIX = /badge:/ig; -const REGEXP_TAGS_PREFIX = /tags?:/ig; -const REGEXP_IN_PREFIX = /in:/ig; -const REGEXP_STATUS_PREFIX = /status:/ig; -const REGEXP_POST_COUNT_PREFIX = /posts_count:/ig; -const REGEXP_POST_TIME_PREFIX = /(before|after):/ig; +const REGEXP_USERNAME_PREFIX = /(user:|@)/ig; +const REGEXP_CATEGORY_PREFIX = /(category:|#)/ig; +const REGEXP_GROUP_PREFIX = /group:/ig; +const REGEXP_BADGE_PREFIX = /badge:/ig; +const REGEXP_TAGS_PREFIX = /tags?:/ig; +const REGEXP_IN_PREFIX = /in:/ig; +const REGEXP_STATUS_PREFIX = /status:/ig; +const REGEXP_MIN_POST_COUNT_PREFIX = /min_post_count:/ig; +const REGEXP_POST_TIME_PREFIX = /(before|after):/ig; const REGEXP_IN_MATCH = /in:(posted|watching|tracking|bookmarks|first|pinned|unpinned)/ig; const REGEXP_SPECIAL_IN_LIKES_MATCH = /in:likes/ig; @@ -73,7 +73,7 @@ export default Em.Component.extend({ } }, status: '', - posts_count: '', + min_post_count: '', time: { when: 'before', days: '' @@ -99,7 +99,7 @@ export default Em.Component.extend({ this.setSearchedTermSpecialInValue('searchedTerms.special.in.wiki', REGEXP_SPECIAL_IN_WIKI_MATCH); this.setSearchedTermValue('searchedTerms.status', REGEXP_STATUS_PREFIX); this.setSearchedTermValueForPostTime(); - this.setSearchedTermValue('searchedTerms.posts_count', REGEXP_POST_COUNT_PREFIX); + this.setSearchedTermValue('searchedTerms.min_post_count', REGEXP_MIN_POST_COUNT_PREFIX); }, findSearchTerms() { @@ -490,17 +490,17 @@ export default Em.Component.extend({ } }, - @observes('searchedTerms.posts_count') - updateSearchTermForPostsCount() { - const match = this.filterBlocks(REGEXP_POST_COUNT_PREFIX); - const postsCountFilter = this.get('searchedTerms.posts_count'); + @observes('searchedTerms.min_post_count') + updateSearchTermForMinPostCount() { + const match = this.filterBlocks(REGEXP_MIN_POST_COUNT_PREFIX); + const postsCountFilter = this.get('searchedTerms.min_post_count'); let searchTerm = this.get('searchTerm') || ''; if (postsCountFilter) { if (match.length !== 0) { - searchTerm = searchTerm.replace(match[0], `posts_count:${postsCountFilter}`); + searchTerm = searchTerm.replace(match[0], `min_post_count:${postsCountFilter}`); } else { - searchTerm += ` posts_count:${postsCountFilter}`; + searchTerm += ` min_post_count:${postsCountFilter}`; } this.set('searchTerm', searchTerm.trim()); diff --git a/app/assets/javascripts/discourse/templates/components/search-advanced-options.hbs b/app/assets/javascripts/discourse/templates/components/search-advanced-options.hbs index 554a2d689cf..5ac55038d54 100644 --- a/app/assets/javascripts/discourse/templates/components/search-advanced-options.hbs +++ b/app/assets/javascripts/discourse/templates/components/search-advanced-options.hbs @@ -75,9 +75,9 @@
- +
- {{input type="number" value=searchedTerms.posts_count class="input-small" id='search-posts-count'}} + {{input type="number" value=searchedTerms.min_post_count class="input-small" id='search-min-post-count'}}
diff --git a/lib/search.rb b/lib/search.rb index e9f3cddc16f..f6746980d94 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -252,6 +252,10 @@ class Search posts.where("topics.posts_count = ?", match.to_i) end + advanced_filter(/min_post_count:(\d+)/) do |posts, match| + posts.where("topics.posts_count >= ?", match.to_i) + end + advanced_filter(/in:first/) do |posts| posts.where("posts.post_number = 1") end diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index 20c2046e0b0..8d054157b1d 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -532,6 +532,7 @@ describe Search do expect(Search.execute('test status:closed').posts.length).to eq(0) expect(Search.execute('test status:open').posts.length).to eq(1) 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) topic.closed = true topic.save diff --git a/test/javascripts/acceptance/search-full-test.js.es6 b/test/javascripts/acceptance/search-full-test.js.es6 index 29d863912d7..a9e75f812cc 100644 --- a/test/javascripts/acceptance/search-full-test.js.es6 +++ b/test/javascripts/acceptance/search-full-test.js.es6 @@ -71,7 +71,7 @@ test("open advanced search", assert => { test("validate population of advanced search", assert => { visit("/search"); - fillIn('.search input.full-page-search', 'test user:admin #bug group:moderators badge:Reader tags:monkey in:likes in:private in:wiki in:bookmarks status:open after:2016-10-05 posts_count:10'); + fillIn('.search input.full-page-search', 'test user:admin #bug group:moderators badge:Reader tags:monkey in:likes in:private in:wiki in:bookmarks status:open after:2016-10-05 min_post_count:10'); click('.search-advanced-btn'); andThen(() => { @@ -87,7 +87,7 @@ test("validate population of advanced search", assert => { assert.ok(exists('.search-advanced-options .combobox .select2-choice .select2-chosen:contains("are open")'), 'has "are open" pre-populated'); assert.ok(exists('.search-advanced-options .combobox .select2-choice .select2-chosen:contains("after")'), 'has "after" pre-populated'); assert.equal(find('.search-advanced-options #search-post-date').val(), "2016-10-05", 'has "2016-10-05" pre-populated'); - assert.equal(find('.search-advanced-options #search-posts-count').val(), "10", 'has "10" pre-populated'); + assert.equal(find('.search-advanced-options #search-min-post-count').val(), "10", 'has "10" pre-populated'); }); }); @@ -270,15 +270,15 @@ test("update post time through advanced search ui", assert => { }); }); -test("update posts count through advanced search ui", assert => { +test("update min post count through advanced search ui", assert => { visit("/search"); fillIn('.search input.full-page-search', 'none'); click('.search-advanced-btn'); - fillIn('#search-posts-count', '5'); + fillIn('#search-min-post-count', '5'); andThen(() => { - assert.equal(find('.search-advanced-options #search-posts-count').val(), "5", 'has "5" populated'); - assert.equal(find('.search input.full-page-search').val(), "none posts_count:5", 'has updated search term to "none posts_count:5"'); + assert.equal(find('.search-advanced-options #search-min-post-count').val(), "5", 'has "5" populated'); + assert.equal(find('.search input.full-page-search').val(), "none min_post_count:5", 'has updated search term to "none min_post_count:5"'); }); });