diff --git a/Dockerfile b/Dockerfile index 2e9edc1e..1a6892a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,8 @@ WORKDIR /osem/ RUN bundle config set --local path 'vendor/bundle'; \ bundle install --jobs=4 --retry=3 -# Install our process manager -RUN gem install foreman +# Install our process manager / update chromedriver +RUN gem install foreman; \ + bundle exec bin/rails webdrivers:chromedriver:update CMD ["foreman", "start"] diff --git a/Gemfile b/Gemfile index beab8ce0..bb7ba51d 100644 --- a/Gemfile +++ b/Gemfile @@ -88,9 +88,6 @@ gem 'jquery-ui-rails', '~> 6.0.1' # for languages validation gem 'iso-639' -# as date picker -gem 'bootstrap3-datetimepicker-rails', '~> 4.17.47' - # data tables gem 'ajax-datatables-rails' gem 'jquery-datatables-rails' @@ -216,9 +213,7 @@ group :test do # as test framework gem 'capybara' gem 'database_cleaner' - gem 'geckodriver-helper' gem 'rspec-rails' - gem 'webdrivers' # for measuring test coverage gem 'simplecov-cobertura' # for describing models @@ -242,6 +237,9 @@ group :test do end group :development, :test do + # as capybara driver + gem 'webdrivers' + gem 'geckodriver-helper' # as debugger gem 'byebug' # to test new rails version diff --git a/Gemfile.lock b/Gemfile.lock index 2c2a62f1..92367775 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,8 +99,6 @@ GEM autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) bootstrap-switch-rails (3.3.3) - bootstrap3-datetimepicker-rails (4.17.47) - momentjs-rails (>= 2.8.1) builder (3.2.4) byebug (11.1.3) cancancan (3.6.1) @@ -292,8 +290,6 @@ GEM mini_mime (1.1.5) mini_portile2 (2.8.6) minitest (5.23.1) - momentjs-rails (2.29.4.1) - railties (>= 3.1) monetize (1.13.0) money (~> 6.12) money (6.19.0) @@ -618,7 +614,6 @@ DEPENDENCIES awesome_nested_set bootstrap-sass (~> 3.4.0) bootstrap-switch-rails (= 3.3.3) - bootstrap3-datetimepicker-rails (~> 4.17.47) byebug cancancan capybara diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index cf12a085..9a3b692a 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -31,8 +31,6 @@ //= require momentjs //= require leaflet //= require holderjs -//= require bootstrap-datetimepicker -//= require osem-datepickers //= require osem-datatables //= require osem-tickets //= require bootstrap-switch diff --git a/app/assets/javascripts/osem-datepickers.js b/app/assets/javascripts/osem-datepickers.js deleted file mode 100644 index d2c01bd1..00000000 --- a/app/assets/javascripts/osem-datepickers.js +++ /dev/null @@ -1,67 +0,0 @@ -// get current_date -var today = new Date().toISOString().slice(0, 10); -$(function () { - $("input[id^='datetimepicker']").datetimepicker({ - useCurrent: false, - sideBySide: true, - format: 'YYYY-MM-DD HH:mm' - }); - - $('.datetimepicker').datetimepicker({ - useCurrent: false, - sideBySide: true, - format: 'YYYY-MM-DD HH:mm' - }); - - $("#conference-start-datepicker").datetimepicker({ - useCurrent: false, - ignoreReadonly: true, - format: "YYYY-MM-DD", - }); - - $("#conference-end-datepicker").datetimepicker({ - useCurrent: false, - ignoreReadonly: true, - format: "YYYY-MM-DD" - }); - - // today <= start_registration <= end_registration <= end_conference - var end_conference = $('form').data('end-conference'); - - $('#registration-period-start-datepicker').datetimepicker({ - format: 'YYYY-MM-DD' - }); - - $('#registration-period-end-datepicker').datetimepicker({ - format: 'YYYY-MM-DD' - }); - - $("#conference-start-datepicker").on("dp.change",function (e) { - $('#conference-end-datepicker').data("DateTimePicker").minDate(e.date); - if (!$('#conference-end-datepicker').val()) { - $('#conference-end-datepicker').data("DateTimePicker").date(e.date); - } - }); - - $("#conference-start-datepicker").change(function (e) { - $('#conference-start-datepicker').val()?$('#conference-end-datepicker').data("DateTimePicker").minDate(e.date):$('#conference-end-datepicker').data("DateTimePicker").minDate(null); - }); - - $("#conference-end-datepicker").on("dp.change",function (e) { - $('#conference-start-datepicker').data("DateTimePicker").maxDate(e.date); - }); - - $("#conference-end-datepicker").change(function (e) { - $('#conference-end-datepicker').val()?$('#conference-start-datepicker').data("DateTimePicker").maxDate(e.date):$('#conference-start-datepicker').data("DateTimePicker").maxDate(null); - }); - - $("#registration-period-start-datepicker").on("dp.change",function (e) { - $('#registration-period-end-datepicker').data("DateTimePicker").minDate(e.date); - if (!$('#registration-period-end-datepicker').val()) { - $('#registration-period-end-datepicker').data("DateTimePicker").date(e.date); - } - }); - $("#registration-period-end-datepicker").on("dp.change",function (e) { - $('#registration-period-start-datepicker').data("DateTimePicker").maxDate(e.date); - }); -} ); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 576997ae..02dbfc64 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -9,7 +9,6 @@ *= require osem-splash *= require osem-fonts *= require bootstrap-markdown - *= require bootstrap-datetimepicker *= require leaflet *= require bootstrap3-switch *= require osem-payments diff --git a/app/assets/stylesheets/jquery-ui-timepicker-addon.css b/app/assets/stylesheets/jquery-ui-timepicker-addon.css deleted file mode 100644 index b93a85f6..00000000 --- a/app/assets/stylesheets/jquery-ui-timepicker-addon.css +++ /dev/null @@ -1,10 +0,0 @@ -.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } -.ui-timepicker-div dl { text-align: left; } -.ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; } -.ui-timepicker-div dl dd { margin: 0 10px 10px 65px; } -.ui-timepicker-div td { font-size: 90%; } -.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; } - -.ui-timepicker-rtl{ direction: rtl; } -.ui-timepicker-rtl dl { text-align: right; } -.ui-timepicker-rtl dl dd { margin: 0 65px 10px 10px; } \ No newline at end of file diff --git a/app/assets/stylesheets/strap-on.scss b/app/assets/stylesheets/strap-on.scss index 571161e6..feeecb29 100644 --- a/app/assets/stylesheets/strap-on.scss +++ b/app/assets/stylesheets/strap-on.scss @@ -5,7 +5,6 @@ $navbar-default-color: #ffffff; $navbar-default-link-color: #ffffff; $navbar-default-link-hover-color: #000000; -@import 'bootstrap-datetimepicker'; @import "bootstrap-sprockets"; // diff --git a/app/models/cfp.rb b/app/models/cfp.rb index 6571e701..ccc04097 100644 --- a/app/models/cfp.rb +++ b/app/models/cfp.rb @@ -125,7 +125,7 @@ class Cfp < ApplicationRecord def start_after_end_date errors - .add(:start_date, "can't be after the end date") if start_date && end_date && start_date > end_date + .add(:start_date, "can't be after the end date") if start_date > end_date end def conference_id diff --git a/app/models/registration_period.rb b/app/models/registration_period.rb index 66f02fe0..7902b42c 100644 --- a/app/models/registration_period.rb +++ b/app/models/registration_period.rb @@ -6,21 +6,32 @@ class RegistrationPeriod < ApplicationRecord has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } validates :start_date, :end_date, presence: true - validate :before_end_of_conference + validate :start_before_end_of_conference + validate :end_before_end_of_conference validate :start_date_before_end_date private - def before_end_of_conference - errors - .add(:start_date, "can't be after the conference end date (#{conference.end_date})") if conference&.end_date && start_date && (start_date > conference.end_date) + def start_before_end_of_conference + return unless conference + return unless start_date errors - .add(:end_date, "can't be after the conference end date (#{conference.end_date})") if conference&.end_date && end_date && (end_date > conference.end_date) + .add(:start_date, "can't start after the conference end date (#{conference.end_date})") if start_date > conference.end_date + end + + def end_before_end_of_conference + return unless conference + return unless end_date + + errors + .add(:end_date, "can't end after the conference end date (#{conference.end_date})") if end_date > conference.end_date end def start_date_before_end_date + return unless start_date && end_date + errors - .add(:start_date, "can't be after the end date") if start_date && end_date && start_date > end_date + .add(:start_date, "can't be after the end date") if start_date > end_date end end diff --git a/app/views/admin/cfps/_form.html.haml b/app/views/admin/cfps/_form.html.haml index f6af3687..de5ba1ed 100644 --- a/app/views/admin/cfps/_form.html.haml +++ b/app/views/admin/cfps/_form.html.haml @@ -2,10 +2,12 @@ = f.hidden_field :cfp_type .form-group = f.label :start_date, "Start Date" - = f.text_field :start_date, class: 'form-control', id: 'registration-period-start-datepicker', start_date: @conference.start_date, end_date: @conference.end_date + %abbr{title: 'This field is required'} * + = f.date_field :start_date, class: 'form-control', required: true .form-group = f.label :end_date, "End Date" - = f.text_field :end_date, class: 'form-control', id: 'registration-period-end-datepicker', start_date: @conference.start_date, end_date: @conference.end_date + %abbr{title: 'This field is required'} * + = f.date_field :end_date, class: 'form-control', required: true .form-group = f.label :description, "Description" = f.text_area :description, rows: 2, data: { provide: 'markdown' } diff --git a/app/views/admin/conferences/_form_fields.html.haml b/app/views/admin/conferences/_form_fields.html.haml index ceb72acc..afa644ed 100644 --- a/app/views/admin/conferences/_form_fields.html.haml +++ b/app/views/admin/conferences/_form_fields.html.haml @@ -49,11 +49,11 @@ .form-group = f.label :start_date, "Start Date" %abbr{title: 'This field is required'} * - = f.text_field :start_date, id: 'conference-start-datepicker', required: true, class: 'form-control' + = f.date_field :start_date, required: true, class: 'form-control' .form-group = f.label :end_date, "End Date" %abbr{title: 'This field is required'} * - = f.text_field :end_date, id: 'conference-end-datepicker', required: true, class: 'form-control' + = f.date_field :end_date, required: true, class: 'form-control' - unless f.object.new_record? # We are showing more fields on the edit form .form-group = f.number_field :start_hour, size: 2, min: 0, max: 23, class: 'form-control' diff --git a/app/views/admin/programs/_form.html.haml b/app/views/admin/programs/_form.html.haml index 037418bf..645cc79d 100644 --- a/app/views/admin/programs/_form.html.haml +++ b/app/views/admin/programs/_form.html.haml @@ -25,9 +25,9 @@ For the feature to work you need to set the voting dates below as well .form-group = f.label :voting_start_date - = f.text_field :voting_start_date, id: 'datetimepicker-voting_start_date', value: (f.object.voting_start_date.to_formatted_s(:db_without_seconds) unless f.object.voting_start_date.nil?), class: 'form-control' + = f.datetime_field :voting_start_date, value: (f.object.voting_start_date.to_formatted_s(:db_without_seconds) unless f.object.voting_start_date.nil?), class: 'form-control' = f.label :voting_end_date - = f.text_field :voting_end_date, id: 'datetimepicker-voting_end_date', value: (f.object.voting_end_date.to_formatted_s(:db_without_seconds) unless f.object.voting_end_date.nil?), class: 'form-control' + = f.datetime_field :voting_end_date, value: (f.object.voting_end_date.to_formatted_s(:db_without_seconds) unless f.object.voting_end_date.nil?), class: 'form-control' %h4 Languages %hr diff --git a/app/views/admin/registration_periods/_form.html.haml b/app/views/admin/registration_periods/_form.html.haml index 35b996b1..2bf25a57 100644 --- a/app/views/admin/registration_periods/_form.html.haml +++ b/app/views/admin/registration_periods/_form.html.haml @@ -1,11 +1,20 @@ +%p + Setup the time frame in which people can registrer to your conference = form_for(@registration_period, url: admin_conference_registration_period_path(@conference.short_title)) do |f| .form-group = f.label :start_date %abbr{title: 'This field is required'} * - = f.text_field :start_date, required: true, 'data-end-conference': @conference.end_date.to_s, id: 'registration-period-start-datepicker', class: 'form-control' + %p.small + Must be before conference end (#{@conference.end_date}) and the end date + - if @registration_period.end_date + (#{@registration_period.end_date}) + below + = f.date_field :start_date, required: true, class: 'form-control', max: @conference.end_date, required: true .form-group = f.label :end_date %abbr{title: 'This field is required'} * - = f.text_field :end_date, required: true, id: 'registration-period-end-datepicker', class: 'form-control' + %p.small + Must be before conference end (#{@conference.end_date}) + = f.date_field :end_date, required: true, class: 'form-control', max: @conference.end_date, required: true %p.text-right = f.submit 'Save Registration Period', class: 'btn btn-primary' diff --git a/app/views/admin/survey_questions/_form.html.haml b/app/views/admin/survey_questions/_form.html.haml index b77bb1c5..7b8885ed 100644 --- a/app/views/admin/survey_questions/_form.html.haml +++ b/app/views/admin/survey_questions/_form.html.haml @@ -86,10 +86,10 @@ .kinds.text{ class: @survey_question.text? ? '' : 'hidden' } %textarea.form-control{ rows: 4 } .kinds.datetime{ class: @survey_question.datetime? ? '' : 'hidden' } - .form-group{ class: 'datetimepicker' } + .form-group .input-group .input-group-addon %span.fa-solid.fa-calendar - %input.form-control{ readonly: 'readonly' } + %input.form-control{ type: 'datetime-local', readonly: 'readonly' } .kinds.numeric{ class: @survey_question.numeric? ? '' : 'hidden' } %input.form-control{ type: 'number' } diff --git a/app/views/admin/surveys/_form.html.haml b/app/views/admin/surveys/_form.html.haml index b03022ab..3479bbc7 100644 --- a/app/views/admin/surveys/_form.html.haml +++ b/app/views/admin/surveys/_form.html.haml @@ -22,7 +22,7 @@ = f.select :target, Survey.targets.keys, class: 'form-control' .form-group = f.label :start_date - = f.text_field :start_date, class: 'datetimepicker form-control' + = f.datetime_field :start_date, class: 'form-control' = f.label :end_date - = f.text_field :end_date, class: 'datetimepicker form-control' + = f.datetime_field :end_date, class: 'form-control' = f.submit nil, class: 'btn btn-primary' diff --git a/app/views/admin/surveys/_survey_question.html.haml b/app/views/admin/surveys/_survey_question.html.haml index f006036e..0219ce46 100644 --- a/app/views/admin/surveys/_survey_question.html.haml +++ b/app/views/admin/surveys/_survey_question.html.haml @@ -32,10 +32,10 @@ - elsif survey_question.text? = text_area_tag "survey_submission[#{survey_question.id}][]", survey_reply.text, rows: 4, class: 'form-control', required: survey_question.mandatory - elsif survey_question.datetime? - .form-group{ class: 'datetimepicker' } + .form-group .input-group .input-group-addon %span.fa-solid.fa-calendar - %input.form-control{ readonly: 'readonly', name: "survey_submission[#{survey_question.id}][]", value: survey_reply.text, required: survey_question.mandatory } + %input.form-control{ type: 'datetime-local', readonly: 'readonly', name: "survey_submission[#{survey_question.id}][]", value: survey_reply.text, required: survey_question.mandatory } - elsif survey_question.numeric? %input.form-control{ type: 'number', name: "survey_submission[#{survey_question.id}][]", value: survey_reply.text, required: survey_question.mandatory } diff --git a/app/views/tracks/_form_fields.html.haml b/app/views/tracks/_form_fields.html.haml index b3242099..4c221020 100644 --- a/app/views/tracks/_form_fields.html.haml +++ b/app/views/tracks/_form_fields.html.haml @@ -13,12 +13,12 @@ = f.color_field :color, size: 6, required: true, class: 'form-control' .form-group = f.label :start_date, "Start Date" - = f.text_field :start_date, id: 'registration-period-start-datepicker', start_date: @conference.start_date, end_date: @conference.end_date, required: @track.self_organized_and_accepted_or_confirmed?, class: 'form-control' + = f.date_field :start_date, required: @track.self_organized_and_accepted_or_confirmed?, class: 'form-control' - if @track.self_organized_and_accepted_or_confirmed? %abbr{title: 'This field is required'} * .form-group = f.label :end_date, "End Date" - = f.text_field :end_date, id: 'registration-period-end-datepicker', required: @track.self_organized_and_accepted_or_confirmed?, class: 'form-control' + = f.date_field :end_date, required: @track.self_organized_and_accepted_or_confirmed?, class: 'form-control' - if @track.self_organized_and_accepted_or_confirmed? %abbr{title: 'This field is required'} * - if current_user.is_admin? diff --git a/spec/features/conference_spec.rb b/spec/features/conference_spec.rb index 39d5106f..be4235cc 100644 --- a/spec/features/conference_spec.rb +++ b/spec/features/conference_spec.rb @@ -3,9 +3,19 @@ require 'spec_helper' feature Conference do - let!(:user) { create(:admin) } + let(:user) { create(:admin) } let!(:organization) { create(:organization) } - shared_examples 'add and update conference' do + + describe 'admin' do + let(:conference) { create(:conference, organization: organization) } + + scenario 'has organization name in menu bar for conference views', feature: true, js: true do + sign_in user + visit admin_conference_path(conference.short_title) + + expect(find('.navbar-brand').text).to eq(conference.organization.name) + end + scenario 'adds a new conference', feature: true, js: true do expected_count = Conference.count + 1 sign_in user @@ -19,13 +29,8 @@ feature Conference do select('(GMT+01:00) Berlin', from: 'conference[timezone]') today = Time.zone.today - 1 - page - .execute_script("$('#conference-start-datepicker').val('" + - "#{today.strftime('%d/%m/%Y')}')") - page - .execute_script("$('#conference-end-datepicker').val('" + - "#{(today + 7).strftime('%d/%m/%Y')}')") - + fill_in 'conference_start_date', with: today.strftime('%Y/%m/%d') + fill_in 'conference_end_date', with: (today + 7).strftime('%Y/%m/%d') click_button 'Create Conference' page.find('#flash') @@ -50,13 +55,8 @@ feature Conference do fill_in 'conference_short_title', with: 'NewCon' day = Time.zone.today + 10 - page - .execute_script("$('#conference-start-datepicker').val('" + - "#{day.strftime('%d/%m/%Y')}')") - page - .execute_script("$('#conference-end-datepicker').val('" + - "#{(day + 7).strftime('%d/%m/%Y')}')") - + fill_in 'conference_start_date', with: day.strftime('%Y/%m/%d') + fill_in 'conference_end_date', with: (day + 7).strftime('%Y/%m/%d') page.accept_alert do click_button 'Update Conference' end @@ -70,17 +70,4 @@ feature Conference do expect(Conference.count).to eq(expected_count) end end - - describe 'admin' do - let!(:conference) { create(:conference) } - - scenario 'has organization name in menu bar for conference views', feature: true, js: true do - sign_in user - visit admin_conference_path(conference.short_title) - - expect(find('.navbar-brand').text).to eq(conference.organization.name) - end - - it_behaves_like 'add and update conference' - end end diff --git a/spec/features/registration_periods_spec.rb b/spec/features/registration_periods_spec.rb index 4ef0573b..5e161e11 100644 --- a/spec/features/registration_periods_spec.rb +++ b/spec/features/registration_periods_spec.rb @@ -16,62 +16,31 @@ feature RegistrationPeriod do click_link 'New Registration Period' end - scenario 'requires start date and end date', feature: true do - visit admin_conference_registration_period_path(conference_id: conference) - click_link 'New Registration Period' - - click_button 'Save Registration Period' - page.find('#flash') - expect(flash) - .to eq('An error prohibited the Registration Period from being saved: ' \ - "Start date can't be blank. End date can't be blank.") - end - context 'with tickets' do let!(:registration_ticket) do create(:registration_ticket, conference: conference) end it 'creates registration period', feature: true, js: true do - page - .execute_script("$('#registration-period-start-datepicker').val('" + - "#{start_date.strftime('%d/%m/%Y')}')") - page - .execute_script("$('#registration-period-end-datepicker').val('" + - "#{end_date.strftime('%d/%m/%Y')}')") - + fill_in 'registration_period_start_date', with: start_date.strftime('%Y/%m/%d') + fill_in 'registration_period_end_date', with: end_date.strftime('%Y/%m/%d') click_button 'Save Registration Period' page.find('#flash') expect(flash).to eq('Registration Period successfully updated.') expect(current_path).to eq(admin_conference_registration_period_path(conference.short_title)) expect(page).to have_text("Ticket required?\nYes") - - registration_period = RegistrationPeriod.where(conference_id: conference.id).first - registration_period.reload - expect(registration_period.start_date).to eq(start_date) - expect(registration_period.end_date).to eq(end_date) end end context 'without tickets' do it 'creates registration period', feature: true, js: true do - page - .execute_script("$('#registration-period-start-datepicker').val('" + - "#{start_date.strftime('%d/%m/%Y')}')") - page - .execute_script("$('#registration-period-end-datepicker').val('" + - "#{end_date.strftime('%d/%m/%Y')}')") - + fill_in 'registration_period_start_date', with: start_date.strftime('%Y-%m-%d') + fill_in 'registration_period_end_date', with: end_date.strftime('%Y-%m-%d') click_button 'Save Registration Period' page.find('#flash') expect(flash).to eq('Registration Period successfully updated.') expect(current_path).to eq(admin_conference_registration_period_path(conference.short_title)) expect(page).to have_text("Ticket required?\nNo") - - registration_period = RegistrationPeriod.where(conference_id: conference.id).first - registration_period.reload - expect(registration_period.start_date).to eq(start_date) - expect(registration_period.end_date).to eq(end_date) end end end