diff --git a/Gemfile.lock b/Gemfile.lock index c936aa1..45960c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,9 +103,9 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 2.11.6, < 3) sassc-rails (>= 2.0.0) - bootstrap_form (5.2.2) - actionpack (>= 6.0) - activemodel (>= 6.0) + bootstrap_form (5.4.0) + actionpack (>= 6.1) + activemodel (>= 6.1) builder (3.2.4) byebug (11.1.3) capybara (3.39.2) diff --git a/app/assets/javascripts/cropping.js b/app/assets/javascripts/cropping.js index ea1157f..d0cd818 100644 --- a/app/assets/javascripts/cropping.js +++ b/app/assets/javascripts/cropping.js @@ -88,6 +88,15 @@ $(function () { }); setTitlePreview($('#event_title').val()); + function setTestingWarningVisible(visible) { + $('#requires-testing').toggle(visible); + } + + $('#event_requires_testing').on('change', (e) => { + setTestingWarningVisible(e.target.checked); + }); + setTestingWarningVisible(document.getElementById('event_requires_testing').checked); + const adjuster = new CropAdjuster($("#photo-preview")); function loadImagePreview(input, firstLoad = false) { diff --git a/app/assets/stylesheets/events.scss b/app/assets/stylesheets/events.scss index 975785e..08c362d 100644 --- a/app/assets/stylesheets/events.scss +++ b/app/assets/stylesheets/events.scss @@ -57,12 +57,21 @@ position: relative; } -#event_secret + label::before { +.emojified-warning { + span, em, strong { + &::before, &::after { + content: '⚠️'; + margin: 1em; + } + } +} + +.marked-checkbox + label::before { content: '☐'; margin-right: 0.5em; } -#event_secret:checked + label::before { +.marked-checkbox:checked + label::before { content: '☑'; margin-right: 0.5em; } diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 918bca7..f7d0658 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -144,9 +144,10 @@ def load_prior_addresses def event_params params.require(:event).permit( :title, - :secret, :start_time, :end_time, + :secret, + :requires_testing, :description, :photo, :photo_crop_y_offset, diff --git a/app/views/events/_form.html.haml b/app/views/events/_form.html.haml index ec93d75..122f260 100644 --- a/app/views/events/_form.html.haml +++ b/app/views/events/_form.html.haml @@ -1,24 +1,39 @@ -.hero - .hero-image - %small.form-text#crop-instruction Click and drag to adjust the cropping of your image. - %img#photo-preview{src: event.photo.attached? ? url_for(event.photo) : image_path('default_event_image.jpg'), data: {initial_y_offset: event.photo_crop_y_offset}} - .mx-2 - .hero-title - %h1.title.display-4#title-preview{data: {default: t('event.title_placeholder')}} - %em.text-muted.mb-2 - = t('event.show.hosted_by_you') +.card.mx-md-5 + .card-header.text-center.text-bg-secondary= t('event.form.preview_label') + .hero + .hero-image + %small.form-text#crop-instruction Click and drag to adjust the cropping of your image. + %img#photo-preview{src: event.photo.attached? ? url_for(event.photo) : image_path('default_event_image.jpg'), data: {initial_y_offset: event.photo_crop_y_offset}} + .mx-2 + .hero-title + %h1.title.display-4#title-preview{data: {default: t('event.title_placeholder')}} + %em.text-muted.mb-2 + = t('event.show.hosted_by_you') + .mx-1.alert.alert-danger.text-center.emojified-warning#requires-testing + %strong= t('event.show.requires_testing') + .card-footer.text-center.text-bg-secondary= t('event.form.preview_label') +%hr = bootstrap_form_for(event, url: event.persisted? ? event_path(event) : events_path) do |form| - if event.errors.any? #error_explanation %h2= t('event.form.errors_msg') - = form.form_group help: t('event.form.secret_event_help') do - = form.text_field :title, floating: true - = form.check_box :secret, label: t('event.form.labels.secret'), class: 'btn-check', label_class: 'btn btn-outline-dark' + = form.text_field :title, floating: true = form.form_group(class: 'row') do - .col-md - = form.text_field :start_time, class: 'datetimepicker', value: event.start_time_str, floating: true - .col-md - = form.text_field :end_time, class: 'datetimepicker', value: event.end_time_str, floating: true + .col-md-6 + .row + .col-md-5 + = form.text_field :start_time, class: 'datetimepicker', value: event.start_time_str, floating: true + .col-md-2.align-items-center.d-flex.text-center + %em.col= "…#{t('event.show.time_separator')}…" + .col-md-5 + = form.text_field :end_time, class: 'datetimepicker', value: event.end_time_str, floating: true + .col-md-6 + = form.form_group do + = form.check_box :secret, label: t('event.form.labels.secret'), label_class: 'btn btn-outline-dark', class: 'marked-checkbox btn-check', wrapper_class: 'd-inline-block' + .badge.rounded-pill.text-bg-primary{data: {'bs-title' => t('event.form.secret_event_help'), 'bs-toggle' => 'tooltip', 'bs-placement' => 'auto'} } ? + + = form.check_box :requires_testing, label: t('event.form.labels.covid_testing'), label_class: 'btn btn-outline-dark', class: 'marked-checkbox btn-check', wrapper_class: 'd-inline-block' + .badge.rounded-pill.text-bg-primary{data: {'bs-title' => t('event.form.testing_help'), 'bs-toggle' => 'tooltip', 'bs-placement' => 'auto'} } ? .form-group = form.hidden_field :photo_crop_y_offset = form.file_field :photo, direct_upload: true, help: t('event.form.header_photo_help') diff --git a/app/views/events/show.html.haml b/app/views/events/show.html.haml index 583aa61..2faed74 100644 --- a/app/views/events/show.html.haml +++ b/app/views/events/show.html.haml @@ -19,6 +19,9 @@ = t('event.show.hosted_by_you') - else = t('event.show.hosted_by_other', name: @event.owner.name) +- if @event.requires_testing + .alert.alert-danger.text-center.emojified-warning + %strong= t('event.show.requires_testing') .row .col-lg.order-lg-1.order-sm-2 .row @@ -32,7 +35,7 @@ %strong= @event.start_date = @event.start_time %p - = t('event.show.time_separator') + = "…#{t('event.show.time_separator')}" %strong= @event.end_date = @event.end_time - if @event.address diff --git a/config/locales/models/event/en.yml b/config/locales/models/event/en.yml index fd97d11..e09a196 100644 --- a/config/locales/models/event/en.yml +++ b/config/locales/models/event/en.yml @@ -32,13 +32,18 @@ en: new: New Event show_event_link: See Event errors_msg: There was an error with your event. + preview_label: This is a preview of how your event's title will appear. secret_event_help: Secret events don't appear on the home page unless someone has RSVPed - you'll need to send people the event link yourself for them to find it. This won't stop people who receive the link from giving it to others without your permission. You can find your secret events in the "Host > My Hosted Events" section in the navigation bar. + testing_help: + Events that require testing for COVID-19 will have a banner informing guests of the testing requirement. + Be sure to explain how to send you evidence of a negative test in your event description. header_photo_help: Photos are scaled and cropped to full-screen width (1900px by 500px). header_photo_crop_prompt: Click and drag the header image above to change how your header image will be cropped. labels: + covid_testing: Require COVID testing secret: Make this event secret rsvp_list: headers: @@ -78,6 +83,9 @@ en: self: Organize new event other: Organize your own event show: - time_separator: ...until + time_separator: until hosted_by_other: Hosted by %{name} hosted_by_you: Hosted by you + requires_testing: + You must show a photo of a negative rapid COVID test + from the past 24 hours to be allowed entry to this event. diff --git a/config/locales/models/event/es.yml b/config/locales/models/event/es.yml index ac3446b..fc08b45 100644 --- a/config/locales/models/event/es.yml +++ b/config/locales/models/event/es.yml @@ -34,10 +34,14 @@ es: new: Evento Nuevo show_event_link: Mira a Evento errors_msg: Hubo un errór con su evento. + preview_label: Este es un avance de cómo aparecerá el título de su evento. secret_event_help: Eventos secretos no aparecen en la página de inicio a menos que el usuario haya respondido - se necesita enviar el enlace a las personas usted mismo para que lo encuentren. Esto no impedirá que las personas a las que usted envíe el enlace se darlo a otras personas sin su permiso. Se puede encontrar a sus eventos secretos en la "Hospedador -> Mis Eventos Hospedados" sección en la barra de navegación. + testing_help: + Eventos que requieren pruebas de COVID-19 tendrá un aviso que informará a los invitados sobre el requisito de la + prueba. Asegúrese de explicar cómo enviarle evidencia de una prueba negativa en la descripción del evento. header_photo_help: Fotos se escalan y recortan al ancho de pantalla completo (1900px por 500px). header_photo_crop_prompt: Haga clic y arrastre la imagen de arriba para cambiar cómo se recortará su foto. labels: @@ -80,6 +84,9 @@ es: self: Organiza un evento nuevo other: Organiza su propio evento show: - time_separator: ...hace + time_separator: hace hosted_by_other: Hospedado por %{name} hosted_by_you: Hospedado por usted + requires_testing: + Se debe mostrar una foto de una prueba rápida de COVID negativa + de las últimas 24 horas parar poder entrar a este evento. diff --git a/db/migrate/20231124194655_add_covid_requirement_to_events.rb b/db/migrate/20231124194655_add_covid_requirement_to_events.rb new file mode 100644 index 0000000..2d71de9 --- /dev/null +++ b/db/migrate/20231124194655_add_covid_requirement_to_events.rb @@ -0,0 +1,5 @@ +class AddCovidRequirementToEvents < ActiveRecord::Migration[7.0] + def change + add_column :events, :requires_testing, :boolean, null: false, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index f4dc2e1..94f989d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_17_155030) do +ActiveRecord::Schema[7.0].define(version: 2023_11_24_194655) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -101,6 +101,7 @@ t.boolean "secret", default: false t.string "slug" t.integer "photo_crop_y_offset", default: 0, null: false + t.boolean "requires_testing", default: false, null: false t.index ["address_id"], name: "index_events_on_address_id" t.index ["slug"], name: "index_events_on_slug", unique: true t.index ["user_id"], name: "index_events_on_user_id"