diff --git a/app/assets/javascripts/discourse/controllers/list_controller.js b/app/assets/javascripts/discourse/controllers/list_controller.js index 232ada03a8f..64701102927 100644 --- a/app/assets/javascripts/discourse/controllers/list_controller.js +++ b/app/assets/javascripts/discourse/controllers/list_controller.js @@ -46,14 +46,14 @@ Discourse.ListController = Discourse.Controller.extend({ @returns {Ember.Deferred} the promise that will resolve to the list of items. **/ load: function(filterMode) { - var listController = this; + var self = this; this.set('loading', true); var trackingState = Discourse.TopicTrackingState.current(); if (filterMode === 'categories') { return Discourse.CategoryList.list(filterMode).then(function(items) { - listController.setProperties({ + self.setProperties({ loading: false, filterMode: filterMode, categoryMode: true, @@ -75,7 +75,7 @@ Discourse.ListController = Discourse.Controller.extend({ } return Discourse.TopicList.list(current).then(function(items) { - listController.setProperties({ + self.setProperties({ loading: false, filterMode: filterMode, draft: items.draft, diff --git a/app/assets/javascripts/discourse/controllers/list_topics_controller.js b/app/assets/javascripts/discourse/controllers/list_topics_controller.js index 6c099a6b668..732924018d4 100644 --- a/app/assets/javascripts/discourse/controllers/list_topics_controller.js +++ b/app/assets/javascripts/discourse/controllers/list_topics_controller.js @@ -15,6 +15,10 @@ Discourse.ListTopicsController = Discourse.ObjectController.extend({ latest: Ember.computed.equal('filter', 'latest'), + topicListReloading: function() { + return (!this.get('controllers.list.loading')) && (!this.get('loaded')); + }.property('loaded', 'controllers.list.loading'), + categories: function() { return Discourse.Category.list(); }.property(), diff --git a/app/assets/javascripts/discourse/templates/components/discourse-basic-topic-list.js.handlebars b/app/assets/javascripts/discourse/templates/components/discourse-basic-topic-list.js.handlebars index a8b67a62a3c..3a524253ff1 100644 --- a/app/assets/javascripts/discourse/templates/components/discourse-basic-topic-list.js.handlebars +++ b/app/assets/javascripts/discourse/templates/components/discourse-basic-topic-list.js.handlebars @@ -5,7 +5,7 @@ {{#discourse-heading sortBy="default" sortOrder=sortOrder}} {{i18n topic.title}} {{/discourse-heading}} - {{#discourse-heading}} + {{#discourse-heading sortBy="category" sortOrder=sortOrder}} {{i18n category_title}} {{/discourse-heading}} {{#discourse-heading sortBy="posts" number=true sortOrder=sortOrder}} diff --git a/app/assets/javascripts/discourse/templates/components/discourse-topic-list-loading.js.handlebars b/app/assets/javascripts/discourse/templates/components/discourse-topic-list-loading.js.handlebars new file mode 100644 index 00000000000..5883b28e7a3 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/discourse-topic-list-loading.js.handlebars @@ -0,0 +1,3 @@ +
+
{{i18n loading}}
+
diff --git a/app/assets/javascripts/discourse/templates/list.js.handlebars b/app/assets/javascripts/discourse/templates/list.js.handlebars index 3b7e510a19d..28b8c8f05bb 100644 --- a/app/assets/javascripts/discourse/templates/list.js.handlebars +++ b/app/assets/javascripts/discourse/templates/list.js.handlebars @@ -26,18 +26,7 @@
- {{#if loading}} -
- - - - -
-
{{i18n loading}}
-
-
- {{/if}} - + {{discourse-topic-list-loading loading=loading}} {{outlet listView}}
diff --git a/app/assets/javascripts/discourse/templates/list/topics.js.handlebars b/app/assets/javascripts/discourse/templates/list/topics.js.handlebars index 702cb135a36..d064c96c8f7 100644 --- a/app/assets/javascripts/discourse/templates/list/topics.js.handlebars +++ b/app/assets/javascripts/discourse/templates/list/topics.js.handlebars @@ -1,3 +1,5 @@ +{{discourse-topic-list-loading loading=topicListReloading}} + {{#unless loading}} {{#if loaded}}
@@ -16,17 +18,29 @@ {{#if currentUser}}   {{/if}} - + {{#discourse-heading sortBy="default" sortOrder=sortOrder}} {{i18n topic.title}} - + {{/discourse-heading}} {{#unless category}} - {{i18n category_title}} + {{#discourse-heading sortBy="category" sortOrder=sortOrder}} + {{i18n category_title}} + {{/discourse-heading}} {{/unless}} - {{i18n top_contributors}} - {{i18n posts}} - {{i18n likes}} - {{i18n views}} - {{i18n activity}} + {{#discourse-heading sortBy="posters" sortOrder=sortOrder}} + {{i18n top_contributors}} + {{/discourse-heading}} + {{#discourse-heading sortBy="posts" number=true sortOrder=sortOrder}} + {{i18n posts}} + {{/discourse-heading}} + {{#discourse-heading sortBy="likes" number=true sortOrder=sortOrder}} + {{i18n likes}} + {{/discourse-heading}} + {{#discourse-heading sortBy="views" number=true sortOrder=sortOrder}} + {{i18n views}} + {{/discourse-heading}} + {{#discourse-heading sortBy="activity" number=true colspan="2" sortOrder=sortOrder}} + {{i18n activity}} + {{/discourse-heading}} @@ -67,6 +81,5 @@ {{/if}} - {{/if}} {{/unless}} diff --git a/app/assets/stylesheets/desktop/topic-list.scss b/app/assets/stylesheets/desktop/topic-list.scss index f3aef910f97..15a365b2033 100644 --- a/app/assets/stylesheets/desktop/topic-list.scss +++ b/app/assets/stylesheets/desktop/topic-list.scss @@ -178,7 +178,7 @@ width: 140px; } .posters { - width: 150px; + width: 170px; > a { float: left; margin-right: 4px; @@ -206,7 +206,13 @@ @include unselectable; } .likes { - width: 50px; + width: 65px; + } + .views { + width: 65px; + } + .posts { + width: 65px; } .activity { width: 50px; @@ -216,20 +222,6 @@ } } -.paginated-topics-list { - #topic-list { - .posts { - width: 95px; - } - .likes { - width: 95px; - } - .views { - width: 95px; - } - - } -} #topic-list tbody tr.has-excerpt .star { vertical-align: top; diff --git a/lib/topic_query.rb b/lib/topic_query.rb index f8eda75320e..f9608a104cf 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -24,7 +24,9 @@ class TopicQuery 'likes' => 'like_count', 'views' => 'views', 'posts' => 'posts_count', - 'activity' => 'bumped_at' + 'activity' => 'bumped_at', + 'posters' => 'participant_count', + 'category' => 'category_id' } def initialize(user=nil, options={}) @@ -173,10 +175,23 @@ class TopicQuery # If we are sorting in the default order desc, we should consider including pinned # topics. Otherwise, just use bumped_at. if sort_column == 'default' - return default_ordering(result, options) if sort_dir == 'DESC' + if sort_dir == 'DESC' + + # If something requires a custom order, for example "unread" which sorts the least read + # to the top, do nothing + return result if options[:unordered] + + # Otherwise apply our default ordering + return default_ordering(result, options) + end sort_column = 'bumped_at' end + # If we are sorting by category, actually use the name + if sort_column == 'category_id' + return result.references(:categories).order(TopicQuerySQL.order_by_category_sql(sort_dir)) + end + result.order("topics.#{sort_column} #{sort_dir}") end @@ -203,13 +218,10 @@ class TopicQuery result = result.references(:categories) end - result = apply_ordering(result, options) unless options[:unordered] - + result = apply_ordering(result, options) result = result.listable_topics.includes(category: :topic_only_relative_url) result = result.where('categories.name is null or categories.name <> ?', options[:exclude_category]).references(:categories) if options[:exclude_category] - - result = result.limit(options[:per_page]) unless options[:limit] == false result = result.visible if options[:visible] || @user.nil? || @user.regular? result = result.where('topics.id <> ?', options[:except_topic_id]).references(:topics) if options[:except_topic_id] @@ -233,9 +245,7 @@ class TopicQuery end def new_results(options={}) - result = TopicQuery.new_filter(default_results(options.reverse_merge(:unordered => true)), - @user.treat_as_new_topic_start_date) - + result = TopicQuery.new_filter(default_results(options), @user.treat_as_new_topic_start_date) suggested_ordering(result, options) end diff --git a/lib/topic_query_sql.rb b/lib/topic_query_sql.rb index b8b7e259c6d..d9595e2833b 100644 --- a/lib/topic_query_sql.rb +++ b/lib/topic_query_sql.rb @@ -42,6 +42,10 @@ module TopicQuerySQL end end + def order_by_category_sql(dir) + "CASE WHEN categories.id = #{SiteSetting.uncategorized_category_id.to_i} THEN '' ELSE categories.name END #{dir}" + end + # If you've clearned the pin, use bumped_at, otherwise put it at the top def order_nocategory_with_pinned_sql "CASE diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 7c6acd1e69c..0ef4402a47e 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -65,6 +65,7 @@ describe TopicQuery do views: 100, like_count: 66, posts_count: 3, + participant_count: 11, bumped_at: 15.minutes.ago) end let!(:pinned_topic) do @@ -73,6 +74,7 @@ describe TopicQuery do views: 10, like_count: 100, posts_count: 5, + participant_count: 12, pinned_at: 10.minutes.ago, bumped_at: 10.minutes.ago) end @@ -83,6 +85,7 @@ describe TopicQuery do like_count: 30, posts_count: 4, archived: true, + participant_count: 1, bumped_at: 6.minutes.ago) end let!(:invisible_topic) do @@ -92,6 +95,7 @@ describe TopicQuery do like_count: 5, posts_count: 2, visible: false, + participant_count: 3, bumped_at: 5.minutes.ago) end let!(:closed_topic) do @@ -101,6 +105,7 @@ describe TopicQuery do like_count: 1, posts_count: 1, closed: true, + participant_count: 2, bumped_at: 1.minute.ago) end @@ -149,6 +154,14 @@ describe TopicQuery do ids_in_order('views', false).should == [invisible_topic, closed_topic, pinned_topic, archived_topic, regular_topic].map(&:id) end + it "returns the topics in posters order if requested" do + ids_in_order('posters').should == [pinned_topic, regular_topic, invisible_topic, closed_topic, archived_topic].map(&:id) + end + + it "returns the topics in reverse posters order if requested" do + ids_in_order('posters', false).should == [archived_topic, closed_topic, invisible_topic, regular_topic, pinned_topic].map(&:id) + end + end end