spina-conferences-primer_theme-fork 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +33 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/spina_conferences_primer_theme_manifest.js +9 -0
  6. data/app/assets/javascripts/spina/conferences/primer_theme/application.js +7 -0
  7. data/app/assets/javascripts/spina/conferences/primer_theme/controllers/slideshow_controller.es6 +68 -0
  8. data/app/assets/stylesheets/spina/conferences/primer_theme/_custom.sass +0 -0
  9. data/app/assets/stylesheets/spina/conferences/primer_theme/_custom_variables.sass +0 -0
  10. data/app/assets/stylesheets/spina/conferences/primer_theme/application.sass +44 -0
  11. data/app/controllers/spina/conferences/primer_theme/conferences/application_controller.rb +16 -0
  12. data/app/controllers/spina/conferences/primer_theme/conferences/conferences_controller.rb +72 -0
  13. data/app/controllers/spina/conferences/primer_theme/conferences/presentations_controller.rb +42 -0
  14. data/app/controllers/spina/conferences/primer_theme/journal/application_controller.rb +13 -0
  15. data/app/controllers/spina/conferences/primer_theme/journal/articles_controller.rb +69 -0
  16. data/app/controllers/spina/conferences/primer_theme/journal/issues_controller.rb +53 -0
  17. data/app/helpers/spina/conferences/primer_theme/application_helper.rb +36 -0
  18. data/app/helpers/spina/conferences/primer_theme/asset_helper.rb +51 -0
  19. data/app/helpers/spina/conferences/primer_theme/navigations_helper.rb +24 -0
  20. data/app/views/conferences_primer_theme/pages/about.html.haml +92 -0
  21. data/app/views/conferences_primer_theme/pages/committee.html.haml +42 -0
  22. data/app/views/conferences_primer_theme/pages/embedded_form.html.haml +9 -0
  23. data/app/views/conferences_primer_theme/pages/events.html.haml +59 -0
  24. data/app/views/conferences_primer_theme/pages/homepage.html.haml +34 -0
  25. data/app/views/conferences_primer_theme/pages/information.html.haml +5 -0
  26. data/app/views/conferences_primer_theme/pages/show.html.haml +2 -0
  27. data/app/views/layouts/conferences_primer_theme/application.html.haml +7 -0
  28. data/app/views/layouts/spina/conferences/primer_theme/application.html.haml +40 -0
  29. data/app/views/layouts/spina/conferences/primer_theme/conferences/conferences.html.haml +5 -0
  30. data/app/views/layouts/spina/conferences/primer_theme/conferences/presentations.html.haml +6 -0
  31. data/app/views/layouts/spina/conferences/primer_theme/journal/articles.html.haml +2 -0
  32. data/app/views/layouts/spina/conferences/primer_theme/journal/issues.html.haml +2 -0
  33. data/app/views/spina/admin/layout_partables/texts/_form.html.haml +4 -0
  34. data/app/views/spina/application/_cookies.html.haml +7 -0
  35. data/app/views/spina/application/_current_conference_alert.html.haml +4 -0
  36. data/app/views/spina/application/_footer.html.haml +17 -0
  37. data/app/views/spina/application/_footer_content.html.haml +13 -0
  38. data/app/views/spina/application/_list_item.html.haml +1 -0
  39. data/app/views/spina/application/_logo.html.haml +1 -0
  40. data/app/views/spina/application/_mobile_navigation_item.html.haml +12 -0
  41. data/app/views/spina/application/_mobile_navigation_items.html.haml +4 -0
  42. data/app/views/spina/application/_navigation.html.haml +11 -0
  43. data/app/views/spina/application/_navigation_item.html.haml +11 -0
  44. data/app/views/spina/application/_text.html.haml +1 -0
  45. data/app/views/spina/conferences/primer_theme/conferences/conferences/_conference.html.haml +15 -0
  46. data/app/views/spina/conferences/primer_theme/conferences/conferences/_event.html.haml +12 -0
  47. data/app/views/spina/conferences/primer_theme/conferences/conferences/_events.html.haml +16 -0
  48. data/app/views/spina/conferences/primer_theme/conferences/conferences/_header.html.haml +47 -0
  49. data/app/views/spina/conferences/primer_theme/conferences/conferences/_institution.html.haml +5 -0
  50. data/app/views/spina/conferences/primer_theme/conferences/conferences/_institution_logo.html.haml +4 -0
  51. data/app/views/spina/conferences/primer_theme/conferences/conferences/_presentation.html.haml +15 -0
  52. data/app/views/spina/conferences/primer_theme/conferences/conferences/_presentation_type.html.haml +5 -0
  53. data/app/views/spina/conferences/primer_theme/conferences/conferences/_presentations.html.haml +29 -0
  54. data/app/views/spina/conferences/primer_theme/conferences/conferences/_submission_flash.html.haml +10 -0
  55. data/app/views/spina/conferences/primer_theme/conferences/conferences/index.html.haml +23 -0
  56. data/app/views/spina/conferences/primer_theme/conferences/conferences/show.html.haml +37 -0
  57. data/app/views/spina/conferences/primer_theme/conferences/kaminari/_gap.html.haml +2 -0
  58. data/app/views/spina/conferences/primer_theme/conferences/kaminari/_next_page.html.haml +9 -0
  59. data/app/views/spina/conferences/primer_theme/conferences/kaminari/_page.html.haml +10 -0
  60. data/app/views/spina/conferences/primer_theme/conferences/kaminari/_paginator.html.haml +17 -0
  61. data/app/views/spina/conferences/primer_theme/conferences/kaminari/_prev_page.html.haml +9 -0
  62. data/app/views/spina/conferences/primer_theme/conferences/presentations/_abstract.html.haml +2 -0
  63. data/app/views/spina/conferences/primer_theme/conferences/presentations/_attachment.html.haml +5 -0
  64. data/app/views/spina/conferences/primer_theme/conferences/presentations/_attachments.html.haml +5 -0
  65. data/app/views/spina/conferences/primer_theme/conferences/presentations/show.html.haml +18 -0
  66. data/app/views/spina/conferences/primer_theme/journal/articles/_authorship.html.haml +6 -0
  67. data/app/views/spina/conferences/primer_theme/journal/articles/_metadata.html.haml +36 -0
  68. data/app/views/spina/conferences/primer_theme/journal/articles/show.html.haml +70 -0
  69. data/app/views/spina/conferences/primer_theme/journal/issues/_article.html.haml +15 -0
  70. data/app/views/spina/conferences/primer_theme/journal/issues/_issue.html.haml +17 -0
  71. data/app/views/spina/conferences/primer_theme/journal/issues/_issue_cover.html.haml +6 -0
  72. data/app/views/spina/conferences/primer_theme/journal/issues/index.html.haml +30 -0
  73. data/app/views/spina/conferences/primer_theme/journal/issues/show.html.haml +27 -0
  74. data/config/initializers/assets.rb +13 -0
  75. data/config/initializers/mime_types.rb +1 -0
  76. data/config/initializers/primer.rb +3 -0
  77. data/config/initializers/themes/conferences_primer_theme.rb +237 -0
  78. data/config/locales/en.rb +16 -0
  79. data/config/locales/en.yml +198 -0
  80. data/config/routes.rb +17 -0
  81. data/db/migrate/20210206170704_change_current_conference_alert_to_text.rb +46 -0
  82. data/lib/spina/conferences/primer_theme.rb +17 -0
  83. data/lib/spina/conferences/primer_theme/breadcrumbs/builder.rb +34 -0
  84. data/lib/spina/conferences/primer_theme/engine.rb +13 -0
  85. data/lib/spina/conferences/primer_theme/version.rb +9 -0
  86. data/lib/tasks/spina/conferences/primer_theme_tasks.rake +6 -0
  87. metadata +396 -0
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Conferences
5
+ module PrimerTheme
6
+ module Journal
7
+ # User-facing controller for journal issues
8
+ class IssuesController < ApplicationController
9
+ before_action :set_journal
10
+ before_action :set_issue, :set_breadcrumb, only: :show
11
+ before_action :set_metadata
12
+
13
+ def index
14
+ # having multiple journals is not currently allowed anyway
15
+ @issues = if current_spina_user.present?
16
+ Admin::Journal::Issue.sorted_desc
17
+ else
18
+ Admin::Journal::Issue.sorted_desc.where('date <= ?', Time.zone.today)
19
+ end
20
+ @latest_issue = @issues.first
21
+ end
22
+
23
+ def show
24
+ @articles = current_spina_user.present? ? @issue.articles : @issue.articles.visible
25
+ add_breadcrumb t('spina.conferences.primer_theme.journal.volume_issue', volume_number: @issue.volume.number, issue_number: @issue.number)
26
+ end
27
+
28
+ private
29
+
30
+ def set_journal
31
+ @journal = Admin::Journal::Journal.instance
32
+ end
33
+
34
+ def set_issue
35
+ @issue = Admin::Journal::Issue.includes(:volume, :articles).find(params[:id])
36
+ rescue ActiveRecord::RecordNotFound
37
+ send_file Rails.root.join('public/404.html'), type: 'text/html; charset=utf-8', status: 404
38
+ end
39
+
40
+ def set_breadcrumb
41
+ add_breadcrumb @journal.name, frontend_issues_path
42
+ add_breadcrumb Admin::Journal::Issue.model_name.human.pluralize, frontend_issues_path
43
+ end
44
+
45
+ def set_metadata
46
+ @title = @journal.name
47
+ @description = ActionView::Base.full_sanitizer.sanitize(@journal.content(:description))
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Conferences
5
+ module PrimerTheme
6
+ # Base helper
7
+ module ApplicationHelper
8
+ include Spina::PagesHelper
9
+
10
+ # Because the upper bound is exclusive a conference is current the day after it ends
11
+ def current_conference
12
+ Spina::Admin::Conferences::Conference.order(dates: :asc).find_by('upper(dates) >= ?', Date.today)
13
+ end
14
+
15
+ def ancestors
16
+ return [] if current_page.blank?
17
+
18
+ render Primer::BreadcrumbComponent.new(mb: 4) do |component|
19
+ current_page.ancestors.each do |ancestor|
20
+ component.item(href: ancestor.materialized_path) { ancestor.menu_title }
21
+ end
22
+ component.item(selected: true) { current_page.menu_title }
23
+ end
24
+ end
25
+
26
+ def calendar(name:)
27
+ Icalendar::Calendar.new
28
+ .tap { |calendar| calendar.x_wr_calname = name }
29
+ .tap { |calendar| yield(calendar) }
30
+ .tap(&:publish)
31
+ .then(&:to_ical)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Conferences
5
+ module PrimerTheme
6
+ # Helper for computing asset sources
7
+ module AssetHelper
8
+ def srcset(image, **options)
9
+ return if image.blank?
10
+
11
+ options = options.symbolize_keys
12
+ variant_options = options.delete(:variant)
13
+ return if variant_options.blank?
14
+
15
+ factors = options.delete(:factors) || DEFAULT_FACTORS
16
+ variants_for image, variant_options: variant_options, factors: factors
17
+ end
18
+
19
+ def srcset_string(image, **options)
20
+ srcset(image, **options).collect { |key, value| "#{key} #{value}" }
21
+ .join(', ')
22
+ end
23
+
24
+ private
25
+
26
+ METHODS_TO_RESIZE = %i[resize_to_limit resize_to_fit resize_to_fill resize_and_pad].freeze
27
+ DEFAULT_FACTORS = [1, 2, 3, 4].freeze
28
+
29
+ def variants_for(image, variant_options:, factors:)
30
+ factors.inject({}) { |srcset, factor| srcset.update(variant_url(image, variant_options, factor) => "#{factor}x") }
31
+ end
32
+
33
+ def variant_url(image, variant_options, factor)
34
+ main_app.url_for(image.variant(resize_options(variant_options, factor)))
35
+ end
36
+
37
+ def resize_options(variant_options, factor)
38
+ variant_options.to_h { |key, value| [key, resize_dimensions_for_key(key, factor, value)] }
39
+ end
40
+
41
+ def resize_dimensions_for_key(key, factor, dimensions)
42
+ METHODS_TO_RESIZE.include?(key) ? dimensions.collect { |dimension| resize_dimension(dimension, factor) } : dimensions
43
+ end
44
+
45
+ def resize_dimension(dimension = 0, factor = 0)
46
+ factor * dimension
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Conferences
5
+ module PrimerTheme
6
+ # Helper for accessing navigation items
7
+ module NavigationsHelper
8
+ def main_navigation_items
9
+ @main_navigation_items ||= live_navigation_items('main')
10
+ end
11
+
12
+ def footer_navigation_items
13
+ @footer_navigation_items ||= live_navigation_items('footer')
14
+ end
15
+
16
+ private
17
+
18
+ def live_navigation_items(name)
19
+ ::Spina::NavigationItem.joins(:navigation).where(spina_navigations: { name: name }).roots.regular_pages.in_menu.live.sorted
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,92 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
3
+
4
+ - if content(:text).present?
5
+ = render(Primer::MarkdownComponent.new(mt: 4)) { content.html(:text) }
6
+ - if content(:contact).present?
7
+ = render Primer::SubheadComponent.new(mt: 4) do |component|
8
+ = component.heading { t :'.contact.title' }
9
+ = render(Primer::MarkdownComponent.new) { content.html(:contact) }
10
+
11
+ .clearfix.gutter
12
+ = render Primer::BoxComponent.new(mt: 4, col: [12, nil, 6, nil], float: [nil, nil, :left, nil]) do
13
+ = render Primer::SubheadComponent.new do |component|
14
+ = component.heading { t :'.constitution.title' }
15
+ - if content(:constitution).present?
16
+ = render Primer::FlexComponent.new(align_items: :center, py: 1) do
17
+ = render Primer::FlexItemComponent.new(flex_auto: true, pr: 1) do
18
+ = t :'.constitution.uploaded',
19
+ date: l(Spina::Attachment.find(content(:constitution).attachment_id).created_at.to_date, format: :long)
20
+ = render Primer::ButtonComponent.new(tag: :a, href: content.attachment_url(:constitution), ml: 2, download: '') do
21
+ = render Primer::OcticonComponent.new('desktop-download')
22
+ = t :'.constitution.download'
23
+ - else
24
+ = render Primer::BlankslateComponent.new(title: t(:'.constitution.no_constitution'), icon: 'law')
25
+
26
+ = render Primer::BoxComponent.new(mt: 4, col: [12, nil, 6, nil], float: [nil, nil, :left, nil]) do
27
+ = render Primer::SubheadComponent.new do |component|
28
+ = component.heading { t :'.minutes.title' }
29
+ - if content(:minutes).present?
30
+ %ul
31
+ - repeater :minutes do |minutes_entry|
32
+ %li.list-style-none.py-1.d-flex.flex-items-center
33
+ = render Primer::FlexItemComponent.new(flex_auto: true) do
34
+ - if minutes_entry.content(:date).present?
35
+ = t(:'.minutes.minutes_for_html', date: time_tag(minutes_entry.content(:date)))
36
+ - else
37
+ = t(:'.minutes.no_date')
38
+ - if minutes_entry.content(:attachment).present?
39
+ = render Primer::ButtonComponent.new(tag: :a, ml: 2, href: minutes_entry.content.attachment_url(:attachment),
40
+ download: '') do
41
+ = render Primer::OcticonComponent.new('desktop-download')
42
+ = t(:'.minutes.download')
43
+ - else
44
+ = render(Primer::TextComponent.new(color: :text_secondary, font_size: 6)) { t :'.minutes.no_file' }
45
+ - else
46
+ = render Primer::BlankslateComponent.new(title: t(:'.minutes.no_minutes'), icon: 'file')
47
+
48
+ = render Primer::BoxComponent.new(mt: 4, col: [12, nil, 6, nil], float: [nil, nil, :left, nil]) do
49
+ - if content(:documents).present?
50
+ = render Primer::SubheadComponent.new do |component|
51
+ = component.heading { t :'.documents.title' }
52
+ %ul
53
+ - repeater :documents do |document|
54
+ %li.list-style-none.py-1.d-flex.flex-items-center
55
+ = render(Primer::TextComponent.new(tag: :div, flex: :auto)) { document.content(:name).presence || t(:'.documents.no_name') }
56
+ - if document.content(:attachment).present?
57
+ = render Primer::ButtonComponent.new(tag: :a, ml: 2, href: document.content.attachment_url(:attachment), download: '') do
58
+ = render Primer::OcticonComponent.new('desktop-download')
59
+ = t :'.documents.download'
60
+ - else
61
+ = render(Primer::TextComponent.new(tag: :div, font_size: 6, color: :text_secondary)) { t :'.documents.no_file' }
62
+
63
+ = render Primer::SubheadComponent.new(mt: 4) do |component|
64
+ = component.heading { t :'.partner_societies.title' }
65
+ - if content(:partner_societies).present?
66
+ %ul
67
+ - repeater :partner_societies do |partner_society|
68
+ %li.list-style-none.py-4.border-bottom
69
+ = render Primer::FlexComponent.new(direction: [:column, nil, :row_reverse, nil], align_items: :start) do
70
+ = render Primer::BaseComponent.new(tag: :div, flex: :auto) do
71
+ = render Primer::HeadingComponent.new(tag: :h3, mb: 1) do
72
+ = render Primer::FlexComponent.new(flex_wrap: true, justify_content: :space_between) do
73
+ - if partner_society.content(:name).present?
74
+ = render(Primer::TextComponent.new(tag: :div)) { partner_society.content(:name) }
75
+ = render Primer::ButtonGroupComponent.new(aria: { label: t(:'.partner_societies.contact_buttons') }) do |component|
76
+ - if partner_society.content(:website).present?
77
+ = component.button(tag: :a, href: partner_society.content(:website)) do
78
+ = render Primer::OcticonComponent.new('browser')
79
+ = t(:'.partner_societies.website')
80
+ - if partner_society.content(:email_address).present?
81
+ = component.button(tag: :a, href: "mailto:#{partner_society.content(:email_address)}") do
82
+ = render Primer::OcticonComponent.new('mail')
83
+ = t(:'.partner_societies.email')
84
+ - if partner_society.content(:description).present?
85
+ = render Primer::MarkdownComponent.new(color: :text_secondary) do
86
+ = partner_society.content(:description).try(:html_safe)
87
+ - if partner_society.content(:logo).present?
88
+ = partner_society.content.image_tag(:logo, { resize_to_limit: [200, 150] }, size: nil, draggable: false,
89
+ srcset: srcset(partner_society.content(:logo), variant: { resize_to_limit: [200, 150] }),
90
+ class: %w[mt-4 mt-md-0 mr-md-4])
91
+ - else
92
+ = render Primer::BlankslateComponent.new(title: t(:'.partner_societies.no_societies'), icon: 'organization')
@@ -0,0 +1,42 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
3
+
4
+ - if content(:text).present?
5
+ = render(Primer::MarkdownComponent.new(mt: 4)) { content.html(:text) }
6
+
7
+ - if content(:committee_bios).present?
8
+ %ul.mt-4
9
+ - repeater(:committee_bios) do |committee_bio|
10
+ %li.list-style-none.py-4.border-bottom
11
+ = render Primer::FlexComponent.new(direction: [:column, nil, :row, nil], align_items: :start) do
12
+ - if committee_bio.content(:profile_picture).present?
13
+ = render Primer::AvatarComponent.new(src: committee_bio.content.image_url(:profile_picture, resize_to_fill: [150, 150]),
14
+ srcset: srcset_string(committee_bio.content(:profile_picture),
15
+ variant: { resize_to_fill: [150, 150] }),
16
+ draggable: false, alt: committee_bio.content(:profile_picture).alt, size: 150,
17
+ mr: [nil, nil, 3, nil], mb: [3, nil, 0, nil], flex_shrink: 0)
18
+ = render Primer::FlexItemComponent.new(flex_auto: true) do
19
+ = render Primer::FlexComponent.new(direction: [:column, nil, :row, nil], mb: 1) do
20
+ = render Primer::BoxComponent.new do
21
+ - if committee_bio.content(:name).present?
22
+ = render(Primer::HeadingComponent.new(tag: :h3)) do
23
+ - if committee_bio.content(:role).present?
24
+ = t :'.name_and_role', name: committee_bio.content(:name), role: committee_bio.content(:role)
25
+ - else
26
+ = committee_bio.content(:name)
27
+ - if committee_bio.content(:institution).present?
28
+ = render(Primer::HeadingComponent.new(tag: :h4)) { committee_bio.content(:institution) }
29
+ = render Primer::ButtonGroupComponent.new(mt: [1, nil, 0, nil], ml: [nil, nil, 1, nil],
30
+ aria: { label: t(:'.contact_buttons') }) do |component|
31
+ - if committee_bio.content(:twitter_profile).present?
32
+ = component.button(tag: :a, href: committee_bio.content(:twitter_profile)) do
33
+ = render Primer::OcticonComponent.new('link-external')
34
+ = t(:'.twitter')
35
+ - if committee_bio.content(:facebook_profile).present?
36
+ = component.button(tag: :a, href: committee_bio.content(:facebook_profile)) do
37
+ = render Primer::OcticonComponent.new('link-external')
38
+ = t(:'.facebook')
39
+ - if committee_bio.content(:bio).present?
40
+ = render(Primer::TextComponent.new(tag: :div, color: :text_secondary)) { committee_bio.content.html(:bio) }
41
+ - else
42
+ = render Primer::BlankslateComponent.new(title: t(:'.no_bios'), icon: 'file')
@@ -0,0 +1,9 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
3
+
4
+ - if content(:text).present?
5
+ = render(Primer::MarkdownComponent.new(mt: 4)) { content.html(:text) }
6
+
7
+ - if content(:embed_url).present?
8
+ = render Primer::BoxComponent.new(mt: 4, col: 12) do
9
+ %iframe#form_frame{ src: content(:embed_url), allowfullscreen: true }
@@ -0,0 +1,59 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
3
+
4
+ - if content(:text).present?
5
+ = render(Primer::MarkdownComponent.new(mt: 4)) { content.html(:text) }
6
+
7
+ - if content(:events_list).present?
8
+ = render Primer::SubheadComponent.new(mt: 4) do |component|
9
+ = component.heading { t :'.upcoming' }
10
+ - content(:events_list).filter { |event| event.content(:start_time).blank? || event.content(:start_time) >= Time.now }.then do |events|
11
+ - if events.any?
12
+ %ul
13
+ - repeater(events) do |event|
14
+ %li.list-style-none.py-4.border-bottom
15
+ = render Primer::FlexComponent.new(direction: :column, align_items: :start) do
16
+ - if event.content(:name).present?
17
+ = render(Primer::HeadingComponent.new(tag: :h3, flex: :auto)) { event.content(:name) }
18
+ = render Primer::HeadingComponent.new(tag: :h4, flex: :auto) do
19
+ - if event.content(:start_time).present?
20
+ = t(:'.time_and_place_html',
21
+ time: time_tag(event.content(:start_time), format: :ordinal_datetime_with_year),
22
+ place: event.content(:location).presence || t('.location_tbc'))
23
+ - else
24
+ = t(:'.time_and_place_html', time: t('.time_tbc'), place: event.content(:location).presence || t('.location_tbc'))
25
+ - if event.content(:description).present?
26
+ = render(Primer::TextComponent.new(mt: 1, color: :text_secondary)) { event.content.html(:description) }
27
+ - if event.content(:url).present?
28
+ = render Primer::ButtonComponent.new(tag: :a, href: event.content(:url), mt: 2) do
29
+ = render Primer::OcticonComponent.new('link-external')
30
+ = t :'.more_info'
31
+ - else
32
+ = render Primer::BlankslateComponent.new(title: t(:'.no_events'), icon: 'calendar')
33
+ = render Primer::SubheadComponent.new(mt: 4) do |component|
34
+ = component.heading { t :'.past' }
35
+ - content(:events_list).filter { |event| event.content(:start_time).present? && event.content(:start_time) < Time.now }.then do |events|
36
+ - if events.any?
37
+ %ul
38
+ - repeater(events) do |event|
39
+ %li.list-style-none.py-4.border-bottom
40
+ = render Primer::FlexComponent.new(direction: :column, align_items: :start) do
41
+ - if event.content(:name).present?
42
+ = render(Primer::HeadingComponent.new(tag: :h3, flex: :auto)) { event.content(:name) }
43
+ = render Primer::HeadingComponent.new(tag: :h4, flex: :auto) do
44
+ - if event.content(:start_time).present?
45
+ = t(:'.time_and_place_html',
46
+ time: time_tag(event.content(:start_time), format: :ordinal_datetime_with_year),
47
+ place: event.content(:location).presence || t('.location_tbc'))
48
+ - else
49
+ = t(:'.time_and_place_html', time: t('.time_tbc'), place: event.content(:location).presence || t('.location_tbc'))
50
+ - if event.content(:description).present?
51
+ = render(Primer::TextComponent.new(mt: 1, color: :text_secondary)) { event.content.html(:description) }
52
+ - if event.content(:url).present?
53
+ = render Primer::ButtonComponent.new(tag: :a, href: event.content(:url), mt: 2) do
54
+ = render Primer::OcticonComponent.new('link-external')
55
+ = t :'.more_info'
56
+ - else
57
+ = render Primer::BlankslateComponent.new(title: t(:'.no_events'), icon: 'calendar')
58
+ - else
59
+ = render Primer::BlankslateComponent.new(title: t(:'.no_events'), icon: 'calendar')
@@ -0,0 +1,34 @@
1
+ - content_for :hero do
2
+ - cache [current_page, current_conference] do
3
+ = render Primer::BoxComponent.new(position: :relative, style: 'height: 639px') do
4
+ = render Primer::BoxComponent.new(position: :absolute, top: false, left: false, right: false, bottom: false,
5
+ style: 'background-color: var(--color-scale-blue-9)')
6
+ - if content(:gallery).present?
7
+ = render Primer::FlexComponent.new(position: :absolute, top: false, left: false, right: false, bottom: false, style: 'z-index: 1',
8
+ flex_direction: :column, justify_content: :center, align_items: :center,
9
+ data: { controller: :slideshow, slideshow_incrementer: 0, slideshow_advance: true }) do
10
+ - content(:gallery).each_with_index do |image, index|
11
+ = content.image_tag(image, { resize_to_limit: [1680, 1680] }, draggable: false, hidden: index != 0,
12
+ srcset: srcset(image, variant: { resize_to_limit: [1680, 1680] }),
13
+ style: 'object-fit: cover; max-width: max-content; max-height: max-content',
14
+ data: { slideshow_target: 'slide' }, class: %w[width-full height-full])
15
+ .container-lg.p-responsive.position-relative.color-text-white.height-full{ style: 'z-index: 2' }
16
+ = render Primer::BoxComponent.new(py: [3, nil, nil, 6]) do
17
+ %div{ style: 'text-shadow: 0 1px 1px #01040940, 0 1px 25px #010409bf;' }
18
+ - if current_conference.present?
19
+ = render(Primer::HeadingComponent.new(tag: :h1, classes: 'h000-mktg lh-condensed-ultra')) { current_conference.name }
20
+ = render Primer::TextComponent.new(tag: :address, classes: 'f2-light') do
21
+ = current_conference.institutions.collect(&:name).to_sentence
22
+ = render(Primer::TextComponent.new(tag: :time, classes: 'f2-light')) do
23
+ = t :'.dates_html', start_date: time_tag(current_conference.start_date, format: :day_and_month),
24
+ finish_date: time_tag(current_conference.finish_date, format: :day_and_month)
25
+ - else
26
+ = render(Primer::HeadingComponent.new(tag: :h1, classes: 'h000-mktg lh-condensed-ultra')) { Spina::Account.first.name }
27
+ - if current_conference.present? && current_conference.finish_date >= Date.today
28
+ = link_to t('.more_info'), frontend_conference_path(current_conference),
29
+ class: %w[btn-mktg btn-large-mktg btn-primary-mktg f3 mt-4]
30
+ - else
31
+ = link_to t('.more_info'), Spina::Page.find_by(name: 'about').materialized_path,
32
+ class: %w[btn-mktg btn-large-mktg btn-primary-mktg f3 mt-4]
33
+ %div{ style: 'text-shadow: 0 1px 1px rgba(var(--color-scale-black), 0.25), 0 1px 25px rgba(var(--color-scale-black), 0.75);' }
34
+ = render(Primer::MarkdownComponent.new(my: 4)) { content(:text).try(:html_safe) }
@@ -0,0 +1,5 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
3
+
4
+ - if content(:text).present?
5
+ = render(Primer::MarkdownComponent.new(mt: 4)) { content.html(:text) }
@@ -0,0 +1,2 @@
1
+ - cache current_page do
2
+ = render(Primer::HeadingComponent.new) { current_page.title }
@@ -0,0 +1,7 @@
1
+ - content_for :breadcrumbs do
2
+ - if current_page.ancestors.any?
3
+ = ancestors
4
+
5
+ = render template: 'layouts/spina/conferences/primer_theme/application',
6
+ locals: { author: current_account.name, description: current_page.description,
7
+ seo_title: current_page.seo_title, title: current_page.title }
@@ -0,0 +1,40 @@
1
+ !!!
2
+ %html{ lang: I18n.locale, data: { color_mode: 'auto', light_theme: 'light', dark_theme: 'dark' } }
3
+ %head
4
+ %meta{ charset: 'utf-8' }
5
+ %meta{ name: 'author', content: author }
6
+ %meta{ name: 'description', content: description }
7
+ %meta{ name: 'viewport', content: 'initial-scale=1.0' }
8
+ %meta{ name: 'og:title', content: t(:'.title', title: title, suffix: current_account.name) }
9
+ %meta{ name: 'og:description', content: description }
10
+ %meta{ name: 'turbolinks-cache-control', content: 'no-preview' }
11
+ %base{ target: '_blank' }
12
+ = csrf_meta_tags
13
+ %title= t(:'.title', title: seo_title, suffix: current_account.name)
14
+ = render 'spina/shared/google_site_verification'
15
+ = render 'spina/shared/analytics'
16
+ = stylesheet_link_tag 'spina/conferences/primer_theme/application', media: 'all', data: { turbolinks_track: true }
17
+ = javascript_include_tag 'spina/conferences/primer_theme/application', data: { turbolinks_track: true }
18
+ = javascript_include_tag 'turbo', type: 'module'
19
+ %script{ type: 'module', src: asset_path('@github/details-dialog-element/dist/index.js') }
20
+ %script{ type: 'module', src: asset_path('@github/include-fragment-element/dist/index.js') }
21
+ %script{ type: 'module', src: asset_path('@github/filter-input-element/dist/index.js') }
22
+ %script{ type: 'module', src: asset_path('@github/details-menu-element/dist/index.js') }
23
+ = yield :head
24
+ %body
25
+ - if current_spina_user.present?
26
+ .admin= render 'spina/shared/admin_bar'
27
+ %header= render 'navigation'
28
+ - unless local_assigns[:hide_alert]
29
+ = render 'current_conference_alert'
30
+ - if content_for? :flash
31
+ .flash-messages= yield :flash
32
+ %main
33
+ = yield :hero
34
+ - if content_for? :breadcrumbs
35
+ .container-lg.p-responsive.mt-4= yield :breadcrumbs
36
+ = yield :header
37
+ .container-lg.p-responsive.mt-4= yield
38
+ %footer
39
+ .container-lg.p-responsive.py-4= render 'footer'
40
+ = render 'spina/shared/social'