diff --git a/ruby/lib/jam_ruby/models/rsvp_request.rb b/ruby/lib/jam_ruby/models/rsvp_request.rb index 0b6a94e85..58cbe9ec7 100644 --- a/ruby/lib/jam_ruby/models/rsvp_request.rb +++ b/ruby/lib/jam_ruby/models/rsvp_request.rb @@ -154,7 +154,7 @@ module JamRuby raise StateError, "Slot does not exist" end - if rsvp_slot.chosen + if rsvp_slot.chosen && r[:accept] raise StateError, "The #{rsvp_slot.instrument_id} slot has already been approved for another user." end diff --git a/web/app/assets/javascripts/web/session_info.js b/web/app/assets/javascripts/web/session_info.js index ec86025cc..004fc8b23 100644 --- a/web/app/assets/javascripts/web/session_info.js +++ b/web/app/assets/javascripts/web/session_info.js @@ -83,18 +83,33 @@ rest.getRsvpRequests(musicSessionId) .done(function(rsvps) { if (rsvps && rsvps.length > 0) { - // should only be 1 RSVP for this session + // should only be 1 RSVP for this session and user var rsvp = rsvps[0]; if (rsvp.canceled) { $('.call-to-action').html('Your RSVP request to this session has been cancelled.'); $btnAction.hide(); } else { - $('.call-to-action').html('Tell the session organizer if you can no longer join this session'); - $btnAction.html('CANCEL RSVP'); - $btnAction.click(function(e) { - ui.launchRsvpCancelDialog(musicSessionId, rsvp.id); - }); + var declined = true; + if (rsvp.rsvp_requests_rsvp_slots) { + for (var x=0; x < rsvp.rsvp_requests_rsvp_slots.length; x++) { + if (rsvp.rsvp_requests_rsvp_slots[x].chosen) { + declined = false; + } + } + } + + if (declined) { + $('.call-to-action').html('Your RSVP request to this session has been declined.'); + $btnAction.hide(); + } + else { + $('.call-to-action').html('Tell the session organizer if you can no longer join this session'); + $btnAction.html('CANCEL RSVP'); + $btnAction.click(function(e) { + ui.launchRsvpCancelDialog(musicSessionId, rsvp.id); + }); + } } } // no RSVP diff --git a/web/app/views/api_rsvp_requests/show.rabl b/web/app/views/api_rsvp_requests/show.rabl index 0f113d7f7..8e9760e34 100644 --- a/web/app/views/api_rsvp_requests/show.rabl +++ b/web/app/views/api_rsvp_requests/show.rabl @@ -1,15 +1,15 @@ object @rsvp_request -attributes :id, :canceled, :created_at +attributes :id, :canceled, :cancel_all, :created_at child(:user => :user) { attributes :id, :name, :photo_url } -child(:rsvp_slots => :rsvp_slots) { - attributes :id, :instrument_id, :proficiency_level, :music_session_id +child(:rsvp_requests_rsvp_slots => :rsvp_requests_rsvp_slots) { + attributes :id, :chosen - child(:rsvp_requests_rsvp_slots => :rsvp_requests_rsvp_slots) { - attributes :id, :chosen + child(:rsvp_slot => :rsvp_slot) { + attributes :id, :instrument_id, :proficiency_level, :music_session_id } } \ No newline at end of file diff --git a/web/spec/features/session_info_spec.rb b/web/spec/features/session_info_spec.rb index 61159af6a..ad5e9f717 100644 --- a/web/spec/features/session_info_spec.rb +++ b/web/spec/features/session_info_spec.rb @@ -12,8 +12,11 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr MusicSession.delete_all User.delete_all - @rsvp_user = FactoryGirl.create(:user) - @rsvp_user.save + @rsvp_approved_user = FactoryGirl.create(:user) + @rsvp_approved_user.save + + @rsvp_declined_user = FactoryGirl.create(:user) + @rsvp_declined_user.save @session_invitee = FactoryGirl.create(:user) @session_invitee.save @@ -28,12 +31,17 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr FactoryGirl.create(:friendship, :user => @session_invitee, :friend => @session_creator) FactoryGirl.create(:friendship, :user => @session_creator, :friend => @session_invitee) - FactoryGirl.create(:friendship, :user => @rsvp_user, :friend => @session_creator) - FactoryGirl.create(:friendship, :user => @session_creator, :friend => @rsvp_user) + FactoryGirl.create(:friendship, :user => @rsvp_approved_user, :friend => @session_creator) + FactoryGirl.create(:friendship, :user => @session_creator, :friend => @rsvp_approved_user) + + FactoryGirl.create(:friendship, :user => @rsvp_declined_user, :friend => @session_creator) + FactoryGirl.create(:friendship, :user => @session_creator, :friend => @rsvp_declined_user) @music_session = FactoryGirl.build(:music_session, :creator => @session_creator) @music_session.save + @url = "/sessions/#{@music_session.id}/details" + @slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('electric guitar')) @slot1.save @@ -43,17 +51,27 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr @invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @session_invitee, :music_session => @music_session) @invitation.save - @invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @rsvp_user, :music_session => @music_session) + @invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @rsvp_approved_user, :music_session => @music_session) @invitation.save - # create RSVP request - rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @rsvp_user) + @invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @rsvp_declined_user, :music_session => @music_session) + @invitation.save + + # create RSVP request 1 + @rsvp1 = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @rsvp_approved_user) + + # create RSVP request 2 + @rsvp2 = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @rsvp_declined_user) # approve slot1 - rs1 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot1.id) - rs2 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot2.id) - RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => false}]}, @session_creator) + rs1 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(@rsvp1.id, @slot1.id) + rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(@rsvp1.id, @slot2.id) + RsvpRequest.update({:id => @rsvp1.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => false}]}, @session_creator) + # reject slot1 and slot2 + rs1 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(@rsvp2.id, @slot1.id) + rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(@rsvp2.id, @slot2.id) + RsvpRequest.update({:id => @rsvp2.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => false}, {:request_slot_id => rs2.id, :accept => false}]}, @session_creator) end def ensure_success(options = {}) @@ -64,7 +82,11 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr find('div.creator-name', text: @session_creator.name) # action button - find('#btn-action') if options[:show_cta] + if options[:show_cta] + find('#btn-action', :text => options[:button_text]) + else + expect {find('#btn-action')}.to raise_error(Capybara::ElementNotFound) + end # session details find('div.scheduled_start') @@ -78,13 +100,13 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr # right sidebar - RSVPs find('div.rsvp-details .avatar-tiny') - find('div.rsvp-details .rsvp-name', text: @rsvp_user.name) + find('div.rsvp-details .rsvp-name', text: @rsvp_approved_user.name) find('div.rsvp-details img.instrument-icon') # right sidebar - Still Needed find('div.still-needed', text: @slot2.instrument.id.capitalize) - # right sidebar - Invited + # right sidebar - Pending Invitations find('div[user-id="' + @session_invitee.id + '"]') # comments @@ -103,30 +125,34 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr @music_session.save # attempt to access with musician who was invited but didn't RSVP - sign_in_poltergeist(@session_invitee) - url = "/sessions/#{@music_session.id}/details" - visit url - ensure_success({:show_cta => true}) + sign_in_poltergeist(@session_invitee) + visit @url + ensure_success({:show_cta => true, :button_text => 'RSVP NOW!'}) sign_out_poltergeist - # attempt to access with musician who wasn't invited sign_in_poltergeist(@non_session_invitee) - + visit @url + ensure_success({:show_cta => true, :button_text => 'RSVP NOW!'}) sign_out_poltergeist + # attempt to access with musician who RSVP'ed but wasn't approved + sign_in_poltergeist(@rsvp_declined_user) + visit @url + ensure_success({:show_cta => false}) + sign_out_poltergeist + + # attempt to access with musician who RSVP'ed and was approved + sign_in_poltergeist(@rsvp_approved_user) + visit @url + ensure_success({:show_cta => true, :button_text => 'CANCEL RSVP'}) + sign_out_poltergeist # attempt to access with session creator sign_in_poltergeist(@session_creator) - + visit @url + ensure_success({:show_cta => false}) sign_out_poltergeist - - - - # attempt to access with musician who RSVP'ed but wasn't approved - - - # attempt to access with musician who RSVP'ed and was approved end it "should render only for session invitees for sessions with closed RSVPs before session starts" do @@ -184,45 +210,13 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr # attempt to access with musician who RSVP'ed and was approved end - it "should render all required information" do - # access with a user who was invited but hasn't RSVPed yet - - - # session creator - - # date/time - - # genre - - # name - - # description - - # notation files - - # language - - # access - - # legal info - - # view comments - - - # sidebar - Approved RSVPs - - # sidebar - Open Slots - - # sidebar - Pending Invitations - end - it "should allow only RSVP approvals or session invitees to add comments" do end it "should show no call to action button if user has not RSVPed and all slots are taken" do end - it "should show no call to action button if the session organizer is viewing" do + it "should show no call to action button for session organizer" do end end