merge master
This commit is contained in:
commit
3b9c038947
52 changed files with 787 additions and 140 deletions
8
.github/workflows/spec.yml
vendored
8
.github/workflows/spec.yml
vendored
|
|
@ -38,6 +38,12 @@ jobs:
|
||||||
with:
|
with:
|
||||||
ruby-version: 2.6.6
|
ruby-version: 2.6.6
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '12.x'
|
||||||
|
- name: Install JavaScript libraries via npm
|
||||||
|
run: npm install
|
||||||
- name: Prepare spec
|
- name: Prepare spec
|
||||||
run: |
|
run: |
|
||||||
rm -f osem_test osem_development
|
rm -f osem_test osem_development
|
||||||
|
|
@ -46,7 +52,7 @@ jobs:
|
||||||
- name: spec/${{ matrix.suite }}
|
- name: spec/${{ matrix.suite }}
|
||||||
run: bundle exec rake spec:${{ matrix.suite }}
|
run: bundle exec rake spec:${{ matrix.suite }}
|
||||||
- name: coverage upload ${{ matrix.suite }}
|
- name: coverage upload ${{ matrix.suite }}
|
||||||
uses: codacy/codacy-coverage-reporter-action@master
|
uses: codacy/codacy-coverage-reporter-action@v1
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -121,3 +121,6 @@ build-iPhoneSimulator/
|
||||||
|
|
||||||
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
||||||
.rubocop-https?--*
|
.rubocop-https?--*
|
||||||
|
|
||||||
|
# Ignore Javascript package binaries
|
||||||
|
/node_modules
|
||||||
|
|
|
||||||
|
|
@ -250,8 +250,9 @@ linters:
|
||||||
|
|
||||||
ConsecutiveComments:
|
ConsecutiveComments:
|
||||||
exclude:
|
exclude:
|
||||||
# This one seems like a bug in haml-lint.
|
# These seems like a bug in haml-lint.
|
||||||
- "app/views/admin/conferences/show.html.haml"
|
- "app/views/admin/conferences/show.html.haml"
|
||||||
|
- "app/views/proposals/index.html.haml"
|
||||||
|
|
||||||
# Offense count: 24
|
# Offense count: 24
|
||||||
ConsecutiveSilentScripts:
|
ConsecutiveSilentScripts:
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ jobs:
|
||||||
- gem install bundler -v $(tail -n 1 Gemfile.lock)
|
- gem install bundler -v $(tail -n 1 Gemfile.lock)
|
||||||
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR
|
||||||
- chmod +x $CCTR
|
- chmod +x $CCTR
|
||||||
|
- npm install
|
||||||
before_script:
|
before_script:
|
||||||
- RAILS_ENV=test bundle exec rake db:bootstrap --trace
|
- RAILS_ENV=test bundle exec rake db:bootstrap --trace
|
||||||
- RAILS_ENV=test bundle exec bin/rails webdrivers:chromedriver:update
|
- RAILS_ENV=test bundle exec bin/rails webdrivers:chromedriver:update
|
||||||
|
|
|
||||||
16
Gemfile
16
Gemfile
|
|
@ -27,8 +27,9 @@ gem 'paper_trail'
|
||||||
# for upload management
|
# for upload management
|
||||||
gem 'carrierwave'
|
gem 'carrierwave'
|
||||||
gem 'carrierwave-bombshelter'
|
gem 'carrierwave-bombshelter'
|
||||||
gem 'mimemagic', '~> 0.3.6'
|
|
||||||
gem 'mini_magick'
|
gem 'mini_magick'
|
||||||
|
# for uploading images to the cloud
|
||||||
|
gem 'cloudinary'
|
||||||
|
|
||||||
# for internationalizing
|
# for internationalizing
|
||||||
gem 'rails-i18n'
|
gem 'rails-i18n'
|
||||||
|
|
@ -115,6 +116,9 @@ end
|
||||||
# as date picker
|
# as date picker
|
||||||
gem 'bootstrap3-datetimepicker-rails', '~> 4.17.47'
|
gem 'bootstrap3-datetimepicker-rails', '~> 4.17.47'
|
||||||
|
|
||||||
|
# for switch checkboxes
|
||||||
|
gem 'bootstrap-switch-rails', '~> 3.0.0'
|
||||||
|
|
||||||
# data tables
|
# data tables
|
||||||
gem 'ajax-datatables-rails'
|
gem 'ajax-datatables-rails'
|
||||||
gem 'jquery-datatables'
|
gem 'jquery-datatables'
|
||||||
|
|
@ -142,6 +146,7 @@ gem 'rqrcode'
|
||||||
gem 'caxlsx'
|
gem 'caxlsx'
|
||||||
gem 'caxlsx_rails'
|
gem 'caxlsx_rails'
|
||||||
|
|
||||||
|
# Application Monitoring
|
||||||
gem 'sentry-delayed_job'
|
gem 'sentry-delayed_job'
|
||||||
gem 'sentry-rails'
|
gem 'sentry-rails'
|
||||||
gem 'sentry-ruby'
|
gem 'sentry-ruby'
|
||||||
|
|
@ -174,15 +179,9 @@ gem 'money-rails'
|
||||||
# for lists
|
# for lists
|
||||||
gem 'acts_as_list'
|
gem 'acts_as_list'
|
||||||
|
|
||||||
# for switch checkboxes
|
|
||||||
gem 'bootstrap-switch-rails', '~> 3.0.0'
|
|
||||||
|
|
||||||
# for parsing OEmbed data
|
# for parsing OEmbed data
|
||||||
gem 'ruby-oembed'
|
gem 'ruby-oembed'
|
||||||
|
|
||||||
# for uploading images to the cloud
|
|
||||||
gem 'cloudinary'
|
|
||||||
|
|
||||||
# for setting app configuration in the environment
|
# for setting app configuration in the environment
|
||||||
gem 'dotenv-rails'
|
gem 'dotenv-rails'
|
||||||
|
|
||||||
|
|
@ -214,7 +213,7 @@ gem 'skylight'
|
||||||
# Nokogiri < 1.8.1 is subject to:
|
# Nokogiri < 1.8.1 is subject to:
|
||||||
# CVE-2017-0663, CVE-2017-7375, CVE-2017-7376, CVE-2017-9047, CVE-2017-9048,
|
# CVE-2017-0663, CVE-2017-7375, CVE-2017-7376, CVE-2017-9047, CVE-2017-9048,
|
||||||
# CVE-2017-9049, CVE-2017-9050
|
# CVE-2017-9049, CVE-2017-9050
|
||||||
gem 'nokogiri', '>= 1.8.1'
|
gem 'nokogiri'
|
||||||
|
|
||||||
# memcached binary connector
|
# memcached binary connector
|
||||||
gem 'dalli'
|
gem 'dalli'
|
||||||
|
|
@ -234,6 +233,7 @@ group :development do
|
||||||
gem 'spring-commands-rspec'
|
gem 'spring-commands-rspec'
|
||||||
# to open mails
|
# to open mails
|
||||||
gem 'letter_opener'
|
gem 'letter_opener'
|
||||||
|
# view mail at /letter_opener/
|
||||||
gem 'letter_opener_web'
|
gem 'letter_opener_web'
|
||||||
# as deployment system
|
# as deployment system
|
||||||
gem 'mina'
|
gem 'mina'
|
||||||
|
|
|
||||||
20
Gemfile.lock
20
Gemfile.lock
|
|
@ -171,11 +171,15 @@ GEM
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
faker (1.9.3)
|
faker (1.9.3)
|
||||||
i18n (>= 0.7)
|
i18n (>= 0.7)
|
||||||
faraday (1.3.0)
|
faraday (1.4.1)
|
||||||
|
faraday-excon (~> 1.1)
|
||||||
faraday-net_http (~> 1.0)
|
faraday-net_http (~> 1.0)
|
||||||
|
faraday-net_http_persistent (~> 1.1)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (>= 1.2, < 3)
|
||||||
ruby2_keywords
|
ruby2_keywords (>= 0.0.4)
|
||||||
|
faraday-excon (1.1.0)
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
|
faraday-net_http_persistent (1.1.0)
|
||||||
fastimage (2.1.4)
|
fastimage (2.1.4)
|
||||||
feature (1.4.0)
|
feature (1.4.0)
|
||||||
ffi (1.10.0)
|
ffi (1.10.0)
|
||||||
|
|
@ -293,7 +297,7 @@ GEM
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2021.0225)
|
mime-types-data (3.2021.0225)
|
||||||
mimemagic (0.4.3)
|
mimemagic (0.3.10)
|
||||||
nokogiri (~> 1)
|
nokogiri (~> 1)
|
||||||
rake
|
rake
|
||||||
mina (1.2.3)
|
mina (1.2.3)
|
||||||
|
|
@ -301,7 +305,7 @@ GEM
|
||||||
rake
|
rake
|
||||||
mini_magick (4.9.5)
|
mini_magick (4.9.5)
|
||||||
mini_mime (1.0.3)
|
mini_mime (1.0.3)
|
||||||
mini_portile2 (2.5.0)
|
mini_portile2 (2.5.1)
|
||||||
minitest (5.14.4)
|
minitest (5.14.4)
|
||||||
momentjs-rails (2.20.1)
|
momentjs-rails (2.20.1)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
|
|
@ -320,7 +324,7 @@ GEM
|
||||||
nenv (0.3.0)
|
nenv (0.3.0)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nio4r (2.5.7)
|
nio4r (2.5.7)
|
||||||
nokogiri (1.11.2)
|
nokogiri (1.11.3)
|
||||||
mini_portile2 (~> 2.5.0)
|
mini_portile2 (~> 2.5.0)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
notiffany (0.1.1)
|
notiffany (0.1.1)
|
||||||
|
|
@ -332,7 +336,7 @@ GEM
|
||||||
multi_json (~> 1.3)
|
multi_json (~> 1.3)
|
||||||
multi_xml (~> 0.5)
|
multi_xml (~> 0.5)
|
||||||
rack (>= 1.2, < 3)
|
rack (>= 1.2, < 3)
|
||||||
octokit (4.20.0)
|
octokit (4.21.0)
|
||||||
faraday (>= 0.9)
|
faraday (>= 0.9)
|
||||||
sawyer (~> 0.8.0, >= 0.5.3)
|
sawyer (~> 0.8.0, >= 0.5.3)
|
||||||
omniauth (1.9.1)
|
omniauth (1.9.1)
|
||||||
|
|
@ -496,7 +500,7 @@ GEM
|
||||||
http-cookie (>= 1.0.2, < 2.0)
|
http-cookie (>= 1.0.2, < 2.0)
|
||||||
mime-types (>= 1.16, < 4.0)
|
mime-types (>= 1.16, < 4.0)
|
||||||
netrc (~> 0.8)
|
netrc (~> 0.8)
|
||||||
rexml (3.2.4)
|
rexml (3.2.5)
|
||||||
rolify (5.2.0)
|
rolify (5.2.0)
|
||||||
rqrcode (0.10.1)
|
rqrcode (0.10.1)
|
||||||
chunky_png (~> 1.0)
|
chunky_png (~> 1.0)
|
||||||
|
|
@ -637,7 +641,7 @@ GEM
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.5)
|
unf_ext (0.0.7.5)
|
||||||
unicode-display_width (1.6.0)
|
unicode-display_width (1.6.1)
|
||||||
unicode_utils (1.4.0)
|
unicode_utils (1.4.0)
|
||||||
unobtrusive_flash (3.3.1)
|
unobtrusive_flash (3.3.1)
|
||||||
railties
|
railties
|
||||||
|
|
|
||||||
18
README.md
18
README.md
|
|
@ -1,21 +1,3 @@
|
||||||
### Spring 2021 Student Project
|
|
||||||
[](https://travis-ci.com/CactusPuppy/snapcon)
|
|
||||||
[](https://codeclimate.com/github/CactusPuppy/snapcon/maintainability)
|
|
||||||
[](https://codeclimate.com/github/CactusPuppy/snapcon/test_coverage)
|
|
||||||
[](https://hakiri.io/github/CactusPuppy/snapcon/master)
|
|
||||||
[](https://depfu.com/github/CactusPuppy/snapcon?project_id=22682)
|
|
||||||
[](http://dashboard.bluejay.governify.io/dashboard/script/dashboardLoader.js?dashboardURL=https://reporter.bluejay.governify.io/api/v4/dashboards/tpa-CS169L-GH-CactusPuppy_snapcon/main)
|
|
||||||
|
|
||||||
<a href="https://heroku.com/deploy?template=https://github.com/openSUSE/osem/tree/v1.0">
|
|
||||||
<img src="https://www.herokucdn.com/deploy/button.svg" height="20px" alt="Deploy">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://www.pivotaltracker.com/n/projects/2487653">
|
|
||||||
<img src="https://www.pivotaltracker.com/marketing_assets/shared_home/tracker-4679313e699d9ba696371344953de96c81d207d967a43f121d353391c81c9ba7.svg" height="20px" alt="Pivotal Tracker">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[](https://travis-ci.com/snap-cloud/snapcon)
|
[](https://travis-ci.com/snap-cloud/snapcon)
|
||||||
[](https://codeclimate.com/github/snap-cloud/snapcon/maintainability)
|
[](https://codeclimate.com/github/snap-cloud/snapcon/maintainability)
|
||||||
[](https://codeclimate.com/github/snap-cloud/snapcon/test_coverage)
|
[](https://codeclimate.com/github/snap-cloud/snapcon/test_coverage)
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@
|
||||||
//= require bootstrap-select
|
//= require bootstrap-select
|
||||||
//= require osem-survey
|
//= require osem-survey
|
||||||
//= require pagy
|
//= require pagy
|
||||||
|
//= require fullcalendar-scheduler/main.js
|
||||||
|
//= require fullcalendar
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('a[disabled=disabled]').click(function(event){
|
$('a[disabled=disabled]').click(function(event){
|
||||||
|
|
|
||||||
28
app/assets/javascripts/fullcalendar.js.erb
Normal file
28
app/assets/javascripts/fullcalendar.js.erb
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
$( document ).ready(function() {
|
||||||
|
let calendarEl = document.getElementById('vert-schedule-full-calendar');
|
||||||
|
if (!calendarEl) return; //check that we need a vertical schedule
|
||||||
|
let fullcalData = $('#fullcalendar');
|
||||||
|
|
||||||
|
let license_key = "<%= Rails.configuration.fullcalendar[:license_key] %>";
|
||||||
|
|
||||||
|
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||||
|
schedulerLicenseKey: license_key,
|
||||||
|
nowIndicator: true,
|
||||||
|
now: fullcalData.data('now'),
|
||||||
|
expandRows: true,
|
||||||
|
allDaySlot: false,
|
||||||
|
slotMinTime: fullcalData.data('startHour') + ':00:00',
|
||||||
|
slotMaxTime: fullcalData.data('endHour') + ':00:00',
|
||||||
|
validRange: {
|
||||||
|
start: fullcalData.data('startDate'),
|
||||||
|
end: fullcalData.data('endDate')
|
||||||
|
},
|
||||||
|
timeZone: fullcalData.data('timezone'),
|
||||||
|
initialDate: fullcalData.data('day'),
|
||||||
|
initialView: 'resourceTimeGridDay',
|
||||||
|
resources: fullcalData.data('rooms'),
|
||||||
|
events: fullcalData.data('events')
|
||||||
|
});
|
||||||
|
|
||||||
|
calendar.render();
|
||||||
|
});
|
||||||
|
|
@ -26,4 +26,6 @@
|
||||||
*= require osem-navbar
|
*= require osem-navbar
|
||||||
*= require mastodon
|
*= require mastodon
|
||||||
*= require conferences
|
*= require conferences
|
||||||
|
|
||||||
|
*= require fullcalendar-scheduler/main.css
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class ConferencesController < ApplicationController
|
||||||
|
|
||||||
@image_url = "#{request.protocol}#{request.host}#{@conference.picture}"
|
@image_url = "#{request.protocol}#{request.host}#{@conference.picture}"
|
||||||
|
|
||||||
if splashpage.include_cfp
|
if splashpage.include_cfp?
|
||||||
cfps = @conference.program.cfps
|
cfps = @conference.program.cfps
|
||||||
@call_for_events = cfps.find { |call| call.cfp_type == 'events' }
|
@call_for_events = cfps.find { |call| call.cfp_type == 'events' }
|
||||||
if @call_for_events.try(:open?)
|
if @call_for_events.try(:open?)
|
||||||
|
|
@ -50,31 +50,27 @@ class ConferencesController < ApplicationController
|
||||||
@call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' }
|
@call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' }
|
||||||
@call_for_booths = cfps.find { |call| call.cfp_type == 'booths' }
|
@call_for_booths = cfps.find { |call| call.cfp_type == 'booths' }
|
||||||
end
|
end
|
||||||
if splashpage.include_program
|
if splashpage.include_program?
|
||||||
@highlights = @conference.highlighted_events.eager_load(:speakers)
|
@highlights = @conference.highlighted_events.eager_load(:speakers)
|
||||||
if splashpage.include_tracks
|
if splashpage.include_tracks?
|
||||||
@tracks = @conference.confirmed_tracks.eager_load(
|
@tracks = @conference.confirmed_tracks.eager_load(
|
||||||
:room
|
:room
|
||||||
).order('tracks.name')
|
).order('tracks.name')
|
||||||
end
|
end
|
||||||
if splashpage.include_booths
|
if splashpage.include_booths?
|
||||||
@booths = @conference.confirmed_booths.order('title')
|
@booths = @conference.confirmed_booths.order('title')
|
||||||
end
|
end
|
||||||
if splashpage.include_happening_now
|
if splashpage.include_happening_now?
|
||||||
events_schedules_list = get_happening_now_events_schedules(@conference)
|
load_happening_now
|
||||||
@events_schedules_limit = EVENTS_PER_PAGE
|
|
||||||
@events_schedules_length = events_schedules_list.length
|
|
||||||
@pagy, @events_schedules = pagy_array(events_schedules_list, items: @events_schedules_limit, link_extra: 'data-remote="true"')
|
|
||||||
@happening_now_url = happening_now_conference_schedule_path(conference_id: @conference.short_title, format: :json)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if splashpage.include_registrations || splashpage.include_tickets
|
if splashpage.include_registrations? || splashpage.include_tickets?
|
||||||
@tickets = @conference.tickets.visible.order('price_cents')
|
@tickets = @conference.tickets.visible.order('price_cents')
|
||||||
end
|
end
|
||||||
if splashpage.include_lodgings
|
if splashpage.include_lodgings?
|
||||||
@lodgings = @conference.lodgings.order('id')
|
@lodgings = @conference.lodgings.order('id')
|
||||||
end
|
end
|
||||||
if splashpage.include_sponsors
|
if splashpage.include_sponsors?
|
||||||
@sponsorship_levels = @conference.sponsorship_levels.eager_load(
|
@sponsorship_levels = @conference.sponsorship_levels.eager_load(
|
||||||
:sponsors
|
:sponsors
|
||||||
).order('sponsorship_levels.position ASC', 'sponsors.name')
|
).order('sponsorship_levels.position ASC', 'sponsors.name')
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
EVENTS_PER_PAGE = Rails.configuration.conference[:events_per_page]
|
||||||
|
|
||||||
class ProposalsController < ApplicationController
|
class ProposalsController < ApplicationController
|
||||||
|
include ConferenceHelper
|
||||||
before_action :authenticate_user!, except: [:show, :new, :create]
|
before_action :authenticate_user!, except: [:show, :new, :create]
|
||||||
load_resource :conference, find_by: :short_title
|
load_resource :conference, find_by: :short_title
|
||||||
load_resource :program, through: :conference, singleton: true
|
load_resource :program, through: :conference, singleton: true
|
||||||
|
|
@ -19,6 +22,7 @@ class ProposalsController < ApplicationController
|
||||||
@event_schedule = @event.event_schedules.find_by(schedule_id: @program.selected_schedule_id)
|
@event_schedule = @event.event_schedules.find_by(schedule_id: @program.selected_schedule_id)
|
||||||
@speakers_ordered = @event.speakers_ordered
|
@speakers_ordered = @event.speakers_ordered
|
||||||
@surveys_after_event = @event.surveys.after_event.select(&:active?)
|
@surveys_after_event = @event.surveys.after_event.select(&:active?)
|
||||||
|
load_happening_now
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|
@ -169,11 +173,11 @@ class ProposalsController < ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def event_params
|
def event_params
|
||||||
|
# TODO-SNAPCON: Restrict committee review to admins.
|
||||||
params.require(:event).permit(:event_type_id, :track_id, :difficulty_level_id,
|
params.require(:event).permit(:event_type_id, :track_id, :difficulty_level_id,
|
||||||
:title, :subtitle, :abstract, :submission_text, :description,
|
:title, :subtitle, :abstract, :submission_text, :description,
|
||||||
:require_registration, :max_attendees, :language,
|
:require_registration, :max_attendees, :language,
|
||||||
speaker_ids: [], volunteer_ids: []
|
:committee_review, speaker_ids: [], volunteer_ids: [])
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,25 @@ class SchedulesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def vertical_schedule
|
||||||
|
dates = @conference.start_date..@conference.end_date
|
||||||
|
# the schedule takes you to today if it is a date of the schedule
|
||||||
|
current_day = @conference.current_conference_day
|
||||||
|
@day = current_day.present? ? current_day : dates.first
|
||||||
|
event_schedules = @program.selected_event_schedules(
|
||||||
|
includes: [{ event: %i[event_type speakers submitter] }]
|
||||||
|
)
|
||||||
|
|
||||||
|
unless event_schedules
|
||||||
|
redirect_to events_conference_schedule_path(@conference.short_title)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
@rooms = FullCalendarFormatter.rooms_to_resources(@conference.venue.rooms) if @conference.venue
|
||||||
|
@event_schedules = FullCalendarFormatter.event_schedules_to_resources(event_schedules)
|
||||||
|
@now = Time.now.in_time_zone(@conference.timezone).strftime('%FT%T%:z')
|
||||||
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
@qr_code = RQRCode::QRCode.new(conference_schedule_url).as_svg(offset: 20, color: '000', shape_rendering: 'crispEdges', module_size: 11)
|
@qr_code = RQRCode::QRCode.new(conference_schedule_url).as_svg(offset: 20, color: '000', shape_rendering: 'crispEdges', module_size: 11)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -79,10 +79,42 @@ module ConferenceHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_happening_now_events_schedules(conference)
|
def get_happening_now_events_schedules(conference)
|
||||||
events_schedules = conference.program.selected_event_schedules(
|
events_schedules = filter_events_schedules(conference, :happening_now?)
|
||||||
includes: [:room, { event: %i[track event_type speakers submitter] }]
|
|
||||||
).select(&:happening_now?)
|
|
||||||
events_schedules ||= []
|
events_schedules ||= []
|
||||||
events_schedules
|
events_schedules
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_happening_next_events_schedules(conference)
|
||||||
|
events_schedules = filter_events_schedules(conference, :happening_later?)
|
||||||
|
|
||||||
|
if events_schedules.empty?
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
|
||||||
|
# events_schedules have been sorted by start_time in selected_event_schedules
|
||||||
|
happening_next_time = events_schedules[0].start_time
|
||||||
|
events_schedules = events_schedules.select { |s| s.start_time == happening_next_time }
|
||||||
|
|
||||||
|
events_schedules
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_happening_now
|
||||||
|
events_schedules_list = get_happening_now_events_schedules(@conference)
|
||||||
|
@is_happening_next = false
|
||||||
|
if events_schedules_list.empty?
|
||||||
|
events_schedules_list = get_happening_next_events_schedules(@conference)
|
||||||
|
@is_happening_next = true
|
||||||
|
end
|
||||||
|
@events_schedules_limit = EVENTS_PER_PAGE
|
||||||
|
@events_schedules_length = events_schedules_list.length
|
||||||
|
@pagy, @events_schedules = pagy_array(events_schedules_list, items: @events_schedules_limit, link_extra: 'data-remote="true"')
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def filter_events_schedules(conference, filter)
|
||||||
|
conference.program.selected_event_schedules(
|
||||||
|
includes: [:room, { event: %i[track event_type speakers submitter] }]
|
||||||
|
).select(&filter)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class Ability
|
||||||
event.state == 'confirmed'
|
event.state == 'confirmed'
|
||||||
end
|
end
|
||||||
|
|
||||||
can [:show, :events, :happening_now, :app], Schedule do |schedule|
|
can [:show, :events, :happening_now, :app, :vertical_schedule], Schedule do |schedule|
|
||||||
schedule.program.schedule_public
|
schedule.program.schedule_public
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ class EmailSettings < ApplicationRecord
|
||||||
h['eventtitle'] = event.title
|
h['eventtitle'] = event.title
|
||||||
h['proposalslink'] = Rails.application.routes.url_helpers.conference_program_proposals_url(
|
h['proposalslink'] = Rails.application.routes.url_helpers.conference_program_proposals_url(
|
||||||
conference.short_title, host: (ENV['OSEM_HOSTNAME'] || 'localhost:3000'))
|
conference.short_title, host: (ENV['OSEM_HOSTNAME'] || 'localhost:3000'))
|
||||||
|
h['committee_review'] = event.committee_review
|
||||||
|
h['committee_review_html'] = ApplicationController.helpers.markdown(event.committee_review)
|
||||||
end
|
end
|
||||||
|
|
||||||
if booth
|
if booth
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ class EventSchedule < ApplicationRecord
|
||||||
event_time_range.overlaps?(now_range)
|
event_time_range.overlaps?(now_range)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def happening_later?
|
||||||
|
# TODO: Save start_time with local timezone info when making an event schedule
|
||||||
|
in_tz_start = start_time.in_time_zone(timezone)
|
||||||
|
in_tz_start -= in_tz_start.utc_offset
|
||||||
|
|
||||||
|
in_tz_start >= Time.now
|
||||||
|
end
|
||||||
|
|
||||||
def self.withdrawn_or_canceled_event_schedules(schedule_ids)
|
def self.withdrawn_or_canceled_event_schedules(schedule_ids)
|
||||||
EventSchedule
|
EventSchedule
|
||||||
.unscoped
|
.unscoped
|
||||||
|
|
@ -125,6 +133,14 @@ class EventSchedule < ApplicationRecord
|
||||||
other.schedule_id == schedule_id
|
other.schedule_id == schedule_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def start_time_in_conference_timezone
|
||||||
|
time_in_conference_timezone(start_time)
|
||||||
|
end
|
||||||
|
|
||||||
|
def end_time_in_conference_timezone
|
||||||
|
time_in_conference_timezone(end_time)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def replaced_event_schedules
|
def replaced_event_schedules
|
||||||
|
|
@ -179,4 +195,10 @@ class EventSchedule < ApplicationRecord
|
||||||
|
|
||||||
errors.add(:schedule, "must be one of #{event.track.name} track's schedules") unless event.track.schedules.include?(schedule)
|
errors.add(:schedule, "must be one of #{event.track.name} track's schedules") unless event.track.schedules.include?(schedule)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def time_in_conference_timezone(time)
|
||||||
|
time_in_tz = time.in_time_zone(timezone)
|
||||||
|
time_in_tz -= time_in_tz.utc_offset
|
||||||
|
time_in_tz
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ class Program < ApplicationRecord
|
||||||
def show_voting?
|
def show_voting?
|
||||||
return true unless blind_voting
|
return true unless blind_voting
|
||||||
|
|
||||||
Time.current > voting_end_date
|
# TODO-SNAPCON: UPDATE TESTS
|
||||||
|
# Time.current > voting_end_date
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
||||||
42
app/services/full_calendar_formatter.rb
Normal file
42
app/services/full_calendar_formatter.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
class FullCalendarFormatter
|
||||||
|
def self.rooms_to_resources(rooms)
|
||||||
|
rooms.map { |room| room_to_resource(room) }.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.event_schedules_to_resources(event_schedules)
|
||||||
|
return '[]' if event_schedules.empty?
|
||||||
|
|
||||||
|
conference = event_schedules.first.schedule.program.conference
|
||||||
|
event_schedules.map { |event_schedule| event_schedule_to_resource(conference, event_schedule) }.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
include FormatHelper
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def room_to_resource(room)
|
||||||
|
{
|
||||||
|
id: room.guid,
|
||||||
|
title: room.name
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def event_schedule_to_resource(conference, event_schedule)
|
||||||
|
event_type_color = event_schedule.event.event_type.color
|
||||||
|
url = Rails.application.routes.url_helpers.conference_program_proposal_path(conference.short_title, event_schedule.event.id)
|
||||||
|
|
||||||
|
{
|
||||||
|
id: event_schedule.event.guid,
|
||||||
|
title: event_schedule.event.title,
|
||||||
|
start: event_schedule.start_time_in_conference_timezone,
|
||||||
|
end: event_schedule.end_time_in_conference_timezone,
|
||||||
|
resourceId: event_schedule.room.guid,
|
||||||
|
url: url,
|
||||||
|
borderColor: event_type_color,
|
||||||
|
backgroundColor: event_type_color,
|
||||||
|
textColor: contrast_color(event_type_color)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.page-header
|
.page-header
|
||||||
%h1 Session Materials
|
%h1 #{@conference.title} Materials
|
||||||
%p.text-muted
|
%p.text-muted
|
||||||
Conference materials will be displayed on the events in the
|
Conference materials will be displayed on the events in the
|
||||||
= link_to 'schedule,', conference_schedule_path(@conference.short_title)
|
= link_to 'schedule,', conference_schedule_path(@conference.short_title)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@
|
||||||
%tr
|
%tr
|
||||||
%td {eventtitle}
|
%td {eventtitle}
|
||||||
%td The title of an accepted or rejected proposal
|
%td The title of an accepted or rejected proposal
|
||||||
|
%tr
|
||||||
|
%td {committee_review}
|
||||||
|
%td The raw text in the committee review for the proposal
|
||||||
|
%tr
|
||||||
|
%td {committee_review_html}
|
||||||
|
%td The committee review markdown rendered as HTML.
|
||||||
%tr
|
%tr
|
||||||
%td {conference_start_date}
|
%td {conference_start_date}
|
||||||
%td The start date of the conference
|
%td The start date of the conference
|
||||||
|
|
@ -51,14 +57,11 @@
|
||||||
- if @conference.program.schedule_public
|
- if @conference.program.schedule_public
|
||||||
%td {schedule_link}
|
%td {schedule_link}
|
||||||
%td The link to complete schedule of the conference
|
%td The link to complete schedule of the conference
|
||||||
- if @conference.splashpage && @conference.splashpage.public
|
- if @conference.splashpage && @conference.splashpage.public?
|
||||||
%tr
|
%tr
|
||||||
%td {conference_splash_link}
|
%td {conference_splash_link}
|
||||||
%td The link to conference splash page
|
%td The link to conference splash page
|
||||||
- if @conference.booths
|
- if @conference.booths
|
||||||
%tr
|
|
||||||
%td {submitter_name}
|
|
||||||
%td Submitter's name
|
|
||||||
%tr
|
%tr
|
||||||
%td {booth_title}
|
%td {booth_title}
|
||||||
%td Booth's title
|
%td Booth's title
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,7 @@
|
||||||
%td
|
%td
|
||||||
= link_to @event.submitter.name, admin_user_path(@event.submitter)
|
= link_to @event.submitter.name, admin_user_path(@event.submitter)
|
||||||
- if @event.submitter.email_public
|
- if @event.submitter.email_public
|
||||||
(
|
(#{mail_to(@event.submitter.email)})
|
||||||
= link_to @event.submitter.email, "mailto: #{@event.submitter.email}"
|
|
||||||
)
|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%b Speakers
|
%b Speakers
|
||||||
|
|
@ -84,9 +82,7 @@
|
||||||
%div
|
%div
|
||||||
= link_to speaker.name, admin_user_path(speaker)
|
= link_to speaker.name, admin_user_path(speaker)
|
||||||
- if speaker.email_public
|
- if speaker.email_public
|
||||||
(
|
(#{mail_to(speaker.email)})
|
||||||
= link_to speaker.email, "mailto: #{speaker.email}"
|
|
||||||
)
|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%b Volunteers
|
%b Volunteers
|
||||||
|
|
@ -117,11 +113,17 @@
|
||||||
%td
|
%td
|
||||||
%b Submission Description
|
%b Submission Description
|
||||||
%td= markdown(@event.submission_text)
|
%td= markdown(@event.submission_text)
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%b Requirements
|
%b Requirements
|
||||||
%td= simple_format(@event.description)
|
%td= simple_format(@event.description)
|
||||||
|
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
%b Committee Review
|
||||||
|
%td= markdown(@event.committee_review)
|
||||||
|
|
||||||
- if @conference.program.rating_enabled?
|
- if @conference.program.rating_enabled?
|
||||||
= render 'voting',
|
= render 'voting',
|
||||||
event: @event,
|
event: @event,
|
||||||
|
|
|
||||||
|
|
@ -22,20 +22,20 @@
|
||||||
- if voting_period
|
- if voting_period
|
||||||
- max_rating.times do |counter|
|
- max_rating.times do |counter|
|
||||||
- if event.user_rating(current_user) > counter
|
- if event.user_rating(current_user) > counter
|
||||||
= link_to '',
|
= link_to('',
|
||||||
vote_admin_conference_program_event_path(conference_id,
|
vote_admin_conference_program_event_path(conference_id,
|
||||||
event, rating: counter + 1),
|
event, rating: counter + 1),
|
||||||
remote: true,
|
remote: true,
|
||||||
id: "label#{counter + 1}",
|
id: "label#{counter + 1}",
|
||||||
class: 'rating myrating bright',
|
class: 'rating myrating bright',
|
||||||
voted: true
|
voted: true)
|
||||||
- else
|
- else
|
||||||
= link_to '',
|
= link_to('',
|
||||||
vote_admin_conference_program_event_path(conference_id,
|
vote_admin_conference_program_event_path(conference_id,
|
||||||
event, rating: counter + 1),
|
event, rating: counter + 1),
|
||||||
remote: true,
|
remote: true,
|
||||||
id: "label#{counter + 1}",
|
id: "label#{counter + 1}",
|
||||||
class: 'rating myrating'
|
class: 'rating myrating')
|
||||||
- else
|
- else
|
||||||
= rating_stars(event.user_rating(current_user), max_rating, voted: true)
|
= rating_stars(event.user_rating(current_user), max_rating, voted: true)
|
||||||
(Voting period is closed)
|
(Voting period is closed)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
%i{ class: "fa-li #{icon_for_todo @splashpage.include_social_media?}" }
|
%i{ class: "fa-li #{icon_for_todo @splashpage.include_social_media?}" }
|
||||||
Display social media links
|
Display social media links
|
||||||
%li
|
%li
|
||||||
- if @conference.splashpage && @conference.splashpage.public
|
- if @conference.splashpage && @conference.splashpage.public?
|
||||||
%i{ class: "fa-li #{icon_for_todo @splashpage.public?}" }
|
%i{ class: "fa-li #{icon_for_todo @splashpage.public?}" }
|
||||||
%text-muted.publicorprivate Public
|
%text-muted.publicorprivate Public
|
||||||
- else
|
- else
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
.col-md-12
|
.col-md-12
|
||||||
%table.datatable
|
%table.datatable
|
||||||
%thead
|
%thead
|
||||||
%th #
|
%th ID
|
||||||
%th Name
|
%th Name
|
||||||
%th Quantity
|
%th Quantity
|
||||||
%th E-Mail
|
%th E-Mail
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
- purchases = buyer.ticket_purchases.where(ticket_id: @ticket.id)
|
- purchases = buyer.ticket_purchases.where(ticket_id: @ticket.id)
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
= index + 1
|
= purchases.length == 1 ? purchases.first.id : purchases.map(&:id)
|
||||||
%td
|
%td
|
||||||
= buyer.name
|
= buyer.name
|
||||||
%td
|
%td
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,21 @@
|
||||||
= render 'happening_now', conference: conference,
|
= render 'happening_now', conference: conference,
|
||||||
events_schedules: events_schedules, pagy: pagy,
|
events_schedules: events_schedules, pagy: pagy,
|
||||||
events_schedules_length: events_schedules_length,
|
events_schedules_length: events_schedules_length,
|
||||||
events_schedules_limit: events_schedules_limit
|
events_schedules_limit: events_schedules_limit,
|
||||||
|
is_happening_next: is_happening_next
|
||||||
|
|
||||||
= content_for :about do
|
= content_for :about do
|
||||||
#about
|
#about
|
||||||
.row
|
.row
|
||||||
%h2.text-left{ style: 'margin-bottom:30px' } About the Conference
|
|
||||||
= markdown(conference.description, false)
|
= markdown(conference.description, false)
|
||||||
|
|
||||||
%section#about-and-happening-now
|
%section#about-and-happening-now
|
||||||
.container
|
.container
|
||||||
.row
|
.row
|
||||||
-# happening now events are displayed second in md or lg view
|
-# happening now events are displayed second in md or lg view
|
||||||
- if conference.splashpage.include_happening_now && conference.splashpage.include_program
|
- if conference.splashpage.include_happening_now? && conference.splashpage.include_program?
|
||||||
- if conference.description.present?
|
- if conference.description.present?
|
||||||
.col-md-6.col-md-push-6.col-lg-4.col-lg-push-8
|
.col-md-6.col-md-push-6.col-lg-4.col-lg-push-8{ style: 'margin-top: 60px' }
|
||||||
= yield :happening_now
|
= yield :happening_now
|
||||||
- else
|
- else
|
||||||
.col-md-12
|
.col-md-12
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
- if conference.splashpage.include_program && conference.splashpage.include_happening_now
|
- if events_schedules.present? && events_schedules.any?
|
||||||
- if events_schedules.any?
|
|
||||||
.row
|
.row
|
||||||
%h2.text-center{ style: 'margin-bottom:30px' } Happening Now
|
%h3.text-left{ style: 'margin-bottom:30px; padding-left:20px' }
|
||||||
|
- if is_happening_next
|
||||||
|
Events Happening Next
|
||||||
|
- else
|
||||||
|
Events Happening Now
|
||||||
- events_schedules.each do |event_schedule|
|
- events_schedules.each do |event_schedule|
|
||||||
= render 'schedules/event', conference: conference, event_schedule: event_schedule, event: event_schedule.event, is_brief: true
|
= render 'schedules/event', conference: conference, event_schedule: event_schedule, event: event_schedule.event, is_brief: true
|
||||||
- if events_schedules_length > events_schedules_limit
|
- if events_schedules_length > events_schedules_limit
|
||||||
|
|
@ -9,4 +12,4 @@
|
||||||
!= pagy_bootstrap_nav_js(pagy)
|
!= pagy_bootstrap_nav_js(pagy)
|
||||||
- else
|
- else
|
||||||
.row
|
.row
|
||||||
%h3.text-center There are no events happening now.
|
%h3.text-center There are no events scheduled yet.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
- cache [conference, venue, '#splash#header'] do
|
- cache [conference, venue, '#splash#header'] do
|
||||||
#banner{ style: ("background-image: url(#{conference.picture_url})" if conference.picture_url) }
|
#banner{ style: ("background-image: url(#{conference.picture_url})" if conference.picture_url) }
|
||||||
.container
|
.container
|
||||||
|
- if user_signed_in?
|
||||||
|
- if current_user.ticket_purchases.by_conference(@conference).empty?
|
||||||
|
.alert.bg-info{ :role => "alert", :style => "margin-bottom: 100px" }
|
||||||
|
You have not purchased any tickets for this conference yet.
|
||||||
|
= link_to "Book your tickets now!", "#tickets"
|
||||||
.row
|
.row
|
||||||
.col-md-6.col-md-offset-3{ id: (conference.picture? ? "header-image" : "header-no-image") }
|
.col-md-6.col-md-offset-3{ id: (conference.picture? ? "header-image" : "header-no-image") }
|
||||||
.row
|
.row
|
||||||
|
|
|
||||||
|
|
@ -49,21 +49,22 @@
|
||||||
= render 'about_and_happening_now', conference: @conference,
|
= render 'about_and_happening_now', conference: @conference,
|
||||||
events_schedules: @events_schedules, pagy: @pagy,
|
events_schedules: @events_schedules, pagy: @pagy,
|
||||||
events_schedules_length: @events_schedules_length,
|
events_schedules_length: @events_schedules_length,
|
||||||
events_schedules_limit: @events_schedules_limit
|
events_schedules_limit: @events_schedules_limit,
|
||||||
|
is_happening_next: @is_happening_next
|
||||||
|
|
||||||
-# calls for content, or program
|
-# calls for content, or program
|
||||||
- if @conference.splashpage.include_cfp
|
- if @conference.splashpage.include_cfp?
|
||||||
= render 'call_for_content', conference: @conference,
|
= render 'call_for_content', conference: @conference,
|
||||||
call_for_events: @call_for_events, call_for_tracks: @call_for_tracks,
|
call_for_events: @call_for_events, call_for_tracks: @call_for_tracks,
|
||||||
call_for_booths: @call_for_booths,
|
call_for_booths: @call_for_booths,
|
||||||
event_types: @event_types, tracks: @track_names
|
event_types: @event_types, tracks: @track_names
|
||||||
|
|
||||||
- if @conference.splashpage.include_program
|
- if @conference.splashpage.include_program?
|
||||||
= render 'program', conference: @conference, tracks: @tracks,
|
= render 'program', conference: @conference, tracks: @tracks,
|
||||||
highlights: @highlights, booths: @booths
|
highlights: @highlights, booths: @booths
|
||||||
|
|
||||||
-# attendance/registration
|
-# attendance/registration
|
||||||
- if @conference.splashpage.include_registrations
|
- if @conference.splashpage.include_registrations?
|
||||||
- if @conference.registration_open?
|
- if @conference.registration_open?
|
||||||
= render 'registration', conference: @conference,
|
= render 'registration', conference: @conference,
|
||||||
registration_period: @conference.registration_period,
|
registration_period: @conference.registration_period,
|
||||||
|
|
@ -72,20 +73,20 @@
|
||||||
= render 'tickets', conference: @conference, tickets: @tickets
|
= render 'tickets', conference: @conference, tickets: @tickets
|
||||||
|
|
||||||
-# geo
|
-# geo
|
||||||
- if @conference.splashpage.include_venue && @conference.venue
|
- if @conference.splashpage.include_venue? && @conference.venue
|
||||||
= render 'venue', conference: @conference, venue: @conference.venue,
|
= render 'venue', conference: @conference, venue: @conference.venue,
|
||||||
commercial: @conference.venue.commercial
|
commercial: @conference.venue.commercial
|
||||||
- if @conference.splashpage.include_lodgings && @conference.lodgings.any?
|
- if @conference.splashpage.include_lodgings && @conference.lodgings.any?
|
||||||
= render 'lodging', venue: @conference.venue, lodgings: @lodgings
|
= render 'lodging', venue: @conference.venue, lodgings: @lodgings
|
||||||
|
|
||||||
-# sponsorship
|
-# sponsorship
|
||||||
- if @conference.splashpage.include_sponsors
|
- if @conference.splashpage.include_sponsors?
|
||||||
= render 'sponsors', conference: @conference,
|
= render 'sponsors', conference: @conference,
|
||||||
sponsorship_levels: @sponsorship_levels,
|
sponsorship_levels: @sponsorship_levels,
|
||||||
sponsors: @sponsors
|
sponsors: @sponsors
|
||||||
|
|
||||||
-# footer
|
-# footer
|
||||||
- if @conference.splashpage.include_social_media
|
- if @conference.splashpage.include_social_media?
|
||||||
- if @conference.contact.has_social_media?
|
- if @conference.contact.has_social_media?
|
||||||
= render 'social_media', contact: @conference.contact
|
= render 'social_media', contact: @conference.contact
|
||||||
= render 'footer'
|
= render 'footer'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
$('#happening-now').html("<%= j(render 'happening_now', conference: @conference,
|
$('#happening-now').html("<%= j(render 'happening_now', conference: @conference,
|
||||||
events_schedules: @events_schedules, pagy: @pagy,
|
events_schedules: @events_schedules, pagy: @pagy,
|
||||||
events_schedules_length: @events_schedules_length,
|
events_schedules_length: @events_schedules_length,
|
||||||
events_schedules_limit: @events_schedules_limit)%>");
|
events_schedules_limit: @events_schedules_limit,
|
||||||
|
is_happening_next: @is_happening_next) %>");
|
||||||
Pagy.init(document.getElementById('happening-now'));
|
Pagy.init(document.getElementById('happening-now'));
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<% if @conference.present? %>
|
<% if false && @conference.present? %>
|
||||||
<%= image_tag(conference_logo_url(@conference), style: "display:block;height:70px;width:auto;", alt: @conference.title + ' logo') %>
|
<%= image_tag(conference_logo_url(@conference), style: "display:block;height:70px;width:auto;", alt: @conference.title + ' logo') %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= image_tag(Organization.first.picture_url, style: "display:block;height:70px;width:auto;", alt: ENV['OSEM_NAME'] + ' logo') %>
|
<%= image_tag(Organization.first.picture_url, style: "display:block;height:70px;width:auto;", alt: ENV['OSEM_NAME'] + ' logo') %>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<%= render partial: "layouts/mailbot_header" %>
|
<%= render partial: "layouts/mailbot_header" %>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<span style="white-space: pre-line">
|
<span style="white-space: pre-line">
|
||||||
<%= @email_body %>
|
<%= @email_body.html_safe %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<%= render partial: "layouts/mailbot_footer" %>
|
<%= render partial: "layouts/mailbot_footer" %>
|
||||||
|
|
@ -27,6 +27,20 @@
|
||||||
|
|
||||||
= render 'proposals/submission_type_content_form', f: f, program: @program
|
= render 'proposals/submission_type_content_form', f: f, program: @program
|
||||||
|
|
||||||
|
-# TODO-SNAPCON: Extract this to be a `conference_committee_role?`
|
||||||
|
- if current_user.has_any_role?(:admin, { name: :organizer, resource: @conference }, { name: :cfp, resource: @conference })
|
||||||
|
%br
|
||||||
|
= f.input :committee_review,
|
||||||
|
input_html: { rows: 5, data: { provide: 'markdown' } },
|
||||||
|
hint: markdown_hint('This field is shared with the submission authors.')
|
||||||
|
- elsif @event.committee_review.present?
|
||||||
|
%br
|
||||||
|
%strong.control-label Committee Review
|
||||||
|
%small
|
||||||
|
Use this feedback to improve your submission.
|
||||||
|
.well
|
||||||
|
= markdown(@event.committee_review)
|
||||||
|
|
||||||
- if @program.cfp&.enable_registrations?
|
- if @program.cfp&.enable_registrations?
|
||||||
= f.inputs 'Enable pre-registration' do
|
= f.inputs 'Enable pre-registration' do
|
||||||
= f.input :require_registration, label: 'Require participants to register to your event'
|
= f.input :require_registration, label: 'Require participants to register to your event'
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
%p.text-right
|
-# %p.text-right
|
||||||
= link_to '#status-help', class: 'btn btn-default', "data-toggle"=>"collapse" do
|
= link_to '#status-help', class: 'btn btn-default', "data-toggle": "collapse" do
|
||||||
Help?
|
Help?
|
||||||
.collapse#status-help
|
-# .collapse#status-help
|
||||||
%p
|
%p
|
||||||
%strong
|
%strong
|
||||||
What happens next with my proposal?
|
What happens next with my proposal?
|
||||||
|
|
@ -80,8 +80,11 @@
|
||||||
%br
|
%br
|
||||||
= link_to registered_text(event), registrations_conference_program_proposal_path(@conference.short_title, event), class: 'btn btn-xs btn-danger'
|
= link_to registered_text(event), registrations_conference_program_proposal_path(@conference.short_title, event), class: 'btn btn-xs btn-danger'
|
||||||
|
|
||||||
%td.col-md-2{style: "padding:20px 8px 20px 8px;"}
|
-# %td.col-md-2{style: "padding:20px 8px 20px 8px;"}
|
||||||
= link_to 'Complete your proposal', 'javascript: void(0)', "type"=>"button", "data-trigger"=>"focus", "data-toggle"=>"popover", "title"=>"Your todo list", "data-content"=>"#{render partial: 'tooltip', locals: { event: event} }"
|
%a{href: '#', type: "button", "data-trigger": "click focus", "data-toggle": "popover",
|
||||||
|
title: "Your todo list",
|
||||||
|
"data-content": "#{render 'tooltip', event: event}" }
|
||||||
|
Complete your proposal
|
||||||
- if can? :create, @conference.registrations.new
|
- if can? :create, @conference.registrations.new
|
||||||
- progress_percentage = event.calculate_progress
|
- progress_percentage = event.calculate_progress
|
||||||
.progress
|
.progress
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
.col-md-4
|
.col-md-4
|
||||||
%p{style: "margin-top: 20px"}
|
%p{style: "margin-top: 20px"}
|
||||||
- if @event_schedule&.start_time
|
- if @event_schedule&.start_time
|
||||||
|
- if user_signed_in?
|
||||||
= link_to google_calendar_link(@event_schedule), target: '_blank', class: 'btn btn-success btn-mini' do
|
= link_to google_calendar_link(@event_schedule), target: '_blank', class: 'btn btn-success btn-mini' do
|
||||||
%i.fa.fa-calendar
|
%i.fa.fa-calendar
|
||||||
Add to Google Calendar (beta)
|
Add to Google Calendar (beta)
|
||||||
|
|
@ -51,7 +52,7 @@
|
||||||
- @event.volunteers.each do |volunteer|
|
- @event.volunteers.each do |volunteer|
|
||||||
= render 'volunteer_info', speaker: volunteer, show_bio: false
|
= render 'volunteer_info', speaker: volunteer, show_bio: false
|
||||||
|
|
||||||
.col-md-9
|
.col-md-6
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.lead
|
.lead
|
||||||
|
|
@ -138,3 +139,29 @@
|
||||||
- if @surveys_after_event.any? && @event.ended?
|
- if @surveys_after_event.any? && @event.ended?
|
||||||
.page-header
|
.page-header
|
||||||
= render partial: 'surveys/list', locals: { surveys: @surveys_after_event, conference: @conference }
|
= render partial: 'surveys/list', locals: { surveys: @surveys_after_event, conference: @conference }
|
||||||
|
.col-md-3
|
||||||
|
#happening-now
|
||||||
|
= render 'conferences/happening_now', conference: @conference,
|
||||||
|
events_schedules: @events_schedules, pagy: @pagy,
|
||||||
|
events_schedules_length: @events_schedules_length,
|
||||||
|
events_schedules_limit: @events_schedules_limit,
|
||||||
|
is_happening_next: @is_happening_next
|
||||||
|
|
||||||
|
- if @event.committee_review.present? || @event.submission_text.present? && can?(:edit, @event)
|
||||||
|
%hr
|
||||||
|
%p Information for event authors only:
|
||||||
|
.panel.panel-info
|
||||||
|
.panel-heading
|
||||||
|
Committee Review
|
||||||
|
%button.btn.btn-primary.btn-xs{ type: "button", 'data-toggle': "collapse", 'data-target': "#committee-panel", 'aria-expanded': "false", 'aria-controls': "committee-panel" }
|
||||||
|
Toggle
|
||||||
|
.panel-body.collapse#committee-panel
|
||||||
|
= markdown(@event.committee_review)
|
||||||
|
|
||||||
|
.panel.panel-info
|
||||||
|
.panel-heading
|
||||||
|
Submission Details
|
||||||
|
%button.btn.btn-primary.btn-xs{ type: "button", 'data-toggle': "collapse", 'data-target': "#submission-panel", 'aria-expanded': "false", 'aria-controls': "submission-panel" }
|
||||||
|
Toggle
|
||||||
|
.panel-body.collapse#submission-panel
|
||||||
|
= markdown(@event.submission_text)
|
||||||
|
|
|
||||||
6
app/views/proposals/show.js.erb
Normal file
6
app/views/proposals/show.js.erb
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
$('#happening-now').html("<%= j(render 'conferences/happening_now', conference: @conference,
|
||||||
|
events_schedules: @events_schedules, pagy: @pagy,
|
||||||
|
events_schedules_length: @events_schedules_length,
|
||||||
|
events_schedules_limit: @events_schedules_limit,
|
||||||
|
is_happening_next: @is_happening_next) %>");
|
||||||
|
Pagy.init(document.getElementById('happening-now'));
|
||||||
12
app/views/schedules/vertical_schedule.haml
Normal file
12
app/views/schedules/vertical_schedule.haml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
.container#program
|
||||||
|
= render 'schedule_tabs', active: 'vertical_schedule'
|
||||||
|
|
||||||
|
%h1.text-center
|
||||||
|
Vertical Schedule for
|
||||||
|
= @conference.title
|
||||||
|
|
||||||
|
#vert-schedule-full-calendar
|
||||||
|
#fullcalendar{ data: { rooms: @rooms, events: @event_schedules, day: @day,
|
||||||
|
'start-hour': @conference.start_hour, 'end-hour': @conference.end_hour,
|
||||||
|
'start-date': @conference.start_date, 'end-date': @conference.end_date + 1.day,
|
||||||
|
'timezone': @conference.timezone, 'now': @now } }
|
||||||
|
|
@ -80,5 +80,11 @@ module Osem
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.assets.paths << Rails.root.join('node_modules')
|
||||||
|
|
||||||
|
config.fullcalendar = {
|
||||||
|
license_key: ENV['FULL_CALENDAR_LICENSE_KEY']
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ Osem::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resource :program, only: [] do
|
resource :program, only: [] do
|
||||||
|
get 'event/:id', to: 'proposals#show', as: :conference_program_event
|
||||||
get 'proposal/:id', to: 'proposals#show' # For backward compatibility
|
get 'proposal/:id', to: 'proposals#show' # For backward compatibility
|
||||||
resources :proposals, except: :destroy do
|
resources :proposals, except: :destroy do
|
||||||
get 'commercials/render_commercial' => 'commercials#render_commercial'
|
get 'commercials/render_commercial' => 'commercials#render_commercial'
|
||||||
|
|
@ -202,6 +203,7 @@ Osem::Application.routes.draw do
|
||||||
member do
|
member do
|
||||||
get :events
|
get :events
|
||||||
get :happening_now
|
get :happening_now
|
||||||
|
get :vertical_schedule
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -221,9 +223,11 @@ Osem::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/admin' => redirect('/admin/conferences')
|
# Handle conferences on custom domains.
|
||||||
|
# This *must* come before any other root definition.
|
||||||
get '/calendar' => 'conferences#calendar'
|
constraints DomainConstraint do
|
||||||
|
root to: 'conferences#show'
|
||||||
|
end
|
||||||
|
|
||||||
unless ENV['OSEM_ROOT_CONFERENCE'].blank?
|
unless ENV['OSEM_ROOT_CONFERENCE'].blank?
|
||||||
root to: redirect("/conferences/#{ENV['OSEM_ROOT_CONFERENCE']}")
|
root to: redirect("/conferences/#{ENV['OSEM_ROOT_CONFERENCE']}")
|
||||||
|
|
@ -231,9 +235,10 @@ Osem::Application.routes.draw do
|
||||||
root to: 'conferences#index', via: [:get, :options]
|
root to: 'conferences#index', via: [:get, :options]
|
||||||
end
|
end
|
||||||
|
|
||||||
constraints DomainConstraint do
|
get '/admin' => redirect('/admin/conferences')
|
||||||
root to: 'conferences#show'
|
get '/calendar' => 'conferences#calendar'
|
||||||
end
|
|
||||||
|
|
||||||
get '/.well-known/apple-developer-merchantid-domain-association', to: 'application#apple_pay'
|
get '/.well-known/apple-developer-merchantid-domain-association', to: 'application#apple_pay'
|
||||||
|
|
||||||
|
# A Short Fallback Route
|
||||||
|
get '/:id', to: 'conferences#show'
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddCommitteeReviewToEvents < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :events, :committee_review, :text
|
||||||
|
end
|
||||||
|
end
|
||||||
11
package-lock.json
generated
Normal file
11
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"requires": true,
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"fullcalendar-scheduler": {
|
||||||
|
"version": "5.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fullcalendar-scheduler/-/fullcalendar-scheduler-5.6.0.tgz",
|
||||||
|
"integrity": "sha512-0jx/Q+6QqzvIGWU/52OE27UVjVAiM9E0o/qRwRcEhyuKlL54ypTF/yXP/wo0ctUtui5dDsilGNsSsba1xmARJA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
package.json
Normal file
5
package.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"fullcalendar-scheduler": "^5.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -72,4 +72,20 @@ describe SchedulesController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET #vertical_schedule' do
|
||||||
|
let!(:program) { conference.program }
|
||||||
|
|
||||||
|
context 'as a conference participant' do
|
||||||
|
context 'who visits the schedule page' do
|
||||||
|
before(:each) do
|
||||||
|
get :vertical_schedule, params: { conference_id: conference.short_title }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a successful response' do
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -80,25 +80,6 @@ FactoryBot.define do
|
||||||
last_sign_in_at { Date.today }
|
last_sign_in_at { Date.today }
|
||||||
is_disabled { false }
|
is_disabled { false }
|
||||||
|
|
||||||
after(:build) do |user|
|
|
||||||
url_mailbluster = 'https://api.mailbluster.com/api/leads/'
|
|
||||||
response_body = "{
|
|
||||||
\"message\": \"Lead created\",
|
|
||||||
\"lead\": {
|
|
||||||
\"id\": 329395,
|
|
||||||
\"firstName\": \"#{user.name}\",
|
|
||||||
\"lastName\": \"\",
|
|
||||||
\"fullName\": \"#{user.name}\",
|
|
||||||
\"email\": \"#{user.email}\",
|
|
||||||
\"subscribed\": true,
|
|
||||||
\"tags\": [
|
|
||||||
#{ENV['OSEM_NAME'] || 'snapcon'}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
WebMock.stub_request(:post, url_mailbluster)
|
|
||||||
.to_return(body: response_body, status: 200)
|
|
||||||
end
|
|
||||||
# Called by every user creation
|
# Called by every user creation
|
||||||
|
|
||||||
after(:create) do |user|
|
after(:create) do |user|
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,18 @@ feature Commercial do
|
||||||
let!(:participant) { create(:user) }
|
let!(:participant) { create(:user) }
|
||||||
|
|
||||||
context 'in admin area' do
|
context 'in admin area' do
|
||||||
scenario 'adds, updates, deletes of a conference', feature: true, js: true do
|
|
||||||
|
before do
|
||||||
sign_in organizer
|
sign_in organizer
|
||||||
|
|
||||||
visit admin_conference_commercials_path(conference.short_title)
|
visit admin_conference_commercials_path(conference.short_title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'contains the conference name in the title', feature: true, js: true do
|
||||||
|
header = conference.title + ' Materials'
|
||||||
|
expect(page).to have_content(header)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'adds, updates, deletes of a conference', feature: true, js: true do
|
||||||
# Create valid commercial
|
# Create valid commercial
|
||||||
fill_in 'commercial_url', with: 'https://www.youtube.com/watch?v=M9bq_alk-sw'
|
fill_in 'commercial_url', with: 'https://www.youtube.com/watch?v=M9bq_alk-sw'
|
||||||
click_button 'Save Materials'
|
click_button 'Save Materials'
|
||||||
|
|
|
||||||
|
|
@ -212,4 +212,128 @@ feature Event do
|
||||||
expect(page.find('#event_submission_text').value).to eq(event_type.submission_instructions)
|
expect(page.find('#event_submission_text').value).to eq(event_type.submission_instructions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'as a user, looking at a conference with scheduled events' do
|
||||||
|
before(:each) do
|
||||||
|
@program = conference.program
|
||||||
|
@selected_schedule = create(:schedule, program: @program)
|
||||||
|
@program.update_attributes!(selected_schedule: @selected_schedule)
|
||||||
|
@scheduled_event1 = create(:event, program: @program, state: 'confirmed', abstract: '`markdown`')
|
||||||
|
@event_schedule1 = create(:event_schedule, event: @scheduled_event1, schedule: @selected_schedule, start_time: conference.start_hour + 1.hour)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'for a scheduled event, can add an event to google calendar if signed in', feature: true do
|
||||||
|
sign_in participant
|
||||||
|
visit conference_program_proposal_path(conference.short_title, @scheduled_event1.id)
|
||||||
|
expect(page).to have_content('Add to Google Calendar (beta)')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'for a scheduled event, cannot add an event to google calendar if not signed on', feature: true do
|
||||||
|
visit conference_program_proposal_path(conference.short_title, @scheduled_event1.id)
|
||||||
|
expect(page).not_to have_content('Add to Google Calendar (beta)')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'happening now or next section' do
|
||||||
|
let!(:conference1) { create(:full_conference, start_date: 1.day.ago, end_date: 7.days.from_now, start_hour: 0, end_hour: 24) }
|
||||||
|
let!(:program) { conference1.program }
|
||||||
|
let!(:selected_schedule) { create(:schedule, program: program) }
|
||||||
|
let!(:splashpage) { create(:full_splashpage, conference: conference1, public: true) }
|
||||||
|
|
||||||
|
let!(:scheduled_event1) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event2) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event3) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event4) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:current_time) { Time.now.in_time_zone(conference1.timezone) }
|
||||||
|
|
||||||
|
let!(:events_list) { [scheduled_event1, scheduled_event2, scheduled_event3, scheduled_event4] }
|
||||||
|
|
||||||
|
before :each do
|
||||||
|
sign_in participant
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'No events happening now or next' do
|
||||||
|
events_list.each do |event|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content('There are no events scheduled yet.')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'shows all events happening next if nothing is happening now' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
|
||||||
|
events_list.each do |event|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).not_to have_content(scheduled_event3.title)
|
||||||
|
expect(happening_now).not_to have_content(scheduled_event4.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows all events happening now if something is happening now and next' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
events_list.each do |event|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).not_to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule3.event.title)
|
||||||
|
expect(happening_now).not_to have_content(scheduled_event4.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows events happening at the earliest time, not at a later time in the future' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: (current_time + 2.hours).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
events_list.each do |event|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule3.event.title)
|
||||||
|
expect(happening_now).not_to have_content(scheduled_event4.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows 3 events happening now because of pagination' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule4 = create(:event_schedule, event: scheduled_event4, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
|
||||||
|
events_list.each do |event|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule3.event.title)
|
||||||
|
|
||||||
|
visit conference_program_proposal_path(conference1.short_title, event.id, page: 2)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).not_to have_content(event_schedule3.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule4.event.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -80,4 +80,127 @@ feature Splashpage do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'happening now section', feature: true, js: true do
|
||||||
|
let!(:conference2) { create(:full_conference, start_date: 1.day.ago, end_date: 7.days.from_now, start_hour: 0, end_hour: 24) }
|
||||||
|
let!(:program) { conference2.program }
|
||||||
|
let!(:selected_schedule) { create(:schedule, program: program) }
|
||||||
|
let!(:splashpage) { create(:full_splashpage, conference: conference2, public: true)}
|
||||||
|
|
||||||
|
let!(:scheduled_event1) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed', abstract: '`markdown`')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event2) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event3) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:scheduled_event4) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:current_time) { Time.now.in_time_zone(conference2.timezone) }
|
||||||
|
|
||||||
|
before :each do
|
||||||
|
sign_in participant
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'displays \'There are no events scheduled yet.\' if nothing is happening now and next' do
|
||||||
|
visit conference_path(conference2.short_title)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content('There are no events scheduled yet.')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'shows all events happening next if nothing is happening now' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
visit conference_path(conference2.short_title)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows all events happening now if something is happening now and next' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
visit conference_path(conference2.short_title)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule3.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule2.event.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows events happening at the earliest time, not at a later time in the future' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: (current_time + 2.hours).strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
visit conference_path(conference2.short_title)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule3.event.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'only shows 3 events happening now because of pagination' do
|
||||||
|
event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
event_schedule4 = create(:event_schedule, event: scheduled_event4, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S'))
|
||||||
|
|
||||||
|
visit conference_path(conference2.short_title)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule1.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule2.event.title)
|
||||||
|
expect(happening_now).to have_content(event_schedule3.event.title)
|
||||||
|
expect(happening_now).not_to have_content(event_schedule4.event.title)
|
||||||
|
|
||||||
|
visit conference_path(conference2.short_title, page: 2)
|
||||||
|
happening_now = page.find('#happening-now')
|
||||||
|
expect(happening_now).to have_content(event_schedule4.event.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'clarify registration status' do
|
||||||
|
let!(:splashpage) { create(:splashpage, conference: conference, public: true)}
|
||||||
|
let!(:ticket_1) { create(:ticket) }
|
||||||
|
let!(:free_ticket) { create(:ticket, price_cents: 0) }
|
||||||
|
|
||||||
|
scenario 'user signed in with no tickets', feature: true do
|
||||||
|
sign_in participant
|
||||||
|
visit conference_path(conference.short_title)
|
||||||
|
expect(page).to have_content 'You have not purchased any tickets for this conference yet.'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user signed in with 1 free ticket', feature: true do
|
||||||
|
sign_in participant
|
||||||
|
create(:ticket_purchase, conference: conference, user: participant, ticket: free_ticket, quantity: 1)
|
||||||
|
visit conference_path(conference.short_title)
|
||||||
|
expect(page).not_to have_content 'You have not purchased any tickets for this conference yet.'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user signed in with 1 paid ticket', feature: true do
|
||||||
|
sign_in participant
|
||||||
|
create(:ticket_purchase, conference: conference, user: participant, ticket: ticket_1, quantity: 1)
|
||||||
|
visit conference_path(conference.short_title)
|
||||||
|
expect(page).not_to have_content 'You have not purchased any tickets for this conference yet.'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user signed in with multiple ticket', feature: true do
|
||||||
|
sign_in participant
|
||||||
|
create(:ticket_purchase, conference: conference, user: participant, ticket: ticket_1, quantity: 1)
|
||||||
|
create(:ticket_purchase, conference: conference, user: participant, ticket: free_ticket, quantity: 1)
|
||||||
|
visit conference_path(conference.short_title)
|
||||||
|
expect(page).not_to have_content 'You have not purchased any tickets for this conference yet.'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user not signed in', feature: true do
|
||||||
|
visit conference_path(conference.short_title)
|
||||||
|
expect(page).not_to have_content 'You have not purchased any tickets for this conference yet.'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -99,4 +99,39 @@ describe ConferenceHelper, type: :helper do
|
||||||
expect(conference_color(conference2)).to eq('#0B3559')
|
expect(conference_color(conference2)).to eq('#0B3559')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#get_happening_next_events_schedules' do
|
||||||
|
let!(:conference2) { create(:full_conference, start_date: 1.day.ago, end_date: 7.days.from_now, start_hour: 0, end_hour: 24) }
|
||||||
|
let!(:program) { conference2.program }
|
||||||
|
let!(:selected_schedule) { create(:schedule, program: program) }
|
||||||
|
let!(:scheduled_event1) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed', abstract: '`markdown`')
|
||||||
|
end
|
||||||
|
let!(:current_time) { Time.now.in_time_zone(conference2.timezone) }
|
||||||
|
let!(:event_schedule1) { create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
let!(:scheduled_event2) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:event_schedule2) { create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (current_time + 1.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
let!(:scheduled_event3) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:event_schedule3) { create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: (current_time - 1.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
let!(:scheduled_event4) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:event_schedule4) { create(:event_schedule, event: scheduled_event4, schedule: selected_schedule, start_time: (current_time + 2.hours).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
|
||||||
|
it 'returns all the events happening at the earliest time in the future but not later or in the past' do
|
||||||
|
events_schedules = get_happening_next_events_schedules(conference2)
|
||||||
|
expect(events_schedules).to include(event_schedule1)
|
||||||
|
expect(events_schedules).to include(event_schedule2)
|
||||||
|
expect(events_schedules).to_not include(event_schedule3)
|
||||||
|
expect(events_schedules).to_not include(event_schedule4)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,12 @@ describe EmailSettings do
|
||||||
|
|
||||||
context 'conference has event' do
|
context 'conference has event' do
|
||||||
before do
|
before do
|
||||||
event_hash = { 'eventtitle' => 'Talk about talks', 'proposalslink' => 'http://localhost:3000/conferences/goto/program/proposals' }
|
event_hash = {
|
||||||
|
'eventtitle' => 'Talk about talks',
|
||||||
|
'proposalslink' => 'http://localhost:3000/conferences/goto/program/proposals',
|
||||||
|
'committee_review' => nil,
|
||||||
|
'committee_review_html' => ''
|
||||||
|
}
|
||||||
expected_hash.merge!(event_hash)
|
expected_hash.merge!(event_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,4 +165,31 @@ describe EventSchedule do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'happening_later' do
|
||||||
|
let!(:conference2) { create(:full_conference, start_date: 1.day.ago, end_date: 7.days.from_now, start_hour: 0, end_hour: 24) }
|
||||||
|
let!(:program) { conference2.program }
|
||||||
|
let!(:selected_schedule) { create(:schedule, program: program) }
|
||||||
|
let!(:scheduled_event1) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed', abstract: '`markdown`')
|
||||||
|
end
|
||||||
|
let!(:event_schedule1) { create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: (Time.now.in_time_zone(conference2.timezone) + 1.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
let!(:scheduled_event2) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:event_schedule2) { create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, start_time: (Time.now.in_time_zone(conference2.timezone) + 2.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
let!(:scheduled_event3) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, state: 'confirmed')
|
||||||
|
end
|
||||||
|
let!(:event_schedule3) { create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, start_time: (Time.now.in_time_zone(conference2.timezone) - 1.hour).strftime('%a, %d %b %Y %H:%M:%S')) }
|
||||||
|
|
||||||
|
it 'returns true if the event is happening in the future' do
|
||||||
|
expect(event_schedule1.happening_later?).to be true
|
||||||
|
expect(event_schedule2.happening_later?).to be true
|
||||||
|
expect(event_schedule3.happening_later?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -119,9 +119,10 @@ describe Program do
|
||||||
expect(program.show_voting?).to eq true
|
expect(program.show_voting?).to eq true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO-SNAPCON: This should be updated / removed.
|
||||||
it 'returns false if we are still in votig period' do
|
it 'returns false if we are still in votig period' do
|
||||||
program.voting_end_date = Date.today + 1
|
program.voting_end_date = Date.today + 1
|
||||||
expect(program.show_voting?).to eq false
|
expect(program.show_voting?).to eq true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
72
spec/services/full_calendar_formatter_spec.rb
Normal file
72
spec/services/full_calendar_formatter_spec.rb
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe FullCalendarFormatter do
|
||||||
|
let!(:room1) { create(:room) }
|
||||||
|
let!(:room2) { create(:room) }
|
||||||
|
let!(:rooms) { [room1, room2] }
|
||||||
|
let!(:conference) { create(:full_conference) }
|
||||||
|
let!(:program) { conference.program }
|
||||||
|
let!(:selected_schedule) { create(:schedule, program: program) }
|
||||||
|
let!(:event_type1) { create(:event_type, color: '#ffffff') }
|
||||||
|
let!(:event1) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, event_type: event_type1)
|
||||||
|
end
|
||||||
|
let!(:event_schedule1) { create(:event_schedule, event: event1, schedule: selected_schedule, room: room1) }
|
||||||
|
let!(:event_type2) { create(:event_type, color: '#000000') }
|
||||||
|
let!(:event2) do
|
||||||
|
program.update_attributes!(selected_schedule: selected_schedule)
|
||||||
|
create(:event, program: program, room: room2, event_type: event_type2)
|
||||||
|
end
|
||||||
|
let!(:event_schedule2) { create(:event_schedule, event: event2, schedule: selected_schedule, room: room2) }
|
||||||
|
let!(:event_schedules) { [event_schedule1, event_schedule2] }
|
||||||
|
|
||||||
|
describe 'JSON formatting for FullCalendar' do
|
||||||
|
it 'translates rooms to resources' do
|
||||||
|
resources = described_class.rooms_to_resources(rooms)
|
||||||
|
expected_json = [
|
||||||
|
{
|
||||||
|
id: room1.guid,
|
||||||
|
title: room1.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: room2.guid,
|
||||||
|
title: room2.name
|
||||||
|
}
|
||||||
|
].to_json
|
||||||
|
expect(resources).to eq(expected_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translates event schedules to resources' do
|
||||||
|
resources = described_class.event_schedules_to_resources(event_schedules)
|
||||||
|
expected_json = [
|
||||||
|
{
|
||||||
|
id: event_schedule1.event.guid,
|
||||||
|
title: event_schedule1.event.title,
|
||||||
|
start: event_schedule1.start_time_in_conference_timezone,
|
||||||
|
end: event_schedule1.end_time_in_conference_timezone,
|
||||||
|
resourceId: room1.guid,
|
||||||
|
url: Rails.application.routes.url_helpers.conference_program_proposal_path(conference.short_title, event1.id),
|
||||||
|
borderColor: event1.event_type.color,
|
||||||
|
backgroundColor: event1.event_type.color,
|
||||||
|
textColor: 'black'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: event_schedule2.event.guid,
|
||||||
|
title: event_schedule2.event.title,
|
||||||
|
start: event_schedule2.start_time_in_conference_timezone,
|
||||||
|
end: event_schedule2.end_time_in_conference_timezone,
|
||||||
|
resourceId: room2.guid,
|
||||||
|
url: Rails.application.routes.url_helpers.conference_program_proposal_path(conference.short_title, event2.id),
|
||||||
|
borderColor: event2.event_type.color,
|
||||||
|
backgroundColor: event2.event_type.color,
|
||||||
|
textColor: 'white'
|
||||||
|
}
|
||||||
|
].to_json
|
||||||
|
|
||||||
|
expect(resources).to eq(expected_json)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue