spina-admin-conferences 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +101 -0
- data/Rakefile +40 -0
- data/app/assets/config/spina_admin_conferences_manifest.js +4 -0
- data/app/assets/javascripts/spina/admin/conferences/application.es6 +20 -0
- data/app/assets/javascripts/spina/admin/conferences/controllers/conference_events_form_controller.es6 +175 -0
- data/app/assets/javascripts/spina/admin/conferences/controllers/presentation_attachments_form_controller.es6 +175 -0
- data/app/assets/javascripts/spina/admin/conferences/controllers/select_options_controller.es6 +216 -0
- data/app/assets/stylesheets/spina/admin/conferences/application.sass +14 -0
- data/app/controllers/spina/admin/conferences/application_controller.rb +20 -0
- data/app/controllers/spina/admin/conferences/conferences_controller.rb +148 -0
- data/app/controllers/spina/admin/conferences/delegates_controller.rb +116 -0
- data/app/controllers/spina/admin/conferences/dietary_requirements_controller.rb +106 -0
- data/app/controllers/spina/admin/conferences/events_controller.rb +24 -0
- data/app/controllers/spina/admin/conferences/institutions_controller.rb +106 -0
- data/app/controllers/spina/admin/conferences/presentation_attachment_types_controller.rb +104 -0
- data/app/controllers/spina/admin/conferences/presentation_attachments_controller.rb +24 -0
- data/app/controllers/spina/admin/conferences/presentation_types_controller.rb +109 -0
- data/app/controllers/spina/admin/conferences/presentations_controller.rb +124 -0
- data/app/controllers/spina/admin/conferences/rooms_controller.rb +109 -0
- data/app/controllers/spina/admin/conferences/sessions_controller.rb +118 -0
- data/app/helpers/spina/admin/conferences/conferences_helper.rb +44 -0
- data/app/jobs/spina/admin/conferences/application_job.rb +11 -0
- data/app/jobs/spina/admin/conferences/delegate_import_job.rb +37 -0
- data/app/jobs/spina/admin/conferences/import_job.rb +26 -0
- data/app/jobs/spina/admin/conferences/presentation_import_job.rb +38 -0
- data/app/mailers/spina/admin/conferences/application_mailer.rb +13 -0
- data/app/models/spina/admin/conferences.rb +11 -0
- data/app/models/spina/admin/conferences/application_record.rb +14 -0
- data/app/models/spina/admin/conferences/conference.rb +152 -0
- data/app/models/spina/admin/conferences/date_part.rb +15 -0
- data/app/models/spina/admin/conferences/delegate.rb +89 -0
- data/app/models/spina/admin/conferences/dietary_requirement.rb +33 -0
- data/app/models/spina/admin/conferences/email_address_part.rb +21 -0
- data/app/models/spina/admin/conferences/event.rb +120 -0
- data/app/models/spina/admin/conferences/institution.rb +46 -0
- data/app/models/spina/admin/conferences/part.rb +20 -0
- data/app/models/spina/admin/conferences/presentation.rb +143 -0
- data/app/models/spina/admin/conferences/presentation_attachment.rb +27 -0
- data/app/models/spina/admin/conferences/presentation_attachment_type.rb +35 -0
- data/app/models/spina/admin/conferences/presentation_type.rb +60 -0
- data/app/models/spina/admin/conferences/room.rb +52 -0
- data/app/models/spina/admin/conferences/session.rb +56 -0
- data/app/models/spina/admin/conferences/time_part.rb +53 -0
- data/app/models/spina/admin/conferences/url_part.rb +21 -0
- data/app/validators/spina/admin/conferences/conference_date_validator.rb +20 -0
- data/app/validators/spina/admin/conferences/email_address_validator.rb +28 -0
- data/app/validators/spina/admin/conferences/finish_date_validator.rb +20 -0
- data/app/validators/spina/admin/conferences/finish_time_validator.rb +20 -0
- data/app/validators/spina/admin/conferences/http_url_validator.rb +28 -0
- data/app/views/layouts/spina/admin/conferences/conferences.html.haml +19 -0
- data/app/views/layouts/spina/admin/conferences/delegates.html.haml +10 -0
- data/app/views/layouts/spina/admin/conferences/dietary_requirements.html.haml +10 -0
- data/app/views/layouts/spina/admin/conferences/institutions.html.haml +17 -0
- data/app/views/layouts/spina/admin/conferences/presentation_attachment_types.html.haml +10 -0
- data/app/views/layouts/spina/admin/conferences/presentations.html.haml +10 -0
- data/app/views/spina/admin/conferences/application/_empty_list.html.haml +3 -0
- data/app/views/spina/admin/conferences/application/_errors.html.haml +11 -0
- data/app/views/spina/admin/conferences/application/_errors.js.erb +2 -0
- data/app/views/spina/admin/conferences/conferences/_conference.html.haml +9 -0
- data/app/views/spina/admin/conferences/conferences/_event_fields.html.haml +39 -0
- data/app/views/spina/admin/conferences/conferences/_event_row.html.haml +5 -0
- data/app/views/spina/admin/conferences/conferences/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/conferences/_form_conference_details.html.haml +29 -0
- data/app/views/spina/admin/conferences/conferences/_form_delegates.html.haml +12 -0
- data/app/views/spina/admin/conferences/conferences/_form_parts.html.haml +15 -0
- data/app/views/spina/admin/conferences/conferences/_form_presentation_types.html.haml +12 -0
- data/app/views/spina/admin/conferences/conferences/_form_presentations.html.haml +12 -0
- data/app/views/spina/admin/conferences/conferences/_form_rooms.html.haml +12 -0
- data/app/views/spina/admin/conferences/conferences/_form_structure.html.haml +19 -0
- data/app/views/spina/admin/conferences/conferences/_form_structure_item.html.haml +13 -0
- data/app/views/spina/admin/conferences/conferences/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/conferences/index.html.haml +18 -0
- data/app/views/spina/admin/conferences/conferences/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/delegates/_delegate.html.haml +13 -0
- data/app/views/spina/admin/conferences/delegates/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/delegates/_form_conferences.html.haml +14 -0
- data/app/views/spina/admin/conferences/delegates/_form_delegate_details.html.haml +38 -0
- data/app/views/spina/admin/conferences/delegates/_form_presentations.html.haml +12 -0
- data/app/views/spina/admin/conferences/delegates/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/delegates/index.html.haml +23 -0
- data/app/views/spina/admin/conferences/delegates/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/dietary_requirements/_dietary_requirement.html.haml +6 -0
- data/app/views/spina/admin/conferences/dietary_requirements/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/dietary_requirements/_form_delegates.html.haml +12 -0
- data/app/views/spina/admin/conferences/dietary_requirements/_form_dietary_requirement_details.html.haml +9 -0
- data/app/views/spina/admin/conferences/dietary_requirements/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/dietary_requirements/index.html.haml +15 -0
- data/app/views/spina/admin/conferences/dietary_requirements/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/events/new.js.erb +27 -0
- data/app/views/spina/admin/conferences/institutions/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/institutions/_form_delegates.html.haml +12 -0
- data/app/views/spina/admin/conferences/institutions/_form_institution_details.html.haml +35 -0
- data/app/views/spina/admin/conferences/institutions/_form_rooms.html.haml +12 -0
- data/app/views/spina/admin/conferences/institutions/_institution.html.haml +7 -0
- data/app/views/spina/admin/conferences/institutions/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/institutions/index.html.haml +16 -0
- data/app/views/spina/admin/conferences/institutions/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentation_attachment_types/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/presentation_attachment_types/_presentation_attachment_type.html.haml +6 -0
- data/app/views/spina/admin/conferences/presentation_attachment_types/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentation_attachment_types/index.html.haml +15 -0
- data/app/views/spina/admin/conferences/presentation_attachment_types/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentation_attachments/new.js.erb +21 -0
- data/app/views/spina/admin/conferences/presentation_types/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/presentation_types/_form_presentation_type_details.html.haml +20 -0
- data/app/views/spina/admin/conferences/presentation_types/_form_presentations.html.haml +12 -0
- data/app/views/spina/admin/conferences/presentation_types/_form_sessions.html.haml +12 -0
- data/app/views/spina/admin/conferences/presentation_types/_presentation_type.html.haml +8 -0
- data/app/views/spina/admin/conferences/presentation_types/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentation_types/index.html.haml +17 -0
- data/app/views/spina/admin/conferences/presentation_types/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentations/_attachment_fields.html.haml +27 -0
- data/app/views/spina/admin/conferences/presentations/_attachment_row.html.haml +2 -0
- data/app/views/spina/admin/conferences/presentations/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/presentations/_form_presentation_details.html.haml +55 -0
- data/app/views/spina/admin/conferences/presentations/_form_presenters.html.haml +12 -0
- data/app/views/spina/admin/conferences/presentations/_presentation.html.haml +11 -0
- data/app/views/spina/admin/conferences/presentations/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/presentations/index.html.haml +23 -0
- data/app/views/spina/admin/conferences/presentations/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/rooms/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/rooms/_form_presentations.html.haml +12 -0
- data/app/views/spina/admin/conferences/rooms/_form_room_details.html.haml +18 -0
- data/app/views/spina/admin/conferences/rooms/_room.html.haml +8 -0
- data/app/views/spina/admin/conferences/rooms/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/rooms/index.html.haml +17 -0
- data/app/views/spina/admin/conferences/rooms/new.html.haml +1 -0
- data/app/views/spina/admin/conferences/sessions/_form.html.haml +23 -0
- data/app/views/spina/admin/conferences/sessions/_form_presentations.html.haml +12 -0
- data/app/views/spina/admin/conferences/sessions/_form_session_details.html.haml +23 -0
- data/app/views/spina/admin/conferences/sessions/_session.html.haml +8 -0
- data/app/views/spina/admin/conferences/sessions/edit.html.haml +1 -0
- data/app/views/spina/admin/conferences/sessions/index.html.haml +17 -0
- data/app/views/spina/admin/conferences/sessions/new.html.haml +1 -0
- data/app/views/spina/admin/hooks/conferences/_head.html.haml +2 -0
- data/app/views/spina/admin/hooks/conferences/_primary_navigation.html.haml +20 -0
- data/app/views/spina/admin/hooks/conferences/_settings_secondary_navigation.html.haml +4 -0
- data/app/views/spina/admin/partables/admin/conferences/date_parts/_form.html.haml +5 -0
- data/app/views/spina/admin/partables/admin/conferences/email_address_parts/_form.html.haml +5 -0
- data/app/views/spina/admin/partables/admin/conferences/time_parts/_form.html.haml +7 -0
- data/app/views/spina/admin/partables/admin/conferences/url_parts/_form.html.haml +5 -0
- data/config/initializers/assets.rb +13 -0
- data/config/initializers/types.rb +13 -0
- data/config/locales/en.yml +354 -0
- data/config/routes.rb +27 -0
- data/db/migrate/20180907141228_create_spina_dates.rb +11 -0
- data/db/migrate/20180907141229_create_spina_email_addresses.rb +11 -0
- data/db/migrate/20180907141230_create_spina_urls.rb +11 -0
- data/db/migrate/20180907141231_create_spina_conferences_institutions.rb +12 -0
- data/db/migrate/20180907141232_create_spina_conferences_delegates.rb +15 -0
- data/db/migrate/20180907141234_create_spina_conferences_dietary_requirements.rb +11 -0
- data/db/migrate/20180907141235_create_spina_conferences_conferences.rb +12 -0
- data/db/migrate/20180907141236_create_spina_conferences_presentation_types.rb +13 -0
- data/db/migrate/20180907141238_create_join_table_spina_conferences_conference_delegate.rb +7 -0
- data/db/migrate/20180907141239_create_join_table_spina_conferences_delegate_presentation.rb +7 -0
- data/db/migrate/20180907141240_create_join_table_spina_conferences_delegate_dietary_requirement.rb +7 -0
- data/db/migrate/20180907141242_add_type_to_spina_pages.rb +7 -0
- data/db/migrate/20180907141243_create_spina_conferences_conference_page_parts.rb +14 -0
- data/db/migrate/20180914121905_add_logo_ref_to_spina_conferences_institutions.rb +7 -0
- data/db/migrate/20180916135431_create_spina_conferences_rooms.rb +13 -0
- data/db/migrate/20180916135432_create_spina_conferences_room_possessions.rb +10 -0
- data/db/migrate/20180916135433_create_spina_conferences_room_uses.rb +10 -0
- data/db/migrate/20180916135434_create_spina_conferences_presentations.rb +15 -0
- data/db/migrate/20181009122503_create_spina_times.rb +11 -0
- data/db/migrate/20181009130631_rename_spina_page_parts.rb +10 -0
- data/db/migrate/20181012190811_rename_spina_conferences_page_parts.rb +10 -0
- data/db/migrate/20181012213049_change_start_time_in_spina_conferences_conferences.rb +15 -0
- data/db/migrate/20181012214813_rename_start_time_in_spina_conferences_conferences.rb +7 -0
- data/db/migrate/20181017155705_add_dependent_option_to_foreign_keys.rb +36 -0
- data/db/migrate/20190408131354_change_spina_resources.rb +56 -0
- data/db/migrate/20190622131423_create_spina_conferences_parts.rb +12 -0
- data/db/migrate/20190701174807_remove_spina_conference_pages.rb +199 -0
- data/db/migrate/20190704135524_add_constraints_to_columns.rb +24 -0
- data/db/migrate/20200126034441_create_spina_conferences_presentation_attachment_types.rb +11 -0
- data/db/migrate/20200126213718_create_spina_conferences_presentation_attachments.rb +19 -0
- data/db/migrate/20200420104603_create_spina_conferences_dietary_requirement_name_translations.rb +19 -0
- data/db/migrate/20200420104740_create_spina_conferences_institution_name_and_city_translations.rb +20 -0
- data/db/migrate/20200420105057_create_spina_conferences_presentation_title_and_abstract_translations.rb +20 -0
- data/db/migrate/20200420105144_create_spina_conferences_presentation_attachment_type_name_translations.rb +20 -0
- data/db/migrate/20200420105201_create_spina_conferences_presentation_type_name_translations.rb +19 -0
- data/db/migrate/20200420105458_create_spina_conferences_room_building_and_number_translations.rb +20 -0
- data/db/migrate/20200420110407_move_attributes_to_translation_tables.rb +161 -0
- data/db/migrate/20200420120706_remove_name_from_spina_conferences_dietary_requirements.rb +7 -0
- data/db/migrate/20200420120759_remove_name_and_city_from_spina_conferences_institutions.rb +8 -0
- data/db/migrate/20200420120946_remove_title_and_abstract_from_spina_conferences_presentations.rb +8 -0
- data/db/migrate/20200420121310_remove_name_from_spina_conferences_presentation_attachment_types.rb +7 -0
- data/db/migrate/20200420121321_remove_name_from_spina_conferences_presentation_types.rb +7 -0
- data/db/migrate/20200420121443_remove_building_and_number_from_spina_conferences_rooms.rb +8 -0
- data/db/migrate/20200502133408_create_spina_conferences_conference_name_translations.rb +19 -0
- data/db/migrate/20200502183409_set_name_for_spina_conferences_conferences.rb +47 -0
- data/db/migrate/20200502183410_remove_institution_from_spina_conferences_conferences.rb +8 -0
- data/db/migrate/20200502183719_remove_spina_conferences_room_possessions.rb +60 -0
- data/db/migrate/20200503230732_rename_spina_conferences_room_uses.rb +8 -0
- data/db/migrate/20200510125131_create_spina_conferences_session_name_translations.rb +19 -0
- data/db/migrate/20200802165242_create_spina_conferences_events.rb +13 -0
- data/db/migrate/20200802184921_create_spina_conferences_event_name_description_and_location_translations.rb +21 -0
- data/db/migrate/20200911161632_update_spina_conferences_parts.rb +23 -0
- data/db/migrate/20200911161651_update_spina_parts.rb +37 -0
- data/db/migrate/20200911161726_move_presentation_parts.rb +101 -0
- data/db/migrate/20200911161739_move_conference_parts.rb +219 -0
- data/db/migrate/20201002122517_remove_spina_conferences_conference_page_parts.rb +14 -0
- data/db/migrate/20201007125625_add_timestamps_to_spina_conferences_parts.rb +9 -0
- data/lib/spina/admin/conferences.rb +20 -0
- data/lib/spina/admin/conferences/engine.rb +26 -0
- data/lib/spina/admin/conferences/migration/renaming.rb +81 -0
- data/lib/spina/admin/conferences/railtie.rb +34 -0
- data/lib/spina/admin/conferences/types/interval_type.rb +29 -0
- data/lib/spina/admin/conferences/version.rb +10 -0
- data/lib/tasks/spina/admin/conferences_tasks.rake +4 -0
- metadata +561 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'csv'
|
|
4
|
+
|
|
5
|
+
module Spina
|
|
6
|
+
module Admin
|
|
7
|
+
module Conferences
|
|
8
|
+
# Job for importing CSV files.
|
|
9
|
+
class ImportJob < ApplicationJob
|
|
10
|
+
CSV::Converters[:json] = lambda do |field|
|
|
11
|
+
JSON.parse field, symbolize_names: true
|
|
12
|
+
rescue JSON::ParserError
|
|
13
|
+
field
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Performs the job.
|
|
17
|
+
# @param file [String] the UTF-8-encoded string to parse as a CSV
|
|
18
|
+
# @yieldparam row [Hash] the current row of the CSV
|
|
19
|
+
def import(file)
|
|
20
|
+
csv_rows = CSV.parse file, encoding: 'UTF-8', headers: true, header_converters: :symbol, converters: [:json]
|
|
21
|
+
csv_rows.each { |row| yield(row) }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Job for importing {Presentation} objects
|
|
7
|
+
# @see Presentation
|
|
8
|
+
class PresentationImportJob < ImportJob
|
|
9
|
+
queue_as :default
|
|
10
|
+
|
|
11
|
+
# Performs the job.
|
|
12
|
+
# @param csv [String] the UTF-8-encoded string to parse as a CSV
|
|
13
|
+
# == Columns
|
|
14
|
+
# The CSV should has the following columns. Make sure to include the column names in the header row.
|
|
15
|
+
# +session_id+:: The id of the associated session.
|
|
16
|
+
# +date+:: The date of the presentation, in ISO 8601 format.
|
|
17
|
+
# +start_time+:: The start time of the presentation, in HH:MM format.
|
|
18
|
+
# +title+:: The title of the presentation for the default locale.
|
|
19
|
+
# +abstract+:: The presentation's abstract.
|
|
20
|
+
# +presenter_ids+:: The ids of the presenters.
|
|
21
|
+
#
|
|
22
|
+
# @return [void]
|
|
23
|
+
def perform(csv)
|
|
24
|
+
Presentation.transaction do
|
|
25
|
+
import(csv) { |row| Presentation.create! presentation_params(row.to_h) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def presentation_params(params)
|
|
32
|
+
params = ActionController::Parameters.new(params)
|
|
33
|
+
params.permit :title, :date, :start_time, :abstract, :session_id, presenter_ids: []
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# @abstract Abstract mailer from which all others inherit.
|
|
7
|
+
class ApplicationMailer < ActionMailer::Base
|
|
8
|
+
default from: 'from@example.com'
|
|
9
|
+
layout 'mailer'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# @abstract Subclass to implement a custom record.
|
|
7
|
+
class ApplicationRecord < ActiveRecord::Base
|
|
8
|
+
extend Mobility
|
|
9
|
+
|
|
10
|
+
self.abstract_class = true
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Conference records.
|
|
7
|
+
#
|
|
8
|
+
# = Validators
|
|
9
|
+
# Presence:: {#name}, {#start_date}, {#finish_date}, {#year}.
|
|
10
|
+
# Conference date (using {FinishDateValidator}):: {#finish_date}.
|
|
11
|
+
# @see FinishDateValidator
|
|
12
|
+
#
|
|
13
|
+
# = Translations
|
|
14
|
+
# - {#name}
|
|
15
|
+
class Conference < ApplicationRecord
|
|
16
|
+
include Partable
|
|
17
|
+
|
|
18
|
+
default_scope { includes(:translations) }
|
|
19
|
+
|
|
20
|
+
# @!attribute [rw] dates
|
|
21
|
+
# @return [Range<Date>, nil] the dates of the conference
|
|
22
|
+
|
|
23
|
+
# @!attribute [rw] name
|
|
24
|
+
# @return [String, nil] the translated name of the conference
|
|
25
|
+
translates :name, fallbacks: true
|
|
26
|
+
|
|
27
|
+
# @return [ActiveRecord::Relation] all conferences, ordered by date
|
|
28
|
+
scope :sorted, -> { order dates: :desc }
|
|
29
|
+
|
|
30
|
+
# @!attribute [rw] presentation_types
|
|
31
|
+
# @return [ActiveRecord::Relation] directly associated presentation types
|
|
32
|
+
# @note A conference cannot be destroyed if it has dependent presentation types.
|
|
33
|
+
# @see PresentationType
|
|
34
|
+
has_many :presentation_types, -> { includes(:translations) }, inverse_of: :conference, dependent: :restrict_with_error
|
|
35
|
+
# @!attribute [rw] events
|
|
36
|
+
# @return [ActiveRecord::Relation] directly associated events
|
|
37
|
+
# @note Destroying a conference destroys dependent events.
|
|
38
|
+
# @see Event
|
|
39
|
+
has_many :events, -> { includes(:translations) }, inverse_of: :conference, dependent: :destroy
|
|
40
|
+
# @!attribute [rw] events
|
|
41
|
+
# @return [ActiveRecord::Relation] directly associated events
|
|
42
|
+
# @note Destroying a conference destroys dependent events.
|
|
43
|
+
# @see Event
|
|
44
|
+
has_many :parts, as: :pageable, dependent: :destroy
|
|
45
|
+
# @!attribute [rw] sessions
|
|
46
|
+
# @return [ActiveRecord::Relation] Sessions associated with {#presentation_types}
|
|
47
|
+
# @see Session
|
|
48
|
+
# @see PresentationType#sessions
|
|
49
|
+
has_many :sessions, -> { distinct.includes(:translations) }, through: :presentation_types
|
|
50
|
+
# @!attribute [rw] presentations
|
|
51
|
+
# @return [ActiveRecord::Relation] Presentations associated with {#sessions}
|
|
52
|
+
# @see Presentation
|
|
53
|
+
# @see Session#presentations
|
|
54
|
+
has_many :presentations, -> { distinct.includes(:translations) }, through: :sessions
|
|
55
|
+
# @!attribute [rw] rooms
|
|
56
|
+
# @return [ActiveRecord::Relation] Rooms associated with {#sessions}
|
|
57
|
+
# @see Room
|
|
58
|
+
# @see Session#rooms
|
|
59
|
+
has_many :rooms, -> { distinct.includes(:translations) }, through: :sessions
|
|
60
|
+
# @!attribute [rw] institutions
|
|
61
|
+
# @return [ActiveRecord::Relation] Institutions associated with {#rooms}
|
|
62
|
+
# @see Institution
|
|
63
|
+
# @see Room#institutions
|
|
64
|
+
has_many :institutions, -> { distinct.includes(:translations) }, through: :rooms
|
|
65
|
+
# @!attribute [rw] delegates
|
|
66
|
+
# @return [ActiveRecord::Relation] directly associated delegates
|
|
67
|
+
# @see Delegate
|
|
68
|
+
has_and_belongs_to_many :delegates, foreign_key: :spina_conferences_conference_id, # rubocop:disable Rails/HasAndBelongsToMany
|
|
69
|
+
association_foreign_key: :spina_conferences_delegate_id
|
|
70
|
+
accepts_nested_attributes_for :events, allow_destroy: true
|
|
71
|
+
accepts_nested_attributes_for :parts, allow_destroy: true
|
|
72
|
+
|
|
73
|
+
validates :name, :start_date, :finish_date, :year, presence: true
|
|
74
|
+
validates :finish_date, 'spina/admin/conferences/finish_date': true, unless: proc { |conference| conference.start_date.blank? }
|
|
75
|
+
|
|
76
|
+
# @return [Date, nil] the start date of the conference. Nil if the conference has no dates
|
|
77
|
+
def start_date
|
|
78
|
+
return if dates.blank?
|
|
79
|
+
|
|
80
|
+
dates.begin
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Sets the start date of the conference.
|
|
84
|
+
# @param date [Date] the new start date
|
|
85
|
+
# @return [void]
|
|
86
|
+
def start_date=(date)
|
|
87
|
+
self.dates = date.try(:to_date)..finish_date
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @return [Date, nil] the finish date of the conference. Nil if the conference has no dates
|
|
91
|
+
def finish_date
|
|
92
|
+
return if dates.blank?
|
|
93
|
+
|
|
94
|
+
if dates.exclude_end?
|
|
95
|
+
dates.end - 1.day if dates.end.is_a? Date
|
|
96
|
+
else
|
|
97
|
+
dates.end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Sets the finish date of the conference.
|
|
102
|
+
# @param date [Date] the new finish date
|
|
103
|
+
# @return [void]
|
|
104
|
+
def finish_date=(date)
|
|
105
|
+
self.dates = start_date..date.try(:to_date)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @return [Integer, nil] the year of the conference. Nil if the conference has no dates
|
|
109
|
+
def year
|
|
110
|
+
return if start_date.blank?
|
|
111
|
+
|
|
112
|
+
start_date.try(:year)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Array<Hash{Symbol=>String}>, nil] an array of hashes containing the date in ISO 8601 format and as a localised string
|
|
116
|
+
# Nil if the conference has no dates.
|
|
117
|
+
def localized_dates
|
|
118
|
+
return if dates.blank?
|
|
119
|
+
|
|
120
|
+
dates.entries.collect { |date| { date: date.to_formatted_s(:iso8601), localization: I18n.l(date, format: :long) } }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# @return [String] the names of each institution associated with the conference
|
|
124
|
+
def location
|
|
125
|
+
institutions.collect(&:name).to_sentence
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @return [Icalendar::Event] the conference as an iCal event
|
|
129
|
+
def to_event # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
130
|
+
event = Icalendar::Event.new
|
|
131
|
+
return event if invalid?
|
|
132
|
+
|
|
133
|
+
event.dtstart = start_date
|
|
134
|
+
event.dtstart.ical_param(:value, 'DATE')
|
|
135
|
+
event.dtend = finish_date
|
|
136
|
+
event.dtend.ical_param(:value, 'DATE')
|
|
137
|
+
event.location = location
|
|
138
|
+
event.contact = Spina::Account.first.email
|
|
139
|
+
event.categories = Conference.model_name.human(count: 0)
|
|
140
|
+
event.summary = name
|
|
141
|
+
event
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# @param (see #to_event)
|
|
145
|
+
# @deprecated Use {#to_event} instead
|
|
146
|
+
def to_ics
|
|
147
|
+
to_event
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Date parts, without associated times.
|
|
7
|
+
class DatePart < ApplicationRecord
|
|
8
|
+
has_many :page_parts, as: :page_partable
|
|
9
|
+
has_many :parts, as: :partable
|
|
10
|
+
has_many :layout_parts, as: :layout_partable
|
|
11
|
+
has_many :structure_parts, as: :structure_partable
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Delegate records.
|
|
7
|
+
#
|
|
8
|
+
# = Validators
|
|
9
|
+
# Presence:: {#first_name}, {#last_name}.
|
|
10
|
+
# Email address (using {EmailAddressValidator}):: {#email_address}.
|
|
11
|
+
# HTTP(S) URL (using {HttpUrlValidator}):: {#url}.
|
|
12
|
+
# @see EmailAddressValidator
|
|
13
|
+
# @see HttpUrlValidator
|
|
14
|
+
class Delegate < ApplicationRecord
|
|
15
|
+
# @!attribute [rw] first_name
|
|
16
|
+
# @return [String, nil] the first name of the delegate
|
|
17
|
+
# @!attribute [rw] last_name
|
|
18
|
+
# @return [String, nil] the last name of the delegate
|
|
19
|
+
# @!attribute [rw] email_address
|
|
20
|
+
# @return [String, nil] the email address of the delegate
|
|
21
|
+
# @!attribute [rw] url
|
|
22
|
+
# @return [String, nil] the website belonging to the delegate
|
|
23
|
+
|
|
24
|
+
# @return [ActiveRecord::Relation] all delegates, ordered by last name and first name
|
|
25
|
+
scope :sorted, -> { order :last_name, :first_name }
|
|
26
|
+
|
|
27
|
+
# @!attribute [rw] institution
|
|
28
|
+
# @return [Institution, nil] directly associated institution
|
|
29
|
+
# @see Institution
|
|
30
|
+
belongs_to :institution, inverse_of: :delegates, touch: true
|
|
31
|
+
# @!attribute [rw] conferences
|
|
32
|
+
# @return [ActiveRecord::Relation] directly associated conferences
|
|
33
|
+
# @see Conference
|
|
34
|
+
has_and_belongs_to_many :conferences, -> { includes(:translations) }, foreign_key: :spina_conferences_delegate_id, # rubocop:disable Rails/HasAndBelongsToMany
|
|
35
|
+
association_foreign_key: :spina_conferences_conference_id
|
|
36
|
+
# @!attribute [rw] presentations
|
|
37
|
+
# @return [ActiveRecord::Relation] directly associated presentations
|
|
38
|
+
# @see Presentation
|
|
39
|
+
has_and_belongs_to_many :presentations, -> { includes(:translations) }, foreign_key: :spina_conferences_delegate_id, # rubocop:disable Rails/HasAndBelongsToMany
|
|
40
|
+
association_foreign_key: :spina_conferences_presentation_id
|
|
41
|
+
# @!attribute [rw] dietary_requirements
|
|
42
|
+
# @return [ActiveRecord::Relation] directly associated dietary requirements
|
|
43
|
+
# @see DietaryRequirement
|
|
44
|
+
has_and_belongs_to_many :dietary_requirements, -> { includes(:translations) }, foreign_key: :spina_conferences_delegate_id, # rubocop:disable Rails/HasAndBelongsToMany
|
|
45
|
+
association_foreign_key: :spina_conferences_dietary_requirement_id
|
|
46
|
+
|
|
47
|
+
validates :first_name, :last_name, presence: true
|
|
48
|
+
validates :email_address, 'spina/admin/conferences/email_address': true
|
|
49
|
+
validates :url, 'spina/admin/conferences/http_url': true
|
|
50
|
+
|
|
51
|
+
# Imports a conference from CSV.
|
|
52
|
+
# @param file [String] the CSV file to be read
|
|
53
|
+
# @return [void]
|
|
54
|
+
# @see DelegateImportJob
|
|
55
|
+
def self.import(file)
|
|
56
|
+
DelegateImportJob.perform_later Pathname.new(file).read
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @return [String] the first name and last name of the delegate
|
|
60
|
+
def full_name
|
|
61
|
+
return if first_name.blank? || last_name.blank?
|
|
62
|
+
|
|
63
|
+
Delegate.human_attribute_name :full_name, first_name: first_name, last_name: last_name
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String] the full name and institution of the delegate
|
|
67
|
+
def full_name_and_institution
|
|
68
|
+
return if full_name.blank? || institution.blank?
|
|
69
|
+
|
|
70
|
+
Delegate.human_attribute_name :name_and_institution, name: full_name, institution: institution.name
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @return [String] the last name and first name of the delegate
|
|
74
|
+
def reversed_name
|
|
75
|
+
return if first_name.blank? || last_name.blank?
|
|
76
|
+
|
|
77
|
+
Delegate.human_attribute_name :reversed_name, first_name: first_name, last_name: last_name
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @return [String] the reversed name and institution of the delegate
|
|
81
|
+
def reversed_name_and_institution
|
|
82
|
+
return if reversed_name.blank? || institution.blank?
|
|
83
|
+
|
|
84
|
+
Delegate.human_attribute_name :name_and_institution, name: reversed_name, institution: institution.name
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Dietary requirement records.
|
|
7
|
+
#
|
|
8
|
+
# = Validators
|
|
9
|
+
# Presence:: {#name}.
|
|
10
|
+
#
|
|
11
|
+
# = Translations
|
|
12
|
+
# - {#name}
|
|
13
|
+
class DietaryRequirement < ApplicationRecord
|
|
14
|
+
default_scope { includes(:translations) }
|
|
15
|
+
|
|
16
|
+
# @!attribute [rw] name
|
|
17
|
+
# @return [String, nil] the name of the dietary requirement
|
|
18
|
+
translates :name, fallbacks: true
|
|
19
|
+
|
|
20
|
+
# @return [ActiveRecord::Relation] all dietary requirements, ordered by name
|
|
21
|
+
scope :sorted, -> { i18n.order :name }
|
|
22
|
+
|
|
23
|
+
# @!attribute [rw] delegates
|
|
24
|
+
# @return [ActiveRecord::Relation] directly associated delegates
|
|
25
|
+
# @see Delegate
|
|
26
|
+
has_and_belongs_to_many :delegates, foreign_key: :spina_conferences_dietary_requirement_id, # rubocop:disable Rails/HasAndBelongsToMany
|
|
27
|
+
association_foreign_key: :spina_conferences_delegate_id
|
|
28
|
+
|
|
29
|
+
validates :name, presence: true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Email address parts. The format is validated.
|
|
7
|
+
#
|
|
8
|
+
# = Validators
|
|
9
|
+
# Email address (using {EmailAddressValidator}):: {#content}.
|
|
10
|
+
# @see EmailAddressValidator
|
|
11
|
+
class EmailAddressPart < ApplicationRecord
|
|
12
|
+
has_many :page_parts, as: :page_partable
|
|
13
|
+
has_many :parts, as: :partable
|
|
14
|
+
has_many :layout_parts, as: :layout_partable
|
|
15
|
+
has_many :structure_parts, as: :structure_partable
|
|
16
|
+
|
|
17
|
+
validates :content, 'spina/admin/conferences/email_address': true, allow_blank: true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spina
|
|
4
|
+
module Admin
|
|
5
|
+
module Conferences
|
|
6
|
+
# Events during conferences.
|
|
7
|
+
#
|
|
8
|
+
# = Validators
|
|
9
|
+
# Presence:: {#name}, {#start_time}, {#finish_time}.
|
|
10
|
+
# Conference date (using {ConferenceDateValidator}):: {#start_time}, {#finish_time}.
|
|
11
|
+
# @see ConferenceDateValidator
|
|
12
|
+
#
|
|
13
|
+
# = Translations
|
|
14
|
+
# - {#name}
|
|
15
|
+
# - {#description}
|
|
16
|
+
# - {#location}
|
|
17
|
+
class Event < ApplicationRecord
|
|
18
|
+
default_scope { includes(:translations) }
|
|
19
|
+
|
|
20
|
+
# @!attribute [rw] name
|
|
21
|
+
# @return [String, nil] the translated name of the conference
|
|
22
|
+
# @!attribute [rw] description
|
|
23
|
+
# @return [String, nil] the translated description of the conference
|
|
24
|
+
# @!attribute [rw] location
|
|
25
|
+
# @return [String, nil] the translated location of the conference
|
|
26
|
+
translates :name, :description, :location, fallbacks: true
|
|
27
|
+
|
|
28
|
+
# @return [ActiveRecord::Relation] all events, ordered by name
|
|
29
|
+
scope :sorted, -> { i18n.order :name }
|
|
30
|
+
|
|
31
|
+
# @!attribute [rw] conference
|
|
32
|
+
# @return [Conference, nil] directly associated conferences
|
|
33
|
+
belongs_to :conference, -> { includes(:translations) }, inverse_of: :events, touch: true
|
|
34
|
+
|
|
35
|
+
validates :name, :date, :start_time, :start_datetime, :finish_time, :finish_datetime, :location, presence: true
|
|
36
|
+
validates :date, 'spina/admin/conferences/conference_date': true
|
|
37
|
+
validates :finish_time, 'spina/admin/conferences/finish_time': true
|
|
38
|
+
|
|
39
|
+
# @return [Date, nil] the start date of the event. Nil if the event has no start date and time
|
|
40
|
+
def date
|
|
41
|
+
return if start_datetime.blank?
|
|
42
|
+
|
|
43
|
+
start_datetime.to_date
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Sets the date of the presentation.
|
|
47
|
+
# @param date [Date] the new date
|
|
48
|
+
# @return [void]
|
|
49
|
+
def date=(date)
|
|
50
|
+
if date.blank? || date.to_date.blank?
|
|
51
|
+
self.start_datetime = nil
|
|
52
|
+
return
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
self.start_datetime = date.to_date + (start_datetime.try(:seconds_since_midnight) || 0).seconds
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @return [ActiveSupport::TimeWithZone, nil] the start time of the event. Nil if the event has no start date and time
|
|
59
|
+
def start_time
|
|
60
|
+
return if start_datetime.blank?
|
|
61
|
+
|
|
62
|
+
start_datetime
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Sets the start time of the event.
|
|
66
|
+
# @param start_time [ActiveSupport::TimeWithZone] the new start time
|
|
67
|
+
# @return [void]
|
|
68
|
+
def start_time=(start_time)
|
|
69
|
+
if start_time.blank?
|
|
70
|
+
self.start_datetime = nil
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
self.start_datetime = Time.parse(start_time, date).to_datetime.in_time_zone
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @return [ActiveSupport::TimeWithZone, nil] the finish time of the event. Nil if the event has no finish date and time
|
|
78
|
+
def finish_time
|
|
79
|
+
return if finish_datetime.blank?
|
|
80
|
+
|
|
81
|
+
finish_datetime
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Sets the finish time of the event.
|
|
85
|
+
# @param finish_time [ActiveSupport::TimeWithZone] the new finish time
|
|
86
|
+
# @return [void]
|
|
87
|
+
def finish_time=(finish_time)
|
|
88
|
+
if finish_time.blank?
|
|
89
|
+
self.finish_datetime = nil
|
|
90
|
+
return
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
self.finish_datetime = Time.parse(finish_time, date).to_datetime.in_time_zone
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @return [Icalendar::Event] the event as an iCal event
|
|
97
|
+
def to_event # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
98
|
+
event = Icalendar::Event.new
|
|
99
|
+
return event if invalid?
|
|
100
|
+
|
|
101
|
+
event.dtstart = start_datetime
|
|
102
|
+
event.dtend = finish_datetime
|
|
103
|
+
event.location = location
|
|
104
|
+
event.contact = Spina::Account.first.email
|
|
105
|
+
event.categories = Event.model_name.human(count: 0)
|
|
106
|
+
event.summary = name
|
|
107
|
+
event.append_custom_property('alt_description', description.try(:html_safe))
|
|
108
|
+
event.description = description.try(:gsub, %r{</?[^>]*>}, '')
|
|
109
|
+
event
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @param (see #to_event)
|
|
113
|
+
# @deprecated Use {#to_event} instead
|
|
114
|
+
def to_ics
|
|
115
|
+
to_event
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|