diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 400f5949..b549ee3b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -535,7 +535,9 @@ Metrics/AbcSize: # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. # AllowedMethods: refine Metrics/BlockLength: - Max: 202 + Exclude: + - 'config/routes.rb' + Max: 100 # Offense count: 1 # Configuration parameters: CountBlocks, CountModifierForms. @@ -1435,7 +1437,7 @@ Rails/RedundantPresenceValidationOnBelongsTo: # Offense count: 2 Rails/RenderInline: Exclude: - - 'app/controllers/conferences_controller.rb' + - 'app/controllers/calendars_controller.rb' - 'app/controllers/schedules_controller.rb' # Offense count: 10 diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb new file mode 100644 index 00000000..b5056147 --- /dev/null +++ b/app/controllers/calendars_controller.rb @@ -0,0 +1,88 @@ +class CalendarsController < ApplicationController + skip_authorization_check only: :index + + # GET /calendars + def index + calendar = Icalendar::Calendar.new + + Conference.all.each do |conference| + if params[:full] + event_schedules = conference.program.selected_event_schedules( + includes: [{ event: %i[event_type speakers submitter] }] + ) + calendar = build_icalendar_from_proposals(calendar, event_schedules.map(&:event), conference) + else + calendar = build_icalender_from_conference(calendar, conference) + end + end + + respond_to do |format| + format.ics do + calendar.publish + render inline: calendar.to_ical + end + end + end + + private + + def build_icalender_from_conference(calendar, conference) + calendar.event do |event| + event.dtstart = conference.start_date + event.dtstart.ical_params = { 'VALUE'=>'DATE' } + event.dtend = conference.end_date + event.dtend.ical_params = { 'VALUE'=>'DATE' } + event.duration = "P#{(conference.end_date - conference.start_date + 1).floor}D" + event.created = conference.created_at + event.last_modified = conference.updated_at + event.summary = conference.title + event.description = conference.description + event.uid = conference.guid + event.url = conference_url(conference.short_title) + + venue = conference.venue + if venue + event.geo = venue.latitude, venue.longitude if venue.latitude && venue.longitude + + location = '' + location += "#{venue.street}, " if venue.street + location += "#{venue.postalcode} #{venue.city}, " if venue.postalcode && venue.city + location += venue.country_name if venue.country_name + event.location = location if location + end + end + calendar + end + + # adds events to icalendar for proposals in a conference + def build_icalendar_from_proposals(calendar, proposals, conference) + proposals.each do |proposal| + calendar.event do |event| + event.dtstart = proposal.time + event.dtend = proposal.time + (proposal.event_type.length * 60) + event.duration = "PT#{proposal.event_type.length}M" + event.created = proposal.created_at + event.last_modified = proposal.updated_at + event.summary = proposal.title + event.description = proposal.abstract + event.uid = proposal.guid + event.url = conference_program_proposal_url(conference.short_title, proposal.id) + venue = conference.venue + if venue + event.geo = venue.latitude, venue.longitude if venue.latitude && venue.longitude + + location = '' + location += "#{proposal.room.name} - " if proposal.room.name + location += " - #{venue.street}, " if venue.street + location += "#{venue.postalcode} #{venue.city}, " if venue.postalcode && venue.city + location += "#{venue.country_name}, " if venue.country_name + event.location = location + end + if proposal.difficulty_level && proposal.track + event.categories = proposal.title, "Difficulty: #{proposal.difficulty_level.title}", "Track: #{proposal.track.name}" + end + end + end + calendar + end +end diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 43809551..f7ec17d4 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -67,47 +67,6 @@ class ConferencesController < ApplicationController end end - def calendar - respond_to do |format| - format.ics do - calendar = Icalendar::Calendar.new - Conference.all.each do |conf| - if params[:full] - event_schedules = conf.program.selected_event_schedules( - includes: [{ event: %i[event_type speakers submitter] }] - ) - calendar = icalendar_proposals(calendar, event_schedules.map(&:event), conf) - else - calendar.event do |e| - e.dtstart = conf.start_date - e.dtstart.ical_params = { 'VALUE'=>'DATE' } - e.dtend = conf.end_date - e.dtend.ical_params = { 'VALUE'=>'DATE' } - e.duration = "P#{(conf.end_date - conf.start_date + 1).floor}D" - e.created = conf.created_at - e.last_modified = conf.updated_at - e.summary = conf.title - e.description = conf.description - e.uid = conf.guid - e.url = conference_url(conf.short_title) - v = conf.venue - if v - e.geo = v.latitude, v.longitude if v.latitude && v.longitude - location = '' - location += "#{v.street}, " if v.street - location += "#{v.postalcode} #{v.city}, " if v.postalcode && v.city - location += v.country_name if v.country_name - e.location = location if location - end - end - end - end - calendar.publish - render inline: calendar.to_ical - end - end - end - def code_of_conduct; end private diff --git a/app/helpers/conference_helper.rb b/app/helpers/conference_helper.rb index f685ed89..a48bed54 100644 --- a/app/helpers/conference_helper.rb +++ b/app/helpers/conference_helper.rb @@ -21,33 +21,4 @@ module ConferenceHelper '%20Sponsorship' ].join end - - # adds events to icalendar for proposals in a conference - def icalendar_proposals(calendar, proposals, conference) - proposals.each do |proposal| - calendar.event do |e| - e.dtstart = proposal.time - e.dtend = proposal.time + proposal.event_type.length * 60 - e.duration = "PT#{proposal.event_type.length}M" - e.created = proposal.created_at - e.last_modified = proposal.updated_at - e.summary = proposal.title - e.description = proposal.abstract - e.uid = proposal.guid - e.url = conference_program_proposal_url(conference.short_title, proposal.id) - v = conference.venue - if v - e.geo = v.latitude, v.longitude if v.latitude && v.longitude - location = '' - location += "#{proposal.room.name} - " if proposal.room.name - location += " - #{v.street}, " if v.street - location += "#{v.postalcode} #{v.city}, " if v.postalcode && v.city - location += "#{v.country_name}, " if v.country_name - e.location = location - end - e.categories = conference.title, "Difficulty: #{proposal.difficulty_level.title}", "Track: #{proposal.track.name}" - end - end - calendar - end end diff --git a/app/views/conferences/index.html.haml b/app/views/conferences/index.html.haml index 720e1cdf..a6719d22 100644 --- a/app/views/conferences/index.html.haml +++ b/app/views/conferences/index.html.haml @@ -21,8 +21,8 @@ %p Add the events to your calendar: %span.btn-group - = link_to("Days only", calendar_url(protocol: 'webcal', format: 'ics'), class: 'btn btn-default') - = link_to("Detailed", calendar_url(protocol: 'webcal', format: 'ics', full: true), class: 'btn btn-default') + = link_to("Days only", calendars_url(protocol: 'webcal', format: 'ics'), class: 'btn btn-default') + = link_to("Detailed", calendars_url(protocol: 'webcal', format: 'ics', full: true), class: 'btn btn-default') -content_for :script_body do :javascript diff --git a/config/routes.rb b/config/routes.rb index 730d43cf..ca4d4072 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -198,6 +198,8 @@ Osem::Application.routes.draw do end end + resources :calendars, only: :index + namespace :api, defaults: {format: 'json'} do namespace :v1 do resources :conferences, only: [ :index, :show ] do diff --git a/spec/controllers/calendars_controller_spec.rb b/spec/controllers/calendars_controller_spec.rb new file mode 100644 index 00000000..c4553705 --- /dev/null +++ b/spec/controllers/calendars_controller_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe CalendarsController do + render_views + + let!(:conference) { create(:conference, splashpage: create(:splashpage, public: true), venue: create(:venue)) } + let!(:events) { create_list(:event_scheduled, 2, program: conference.program) } + + describe 'GET #index' do + before :each do + conference.program.update(schedule_public: true) + get :index, format: :ics + end + + it 'renders a calendar from conference' do + expect(response.body).to match(/#{conference.title}/im) + end + end + + describe 'GET #index with full format' do + before :each do + conference.program.update(schedule_public: true) + get :index, format: :ics, params: { full: 1 } + end + + it 'renders a calendar from events' do + expect(response.body).to match(/#{events.first.title}/im) + end + end +end