diff --git a/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 b/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 index 91e5b907d2c..c6379ba1ab2 100644 --- a/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 +++ b/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 @@ -11,6 +11,8 @@ const SortOrders = [ {name: I18n.t('search.latest_post'), id: 1, term: 'order:latest'}, {name: I18n.t('search.most_liked'), id: 2, term: 'order:likes'}, {name: I18n.t('search.most_viewed'), id: 3, term: 'order:views'}, + {name: I18n.t('search.latest_topic'), id: 4, term: 'order:latest_topic'}, + ]; export default Ember.Controller.extend({ @@ -90,7 +92,9 @@ export default Ember.Controller.extend({ this._searchOnSortChange = false; if (term) { SortOrders.forEach(order => { - if (term.indexOf(order.term) > -1){ + let term_start = term.indexOf(order.term) + let char_after_term = term[term_start + (order.term || '').length] + if (term_start > -1 && (!char_after_term || char_after_term.match(/\s/))){ this.set('sortOrder', order.id); term = term.replace(order.term, ""); term = term.trim(); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 85ad37d3452..20c77e45352 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1276,6 +1276,7 @@ en: sort_by: "Sort by" relevance: "Relevance" latest_post: "Latest Post" + latest_topic: "Latest Topic" most_viewed: "Most Viewed" most_liked: "Most Liked" select_all: "Select All" diff --git a/lib/search.rb b/lib/search.rb index 7c055e0a408..81c924df44b 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -477,6 +477,9 @@ class Search if word == 'order:latest' @order = :latest nil + elsif word == 'order:latest_topic' + @order = :latest_topic + nil elsif word =~ /topic:(\d+)/ topic_id = $1.to_i if topic_id > 1 @@ -680,6 +683,12 @@ class Search else posts = posts.order("posts.created_at DESC") end + elsif @order == :latest_topic + if opts[:aggregate_search] + posts = posts.order("MAX(topics.created_at) DESC") + else + posts = posts.order("topics.created_at DESC") + end elsif @order == :views if opts[:aggregate_search] posts = posts.order("MAX(topics.views) DESC") diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index 0cf29c59aa1..892e5b3dd96 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -613,7 +613,28 @@ describe Search do expect(Search.execute('sam').posts.map(&:id)).to eq([post1.id, post2.id]) expect(Search.execute('sam order:latest').posts.map(&:id)).to eq([post2.id, post1.id]) + end + it 'can order by topic creation' do + today = Date.today + yesterday = 1.day.ago + two_days_ago = 2.days.ago + + old_topic = Fabricate(:topic, + title: 'First Topic, testing the created_at sort', + created_at: two_days_ago) + latest_topic = Fabricate(:topic, + title: 'Second Topic, testing the created_at sort', + created_at: yesterday) + + old_relevant_topic_post = Fabricate(:post, topic: old_topic, created_at: yesterday, raw: 'Relevant Topic') + latest_irelevant_topic_post = Fabricate(:post, topic: latest_topic, created_at: today, raw: 'Not Relevant') + + # Expecting the default results + expect(Search.execute('Topic').posts.map(&:id)).to eq([old_relevant_topic_post.id, latest_irelevant_topic_post.id]) + + # Expecting the ordered by topic creation results + expect(Search.execute('Topic order:latest_topic').posts.map(&:id)).to eq([latest_irelevant_topic_post.id, old_relevant_topic_post.id]) end it 'can tokenize dots' do