From b7d3b52e4f663e93beaa3f47ae8482df67e15a65 Mon Sep 17 00:00:00 2001
From: Sam <sam.saffron@gmail.com>
Date: Thu, 24 Oct 2013 21:05:06 +1100
Subject: [PATCH] basic implementation of per-category new/latest etc filters

---
 .../javascripts/discourse/routes/application_routes.js     | 3 +++
 .../javascripts/discourse/routes/list_category_route.js    | 7 ++++++-
 app/controllers/list_controller.rb                         | 3 ++-
 config/routes.rb                                           | 6 +++++-
 lib/topic_query.rb                                         | 4 ++--
 5 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/app/assets/javascripts/discourse/routes/application_routes.js b/app/assets/javascripts/discourse/routes/application_routes.js
index 7fd5c3756..1d7f4db2e 100644
--- a/app/assets/javascripts/discourse/routes/application_routes.js
+++ b/app/assets/javascripts/discourse/routes/application_routes.js
@@ -26,6 +26,9 @@ Discourse.Route.buildRoutes(function() {
     Discourse.ListController.filters.forEach(function(filter) {
       router.route(filter, { path: "/" + filter });
       router.route(filter, { path: "/" + filter + "/more" });
+      router.route(filter + "Category", { path: "/category/:slug/" + filter });
+      router.route(filter + "Category", { path: "/category/:slug/" + filter + "/more" });
+
     });
 
     // the homepage is the first item of the 'top_menu' site setting
diff --git a/app/assets/javascripts/discourse/routes/list_category_route.js b/app/assets/javascripts/discourse/routes/list_category_route.js
index 38e2e264f..cef425dff 100644
--- a/app/assets/javascripts/discourse/routes/list_category_route.js
+++ b/app/assets/javascripts/discourse/routes/list_category_route.js
@@ -40,7 +40,7 @@ Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({
     this._super();
 
     // Add a search context
-    this.controllerFor('search').set('searchContext', this.modelFor('listCategory').get('searchContext'));
+    this.controllerFor('search').set('searchContext', this.modelFor(this.get('routeName')).get('searchContext'));
   },
 
   deactivate: function() {
@@ -54,3 +54,8 @@ Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({
 });
 
 
+Discourse.ListController.filters.forEach(function(filter) {
+  Discourse["List" + (filter.capitalize()) + "CategoryRoute"] = Discourse.ListCategoryRoute.extend({ filter: filter });
+});
+
+
diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb
index 07b15a5b7..bbae95c6c 100644
--- a/app/controllers/list_controller.rb
+++ b/app/controllers/list_controller.rb
@@ -139,7 +139,8 @@ class ListController < ApplicationController
     return {
       page: params[:page],
       topic_ids: param_to_integer_list(:topic_ids),
-      exclude_category: (params[:exclude_category] || menu_item.try(:filter))
+      exclude_category: (params[:exclude_category] || menu_item.try(:filter)),
+      category: params[:category]
     }
   end
 
diff --git a/config/routes.rb b/config/routes.rb
index 2533fb162..20dfb54c6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -196,7 +196,6 @@ Discourse::Application.routes.draw do
 
   get 'category/:category.rss' => 'list#category_feed', format: :rss, as: 'category_feed'
   get 'category/:category' => 'list#category', as: 'category_list'
-  get 'category/:parent_category/:category' => 'list#category', as: 'category_list_parent'
   get 'category/:category/more' => 'list#category', as: 'category_list_more'
 
   # We've renamed popular to latest. If people access it we want a permanent redirect.
@@ -210,8 +209,13 @@ Discourse::Application.routes.draw do
   [:latest, :hot, :favorited, :read, :posted, :unread, :new].each do |filter|
     get "#{filter}" => "list##{filter}"
     get "#{filter}/more" => "list##{filter}"
+
+    get "category/:category/#{filter}" => "list##{filter}"
+    get "category/:category/#{filter}/more" => "list##{filter}"
   end
 
+  get 'category/:parent_category/:category' => 'list#category', as: 'category_list_parent'
+
   get 'search' => 'search#query'
 
   # Topics resource
diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index b6b442218..e3930dc82 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -7,7 +7,7 @@ require_dependency 'suggested_topics_builder'
 
 class TopicQuery
   # Could be rewritten to %i if Ruby 1.9 is no longer supported
-  VALID_OPTIONS = %w(except_topic_id exclude_category limit page per_page topic_ids visible).map(&:to_sym)
+  VALID_OPTIONS = %w(except_topic_id exclude_category limit page per_page topic_ids visible category).map(&:to_sym)
 
   class << self
     # use the constants in conjuction with COALESCE to determine the order with regard to pinned
@@ -233,7 +233,7 @@ class TopicQuery
 
       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.where('categories.name = ?', options[:only_category]).references(:categories) if options[:only_category]
+      result = result.where('categories.slug = ?', options[:category]).references(:categories) if options[:category].present?
       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]