diff --git a/app/assets/stylesheets/open_conference_ware/custom.css.scss b/app/assets/stylesheets/open_conference_ware/custom.css.scss index dab4cea1..8e61b58e 100644 --- a/app/assets/stylesheets/open_conference_ware/custom.css.scss +++ b/app/assets/stylesheets/open_conference_ware/custom.css.scss @@ -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 { diff --git a/app/controllers/open_conference_ware/proposals_controller.rb b/app/controllers/open_conference_ware/proposals_controller.rb index dfacec7f..7d2ce343 100644 --- a/app/controllers/open_conference_ware/proposals_controller.rb +++ b/app/controllers/open_conference_ware/proposals_controller.rb @@ -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| diff --git a/app/controllers/open_conference_ware/selector_votes_controller.rb b/app/controllers/open_conference_ware/selector_votes_controller.rb index b7a8da27..75aa9c05 100644 --- a/app/controllers/open_conference_ware/selector_votes_controller.rb +++ b/app/controllers/open_conference_ware/selector_votes_controller.rb @@ -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!" diff --git a/app/helpers/open_conference_ware/proposals_helper.rb b/app/helpers/open_conference_ware/proposals_helper.rb index ea4ffe55..832ce42a 100644 --- a/app/helpers/open_conference_ware/proposals_helper.rb +++ b/app/helpers/open_conference_ware/proposals_helper.rb @@ -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 diff --git a/app/models/open_conference_ware/proposal.rb b/app/models/open_conference_ware/proposal.rb index 06658b1a..fd87089e 100644 --- a/app/models/open_conference_ware/proposal.rb +++ b/app/models/open_conference_ware/proposal.rb @@ -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 @@ -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 @@ -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 diff --git a/app/views/open_conference_ware/proposals/_list.html.erb b/app/views/open_conference_ware/proposals/_list.html.erb index 1ff3de02..cdfc006b 100644 --- a/app/views/open_conference_ware/proposals/_list.html.erb +++ b/app/views/open_conference_ware/proposals/_list.html.erb @@ -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? %> @@ -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 %> @@ -41,8 +42,8 @@ records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", p <% end %> <% previous_start_time = record.start_time %> - - + <% voted = selector? && @event.accept_selector_votes? && record.selector_votes.where(user_id: current_user.id).count > 0 %> +

<%= user_favorite_control_for record %> @@ -51,6 +52,9 @@ records = OpenConferenceWare::Proposal.sort(records, params[:sort] || "title", p <% else %> <%= link_to(h(record.presenter)+" — "+h(record.title), record_path(record, kind), :class => "title") %> <% end %> + <% if kind == :proposals && voted %> + (Voted) + <% end %> <% if kind == :proposals && proposal_statuses? && (admin? || (@event.proposal_status_published? && record.confirmed?)) %> (<%= record.status.titleize %>) <% end %> diff --git a/app/views/open_conference_ware/proposals/index.html.erb b/app/views/open_conference_ware/proposals/index.html.erb index 86fa6caf..d63ae4d1 100644 --- a/app/views/open_conference_ware/proposals/index.html.erb +++ b/app/views/open_conference_ware/proposals/index.html.erb @@ -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 %> diff --git a/lib/open_conference_ware/dependencies.rb b/lib/open_conference_ware/dependencies.rb index 4d8205c4..35aeb262 100644 --- a/lib/open_conference_ware/dependencies.rb +++ b/lib/open_conference_ware/dependencies.rb @@ -19,6 +19,7 @@ require 'prawn' require "dynamic_form" require 'rails_rinku' +require 'randumb' require 'jquery-rails' require 'sass-rails' diff --git a/open_conference_ware.gemspec b/open_conference_ware.gemspec index 1625bbf8..1e6bef7b 100644 --- a/open_conference_ware.gemspec +++ b/open_conference_ware.gemspec @@ -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' diff --git a/spec/helpers/open_conference_ware/proposals_helper_spec.rb b/spec/helpers/open_conference_ware/proposals_helper_spec.rb index b7143ecf..3203b958 100644 --- a/spec/helpers/open_conference_ware/proposals_helper_spec.rb +++ b/spec/helpers/open_conference_ware/proposals_helper_spec.rb @@ -3,6 +3,7 @@ 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) @@ -10,22 +11,26 @@ 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