This commit is contained in:
Henne Vogelsang 2026-06-27 18:17:28 +02:00 committed by GitHub
commit 80f09ff250
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 128 additions and 74 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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