Skip to content

Commit

Permalink
Introduce randomization into content selector ordering
Browse files Browse the repository at this point in the history
- Use a seeded random order for context selector next/prev links
- Show selectors this same seeded order on the proposals index
- Show vote status on the proposals index
  • Loading branch information
reidab committed Mar 31, 2015
1 parent d9b6126 commit c3253ab
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 24 deletions.
4 changes: 3 additions & 1 deletion app/assets/stylesheets/open_conference_ware/custom.css.scss
Expand Up @@ -439,12 +439,14 @@ table.proposals h3 {
margin: .3em 0 .5em;
}

table.proposals h3 span.proposal-status {
table.proposals h3 span.proposal-status,
table.proposals h3 span.vote-status {
font-size: .7em;
}

table.proposals h3 span.proposal-status.proposed {
color: #222;
display: none;
}

table.proposals h3 span.proposal-status.confirmed {
Expand Down
8 changes: 6 additions & 2 deletions app/controllers/open_conference_ware/proposals_controller.rb
Expand Up @@ -35,8 +35,12 @@ def index
@proposals = Defer { @proposals_hash.values }

unless params[:sort]
params[:sort] = "submitted_at"
params[:dir] = "desc"
if selector?
params[:sort] = "random"
else
params[:sort] = "submitted_at"
params[:dir] = "desc"
end
end

respond_to do |format|
Expand Down
Expand Up @@ -46,7 +46,7 @@ def create
respond_to do |format|
if @selector_vote.save
format.html {
if next_proposal = @selector_vote.proposal.next_proposal
if next_proposal = @selector_vote.proposal.next_random_proposal(current_user.id)
redirect_to(next_proposal)
else
flash[:success] = "You've voted on the last proposal!"
Expand Down
16 changes: 10 additions & 6 deletions app/helpers/open_conference_ware/proposals_helper.rb
Expand Up @@ -35,20 +35,24 @@ def records_path(kind=nil)

# Return a path to the next proposal after +proposal+. Or none if none.
def next_proposal_path_from(proposal)
if next_proposal = proposal.next_proposal
return proposal_path(next_proposal)
if selector?
next_proposal = proposal.next_random_proposal(current_user.id)
else
return nil
next_proposal = proposal.next_proposal
end

next_proposal ? proposal_path(next_proposal) : nil
end

# Return a path to the previous proposal after +proposal+. Or none if none.
def previous_proposal_path_from(proposal)
if previous_proposal = proposal.previous_proposal
return proposal_path(previous_proposal)
if selector?
previous_proposal = proposal.previous_random_proposal(current_user.id)
else
return nil
previous_proposal = proposal.previous_proposal
end

previous_proposal ? proposal_path(previous_proposal) : nil
end
end
end
22 changes: 21 additions & 1 deletion app/models/open_conference_ware/proposal.rb
Expand Up @@ -419,7 +419,7 @@ def title_downcased
end

# Return array of +proposals+ sorted by +field+ (e.g., "title") in +ascending+ order.
def self.sort(proposals, field="title", is_ascending=true)
def self.sort(proposals, field="title", is_ascending=true, random_seed = nil)
proposals = \
case field.to_sym
when :track
Expand All @@ -435,6 +435,9 @@ def self.sort(proposals, field="title", is_ascending=true)
proposals.sort_by{|proposal| proposal.title_downcased}
when :status
proposals.sort_by{|proposal| [proposal.status, proposal.title_downcased]}
when :random
randomized_ids = proposals.first.randomized_ids(random_seed)
proposals.sort_by{|proposal| randomized_ids.index(proposal.id) }
else
proposals.sort_by(&:submitted_at)
end
Expand Down Expand Up @@ -505,6 +508,23 @@ def previous_proposal
return self.event.proposals.where("id < ?", self.id).order("created_at DESC").first
end

def next_random_proposal(seed = nil)
ids = randomized_ids(seed)
next_id = ids[ids.index(self.id) + 1]
next_id && Proposal.find( next_id )
end

def previous_random_proposal(seed = nil)
ids = randomized_ids(seed)
prev_index = ids.index(self.id) - 1
prev_id = ids[prev_index]
prev_index >= 0 && prev_id && Proposal.find( prev_id )
end

def randomized_ids(seed = nil)
event.proposals.order_by_rand(seed: seed).pluck(:id)
end

# Return the integer sum of the selector votes rating for this proposal. Skips
# the "-1" votes because these mean "I don't know how to rate this proposal".
def selector_vote_points
Expand Down
10 changes: 7 additions & 3 deletions app/views/open_conference_ware/proposals/_list.html.erb
Expand Up @@ -6,7 +6,7 @@
# * kind => Treat these records as :sessions or :proposals. REQUIRED.
# * sorter => Display the sort toolbar? Defaults to false.

records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", params[:dir] != "desc")
records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", params[:dir] != "desc", current_user && current_user.id)
%>
<% if proposal_excerpts? %>
Expand All @@ -17,6 +17,7 @@ records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", p
sort_links << sort_link_for("Submission date", 'submitted_at', kind) if kind == :proposals
sort_links << sort_link_for("Scheduled time", 'start_time', kind) if schedule_visible? && kind == :sessions
sort_links << sort_link_for("Status", 'status', kind) if proposal_statuses? && admin?
sort_links << sort_link_for("Random for content selection", 'random', kind) if selector?
%>
Sort by:
<%= sort_links.join(', ').html_safe %>
Expand All @@ -41,8 +42,8 @@ records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", p
</tr>
<% end %>
<% previous_start_time = record.start_time %>

<tr class='proposal_row' id='proposal_row_<%= record.id %>'>
<% voted = selector? && @event.accept_selector_votes? && record.selector_votes.where(user_id: current_user.id).count > 0 %>
<tr class='proposal_row<%= " voted" if voted %>' id='proposal_row_<%= record.id %>'>
<td rowspan='2' class='description'>
<h3>
<%= user_favorite_control_for record %>
Expand All @@ -51,6 +52,9 @@ records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", p
<% else %>
<%= link_to(h(record.presenter)+" &mdash; "+h(record.title), record_path(record, kind), :class => "title") %>
<% end %>
<% if kind == :proposals && voted %>
<span class='vote-status'>(Voted)</span>
<% end %>
<% if kind == :proposals && proposal_statuses? && (admin? || (@event.proposal_status_published? && record.confirmed?)) %>
<span class='proposal-status <%= record.status %>'>(<%= record.status.titleize %>)</span>
<% end %>
Expand Down
1 change: 1 addition & 0 deletions app/views/open_conference_ware/proposals/index.html.erb
Expand Up @@ -13,6 +13,7 @@
cache_key = "#{@kind}_index,event_#{@event.id},admin_#{admin?},accepting_#{@event.accepting_proposals?}"
cache_key << ",sort_#{params[:sort]}" if params[:sort]
cache_key << ",dir_#{params[:dir]}" if params[:dir]
cache_key << ",selector_#{current_user.id}" if selector?
%>
<% cache cache_key do %>
Expand Down
1 change: 1 addition & 0 deletions lib/open_conference_ware/dependencies.rb
Expand Up @@ -19,6 +19,7 @@
require 'prawn'
require "dynamic_form"
require 'rails_rinku'
require 'randumb'

require 'jquery-rails'
require 'sass-rails'
Expand Down
1 change: 1 addition & 0 deletions open_conference_ware.gemspec
Expand Up @@ -43,6 +43,7 @@ Gem::Specification.new do |s|
s.add_dependency 'prawn', '~> 0.12.0'
s.add_dependency "dynamic_form", '~> 1.1.4'
s.add_dependency 'rinku', '~> 1.7.3'
s.add_dependency 'randumb', '~> 0.5.0'

# Assets
s.add_dependency 'jquery-rails', '~> 3.1.0'
Expand Down
25 changes: 15 additions & 10 deletions spec/helpers/open_conference_ware/proposals_helper_spec.rb
Expand Up @@ -3,29 +3,34 @@
describe OpenConferenceWare::ProposalsHelper do
describe "traversal" do
before :each do
allow(view).to receive(:selector?).and_return(false)
add_all_helpers_to(view)
@event = create :populated_event
@proposal1 = proposal_for_event(@event)
@proposal2 = proposal_for_event(@event)
end

describe "#next_proposal_path_from" do
it "should return a link to the next proposal when it exists" do
helper.next_proposal_path_from(@proposal1).should == view.proposal_path(@proposal2)
end
context "as a mortal" do
it "should return a link to the next proposal when it exists" do
helper.next_proposal_path_from(@proposal1).should == view.proposal_path(@proposal2)
end

it "should return nil when this is the last proposal" do
helper.next_proposal_path_from(@proposal2).should be_nil
it "should return nil when this is the last proposal" do
helper.next_proposal_path_from(@proposal2).should be_nil
end
end
end

describe "#previous_proposal_path_from" do
it "should return a link to the previous proposal when it exists" do
helper.previous_proposal_path_from(@proposal2).should == view.proposal_path(@proposal1)
end
context "as a mortal" do
it "should return a link to the previous proposal when it exists" do
helper.previous_proposal_path_from(@proposal2).should == view.proposal_path(@proposal1)
end

it "should return nil when this is the first proposal" do
helper.previous_proposal_path_from(@proposal1).should be_nil
it "should return nil when this is the first proposal" do
helper.previous_proposal_path_from(@proposal1).should be_nil
end
end
end
end
Expand Down

0 comments on commit c3253ab

Please sign in to comment.