Merge pull request #254 from mlovic/filter-debates
Add filters to specify order of debates on /debates page
This commit is contained in:
@@ -32,6 +32,7 @@ var initialize_modules = function() {
|
|||||||
App.Tags.initialize();
|
App.Tags.initialize();
|
||||||
App.Stats.initialize();
|
App.Stats.initialize();
|
||||||
App.LocaleSwitcher.initialize();
|
App.LocaleSwitcher.initialize();
|
||||||
|
App.DebatesOrderSelector.initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
|
|||||||
17
app/assets/javascripts/debates_order_selector.js.coffee
Normal file
17
app/assets/javascripts/debates_order_selector.js.coffee
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
App.DebatesOrderSelector =
|
||||||
|
|
||||||
|
href_with_params: (query_params) ->
|
||||||
|
loc = window.location
|
||||||
|
|
||||||
|
loc.protocol + "//" + loc.hostname +
|
||||||
|
(if loc.port then ':' + loc.port else '') +
|
||||||
|
loc.pathname +
|
||||||
|
loc.hash +
|
||||||
|
'?' + $.param(query_params)
|
||||||
|
|
||||||
|
initialize: ->
|
||||||
|
$('.js-order-selector').on 'change', ->
|
||||||
|
query_params = window.getQueryParameters()
|
||||||
|
query_params['order'] = $(this).val()
|
||||||
|
window.location.assign(App.DebatesOrderSelector.href_with_params(query_params))
|
||||||
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
class DebatesController < ApplicationController
|
class DebatesController < ApplicationController
|
||||||
|
before_action :parse_order, only: :index
|
||||||
before_action :authenticate_user!, except: [:index, :show]
|
before_action :authenticate_user!, except: [:index, :show]
|
||||||
|
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
respond_to :html, :js
|
respond_to :html, :js
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@debates = Debate.search(params).page(params[:page]).for_render
|
@debates = Debate.search(params).page(params[:page]).for_render.send("sort_by_#{@order}")
|
||||||
set_debate_votes(@debates)
|
set_debate_votes(@debates)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -71,4 +72,9 @@ class DebatesController < ApplicationController
|
|||||||
@featured_tags = ActsAsTaggableOn::Tag.where(featured: true)
|
@featured_tags = ActsAsTaggableOn::Tag.where(featured: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parse_order
|
||||||
|
@valid_orders = ['total_votes', 'created_at', 'likes']
|
||||||
|
@order = @valid_orders.include?(params[:order]) ? params[:order] : 'created_at'
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
12
app/helpers/debates_helper.rb
Normal file
12
app/helpers/debates_helper.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module DebatesHelper
|
||||||
|
def available_options_for_order_selector(valid_orders, current_order)
|
||||||
|
options_for_select(available_order_filters_array(valid_orders), current_order)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def available_order_filters_array(orders)
|
||||||
|
orders.map { |f| [t("debates.index.order_#{f}"), f] }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -28,6 +28,10 @@ class Debate < ActiveRecord::Base
|
|||||||
scope :archived, -> { where("archived_at IS NOT NULL AND hidden_at IS NULL") }
|
scope :archived, -> { where("archived_at IS NOT NULL AND hidden_at IS NULL") }
|
||||||
scope :flagged_as_inappropiate, -> { where("inappropiate_flags_count > 0") }
|
scope :flagged_as_inappropiate, -> { where("inappropiate_flags_count > 0") }
|
||||||
scope :for_render, -> { includes(:tags) }
|
scope :for_render, -> { includes(:tags) }
|
||||||
|
scope :sort_by_total_votes, -> { reorder(cached_votes_total: :desc) }
|
||||||
|
scope :sort_by_likes , -> { reorder(cached_votes_up: :desc) }
|
||||||
|
scope :sort_by_created_at, -> { reorder(created_at: :desc) }
|
||||||
|
|
||||||
|
|
||||||
# Ahoy setup
|
# Ahoy setup
|
||||||
visitable # Ahoy will automatically assign visit_id on create
|
visitable # Ahoy will automatically assign visit_id on create
|
||||||
|
|||||||
5
app/views/debates/_order_selector.erb
Normal file
5
app/views/debates/_order_selector.erb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<form class="inline-block">
|
||||||
|
<select class="js-order-selector" name="order-selector">
|
||||||
|
<%= available_options_for_order_selector(@valid_orders, @order) %>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
@@ -4,18 +4,7 @@
|
|||||||
<div class="filters row">
|
<div class="filters row">
|
||||||
<div class="small-12 column">
|
<div class="small-12 column">
|
||||||
<h2><%= t("debates.index.showing") %></h2>
|
<h2><%= t("debates.index.showing") %></h2>
|
||||||
|
<%= render 'order_selector' %>
|
||||||
<select class="inline-block">
|
|
||||||
<option value="filter_news">
|
|
||||||
<%= t("debates.index.filter_news") %>
|
|
||||||
</option>
|
|
||||||
<option value="filter_votes">
|
|
||||||
<%= t("debates.index.filter_votes") %>
|
|
||||||
</option>
|
|
||||||
<option value="filter_rated">
|
|
||||||
<%= t("debates.index.filter_rated") %>
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /. Filters -->
|
<!-- /. Filters -->
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ en:
|
|||||||
index:
|
index:
|
||||||
create_debate: Create a debate
|
create_debate: Create a debate
|
||||||
showing: You are seeing debates
|
showing: You are seeing debates
|
||||||
filter_news: the newest
|
order_created_at: the newest
|
||||||
filter_votes: the most voted
|
order_total_votes: the most voted
|
||||||
filter_rated: the best rated
|
order_likes: the best rated
|
||||||
filter_topic: "You are seeing %{number} debates with the topic '%{topic}'"
|
filter_topic: "You are seeing %{number} debates with the topic '%{topic}'"
|
||||||
debate:
|
debate:
|
||||||
debate: Debate
|
debate: Debate
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ es:
|
|||||||
index:
|
index:
|
||||||
create_debate: Crea un debate
|
create_debate: Crea un debate
|
||||||
showing: "Estás viendo los debates"
|
showing: "Estás viendo los debates"
|
||||||
filter_news: "más nuevos"
|
order_created_at: "más nuevos"
|
||||||
filter_votes: "más votados"
|
order_total_votes: "más votados"
|
||||||
filter_rated: mejor valorados
|
order_likes: mejor valorados
|
||||||
filter_topic: "Estás viendo %{number} debates con el tema '%{topic}'"
|
filter_topic: "Estás viendo %{number} debates con el tema '%{topic}'"
|
||||||
debate:
|
debate:
|
||||||
debate: Debate
|
debate: Debate
|
||||||
|
|||||||
@@ -350,4 +350,60 @@ feature 'Debates' do
|
|||||||
expect(InappropiateFlag.flagged?(user, debate)).to_not be
|
expect(InappropiateFlag.flagged?(user, debate)).to_not be
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature 'Debate index order filters', :js do
|
||||||
|
|
||||||
|
before do
|
||||||
|
# TODO consider using debate title literally
|
||||||
|
@most_voted_debate = create(:debate)
|
||||||
|
@most_liked_debate = create(:debate)
|
||||||
|
@most_recent_debate = create(:debate)
|
||||||
|
create_list(:vote, 2, votable: @most_liked_debate)
|
||||||
|
create_list(:vote, 2, votable: @most_voted_debate, vote_flag: false)
|
||||||
|
create(:vote, votable: @most_voted_debate)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Default order is created_at' do
|
||||||
|
visit debates_path
|
||||||
|
|
||||||
|
expect(page).to have_select('order-selector', selected: 'the newest')
|
||||||
|
expect(@most_recent_debate.title).to appear_before(@most_liked_debate.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Debates are ordered by most voted' do
|
||||||
|
visit debates_path
|
||||||
|
|
||||||
|
select 'the most voted', from: 'order-selector'
|
||||||
|
expect(page).to have_select('order-selector', selected: 'the most voted')
|
||||||
|
|
||||||
|
expect(find("#debates .debate", match: :first)).to have_content(@most_voted_debate.title) # Necessary to force capybara to wait for redirect
|
||||||
|
expect(current_url).to include('order=total_votes')
|
||||||
|
expect(@most_voted_debate.title).to appear_before(@most_liked_debate.title)
|
||||||
|
expect(@most_liked_debate.title).to appear_before(@most_recent_debate.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Debates are ordered by best rated' do
|
||||||
|
visit debates_path
|
||||||
|
|
||||||
|
select 'the best rated', from: 'order-selector'
|
||||||
|
expect(find("#debates .debate", match: :first)).to have_content(@most_liked_debate.title)
|
||||||
|
|
||||||
|
expect(current_url).to include('order=likes')
|
||||||
|
expect(@most_liked_debate.title).to appear_before(@most_voted_debate.title)
|
||||||
|
expect(@most_voted_debate.title).to appear_before(@most_recent_debate.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Debates are ordered by newest' do
|
||||||
|
visit debates_path
|
||||||
|
|
||||||
|
select 'the most voted', from: 'order-selector'
|
||||||
|
expect(find("#debates .debate", match: :first)).to have_content(@most_voted_debate.title)
|
||||||
|
|
||||||
|
select 'the newest', from: 'order-selector'
|
||||||
|
expect(find("#debates .debate", match: :first)).to have_content(@most_recent_debate.title)
|
||||||
|
|
||||||
|
expect(current_url).to include('order=created_at')
|
||||||
|
expect(@most_recent_debate.title).to appear_before(@most_liked_debate.title)
|
||||||
|
expect(@most_liked_debate.title).to appear_before(@most_voted_debate.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
6
spec/support/matchers/appear_before.rb
Normal file
6
spec/support/matchers/appear_before.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
RSpec::Matchers.define :appear_before do |later_content|
|
||||||
|
match do |earlier_content|
|
||||||
|
page.body.index(earlier_content) < page.body.index(later_content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Reference in New Issue
Block a user