diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 7aedd9c..eb52513 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -9,6 +9,7 @@ def index @withdrawn_proposals = Proposal.withdrawn.all @proposals = Proposal.active.order('created_at desc').all + @suggested_proposal = current_user.proposals_without_own_votes.active.sample || Proposal.active.sample if current_user respond_with @proposals end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 22e9e49..092a74e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -136,15 +136,18 @@ def authentication_links(container = :p) ['Facebook', '/auth/facebook']].map { |name, url| content_tag container, link_to(name, url) }.join("\n").html_safe end - def countdown_to_submissions_end - submissions_end = Phase::ONE.ending_at - if submissions_end > DateTime.now - content_tag :span, '', id: 'counter', data: {countdown_end: submissions_end.to_i * 1000} + def countdown_to(phase_end) + if phase_end > DateTime.now + content_tag :span, '', id: 'counter', data: {countdown_end: phase_end.to_i * 1000} else content_tag :span, 'no time' end end + def countdown_to_phase_end + countdown_to current_phase.ending_at + end + protected def markdown_parser(options = {}) @markdown_parser ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, diff --git a/app/models/phase.rb b/app/models/phase.rb index c107278..caefd8e 100644 --- a/app/models/phase.rb +++ b/app/models/phase.rb @@ -8,8 +8,19 @@ def self.all [ZERO, ONE, INTERLUDE, TWO, CONFIRMATION, LINEUP] end + def self.last_submission_date + ONE.ending_at + end + + def self.last_voting_date + INTERLUDE.ending_at + end + attr_accessor :name + attr_accessor :main_text + attr_accessor :countdown_text + attr_accessor :starting_at attr_accessor :ending_at @@ -30,6 +41,8 @@ def self.all ZERO = Phase.new.tap do |p| p.name = "Before the beginning" + p.main_text = "Be part of #{Settings.event_name}: we highly encourage you to submit as many proposals as you want, help the authors make theirs better and finally select the most interesting ones for the final agenda! What are you waiting for?" + p.countdown_text = "before the submissions open!" p.starting_at = DateTime.new(1970, 1, 1) p.ending_at = DateTime.parse('2013-03-28T00:00:00+2') @@ -42,6 +55,8 @@ def self.all ONE = Phase.new.tap do |p| p.name = "Phase 1: Submissions" + p.main_text = "Be part of #{Settings.event_name}: we highly encourage you to submit as many proposals as you want, help the authors make theirs better and finally select the most interesting ones for the final agenda! What are you waiting for?" + p.countdown_text = "to submit, refine and discuss proposals!" p.starting_at = DateTime.parse('2013-03-28T00:00:00+2') p.ending_at = DateTime.parse('2013-04-24T00:00:00+3') @@ -54,6 +69,8 @@ def self.all INTERLUDE = Phase.new.tap do |p| p.name = "Interlude" + p.main_text = "Make it your #{Settings.event_name}: select the finalists before the grand voting! We highly encourage you to go through every single proposal select the most interesting ones. After all, this is what the conference is all about! What are you waiting for?" + p.countdown_text = "to cast your votes that will define the finalists!" p.starting_at = DateTime.parse('2013-04-24T00:00:00+3') p.ending_at = DateTime.parse('2013-04-29T00:00:00+3') @@ -66,6 +83,8 @@ def self.all TWO = Phase.new.tap do |p| p.name = "Phase 2: Final voting" + p.main_text = "This is it! This is the time you define #{Settings.event_name}! Make your ideal lineup." + p.countdown_text = "to define the conference schedule!" p.starting_at = DateTime.parse('2013-04-29T00:00:00+3') p.ending_at = DateTime.parse('2013-05-06T00:00:00+3') @@ -78,6 +97,7 @@ def self.all CONFIRMATION = Phase.new.tap do |p| p.name = "Speakers confirmation" + p.main_text = "" p.starting_at = DateTime.parse('2013-05-06T00:00:00+3') p.ending_at = DateTime.parse('2013-05-09T00:00:00+3') @@ -90,6 +110,7 @@ def self.all LINEUP = Phase.new.tap do |p| p.name = "Lineup announcement" + p.main_text = "" p.starting_at = DateTime.parse('2013-05-09T00:00:00+3') p.ending_at = DateTime.parse('2100-01-01T00:00:00+2') diff --git a/app/views/dashboard/index.html.erb b/app/views/dashboard/index.html.erb index be81fd4..cb887a1 100644 --- a/app/views/dashboard/index.html.erb +++ b/app/views/dashboard/index.html.erb @@ -9,7 +9,7 @@

Your proposals

- You have still <%= countdown_to_submissions_end %> to submit or edit a proposal! + You have still <%= countdown_to Phase.last_submission_date %> to submit or edit a proposal! Since proposals are anonymised, other users will not see that you are the author of these. <%= link_to "Read more about the process", about_path %>.
diff --git a/app/views/proposals/index.html.erb b/app/views/proposals/index.html.erb index 5450913..e0b86b6 100644 --- a/app/views/proposals/index.html.erb +++ b/app/views/proposals/index.html.erb @@ -1,21 +1,21 @@
<%= page_title "#{Settings.event_name} Call for Presentations" %> -

- Be part of <%= Settings.event_name %>: - we highly encourage you to submit as many proposals as you want, - help the authors make theirs better - and finally select the most interesting ones for the final agenda! - What are you waiting for? -

+ <% if current_phase.main_text %> +

<%= current_phase.main_text.html_safe %>

+ <% end %> -

- You have <%= countdown_to_submissions_end %> to submit, refine and discuss proposals! -

+ <% if current_phase.countdown_text %> +

You have <%= countdown_to_phase_end %> <%= current_phase.countdown_text %>

+ <% end %>

<% if user_signed_in? %> - <%= link_to "Propose a talk", new_proposal_path, :class => 'btn btn-primary' %> + <% if can? :create, Proposal %> + <%= link_to "Propose a talk", new_proposal_path, :class => 'btn btn-primary' %> + <% elsif @suggested_proposal && can?(:vote, @suggested_proposal) %> + <%= link_to "Cast your votes!", proposal_path(@suggested_proposal), :class => 'btn btn-primary' %> + <% end %> <% else %>

<%= link_to 'Join the party', '#', :class => 'btn btn-primary dropdown-toggle', :data => {:toggle => 'dropdown'} %> diff --git a/test/integration/proposal_test.rb b/test/integration/proposal_test.rb index afcdd78..6e22f02 100644 --- a/test/integration/proposal_test.rb +++ b/test/integration/proposal_test.rb @@ -10,7 +10,12 @@ class ProposalTest < IntegrationTestCase context "As a visitor to the site" do should "not see a link to propose a talk" do visit proposals_path - assert !page.has_content?("Propose talk"), "link to propose talk should not be present!" + assert !page.has_content?("Propose a talk"), "link to propose talk should not be present!" + end + + should "not see a link to vote for a talk" do + visit proposals_path + assert !page.has_content?("Cast your votes!"), "link to vote talks should not be present!" end should "not be able to propose a talk" do @@ -67,6 +72,16 @@ class ProposalTest < IntegrationTestCase sign_in @user end + should "see a link to propose a talk" do + visit proposals_path + assert page.has_content?("Propose a talk"), "link to propose talk should be present!" + end + + should "not see a link to vote for a talk" do + visit proposals_path + assert !page.has_content?("Cast your votes!"), "link to vote talks should not be present!" + end + context "and I propose a talk with all the required details" do setup { propose_talk :title => "My Amazing Talk", :description => 'This talk is amazing.' } @@ -220,6 +235,132 @@ class ProposalTest < IntegrationTestCase end end + [Phase::INTERLUDE].each do |phase| + context "During '#{phase.name}'" do + setup do + Phase.stubs(:current).returns(phase) + end + + context "As a visitor to the site" do + should "not see a link to propose a talk" do + visit proposals_path + assert !page.has_content?("Propose a talk"), "link to propose talk should not be present!" + end + + should "not see a link to vote for a talk" do + visit proposals_path + assert !page.has_content?("Cast your votes!"), "link to vote talks should not be present!" + end + + should "not be able to propose a talk" do + visit new_proposal_path + i_am_asked_to_sign_in + end + + context "given a proposal already exists" do + setup do + @proposal = FactoryGirl.create(:proposal, :title => "Ruby Muby Schmuby") + end + + should "be able to see the list of proposals" do + visit proposals_path + assert page.has_css?('ul.proposals') + end + + should "be able to subscribe to the rss feed of proposals" do + visit proposals_path + assert page.has_css?("link[rel='alternate'][type='application/rss+xml'][href$='#{proposals_path(:format => :rss)}']") + visit proposals_path(:format => :rss) + assert_match %r{application/rss\+xml}, page.response_headers['Content-Type'] + assert page.has_xpath?('.//item/title', :text => @proposal.title) + end + + should "be able to read individual proposals" do + visit proposals_path + click_link "Ruby Muby Schmuby" + assert_page_has_proposal :title => "Ruby Muby Schmuby" + end + + should "not see a link to edit a proposal" do + visit proposals_path + click_link "Ruby Muby Schmuby" + assert !page.has_content?("Edit proposal"), "link to edit proposal should not be present" + end + + should "not be able to edit a proposal" do + visit edit_proposal_path(@proposal) + i_am_asked_to_sign_in + end + + should "my page view be tracked" do + assert_difference(lambda { @proposal.impressionist_count }, 1) do + visit proposal_path(@proposal) + end + end + end + end + + context "Given I am logged in" do + setup do + @user = FactoryGirl.create(:user) + sign_in @user + end + + should "not see a link to propose a talk" do + visit proposals_path + assert !page.has_content?("Propose a talk"), "link to propose talk should not be present!" + end + + context "given a proposal already exists" do + setup do + @proposal = FactoryGirl.create(:proposal, :title => "Ruby Muby Schmuby") + end + + should "see a link to vote for a talk" do + visit proposals_path + assert page.has_content?("Cast your votes!"), "link to vote talks should be present!" + end + + should "be able to see the list of proposals" do + visit proposals_path + assert page.has_css?('ul.proposals') + end + + should "be able to subscribe to the rss feed of proposals" do + visit proposals_path + assert page.has_css?("link[rel='alternate'][type='application/rss+xml'][href$='#{proposals_path(:format => :rss)}']") + visit proposals_path(:format => :rss) + assert_match %r{application/rss\+xml}, page.response_headers['Content-Type'] + assert page.has_xpath?('.//item/title', :text => @proposal.title) + end + + should "be able to read individual proposals" do + visit proposals_path + click_link "Ruby Muby Schmuby" + assert_page_has_proposal :title => "Ruby Muby Schmuby" + end + + should "not see a link to edit a proposal" do + visit proposals_path + click_link "Ruby Muby Schmuby" + assert !page.has_content?("Edit proposal"), "link to edit proposal should not be present" + end + + should "not be able to edit a proposal" do + visit edit_proposal_path(@proposal) + i_am_not_authorized + end + + should "my page view be tracked" do + assert_difference(lambda { @proposal.impressionist_count }, 1) do + visit proposal_path(@proposal) + end + end + end + end + end + end + [Phase.all - [Phase::ONE, Phase::INTERLUDE]].flatten.each do |phase| context "During '#{phase.name}'" do setup do @@ -229,7 +370,7 @@ class ProposalTest < IntegrationTestCase context "As a visitor to the site" do should "not see a link to propose a talk" do visit proposals_path - assert !page.has_content?("Propose talk"), "link to propose talk should not be present!" + assert !page.has_content?("Propose a talk"), "link to propose talk should not be present!" end should "not be able to propose a talk" do @@ -288,7 +429,7 @@ class ProposalTest < IntegrationTestCase should "not see a link to propose a talk" do visit proposals_path - assert !page.has_content?("Propose talk"), "link to propose talk should not be present!" + assert !page.has_content?("Propose a talk"), "link to propose talk should not be present!" end should "not be able to propose a talk" do