From 1668b5eab2e218817b8c49b0f94bc2d73b9f97e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= <regis@hanol.fr> Date: Thu, 28 Mar 2013 14:01:13 +0100 Subject: [PATCH] FIX: allows the selection of the default landing tab --- .../discourse/controllers/list_controller.js | 21 +++---- .../javascripts/discourse/models/nav_item.js | 60 +++++++------------ .../discourse/routes/application_routes.js | 18 +++--- app/controllers/list_controller.rb | 6 +- app/models/site_setting.rb | 9 +++ config/routes.rb | 28 ++++----- lib/homepage_constraint.rb | 10 ++++ spec/controllers/list_controller_spec.rb | 17 ++++-- 8 files changed, 81 insertions(+), 88 deletions(-) create mode 100644 lib/homepage_constraint.rb diff --git a/app/assets/javascripts/discourse/controllers/list_controller.js b/app/assets/javascripts/discourse/controllers/list_controller.js index 22d50bb01..046df79dc 100644 --- a/app/assets/javascripts/discourse/controllers/list_controller.js +++ b/app/assets/javascripts/discourse/controllers/list_controller.js @@ -14,7 +14,7 @@ Discourse.ListController = Discourse.Controller.extend({ canCreateTopic: false, needs: ['composer', 'modal', 'listTopics'], - availableNavItems: (function() { + availableNavItems: function() { var hasCategories, loggedOn, summary; summary = this.get('filterSummary'); loggedOn = !!Discourse.get('currentUser'); @@ -28,7 +28,7 @@ Discourse.ListController = Discourse.Controller.extend({ }).filter(function(i) { return i !== null; }); - }).property('filterSummary'), + }.property('filterSummary'), /** Load a list based on a filter @@ -63,26 +63,23 @@ Discourse.ListController = Discourse.Controller.extend({ }, // Put in the appropriate page title based on our view - updateTitle: (function() { + updateTitle: function() { if (this.get('filterMode') === 'categories') { return Discourse.set('title', Em.String.i18n('categories_list')); } else { if (this.present('category')) { - return Discourse.set('title', "" + (this.get('category.name').capitalize()) + " " + (Em.String.i18n('topic.list'))); + return Discourse.set('title', this.get('category.name').capitalize() + " " + Em.String.i18n('topic.list')); } else { return Discourse.set('title', Em.String.i18n('topic.list')); } } - }).observes('filterMode', 'category'), + }.observes('filterMode', 'category'), // Create topic button createTopic: function() { - var topicList; - topicList = this.get('controllers.listTopics.content'); - if (!topicList) { - return; - } - return this.get('controllers.composer').open({ + var topicList = this.get('controllers.listTopics.content'); + if (!topicList) return; + this.get('controllers.composer').open({ categoryName: this.get('category.name'), action: Discourse.Composer.CREATE_TOPIC, draftKey: topicList.get('draft_key'), @@ -100,5 +97,3 @@ Discourse.ListController = Discourse.Controller.extend({ Discourse.ListController.reopenClass({ filters: ['latest', 'hot', 'favorited', 'read', 'unread', 'new', 'posted'] }); - - diff --git a/app/assets/javascripts/discourse/models/nav_item.js b/app/assets/javascripts/discourse/models/nav_item.js index 0e5d0e9db..802b47e0f 100644 --- a/app/assets/javascripts/discourse/models/nav_item.js +++ b/app/assets/javascripts/discourse/models/nav_item.js @@ -6,47 +6,35 @@ @namespace Discourse @module Discourse **/ -var validNavNames = ['read', 'latest', 'hot', 'categories', 'favorited', 'category', 'unread', 'new', 'posted']; -var validAnon = ['latest', 'hot', 'category', 'categories']; +var validNavNames = ['latest', 'hot', 'categories', 'category', 'favorited', 'unread', 'new', 'read', 'posted']; +var validAnon = ['latest', 'hot', 'categories', 'category']; Discourse.NavItem = Discourse.Model.extend({ - categoryName: (function() { - var split; - split = this.get('name').split('/'); - if (split[0] === 'category') { - return split[1]; - } else { - return null; - } - }).property(), - href: (function() { - /* href from this item - */ + categoryName: function() { + var split = this.get('name').split('/'); + return split[0] === 'category' ? split[1] : null; + }.property('name'), - var name; - name = this.get('name'); - if (name === 'category') { - return Discourse.getURL("/") + name + "/" + (this.get('categoryName')); - } else { - return Discourse.getURL("/") + name; - } - }).property() + // href from this item + href: function() { + var name = this.get('name'), + href = Discourse.getURL("/") + name; + if (name === 'category') href += "/" + this.get('categoryName'); + return href; + }.property('name') }); Discourse.NavItem.reopenClass({ // create a nav item from the text, will return null if there is not valid nav item for this particular text fromText: function(text, opts) { - var countSummary, hasCategories, loggedOn, name, split, testName; - countSummary = opts.countSummary; - loggedOn = opts.loggedOn; - hasCategories = opts.hasCategories; - split = text.split(","); - name = split[0]; - testName = name.split("/")[0]; + var countSummary = opts.countSummary, + split = text.split(","), + name = split[0], + testName = name.split("/")[0]; - if (!loggedOn && !validAnon.contains(testName)) return null; - if (!hasCategories && testName === "categories") return null; + if (!opts.loggedOn && !validAnon.contains(testName)) return null; + if (!opts.hasCategories && testName === "categories") return null; if (!validNavNames.contains(testName)) return null; opts = { @@ -54,14 +42,10 @@ Discourse.NavItem.reopenClass({ hasIcon: name === "unread" || name === "favorited", filters: split.splice(1) }; - if (countSummary) { - if (countSummary && countSummary[name]) { - opts.count = countSummary[name]; - } - } + + if (countSummary && countSummary[name]) opts.count = countSummary[name]; + return Discourse.NavItem.create(opts); } }); - - diff --git a/app/assets/javascripts/discourse/routes/application_routes.js b/app/assets/javascripts/discourse/routes/application_routes.js index 8d5cb265b..9d8e487be 100644 --- a/app/assets/javascripts/discourse/routes/application_routes.js +++ b/app/assets/javascripts/discourse/routes/application_routes.js @@ -19,22 +19,20 @@ Discourse.Route.buildRoutes(function() { router.route(p, { path: "/" + p }); }); - this.route('faq', { path: '/faq' }); - this.route('tos', { path: '/tos' }); - this.route('privacy', { path: '/privacy' }); - // List routes this.resource('list', { path: '/' }, function() { router = this; // Generate routes for all our filters - Discourse.ListController.filters.forEach(function(r) { - router.route(r, { path: "/" + r }); - router.route(r, { path: "/" + r + "/more" }); + Discourse.ListController.filters.forEach(function(filter) { + router.route(filter, { path: "/" + filter }); + router.route(filter, { path: "/" + filter + "/more" }); }); - this.route('latest', { path: '/' }); - this.route('hot', { path: '/hot' }); + // the homepage is the first item of the 'top_menu' site setting + var homepage = PreloadStore.get('siteSettings').top_menu.split("|")[0]; + this.route(homepage, { path: '/' }); + this.route('categories', { path: '/categories' }); this.route('category', { path: '/category/:slug/more' }); this.route('category', { path: '/category/:slug' }); @@ -51,5 +49,3 @@ Discourse.Route.buildRoutes(function() { this.route('invited', { path: 'invited' }); }); }); - - diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index 253faa65a..773e05c89 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -1,12 +1,11 @@ class ListController < ApplicationController - before_filter :ensure_logged_in, except: [:index, :hot, :category, :category_feed] + before_filter :ensure_logged_in, except: [:latest, :hot, :category, :category_feed] skip_before_filter :check_xhr # Create our filters [:latest, :hot, :favorited, :read, :posted, :unread, :new].each do |filter| define_method(filter) do - list_opts = {page: params[:page]} # html format means we need to farm exclude from the site options @@ -14,7 +13,7 @@ class ListController < ApplicationController #TODO objectify this stuff SiteSetting.top_menu.split('|').each do |f| s = f.split(",") - if s[0] == action_name || (action_name == "index" && s[0] == "latest") + if s[0] == action_name || (action_name == "index" && s[0] == SiteSetting.homepage) list_opts[:exclude_category] = s[1][1..-1] if s.length == 2 end end @@ -27,7 +26,6 @@ class ListController < ApplicationController respond(list) end end - alias_method :index, :latest def category diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index a7982efab..03f1d535a 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -190,4 +190,13 @@ class SiteSetting < ActiveRecord::Base def self.post_length min_post_length..max_post_length end + + def self.homepage + top_menu.split('|')[0] + end + + def self.anonymous_homepage + top_menu.split('|').select{ |f| ['latest', 'hot', 'categories', 'category'].include? f }[0] + end + end diff --git a/config/routes.rb b/config/routes.rb index 81de68fe7..f6bac25af 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ require 'sidekiq/web' require_dependency 'admin_constraint' +require_dependency 'homepage_constraint' # This used to be User#username_format, but that causes a preload of the User object # and makes Guard not work properly. @@ -154,20 +155,10 @@ Discourse::Application.routes.draw do get 'popular' => 'list#popular_redirect' get 'popular/more' => 'list#popular_redirect' - get 'latest' => 'list#index' - get 'latest/more' => 'list#index' - get 'hot' => 'list#hot' - get 'hot/more' => 'list#hot' - get 'favorited' => 'list#favorited' - get 'favorited/more' => 'list#favorited' - get 'read' => 'list#read' - get 'read/more' => 'list#read' - get 'unread' => 'list#unread' - get 'unread/more' => 'list#unread' - get 'new' => 'list#new' - get 'new/more' => 'list#new' - get 'posted' => 'list#posted' - get 'posted/more' => 'list#posted' + [:latest, :hot, :favorited, :read, :posted, :unread, :new].each do |filter| + get "#{filter}" => "list##{filter}" + get "#{filter}/more" => "list##{filter}" + end get 'search' => 'search#query' @@ -222,11 +213,12 @@ Discourse::Application.routes.draw do post 'draft' => 'draft#update' delete 'draft' => 'draft#destroy' - get 'robots.txt' => 'robots_txt#index' - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - root to: 'list#index' + [:latest, :hot, :unread, :new, :favorited, :read, :posted].each do |filter| + root to: "list##{filter}", constraints: HomePageConstraint.new("#{filter}") + end + # special case for categories + root to: "categories#index", constraints: HomePageConstraint.new("categories") end diff --git a/lib/homepage_constraint.rb b/lib/homepage_constraint.rb new file mode 100644 index 000000000..bbac573ea --- /dev/null +++ b/lib/homepage_constraint.rb @@ -0,0 +1,10 @@ +class HomePageConstraint + def initialize(filter) + @filter = filter + end + + def matches?(request) + homepage = request.session[:current_user_id].present? ? SiteSetting.homepage : SiteSetting.anonymous_homepage + homepage == @filter + end +end \ No newline at end of file diff --git a/spec/controllers/list_controller_spec.rb b/spec/controllers/list_controller_spec.rb index 0725c0bbf..6a39ec4c7 100644 --- a/spec/controllers/list_controller_spec.rb +++ b/spec/controllers/list_controller_spec.rb @@ -8,12 +8,21 @@ describe ListController do @post = Fabricate(:post, user: @user) end - context 'index' do - before do - xhr :get, :index + describe 'indexes' do + + [:latest, :hot].each do |filter| + context '#{filter}' do + before { xhr :get, filter } + it { should respond_with(:success) } + end + end + + [:favorited, :read, :posted, :unread, :new].each do |filter| + context '#{filter}' do + it { expect { xhr :get, filter }.to raise_error(Discourse::NotLoggedIn) } + end end - it { should respond_with(:success) } end context 'category' do