diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb index fd03abc6..bb4590cf 100644 --- a/app/controllers/schedules_controller.rb +++ b/app/controllers/schedules_controller.rb @@ -12,10 +12,11 @@ class SchedulesController < ApplicationController includes: [{ event: %i[event_type speakers submitter] }] ) - unless event_schedules - redirect_to events_conference_schedule_path(@conference.short_title) - return - end + # The +schedule_public+ flag opts a conference into displaying a schedule, + # but the schedule itself only exists once an admin has selected a schedule + # and at least one event has been scheduled. Return 404 to avoid rendering + # a broken page (or crashing) when the schedule has not yet been published. + return not_found if event_schedules.empty? respond_to do |format| format.xml do diff --git a/app/models/program.rb b/app/models/program.rb index d90f5961..cba455b4 100644 --- a/app/models/program.rb +++ b/app/models/program.rb @@ -163,6 +163,23 @@ class Program < ApplicationRecord (!conference.email_settings.program_schedule_public_subject.blank? && !conference.email_settings.program_schedule_public_body.blank?) end + ## + # Checks if there is a published schedule that should be displayed. + # A schedule is displayable only when the admin has enabled the + # +schedule_public+ flag *and* there is at least one event scheduled, + # either on the conference-wide selected schedule or on the selected + # schedule of any confirmed self-organized track. + # + # ====Returns + # * +true+ -> When the schedule is public and contains at least one event + # * +false+ -> Otherwise + def any_published_schedule? + return false unless schedule_public + return true if selected_schedule&.event_schedules&.exists? + + tracks.self_organized.confirmed.any? { |track| track.selected_schedule&.event_schedules&.exists? } + end + def languages_list languages.split(',').map {|l| ISO_639.find(l).english_name} if languages.present? end diff --git a/app/views/conferences/_conference_details.html.haml b/app/views/conferences/_conference_details.html.haml index 571cca4a..6f1c84d2 100644 --- a/app/views/conferences/_conference_details.html.haml +++ b/app/views/conferences/_conference_details.html.haml @@ -24,7 +24,7 @@ - if !@conference || @conference != conference - if conference.splashpage && conference.splashpage.public = link_to "View Conference", conference_path(conference.short_title), class: 'btn btn-default' - - if conference.program and conference.program.schedule_public + - if conference.program&.any_published_schedule? = link_to "Schedule", conference_schedule_path(conference.short_title), class: 'btn btn-default' - if conference.code_of_conduct.present? = link_to "Code of Conduct", code_of_conduct_conference_path(conference.short_title), class: 'btn btn-default' diff --git a/app/views/conferences/_program.haml b/app/views/conferences/_program.haml index 2ab2ef70..db79f480 100644 --- a/app/views/conferences/_program.haml +++ b/app/views/conferences/_program.haml @@ -24,7 +24,7 @@ - unless booths.blank? = render 'booths', booths: booths - - if conference.program.try(:schedule_public?) + - if conference.program&.any_published_schedule? .row .col-md-12 %p.cta-button.text-center diff --git a/spec/controllers/schedules_controller_spec.rb b/spec/controllers/schedules_controller_spec.rb index 2a6613b2..3eed79d7 100644 --- a/spec/controllers/schedules_controller_spec.rb +++ b/spec/controllers/schedules_controller_spec.rb @@ -26,5 +26,17 @@ describe SchedulesController do expect(response).to be_successful end end + + context 'when schedule is public but no events are scheduled' do + before :each do + conference.program.update!(schedule_public: true) + end + + it 'returns 404 instead of rendering a broken page' do + expect do + get :show, params: { conference_id: conference.short_title } + end.to raise_error(ActionController::RoutingError) + end + end end end diff --git a/spec/models/program_spec.rb b/spec/models/program_spec.rb index 23c42ff1..b96a2311 100644 --- a/spec/models/program_spec.rb +++ b/spec/models/program_spec.rb @@ -283,6 +283,27 @@ describe Program do end end + describe '#any_published_schedule?' do + let(:event) { create(:event, program: program) } + let(:schedule) { create(:schedule, program: program) } + let!(:event_schedule) { create(:event_schedule, event: event, schedule: schedule, start_time: DateTime.parse("#{Date.current + 1} 10:00").utc) } + + it 'returns false when schedule_public is disabled' do + program.update!(schedule_public: false, selected_schedule: schedule) + expect(program.any_published_schedule?).to be false + end + + it 'returns false when schedule_public is enabled but no schedule is selected' do + program.update!(schedule_public: true, selected_schedule: nil) + expect(program.any_published_schedule?).to be false + end + + it 'returns true when schedule_public is enabled and the selected schedule has events' do + program.update!(schedule_public: true, selected_schedule: schedule) + expect(program.any_published_schedule?).to be true + end + end + describe '#cfp' do it 'returns the cfp for events' do create(:cfp, cfp_type: 'events', program: program, end_date: Date.current + 1)