From f90435eb329462007b74fb219a9fa09475ed890e Mon Sep 17 00:00:00 2001 From: Warren Huang <62491485+warrenlet@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:57:28 -0800 Subject: [PATCH 01/36] Update .codeclimate.yml --- .codeclimate.yml | 2 +- ...ion_instructions_to_submission_template.rb | 5 +++ spec/models/currency_conversion_spec.rb | 37 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20240226175634_rename_submission_instructions_to_submission_template.rb create mode 100644 spec/models/currency_conversion_spec.rb diff --git a/.codeclimate.yml b/.codeclimate.yml index c9e9a0539..fde9f3784 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,4 +1,4 @@ plugins: rubocop: enabled: true - channel: rubocop-1-56-3 + channel: rubocop-1-48-1 diff --git a/db/migrate/20240226175634_rename_submission_instructions_to_submission_template.rb b/db/migrate/20240226175634_rename_submission_instructions_to_submission_template.rb new file mode 100644 index 000000000..e6c70a134 --- /dev/null +++ b/db/migrate/20240226175634_rename_submission_instructions_to_submission_template.rb @@ -0,0 +1,5 @@ +class RenameSubmissionInstructionsToSubmissionTemplate < ActiveRecord::Migration[7.0] + def change + rename_column :event_types, :submission_instructions, :submission_template + end +end diff --git a/spec/models/currency_conversion_spec.rb b/spec/models/currency_conversion_spec.rb new file mode 100644 index 000000000..0e012594e --- /dev/null +++ b/spec/models/currency_conversion_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: currency_conversions +# +# id :bigint not null, primary key +# from_currency :string +# rate :decimal(, ) +# to_currency :string +# created_at :datetime not null +# updated_at :datetime not null +# conference_id :bigint not null +# +# Indexes +# +# index_currency_conversions_on_conference_id (conference_id) +# +# Foreign Keys +# +# fk_rails_... (conference_id => conferences.id) +# +require 'spec_helper' + +describe CurrencyConversion do + let!(:conference) { create(:conference, title: 'ExampleCon') } + + describe 'validations' do + before do + conference.currency_conversions << create(:currency_conversion) + end + + it { is_expected.to validate_numericality_of(:rate).is_greater_than(0) } + + it { is_expected.to validate_uniqueness_of(:from_currency).scoped_to(:to_currency).on(:create) } + end +end From 4a4df63e0413aa1a42a2241c7272ee2e361de5e1 Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Mon, 18 Mar 2024 17:57:50 -0700 Subject: [PATCH 02/36] Add upload csv schedule button --- app/views/admin/schedules/show.html.haml | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/views/admin/schedules/show.html.haml b/app/views/admin/schedules/show.html.haml index 5777f4836..8340ecab9 100644 --- a/app/views/admin/schedules/show.html.haml +++ b/app/views/admin/schedules/show.html.haml @@ -4,10 +4,37 @@ .col-md-12 .page-header %h1= "#{@conference.title} Schedule" + + .btn-group.pull-right + %button.btn.btn-primary{ title: 'Mass import of schedule for events', + data: { toggle: 'modal', target: '#mass-schedule-modal' } } + Upload with CSV file + %p.text-muted Create the schedules for the conference = render 'schedules/event_types_key', event_types: @event_types, favourites: false +.modal#mass-schedule-modal + .modal-dialog + .modal-content + .modal-header + %h1 + Schedule events + .modal-body + = form_for('', url: mass_upload_schedules_admin_conference_program_path(@conference.short_title), method: :post) do |f| + .form-group + = f.file_field 'file', as: :file + %span.help-block + Upload your file.csv with data in the following format: + %b Event_ID, xx:xx - xx:xx, Room + for instance: + %pre + Event_ID, xx:xx - xx:xx, Room + 1, 10:00 - 11:00, Room 1 + 2, 11:00 - 12:00, Room 2 + .modal-footer + = f.submit nil, class: 'btn btn-primary' + - if @rooms.present? .row .col-md-2 From 2022ffb0abce0904557feac2507525b243774022 Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Wed, 27 Mar 2024 17:27:33 -0700 Subject: [PATCH 03/36] Add comment code to enable button funcionality --- app/views/admin/schedules/show.html.haml | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app/views/admin/schedules/show.html.haml b/app/views/admin/schedules/show.html.haml index 8340ecab9..7a66856fa 100644 --- a/app/views/admin/schedules/show.html.haml +++ b/app/views/admin/schedules/show.html.haml @@ -14,26 +14,26 @@ Create the schedules for the conference = render 'schedules/event_types_key', event_types: @event_types, favourites: false -.modal#mass-schedule-modal - .modal-dialog - .modal-content - .modal-header - %h1 - Schedule events - .modal-body - = form_for('', url: mass_upload_schedules_admin_conference_program_path(@conference.short_title), method: :post) do |f| - .form-group - = f.file_field 'file', as: :file - %span.help-block - Upload your file.csv with data in the following format: - %b Event_ID, xx:xx - xx:xx, Room - for instance: - %pre - Event_ID, xx:xx - xx:xx, Room - 1, 10:00 - 11:00, Room 1 - 2, 11:00 - 12:00, Room 2 - .modal-footer - = f.submit nil, class: 'btn btn-primary' +-# .modal#mass-schedule-modal +-# .modal-dialog +-# .modal-content +-# .modal-header +-# %h1 +-# Schedule events +-# .modal-body +-# = form_for('', url: mass_upload_schedules_admin_conference_program_path(@conference.short_title), method: :post) do |f| +-# .form-group +-# = f.file_field 'file', as: :file +-# %span.help-block +-# Upload your file.csv with data in the following format: +-# %b Event_ID, xx:xx - xx:xx, Room +-# for instance: +-# %pre +-# Event_ID, xx:xx - xx:xx, Room +-# 1, 10:00 - 11:00, Room 1 +-# 2, 11:00 - 12:00, Room 2 +-# .modal-footer +-# = f.submit nil, class: 'btn btn-primary' - if @rooms.present? .row From b1375b577a76e007d6580a2db208ddce06df3fe7 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Mon, 1 Apr 2024 16:22:51 -0700 Subject: [PATCH 04/36] added enable_public_submission to event_types model need to implement in views --- .../admin/event_types_controller.rb | 2 +- app/controllers/proposals_controller.rb | 6 ++++ app/helpers/event_types_helper.rb | 2 +- app/models/event_type.rb | 29 ++++++++++++------- app/views/admin/event_types/_form.html.haml | 5 ++++ app/views/admin/event_types/index.html.haml | 5 +++- ...enable_public_submission_to_event_types.rb | 5 ++++ db/schema.rb | 3 +- spec/factories/event_types.rb | 24 ++++++++------- spec/models/event_type_spec.rb | 23 ++++++++------- 10 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 db/migrate/20240318164346_add_enable_public_submission_to_event_types.rb diff --git a/app/controllers/admin/event_types_controller.rb b/app/controllers/admin/event_types_controller.rb index 0cd2eed20..f0d7656d9 100644 --- a/app/controllers/admin/event_types_controller.rb +++ b/app/controllers/admin/event_types_controller.rb @@ -50,7 +50,7 @@ def destroy def event_type_params params.require(:event_type).permit(:title, :length, :minimum_abstract_length, :maximum_abstract_length, - :submission_template, :color, :conference_id, :description) + :submission_template, :color, :conference_id, :description, :enable_public_submission) end end end diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 48d62c817..9608a1b4a 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -31,6 +31,12 @@ def new @url = conference_program_proposals_path(@conference.short_title) @languages = @program.languages_list @superevents = @program.super_events + + if current_user.is_admin? + @event_types = @program.event_types + else + @event_types = @program.event_types.available_for_public + end end def edit diff --git a/app/helpers/event_types_helper.rb b/app/helpers/event_types_helper.rb index ca7c3e511..1aa439ed8 100644 --- a/app/helpers/event_types_helper.rb +++ b/app/helpers/event_types_helper.rb @@ -15,7 +15,7 @@ def event_type_select_options(event_types = {}) { data: { min_words: type.minimum_abstract_length, max_words: type.maximum_abstract_length, - instructions: type.submission_template + template: type.submission_template } } ] end diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 0d2943dc9..198016a10 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # class EventType < ApplicationRecord belongs_to :program, touch: true @@ -34,6 +35,8 @@ class EventType < ApplicationRecord alias_attribute :name, :title + scope :available_for_public, -> { where(enable_public_submission: true) } + private ## @@ -53,4 +56,8 @@ def capitalize_color def conference_id program.conference_id end + + # def self.available_for_public_submission + # is_admin? all : available_for_public + # end end diff --git a/app/views/admin/event_types/_form.html.haml b/app/views/admin/event_types/_form.html.haml index d0a2739c1..6426a38ab 100644 --- a/app/views/admin/event_types/_form.html.haml +++ b/app/views/admin/event_types/_form.html.haml @@ -15,6 +15,11 @@ = f.label :description = f.text_area :description, class: 'form-control', rows: 5, data: { provide: 'markdown' } .help-block= markdown_hint + .form-group + = f.label "Allow public submission?", for: :enable_public_submission + = f.check_box :enable_public_submission, class: 'switch-checkbox' + .help-block + Do we need description for explanation? .form-group = f.label :minimum_abstract_length %abbr{title: 'This field is required'} * diff --git a/app/views/admin/event_types/index.html.haml b/app/views/admin/event_types/index.html.haml index 56411fb78..b4784b446 100644 --- a/app/views/admin/event_types/index.html.haml +++ b/app/views/admin/event_types/index.html.haml @@ -11,7 +11,8 @@ %tr %th Title %th Description - %th Instructions + %th Enable Public Submission + %th Template %th Length %th Abstract Length %th Color @@ -23,6 +24,8 @@ = event_type.title %td = markdown(event_type.description) + %td + = event_type.enable_public_submission ? 'Yes' : 'No' %td = markdown(event_type.submission_template) %td diff --git a/db/migrate/20240318164346_add_enable_public_submission_to_event_types.rb b/db/migrate/20240318164346_add_enable_public_submission_to_event_types.rb new file mode 100644 index 000000000..f653893c8 --- /dev/null +++ b/db/migrate/20240318164346_add_enable_public_submission_to_event_types.rb @@ -0,0 +1,5 @@ +class AddEnablePublicSubmissionToEventTypes < ActiveRecord::Migration[7.0] + def change + add_column :event_types, :enable_public_submission, :boolean, default: true, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index d8361a539..eae662993 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: 2024_02_26_175634) do +ActiveRecord::Schema[7.0].define(version: 2024_03_18_164346) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "plpgsql" @@ -234,6 +234,7 @@ t.datetime "created_at", precision: nil t.datetime "updated_at", precision: nil t.text "submission_template" + t.boolean "enable_public_submission", default: true, null: false end create_table "event_users", force: :cascade do |t| diff --git a/spec/factories/event_types.rb b/spec/factories/event_types.rb index e3801ca14..d8e3ee758 100644 --- a/spec/factories/event_types.rb +++ b/spec/factories/event_types.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # FactoryBot.define do @@ -22,6 +23,7 @@ title { 'Example Event Type' } length { 30 } description { 'Example Event Description\nThis event type is an example.' } + enable_public_submission { true } minimum_abstract_length { 0 } maximum_abstract_length { 500 } submission_template { 'Example Event Template _with_ **markdown**' } diff --git a/spec/models/event_type_spec.rb b/spec/models/event_type_spec.rb index 2c30203c2..8a97d8cfe 100644 --- a/spec/models/event_type_spec.rb +++ b/spec/models/event_type_spec.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # require 'spec_helper' From 784d50fff11ea1dbb0dcc789bdf80d8ca165f89b Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Thu, 4 Apr 2024 21:20:40 -0700 Subject: [PATCH 05/36] admin vs non-admin dropdown and descriptions event types working --- app/controllers/proposals_controller.rb | 11 +++++------ app/helpers/application_helper.rb | 12 ++++++++++-- app/views/proposals/_encouragement_text.html.haml | 2 +- .../proposals/_submission_type_content_form.haml | 4 ++-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 9608a1b4a..fc31e02f7 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -3,6 +3,7 @@ class ProposalsController < ApplicationController include ConferenceHelper before_action :authenticate_user!, except: %i[show new create] + before_action :set_is_admin load_resource :conference, find_by: :short_title load_resource :program, through: :conference, singleton: true load_and_authorize_resource :event, parent: false, through: :program @@ -31,12 +32,6 @@ def new @url = conference_program_proposals_path(@conference.short_title) @languages = @program.languages_list @superevents = @program.super_events - - if current_user.is_admin? - @event_types = @program.event_types - else - @event_types = @program.event_types.available_for_public - end end def edit @@ -224,4 +219,8 @@ def event_params def user_params params.require(:user).permit(:email, :password, :password_confirmation, :username) end + + def set_is_admin + @is_admin = current_user.is_admin + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6edc74c84..4e3ad1fdb 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -122,8 +122,16 @@ def volunteer_links(event) end, ', ') end - def event_types_sentence(conference) - conference.event_types.map { |et| et.title.pluralize }.to_sentence + def event_types_sentence(conference, is_admin = true) + if is_admin + conference.event_types.map { |et| et.title.pluralize }.to_sentence + else + conference.event_types.available_for_public.map { |et| et.title.pluralize }.to_sentence + end + end + + def event_types_dropdown(conference, is_admin = true) + is_admin ? conference.event_types : conference.event_types.available_for_public end def sign_in_path diff --git a/app/views/proposals/_encouragement_text.html.haml b/app/views/proposals/_encouragement_text.html.haml index f7f6033f0..224f90f2a 100644 --- a/app/views/proposals/_encouragement_text.html.haml +++ b/app/views/proposals/_encouragement_text.html.haml @@ -1,7 +1,7 @@ %p.lead - if @program.event_types.any? You can submit proposals for - = "#{event_types_sentence(@conference)}." + = "#{event_types_sentence(@conference, @is_admin)}." - if @program.tracks.confirmed.cfp_active.any? Proposals should fit in one of the = "#{pluralize(@program.tracks.confirmed.cfp_active.count, 'track')}:" diff --git a/app/views/proposals/_submission_type_content_form.haml b/app/views/proposals/_submission_type_content_form.haml index 6a66fa5a1..5d9e634b1 100644 --- a/app/views/proposals/_submission_type_content_form.haml +++ b/app/views/proposals/_submission_type_content_form.haml @@ -2,8 +2,8 @@ %p Please select a submission type, then fill in the abstract and extended details. .form-group - = f.label :event_type_id, 'Type' - = f.select :event_type_id, event_type_select_options(@conference.program.event_types), { include_blank: false }, { class: 'select-help-toggle form-control' } + = f.label :event_type_id, "Type" + = f.select :event_type_id, event_type_select_options(event_types_dropdown(@conference, @is_admin)), { include_blank: false }, { class: 'select-help-toggle form-control' } - program.event_types.each do |event_type| .help-block.event_event_type_id.collapse{ id: "#{dom_id(event_type)}-help" } From a988487b1232a9194d913269242b1a0261479287 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Fri, 12 Apr 2024 14:17:54 -0700 Subject: [PATCH 06/36] finished applying enable-public-submission plus tests --- app/controllers/proposals_controller.rb | 8 ++------ app/helpers/application_helper.rb | 4 ---- app/models/event_type.rb | 7 ++++--- app/views/admin/event_types/_form.html.haml | 2 -- .../proposals/_encouragement_text.html.haml | 2 +- .../_submission_type_content_form.haml | 5 ++++- spec/helpers/application_helper_spec.rb | 18 +++++++++++++++++ spec/models/event_type_spec.rb | 20 +++++++++++++++++++ 8 files changed, 49 insertions(+), 17 deletions(-) diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index fc31e02f7..3c63782a8 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -3,7 +3,6 @@ class ProposalsController < ApplicationController include ConferenceHelper before_action :authenticate_user!, except: %i[show new create] - before_action :set_is_admin load_resource :conference, find_by: :short_title load_resource :program, through: :conference, singleton: true load_and_authorize_resource :event, parent: false, through: :program @@ -50,6 +49,7 @@ def create authorize! :create, @user if @user.save sign_in(@user) + set_is_admin else flash.now[:error] = "Could not save user: #{@user.errors.full_messages.join(', ')}" render action: 'new' @@ -217,10 +217,6 @@ def event_params end def user_params - params.require(:user).permit(:email, :password, :password_confirmation, :username) + params.require(:user).permit(:email, :password, :password_confirmation, :username, :is_admin) end - - def set_is_admin - @is_admin = current_user.is_admin - end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4e3ad1fdb..86507220e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -130,10 +130,6 @@ def event_types_sentence(conference, is_admin = true) end end - def event_types_dropdown(conference, is_admin = true) - is_admin ? conference.event_types : conference.event_types.available_for_public - end - def sign_in_path if ENV.fetch('OSEM_ICHAIN_ENABLED', nil) == 'true' new_user_ichain_session_path diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 198016a10..9f2c3d72e 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -32,6 +32,7 @@ class EventType < ApplicationRecord validates :color, format: /\A#[0-9A-F]{6}\z/ before_validation :capitalize_color + before_validation :strip_title alias_attribute :name, :title @@ -57,7 +58,7 @@ def conference_id program.conference_id end - # def self.available_for_public_submission - # is_admin? all : available_for_public - # end + def strip_title + self.title = title.strip unless title.nil? + end end diff --git a/app/views/admin/event_types/_form.html.haml b/app/views/admin/event_types/_form.html.haml index 6426a38ab..234d50293 100644 --- a/app/views/admin/event_types/_form.html.haml +++ b/app/views/admin/event_types/_form.html.haml @@ -18,8 +18,6 @@ .form-group = f.label "Allow public submission?", for: :enable_public_submission = f.check_box :enable_public_submission, class: 'switch-checkbox' - .help-block - Do we need description for explanation? .form-group = f.label :minimum_abstract_length %abbr{title: 'This field is required'} * diff --git a/app/views/proposals/_encouragement_text.html.haml b/app/views/proposals/_encouragement_text.html.haml index 224f90f2a..dc39f56b8 100644 --- a/app/views/proposals/_encouragement_text.html.haml +++ b/app/views/proposals/_encouragement_text.html.haml @@ -1,7 +1,7 @@ %p.lead - if @program.event_types.any? You can submit proposals for - = "#{event_types_sentence(@conference, @is_admin)}." + = "#{event_types_sentence(@conference, current_user.is_admin)}." - if @program.tracks.confirmed.cfp_active.any? Proposals should fit in one of the = "#{pluralize(@program.tracks.confirmed.cfp_active.count, 'track')}:" diff --git a/app/views/proposals/_submission_type_content_form.haml b/app/views/proposals/_submission_type_content_form.haml index 5d9e634b1..1f82ee5e2 100644 --- a/app/views/proposals/_submission_type_content_form.haml +++ b/app/views/proposals/_submission_type_content_form.haml @@ -3,7 +3,10 @@ .form-group = f.label :event_type_id, "Type" - = f.select :event_type_id, event_type_select_options(event_types_dropdown(@conference, @is_admin)), { include_blank: false }, { class: 'select-help-toggle form-control' } + - if current_user.is_admin + = f.select :event_type_id, event_type_select_options(@conference.program.event_types), { include_blank: false }, { class: 'select-help-toggle form-control' } + - else + = f.select :event_type_id, event_type_select_options(@conference.program.event_types.available_for_public), { include_blank: false }, { class: 'select-help-toggle form-control' } - program.event_types.each do |event_type| .help-block.event_event_type_id.collapse{ id: "#{dom_id(event_type)}-help" } diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 9e4108337..14ffd3f16 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -155,4 +155,22 @@ expect(conference_logo_url(conference2)).to include('2.png') end end + + describe '#event_type_sentence' do + before do + create(:event_type, title: 'Keynote', program: conference.program, enable_public_submission: false) + end + + context 'when a user is an admin' do + it 'returns a sentence with all event types' do + expect(helper.event_types_sentence(conference, true)).to eq 'Talks, Workshops, and Keynotes' + end + end + + context 'when a user is not an admin' do + it 'returns a sentence only event types that allow public submission' do + expect(helper.event_types_sentence(conference, false)).to eq 'Talks and Workshops' + end + end + end end diff --git a/spec/models/event_type_spec.rb b/spec/models/event_type_spec.rb index 8a97d8cfe..a3cd693c2 100644 --- a/spec/models/event_type_spec.rb +++ b/spec/models/event_type_spec.rb @@ -62,5 +62,25 @@ expect(build(:event_type, program: conference.program, length: 37)).not_to be_valid end end + + describe 'title' do + it 'removes leading and trailing whitespace from title' do + event_type = EventType.new(title: ' Movie ') + event_type.valid? + expect(event_type.title).to eq('Movie') + end + end end + + describe 'scope :available_for_public' do + it 'includes event types with enable_public_submission set to true' do + public_event_type = create(:event_type, program: conference.program, enable_public_submission: true) + expect(EventType.available_for_public).to include(public_event_type) + end + + it 'excludes event types with enable_public_submission set to false' do + non_public_event_type = create(:event_type, program: conference.program, enable_public_submission: false) + expect(EventType.available_for_public).not_to include(non_public_event_type) + end + end end From 28e75c6f37a756241f75930713c5fd918aaffb32 Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Sun, 14 Apr 2024 16:56:59 -0700 Subject: [PATCH 07/36] Migrate include_committee to splash pages --- app/controllers/admin/splashpages_controller.rb | 3 ++- app/controllers/conferences_controller.rb | 5 +++++ app/models/splashpage.rb | 1 + app/views/admin/splashpages/_form.html.haml | 4 ++++ app/views/conferences/show.html.haml | 5 +++++ .../20240414231910_add_include_committee_to_splashpage.rb | 5 +++++ db/schema.rb | 3 ++- spec/factories/splashpages.rb | 1 + 8 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20240414231910_add_include_committee_to_splashpage.rb diff --git a/app/controllers/admin/splashpages_controller.rb b/app/controllers/admin/splashpages_controller.rb index 7e50bb22b..56ead72df 100644 --- a/app/controllers/admin/splashpages_controller.rb +++ b/app/controllers/admin/splashpages_controller.rb @@ -51,7 +51,8 @@ def splashpage_params :include_venue, :include_registrations, :include_tickets, :include_lodgings, :include_sponsors, :include_social_media, - :include_booths, :include_happening_now) + :include_booths, :include_happening_now, + :include_committee) end end end diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index ef90c670c..435cca136 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -65,6 +65,11 @@ def show ).order('sponsorship_levels.position ASC', 'sponsors.name') @sponsors = @conference.sponsors end + if @splashpage.include_committee? + @organizers = @conference.organizers + # @volunteers = @conference.volunteers + # @reviewers = @conference.reviewers + end end # rubocop:enable Metrics/CyclomaticComplexity diff --git a/app/models/splashpage.rb b/app/models/splashpage.rb index 650e06575..9043f20c2 100644 --- a/app/models/splashpage.rb +++ b/app/models/splashpage.rb @@ -11,6 +11,7 @@ # banner_photo_updated_at :datetime # include_booths :boolean # include_cfp :boolean default(FALSE) +# include_committee :boolean # include_happening_now :boolean # include_lodgings :boolean # include_program :boolean diff --git a/app/views/admin/splashpages/_form.html.haml b/app/views/admin/splashpages/_form.html.haml index 338ad4a2e..f494e9a05 100644 --- a/app/views/admin/splashpages/_form.html.haml +++ b/app/views/admin/splashpages/_form.html.haml @@ -55,6 +55,10 @@ %label = f.check_box :include_social_media Display the social media links? + .checkbox + %label + = f.check_box :include_committee + Display the committee? %h4 Access %hr diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index 29c5014e2..056144503 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -86,6 +86,11 @@ sponsorship_levels: @sponsorship_levels, sponsors: @sponsors + -# comittee + - if @conference.splashpage.include_committee? + = render 'organizers', conference: @conference, organizers: @organizers + + -# footer - if @conference.splashpage.include_social_media? && @conference.contact.has_social_media? = render 'social_media', contact: @conference.contact, cached: true diff --git a/db/migrate/20240414231910_add_include_committee_to_splashpage.rb b/db/migrate/20240414231910_add_include_committee_to_splashpage.rb new file mode 100644 index 000000000..87b637c12 --- /dev/null +++ b/db/migrate/20240414231910_add_include_committee_to_splashpage.rb @@ -0,0 +1,5 @@ +class AddIncludeCommitteeToSplashpage < ActiveRecord::Migration[7.0] + def change + add_column :splashpages, :include_committee, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 36c6b9d4a..6fe7ced7b 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: 2024_02_26_175634) do +ActiveRecord::Schema[7.0].define(version: 2024_04_14_231910) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "plpgsql" @@ -467,6 +467,7 @@ t.boolean "include_booths" t.boolean "shuffle_highlights", default: false, null: false t.boolean "include_happening_now" + t.boolean "include_committee" end create_table "sponsors", force: :cascade do |t| diff --git a/spec/factories/splashpages.rb b/spec/factories/splashpages.rb index 6bb3e70ff..a095cffdb 100644 --- a/spec/factories/splashpages.rb +++ b/spec/factories/splashpages.rb @@ -11,6 +11,7 @@ # banner_photo_updated_at :datetime # include_booths :boolean # include_cfp :boolean default(FALSE) +# include_committee :boolean # include_happening_now :boolean # include_lodgings :boolean # include_program :boolean From 8a8f9de7f62d4399cde73bfb2a49a21385eec7d5 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Mon, 15 Apr 2024 09:20:08 -0700 Subject: [PATCH 08/36] proposals work for not signed in user --- app/controllers/proposals_controller.rb | 1 - app/helpers/application_helper.rb | 4 ++-- app/helpers/event_types_helper.rb | 6 ++--- app/views/admin/cfps/_events_cfp.html.haml | 2 +- app/views/admin/programs/show.html.haml | 2 +- .../proposals/_encouragement_text.html.haml | 2 +- .../_submission_type_content_form.haml | 2 +- spec/helpers/application_helper_spec.rb | 24 +++++++++---------- spec/models/event_type_spec.rb | 14 +++++------ 9 files changed, 28 insertions(+), 29 deletions(-) diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 3c63782a8..23087362d 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -49,7 +49,6 @@ def create authorize! :create, @user if @user.save sign_in(@user) - set_is_admin else flash.now[:error] = "Could not save user: #{@user.errors.full_messages.join(', ')}" render action: 'new' diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 86507220e..492c98a7f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -122,10 +122,10 @@ def volunteer_links(event) end, ', ') end - def event_types_sentence(conference, is_admin = true) + def event_types_sentence(conference, is_admin) if is_admin conference.event_types.map { |et| et.title.pluralize }.to_sentence - else + else conference.event_types.available_for_public.map { |et| et.title.pluralize }.to_sentence end end diff --git a/app/helpers/event_types_helper.rb b/app/helpers/event_types_helper.rb index 1aa439ed8..f1306cfec 100644 --- a/app/helpers/event_types_helper.rb +++ b/app/helpers/event_types_helper.rb @@ -13,9 +13,9 @@ def event_type_select_options(event_types = {}) "#{type.title} - #{show_time(type.length)}", type.id, { data: { - min_words: type.minimum_abstract_length, - max_words: type.maximum_abstract_length, - template: type.submission_template + min_words: type.minimum_abstract_length, + max_words: type.maximum_abstract_length, + template: type.submission_template } } ] end diff --git a/app/views/admin/cfps/_events_cfp.html.haml b/app/views/admin/cfps/_events_cfp.html.haml index 6e8066b4a..e04020cd4 100644 --- a/app/views/admin/cfps/_events_cfp.html.haml +++ b/app/views/admin/cfps/_events_cfp.html.haml @@ -21,7 +21,7 @@ %dt Event types: %dd - = event_types_sentence(conference) + = event_types_sentence(conference, true) %dt Tracks: %dd diff --git a/app/views/admin/programs/show.html.haml b/app/views/admin/programs/show.html.haml index db1e91ffb..f2c1949fa 100644 --- a/app/views/admin/programs/show.html.haml +++ b/app/views/admin/programs/show.html.haml @@ -22,7 +22,7 @@ %dt Event types: %dd - = event_types_sentence(@conference) + = event_types_sentence(@conference, true) %dt Tracks: %dd diff --git a/app/views/proposals/_encouragement_text.html.haml b/app/views/proposals/_encouragement_text.html.haml index dc39f56b8..8f831582f 100644 --- a/app/views/proposals/_encouragement_text.html.haml +++ b/app/views/proposals/_encouragement_text.html.haml @@ -1,7 +1,7 @@ %p.lead - if @program.event_types.any? You can submit proposals for - = "#{event_types_sentence(@conference, current_user.is_admin)}." + = "#{event_types_sentence(@conference, current_user&.is_admin || false)}." - if @program.tracks.confirmed.cfp_active.any? Proposals should fit in one of the = "#{pluralize(@program.tracks.confirmed.cfp_active.count, 'track')}:" diff --git a/app/views/proposals/_submission_type_content_form.haml b/app/views/proposals/_submission_type_content_form.haml index 1f82ee5e2..c7b947e25 100644 --- a/app/views/proposals/_submission_type_content_form.haml +++ b/app/views/proposals/_submission_type_content_form.haml @@ -3,7 +3,7 @@ .form-group = f.label :event_type_id, "Type" - - if current_user.is_admin + - if current_user&.is_admin = f.select :event_type_id, event_type_select_options(@conference.program.event_types), { include_blank: false }, { class: 'select-help-toggle form-control' } - else = f.select :event_type_id, event_type_select_options(@conference.program.event_types.available_for_public), { include_blank: false }, { class: 'select-help-toggle form-control' } diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 14ffd3f16..808a2827d 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -156,21 +156,21 @@ end end - describe '#event_type_sentence' do - before do + describe '#event_type_sentence' do + before do create(:event_type, title: 'Keynote', program: conference.program, enable_public_submission: false) - end + end - context 'when a user is an admin' do - it 'returns a sentence with all event types' do + context 'when a user is an admin' do + it 'returns a sentence with all event types' do expect(helper.event_types_sentence(conference, true)).to eq 'Talks, Workshops, and Keynotes' - end - end + end + end - context 'when a user is not an admin' do - it 'returns a sentence only event types that allow public submission' do + context 'when a user is not an admin' do + it 'returns a sentence only event types that allow public submission' do expect(helper.event_types_sentence(conference, false)).to eq 'Talks and Workshops' - end - end - end + end + end + end end diff --git a/spec/models/event_type_spec.rb b/spec/models/event_type_spec.rb index a3cd693c2..840e84da8 100644 --- a/spec/models/event_type_spec.rb +++ b/spec/models/event_type_spec.rb @@ -63,24 +63,24 @@ end end - describe 'title' do - it 'removes leading and trailing whitespace from title' do + describe 'title' do + it 'removes leading and trailing whitespace from title' do event_type = EventType.new(title: ' Movie ') event_type.valid? expect(event_type.title).to eq('Movie') - end - end + end + end end describe 'scope :available_for_public' do it 'includes event types with enable_public_submission set to true' do public_event_type = create(:event_type, program: conference.program, enable_public_submission: true) expect(EventType.available_for_public).to include(public_event_type) - end + end it 'excludes event types with enable_public_submission set to false' do non_public_event_type = create(:event_type, program: conference.program, enable_public_submission: false) expect(EventType.available_for_public).not_to include(non_public_event_type) - end - end + end + end end From d4061ac7f9e2784a8540f349ee411f0dd6acd891 Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Mon, 15 Apr 2024 14:48:37 -0700 Subject: [PATCH 09/36] Add organizers pic on the splashpage --- app/controllers/conferences_controller.rb | 4 +--- app/views/conferences/_committee.haml | 17 +++++++++++++++++ app/views/conferences/show.html.haml | 3 +-- 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 app/views/conferences/_committee.haml diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 435cca136..92688853f 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -66,9 +66,7 @@ def show @sponsors = @conference.sponsors end if @splashpage.include_committee? - @organizers = @conference.organizers - # @volunteers = @conference.volunteers - # @reviewers = @conference.reviewers + @organizers = User.with_role(:organizer, @conference) end end # rubocop:enable Metrics/CyclomaticComplexity diff --git a/app/views/conferences/_committee.haml b/app/views/conferences/_committee.haml new file mode 100644 index 000000000..5944fab67 --- /dev/null +++ b/app/views/conferences/_committee.haml @@ -0,0 +1,17 @@ +-# _committee.haml +.row + .col-md-12 + %h3.text-center + Committee +.row + .col-sd-6 + .row.row-centered + - organizers.shuffle.each do |organizer| + .col-sd-3.col-sm-1.col-xs-3.col-centered + .thumbnail{ style: 'border: none; background: none; padding: 20;' } + - if organizer.profile_picture.present? + = image_tag organizer.profile_picture(size: 150), + class: ['img-responsive', 'img-circle'], + title: organizer.name + .caption + %h4.text-center= organizer.name diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index 056144503..b14f7397e 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -88,8 +88,7 @@ -# comittee - if @conference.splashpage.include_committee? - = render 'organizers', conference: @conference, organizers: @organizers - + = render 'committee', organizers: @organizers -# footer - if @conference.splashpage.include_social_media? && @conference.contact.has_social_media? From 81b174e6b678331f426e39b0753934ac226453cf Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Mon, 15 Apr 2024 14:57:53 -0700 Subject: [PATCH 10/36] add profile link to organizer --- app/views/conferences/_committee.haml | 3 ++- app/views/conferences/show.html.haml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/conferences/_committee.haml b/app/views/conferences/_committee.haml index 5944fab67..4359fba32 100644 --- a/app/views/conferences/_committee.haml +++ b/app/views/conferences/_committee.haml @@ -8,7 +8,8 @@ .row.row-centered - organizers.shuffle.each do |organizer| .col-sd-3.col-sm-1.col-xs-3.col-centered - .thumbnail{ style: 'border: none; background: none; padding: 20;' } + = link_to user_path(organizer), class: 'thumbnail', + style: 'border: none; background: none; padding: 20px;' do - if organizer.profile_picture.present? = image_tag organizer.profile_picture(size: 150), class: ['img-responsive', 'img-circle'], diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index b14f7397e..49aa07b7e 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -86,7 +86,7 @@ sponsorship_levels: @sponsorship_levels, sponsors: @sponsors - -# comittee + -# committee - if @conference.splashpage.include_committee? = render 'committee', organizers: @organizers From ecba0fbb4afed3660b724ef3548075393c76c548 Mon Sep 17 00:00:00 2001 From: Warren Huang <62491485+warrenlet@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:00:38 -0700 Subject: [PATCH 11/36] Update .rubocop_todo.yml adjust PerceivedComplexity limit by 1 to accommodate the adding committee boolean in conference controller --- .rubocop_todo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 48a9a2252..2d6689045 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -87,7 +87,7 @@ Metrics/ModuleLength: # Offense count: 25 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: - Max: 17 + Max: 18 # Offense count: 13 Naming/AccessorMethodName: From a41141f4fbddea6646dfb6806367ed15b48713a2 Mon Sep 17 00:00:00 2001 From: Warren Huang <62491485+warrenlet@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:26:19 -0700 Subject: [PATCH 12/36] Update .rubocop_todo.yml Revert to the previous setting --- .rubocop_todo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2d6689045..48a9a2252 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -87,7 +87,7 @@ Metrics/ModuleLength: # Offense count: 25 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: - Max: 18 + Max: 17 # Offense count: 13 Naming/AccessorMethodName: From 4b1555c7dc6a156307fdeaf2296bf1be6a5d3f0d Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Mon, 15 Apr 2024 18:16:28 -0700 Subject: [PATCH 13/36] Set up button and style --- app/assets/stylesheets/osem-schedule.scss | 7 +++++++ app/views/schedules/events.html.haml | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/osem-schedule.scss b/app/assets/stylesheets/osem-schedule.scss index f722a41e9..6a1fcc52c 100644 --- a/app/assets/stylesheets/osem-schedule.scss +++ b/app/assets/stylesheets/osem-schedule.scss @@ -185,3 +185,10 @@ h3.event-panel-title small { line-height: 1.4; } + +#current-event-btn { + position: fixed; + bottom: 40px; + right: 40px; + z-index: 1000; +} diff --git a/app/views/schedules/events.html.haml b/app/views/schedules/events.html.haml index 4c45a80b6..b046863c3 100644 --- a/app/views/schedules/events.html.haml +++ b/app/views/schedules/events.html.haml @@ -51,8 +51,8 @@ - start_ymd = new_start_time.strftime('%Y-%m-%d') - unless start_ymd.eql?(date) .col-xs-12.col-md-12 - .date-content - %span.date-title{ id: start_ymd } + .date-content{ data: { time: event_schedule.start_time.strftime('%H:%M') } } + %span.date-title{ id: "event-#{event_schedule.id}" } = inyourtz(event_schedule.start_time, @conference.timezone) do = date = start_ymd %a.pull-right{ title: "Go up", href: "#program" } @@ -79,6 +79,8 @@ .unscheduled-event - cache [@program, event, current_user, '#unscheduled#full#panel'] do = render 'event', event: event, event_schedule: nil + %button#current-event-btn.btn.btn-primary{ type: "button" } + Jump to Current Event :javascript $('.program-selector').on('click', function(e) { From 1e4a6460084ce724a91a15a0e9309d762c1a9450 Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Mon, 15 Apr 2024 18:17:38 -0700 Subject: [PATCH 14/36] add javascript to scroll to closest event --- app/assets/javascripts/osem-schedule.js | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/assets/javascripts/osem-schedule.js b/app/assets/javascripts/osem-schedule.js index 45df23908..376764b38 100644 --- a/app/assets/javascripts/osem-schedule.js +++ b/app/assets/javascripts/osem-schedule.js @@ -80,6 +80,36 @@ $(document).ready( function() { $('.unscheduled-events .schedule-event-delete-button').hide(); $('.non_schedulable .schedule-event-delete-button').hide(); + $('#current-event-btn').on('click', function() { + var now = new Date(); + var closestEventId = null; + var smallestDiff = Infinity; + + $('.date-content').each(function() { + var eventTimeStr = $(this).data('time'); + if (eventTimeStr) { + var eventTimeParts = eventTimeStr.split(':'); + var eventMinutes = parseInt(eventTimeParts[0]) * 60 + parseInt(eventTimeParts[1]); + var nowMinutes = now.getHours() * 60 + now.getMinutes(); + var diff = Math.abs(eventMinutes - nowMinutes); + + if (diff < smallestDiff) { + smallestDiff = diff; + closestEventId = $(this).find('.date-title').attr('id'); + } + } + }); + + if (closestEventId) { + //Instead of relying on hash it's probably better to scroll using javascript + //Since the users and click button->scroll->click again, which won't re-scroll + var element = document.getElementById(closestEventId); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + }); + // set events as draggable $('.schedule-event').not('.non_schedulable').draggable({ snap: '.schedule-room-slot', From 3b847b64f9dce0069e91fc595cae5a00e8a62008 Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Thu, 18 Apr 2024 15:25:36 -0700 Subject: [PATCH 15/36] add test and fix error --- app/assets/javascripts/osem-schedule.js | 29 ++++++++-------- app/views/schedules/events.html.haml | 9 ++--- spec/features/event_schedules_spec.rb | 46 +++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 spec/features/event_schedules_spec.rb diff --git a/app/assets/javascripts/osem-schedule.js b/app/assets/javascripts/osem-schedule.js index 376764b38..61e6894bb 100644 --- a/app/assets/javascripts/osem-schedule.js +++ b/app/assets/javascripts/osem-schedule.js @@ -84,29 +84,28 @@ $(document).ready( function() { var now = new Date(); var closestEventId = null; var smallestDiff = Infinity; + var i=0 + + $('.event-item').each(function() { - $('.date-content').each(function() { var eventTimeStr = $(this).data('time'); - if (eventTimeStr) { - var eventTimeParts = eventTimeStr.split(':'); - var eventMinutes = parseInt(eventTimeParts[0]) * 60 + parseInt(eventTimeParts[1]); - var nowMinutes = now.getHours() * 60 + now.getMinutes(); - var diff = Math.abs(eventMinutes - nowMinutes); - - if (diff < smallestDiff) { - smallestDiff = diff; - closestEventId = $(this).find('.date-title').attr('id'); + + if (eventTimeStr) { + var eventTime = new Date(eventTimeStr); + var diff = Math.abs(eventTime - now); + + if (diff < smallestDiff) { + smallestDiff = diff; + closestEventId = $(this).attr('class').split(' ')[1]; + } } - } }); if (closestEventId) { //Instead of relying on hash it's probably better to scroll using javascript //Since the users and click button->scroll->click again, which won't re-scroll - var element = document.getElementById(closestEventId); - if (element) { - element.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } + $('.highlighted').removeClass('highlighted'); + $('.' + closestEventId).addClass('highlighted').get(0).scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); diff --git a/app/views/schedules/events.html.haml b/app/views/schedules/events.html.haml index b046863c3..14a1669ca 100644 --- a/app/views/schedules/events.html.haml +++ b/app/views/schedules/events.html.haml @@ -51,8 +51,8 @@ - start_ymd = new_start_time.strftime('%Y-%m-%d') - unless start_ymd.eql?(date) .col-xs-12.col-md-12 - .date-content{ data: { time: event_schedule.start_time.strftime('%H:%M') } } - %span.date-title{ id: "event-#{event_schedule.id}" } + .date-content + %span.date-title = inyourtz(event_schedule.start_time, @conference.timezone) do = date = start_ymd %a.pull-right{ title: "Go up", href: "#program" } @@ -64,7 +64,8 @@ = time + ' ' + timezone_text(tz_object) .col-xs-12.col-md-11 - cache [@program, event_schedule, event_schedule.event, current_user, event_schedule.happening_now?, '#scheduled#full#panel'] do - = render 'event', event: event_schedule.event, event_schedule: event_schedule + .event-item{ data: { time: event_schedule.start_time.iso8601 }, class: "event-#{event_schedule.event.id}" } + = render 'event', event: event_schedule.event, event_schedule: event_schedule / confirmed events that are not scheduled - if @unscheduled_events.any? @@ -79,7 +80,7 @@ .unscheduled-event - cache [@program, event, current_user, '#unscheduled#full#panel'] do = render 'event', event: event, event_schedule: nil - %button#current-event-btn.btn.btn-primary{ type: "button" } + %button.btn.btn-primary#current-event-btn{ type: "button" } Jump to Current Event :javascript diff --git a/spec/features/event_schedules_spec.rb b/spec/features/event_schedules_spec.rb new file mode 100644 index 000000000..a166a247f --- /dev/null +++ b/spec/features/event_schedules_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe EventSchedule, js: true do + Timecop.return + let(:test_date) { Time.current } + let!(:conference) do + create(:full_conference, start_date: test_date - 1.hour, end_date: test_date + 5.days, start_hour: 0, end_hour: 24) + end + let!(:program) { conference.program } + let!(:selected_schedule) { create(:schedule, program: program) } + let!(:scheduled_event_early) do + program.update!(selected_schedule: selected_schedule) + create(:event, program: program, state: 'confirmed', abstract: '`markdown`') + end + let!(:event_schedule_early) do + create(:event_schedule, event: scheduled_event_early, schedule: selected_schedule, + start_time: test_date - 1.hours) + end + let!(:scheduled_event_mid) do + program.update!(selected_schedule: selected_schedule) + create(:event, program: program, state: 'confirmed') + end + let!(:event_schedule_mid) do + create(:event_schedule, event: scheduled_event_mid, schedule: selected_schedule, + start_time: test_date) + end + let!(:scheduled_event_late) do + program.update!(selected_schedule: selected_schedule) + create(:event, program: program, state: 'confirmed') + end + let!(:event_schedule_late) do + create(:event_schedule, event: scheduled_event_late, schedule: selected_schedule, + start_time: test_date + 1.hours) + end + + before do + login_as(create(:user), scope: :user) + visit events_conference_schedule_path(conference_id: conference.short_title, favourites: false) + end + + it 'jumps to the closest event' do + find('#current-event-btn').click + highlighted_element = page.find('.highlighted', visible: true, wait: 1) + expect(highlighted_element[:class]).to include("event-#{scheduled_event_mid.id}") + end +end From fb3950a5584a253e00bf306873013b4b11003bd8 Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Sun, 21 Apr 2024 20:41:20 -0700 Subject: [PATCH 16/36] parse upload url to check if it is a embeddable snap project --- .../admin/commercials_controller.rb | 4 ++- app/models/commercial.rb | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/commercials_controller.rb b/app/controllers/admin/commercials_controller.rb index 0b7c8af3f..093ea3914 100644 --- a/app/controllers/admin/commercials_controller.rb +++ b/app/controllers/admin/commercials_controller.rb @@ -90,7 +90,9 @@ def aggregate_errors(errors) end def commercial_params - params.require(:commercial).permit(:title, :url) + params.require(:commercial).permit(:title, :url).tap do |params| + params[:url] = Commercial.generate_snap_embed(params[:url]) if params[:url] + end end end end diff --git a/app/models/commercial.rb b/app/models/commercial.rb index 1fcc0a45a..606c8e01a 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -30,6 +30,7 @@ class Commercial < ApplicationRecord def self.render_from_url(url) register_provider + url = generate_snap_embed(url) begin resource = OEmbed::Providers.get(url, maxwidth: 560, maxheight: 315) { html: resource.html.html_safe } @@ -39,6 +40,32 @@ def self.render_from_url(url) end end + def self.generate_snap_embed(url) + uri = URI.parse(url) + if uri.host == 'snap.berkeley.edu' && uri.path == '/project' + args = URI.decode_www_form(uri.query).to_h + else + return url + end + if args.key?('username') && args.key?('projectname') + new_query = URI.encode_www_form({ + 'projectname' => args['projectname'], + 'username' => args['username'], + 'showTitle' => 'true', + 'showAuthor' => 'true', + 'editButton' => 'true', + 'pauseButton' => 'true' + }) + new_uri = URI::HTTPS.build( + host: uri.host, + path: '/embed', + query: new_query + ) + return new_uri.to_s + end + url + end + def self.iframe_fallback(url) "".html_safe end From 6a89df678ce25310bc02a29339472d412709536b Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Mon, 22 Apr 2024 01:22:32 -0700 Subject: [PATCH 17/36] Upload CSV Added --- app/controllers/admin/schedules_controller.rb | 32 +++++++++++++++ app/views/admin/schedules/show.html.haml | 40 +++++++++---------- config/routes.rb | 5 +++ ...20240308190204_add_currency_to_payments.rb | 5 --- ...025823_add_currency_to_ticket_purchases.rb | 5 --- package-lock.json | 2 +- 6 files changed, 58 insertions(+), 31 deletions(-) delete mode 100644 db/migrate/20240308190204_add_currency_to_payments.rb delete mode 100644 db/migrate/20240315025823_add_currency_to_ticket_purchases.rb diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index f3176245c..df7b7b884 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -68,6 +68,38 @@ def destroy end end + def upload_csv + Rails.logger.debug "Entered the upload_csv method" + @conference = Conference.find_by!(short_title: params[:conference_id]) + authorize! :update, @conference + + # Check if the file was included in the params + if params[:schedule] && params[:schedule][:file].present? + file = params[:schedule][:file] + begin + CSV.foreach(file.path, headers: true) do |row| + event_date = Date.strptime(row['Date'], '%m/%d/%y') + event_time = Time.parse(row['Start_Time']) + event_start_time = DateTime.new(event_date.year, event_date.month, event_date.day, event_time.hour, event_time.min, event_time.sec, event_time.zone) + + room = Room.find_or_create_by(name: row['Room']) + event = Event.find_by(id: row['Event_ID']) + + if event + event.update(start_time: event_start_time, room: room) + end + end + flash[:notice] = 'Schedule uploaded successfully!' + rescue => e + flash[:alert] = "Failed to process CSV file: #{e.message}" + end + else + flash[:alert] = 'No file was attached!' + end + redirect_to admin_conference_schedules_path(@conference) + end + + private def schedule_params diff --git a/app/views/admin/schedules/show.html.haml b/app/views/admin/schedules/show.html.haml index 7a66856fa..3e3a8e837 100644 --- a/app/views/admin/schedules/show.html.haml +++ b/app/views/admin/schedules/show.html.haml @@ -14,26 +14,26 @@ Create the schedules for the conference = render 'schedules/event_types_key', event_types: @event_types, favourites: false --# .modal#mass-schedule-modal --# .modal-dialog --# .modal-content --# .modal-header --# %h1 --# Schedule events --# .modal-body --# = form_for('', url: mass_upload_schedules_admin_conference_program_path(@conference.short_title), method: :post) do |f| --# .form-group --# = f.file_field 'file', as: :file --# %span.help-block --# Upload your file.csv with data in the following format: --# %b Event_ID, xx:xx - xx:xx, Room --# for instance: --# %pre --# Event_ID, xx:xx - xx:xx, Room --# 1, 10:00 - 11:00, Room 1 --# 2, 11:00 - 12:00, Room 2 --# .modal-footer --# = f.submit nil, class: 'btn btn-primary' +.modal#mass-schedule-modal + .modal-dialog + .modal-content + .modal-header + %h1 + Schedule events + .modal-body + = form_for :schedule, url: upload_csv_admin_conference_schedules_path(@conference), html: { multipart: true }, method: :post do |f| + .form-group + = f.file_field :file, as: :file + %span.help-block + Upload your CSV file with data in the following format: + %b Event_ID, Start_Time, Date, Room + for instance: + %pre + Event_ID, Start_Time, Date, Room + 1, 10:00, 6/1/2024, Australia + 2, 11:00, 6/2/2024, Brazil + .modal-footer + = f.submit 'Upload', class: 'btn btn-primary' - if @rooms.present? .row diff --git a/config/routes.rb b/config/routes.rb index 6e49e0666..62ac3dfdd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,6 +40,11 @@ resource :ticket_scanning, only: [:create] resources :comments, only: [:index] resources :conferences do + resources :schedules do + collection do + post :upload_csv + end + end resources :surveys do resources :survey_questions, except: :index end diff --git a/db/migrate/20240308190204_add_currency_to_payments.rb b/db/migrate/20240308190204_add_currency_to_payments.rb deleted file mode 100644 index 467a04f43..000000000 --- a/db/migrate/20240308190204_add_currency_to_payments.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddCurrencyToPayments < ActiveRecord::Migration[7.0] - def change - add_column :payments, :currency, :string - end -end diff --git a/db/migrate/20240315025823_add_currency_to_ticket_purchases.rb b/db/migrate/20240315025823_add_currency_to_ticket_purchases.rb deleted file mode 100644 index 70e4f9d96..000000000 --- a/db/migrate/20240315025823_add_currency_to_ticket_purchases.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddCurrencyToTicketPurchases < ActiveRecord::Migration[7.0] - def change - add_column :ticket_purchases, :currency, :string - end -end diff --git a/package-lock.json b/package-lock.json index e5e7a779a..fedc26385 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "snapcon", + "name": "snapcon2", "lockfileVersion": 2, "requires": true, "packages": { From 2591edbca6906fff3611e29e7769e00d1a5f52f0 Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Mon, 22 Apr 2024 14:25:25 -0700 Subject: [PATCH 18/36] add test coverage for snap embed message. Fix cases where url is nil --- app/models/commercial.rb | 2 ++ spec/models/commercial_spec.rb | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/app/models/commercial.rb b/app/models/commercial.rb index 606c8e01a..42d4ccadf 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -41,6 +41,8 @@ def self.render_from_url(url) end def self.generate_snap_embed(url) + return url unless url + uri = URI.parse(url) if uri.host == 'snap.berkeley.edu' && uri.path == '/project' args = URI.decode_www_form(uri.query).to_h diff --git a/spec/models/commercial_spec.rb b/spec/models/commercial_spec.rb index a09077f8e..f2d0a749e 100644 --- a/spec/models/commercial_spec.rb +++ b/spec/models/commercial_spec.rb @@ -15,6 +15,7 @@ # commercialable_id :integer # require 'spec_helper' +require 'uri' describe Commercial do it { is_expected.to validate_presence_of(:url) } @@ -29,4 +30,11 @@ commercial = build(:conference_commercial) expect(commercial.valid?).to be true end + + it 'parses snap url' do + url = 'https://snap.berkeley.edu/project?username=avi_shor&projectname=stamps' + transformed_url = Commercial.generate_snap_embed(url) + expected_url = 'https://snap.berkeley.edu/embed?projectname=stamps&username=avi_shor&showTitle=true&showAuthor=true&editButton=true&pauseButton=true' + expect(transformed_url).to eq expected_url + end end From 78844a03b74b5e5bf792f93f32285bddfb585c51 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Mon, 22 Apr 2024 15:43:32 -0700 Subject: [PATCH 19/36] feature working need to fix some tests --- .../conference_registrations_controller.rb | 15 ++++--- app/controllers/payments_controller.rb | 4 -- app/models/event_type.rb | 23 +++++----- app/models/ticket.rb | 5 --- app/models/ticket_purchase.rb | 42 ++++++++++--------- .../_physical_ticket.html.haml | 3 +- .../admin/physical_tickets/index.html.haml | 1 + .../conference_registrations/show.html.haml | 42 +++++++++---------- app/views/payments/_payment.html.haml | 4 +- ...rency_for_null_ticket_purchase_currency.rb | 5 +++ ...d_amount_paid_cents_to_ticket_purchases.rb | 23 ++++++++++ db/schema.rb | 4 +- ...conference_registration_controller_spec.rb | 18 +------- spec/factories/event_types.rb | 23 +++++----- spec/factories/ticket_purchases.rb | 23 +++++----- spec/models/event_type_spec.rb | 23 +++++----- spec/models/ticket_purchase_spec.rb | 23 +++++----- spec/models/ticket_spec.rb | 8 ++-- 18 files changed, 155 insertions(+), 134 deletions(-) create mode 100644 db/migrate/20240417212948_set_currency_for_null_ticket_purchase_currency.rb create mode 100644 db/migrate/20240422200831_add_amount_paid_cents_to_ticket_purchases.rb diff --git a/app/controllers/conference_registrations_controller.rb b/app/controllers/conference_registrations_controller.rb index 8df31ea05..863438a99 100644 --- a/app/controllers/conference_registrations_controller.rb +++ b/app/controllers/conference_registrations_controller.rb @@ -29,11 +29,16 @@ def new end def show - @total_price = Ticket.total_price_user(@conference, current_user, paid: true) - @tickets = current_user.ticket_purchases.by_conference(@conference).paid - @total_price_per_ticket = @tickets.group(:ticket_id).sum('amount_paid * quantity') - @ticket_payments = @tickets.group_by(&:ticket_id) - @total_quantity = @tickets.group(:ticket_id).sum(:quantity) + @purchases = current_user.ticket_purchases.by_conference(@conference).paid + summed_per_purchase_per_currency = @purchases.group(:ticket_id, :currency).sum('amount_paid_cents * quantity') + @total_price_per_purchase_per_currency = summed_per_purchase_per_currency.each_with_object({}) do |((ticket_id, currency), amount), hash| + hash[[ticket_id, currency]] = Money.new(amount, currency) + end + @total_quantity = @purchases.group(:ticket_id, :currency).sum(:quantity) + sum_total_currency = @purchases.group(:currency).sum('amount_paid_cents * quantity') + @total_price_per_currency = sum_total_currency.each_with_object({}) do |(currency, amount), hash| + hash[currency] = Money.new(amount, currency) + end end def edit; end diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index 94d8d9859..e86f9ffb7 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -23,10 +23,6 @@ def new @has_registration_ticket = params[:has_registration_ticket] @unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference) - @converted_prices = {} - @unpaid_ticket_purchases.each do |ticket_purchase| - @converted_prices[ticket_purchase.id] = ticket_purchase.amount_paid - end @currency = selected_currency end diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 0d2943dc9..fe360b7f9 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # class EventType < ApplicationRecord belongs_to :program, touch: true diff --git a/app/models/ticket.rb b/app/models/ticket.rb index fd6efeace..4786a1920 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -80,11 +80,6 @@ def self.total_price(conference, user, paid: false) result || Money.new(0, 'USD') end - def self.total_price_user(conference, user, paid: false) - tickets = TicketPurchase.where(conference: conference, user: user, paid: paid) - tickets.inject(0) { |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } - end - def tickets_turnover_total(id) ticket = Ticket.find(id) return Money.new(0, 'USD') unless ticket diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index 954d67af3..153f14e26 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -4,17 +4,18 @@ # # Table name: ticket_purchases # -# id :bigint not null, primary key -# amount_paid :float default(0.0) -# currency :string -# paid :boolean default(FALSE) -# quantity :integer default(1) -# week :integer -# created_at :datetime -# conference_id :integer -# payment_id :integer -# ticket_id :integer -# user_id :integer +# id :bigint not null, primary key +# amount_paid :float default(0.0) +# amount_paid_cents :integer default(0) +# currency :string +# paid :boolean default(FALSE) +# quantity :integer default(1) +# week :integer +# created_at :datetime +# conference_id :integer +# payment_id :integer +# ticket_id :integer +# user_id :integer # class TicketPurchase < ApplicationRecord @@ -30,12 +31,14 @@ class TicketPurchase < ApplicationRecord delegate :title, to: :ticket delegate :description, to: :ticket - delegate :price, to: :ticket + # delegate :price, to: :ticket delegate :price_cents, to: :ticket delegate :price_currency, to: :ticket has_many :physical_tickets + monetize :amount_paid_cents, with_model_currency: :currency, as: 'purchase_price' + scope :paid, -> { where(paid: true) } scope :unpaid, -> { where(paid: false) } scope :by_conference, ->(conference) { where(conference_id: conference.id) } @@ -71,12 +74,13 @@ def self.purchase_ticket(conference, quantity, ticket, user, currency) purchase.pay(nil) end if quantity > 0 - purchase = new(ticket_id: ticket.id, - conference_id: conference.id, - user_id: user.id, - quantity: quantity, - amount_paid: converted_amount, - currency: currency) + purchase = new(ticket_id: ticket.id, + conference_id: conference.id, + user_id: user.id, + quantity: quantity, + amount_paid: converted_amount.to_f, + amount_paid_cents: converted_amount.fractional, + currency: currency) purchase.pay(nil) if converted_amount.zero? end purchase @@ -94,7 +98,7 @@ def self.update_quantity(conference, quantity, ticket, user) # Total amount def self.total - sum('amount_paid * quantity') + sum('amount_paid_cents * quantity') end def pay(payment) diff --git a/app/views/admin/physical_tickets/_physical_ticket.html.haml b/app/views/admin/physical_tickets/_physical_ticket.html.haml index 241e88754..d14f3f0cd 100644 --- a/app/views/admin/physical_tickets/_physical_ticket.html.haml +++ b/app/views/admin/physical_tickets/_physical_ticket.html.haml @@ -3,7 +3,8 @@ %td= physical_ticket.ticket.title %td= physical_ticket.ticket.registration_ticket? ? 'Yes' : 'No' %td= physical_ticket.user&.email - %td= humanized_money_with_symbol physical_ticket.ticket_purchase.amount_paid + %td= humanized_money_with_symbol(physical_ticket.ticket_purchase.price) + %td= physical_ticket.ticket_purchase.currency || 'USD' %td - if physical_ticket.ticket_scannings.present? %span Checked in: diff --git a/app/views/admin/physical_tickets/index.html.haml b/app/views/admin/physical_tickets/index.html.haml index 80835f901..96722dc98 100644 --- a/app/views/admin/physical_tickets/index.html.haml +++ b/app/views/admin/physical_tickets/index.html.haml @@ -24,6 +24,7 @@ %th Registration? %th User %th Paid + %th Currency %th Attedance %th Actions %tbody diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index 9d89752ab..9aa5609b7 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -86,27 +86,25 @@ %i.fa-solid.fa-square-dashed.fa-stack-2x %i.fa-solid.fa-ticket.fa-stack-1x Tickets - - if @tickets.any? - Total Purchased: - = "(#{@tickets.first.price.symbol}#{humanized_money @total_price})" - %ul - .col-md-12 - - @ticket_payments.each_pair do |ticket_id, tickets| - %li - = @total_quantity[ticket_id] - = tickets.first.title - = word_pluralize(@total_quantity[ticket_id], 'Ticket') - for - = tickets.first.price.symbol - = humanized_money @total_price_per_ticket[ticket_id] - %br - .btn-group{ role: 'group' } - = link_to 'View all tickets', - conference_physical_tickets_path(@conference.short_title), - class: 'btn btn-success' - = link_to 'Get more tickets', - conference_tickets_path(@conference.short_title), - class: 'btn btn-default' + - if @purchases.any? + .col-md-12 + - @total_price_per_currency.each do |currency, total_price| + %h4 + Total Purchased (#{currency}): + = humanized_money_with_symbol(total_price) + %ul + - @total_price_per_purchase_per_currency.select { |(id, curr)| curr == currency }.each do |(ticket_id, curr), total_amount| + - purchase = @purchases.find { |p| p.ticket_id == ticket_id && p.currency == curr } + %li + = "#{@total_quantity[[ticket_id, currency]]} #{purchase.title} Tickets for " + = humanized_money_with_symbol(total_amount) + .btn-group{ role: 'group' } + = link_to 'View all tickets', + conference_physical_tickets_path(@conference.short_title), + class: 'btn btn-success' + = link_to 'Get more tickets', + conference_tickets_path(@conference.short_title), + class: 'btn btn-default' - else %p You haven't bought any tickets. @@ -125,7 +123,7 @@ - if @registration .btn-group-vertical.pull-right = link_to 'Edit your Registration', edit_conference_conference_registration_path(@conference.short_title), class: 'btn btn-success', disabled: @conference.end_date < Date.today - - if @tickets.any? + - if @purchases.any? = link_to 'Unregister', conference_conference_registration_path(@conference.short_title), method: :delete, class: 'btn btn-danger btn-xs', data: { confirm: "Your ticket purchases won't be refunded. Are you sure you want to unregister?" }, disabled: @conference.end_date < Date.today - else diff --git a/app/views/payments/_payment.html.haml b/app/views/payments/_payment.html.haml index 27a85af5d..76544211e 100644 --- a/app/views/payments/_payment.html.haml +++ b/app/views/payments/_payment.html.haml @@ -15,9 +15,9 @@ %td = ticket.quantity %td - = humanized_money_with_symbol @converted_prices[ticket.id] + = humanized_money_with_symbol ticket.purchase_price %td - = humanized_money_with_symbol (@converted_prices[ticket.id] * ticket.quantity) + = humanized_money_with_symbol ticket.purchase_price * ticket.quantity = form_tag conference_payments_path(@conference.short_title, :has_registration_ticket => @has_registration_ticket) do %script.stripe-button{ src: "https://checkout.stripe.com/checkout.js", data: { amount: @total_amount_to_pay.cents, diff --git a/db/migrate/20240417212948_set_currency_for_null_ticket_purchase_currency.rb b/db/migrate/20240417212948_set_currency_for_null_ticket_purchase_currency.rb new file mode 100644 index 000000000..759aa644c --- /dev/null +++ b/db/migrate/20240417212948_set_currency_for_null_ticket_purchase_currency.rb @@ -0,0 +1,5 @@ +class SetCurrencyForNullTicketPurchaseCurrency < ActiveRecord::Migration[7.0] + def up + TicketPurchase.where(currency: nil).update_all(currency: 'USD') + end +end diff --git a/db/migrate/20240422200831_add_amount_paid_cents_to_ticket_purchases.rb b/db/migrate/20240422200831_add_amount_paid_cents_to_ticket_purchases.rb new file mode 100644 index 000000000..349471109 --- /dev/null +++ b/db/migrate/20240422200831_add_amount_paid_cents_to_ticket_purchases.rb @@ -0,0 +1,23 @@ +class AddAmountPaidCentsToTicketPurchases < ActiveRecord::Migration[7.0] + def up + add_column :ticket_purchases, :amount_paid_cents, :integer, default: 0 + + TicketPurchase.reset_column_information + + TicketPurchase.find_each do |purchase| + converted_amount = CurrencyConversion.convert_currency( + purchase.conference, + purchase.price, + purchase.price_currency, + purchase.currency + ) + + purchase.update_column(:amount_paid_cents, converted_amount.fractional) + end + end + + def down + # Remove the amount_paid_cents column if you roll back this migration + remove_column :ticket_purchases, :amount_paid_cents + end +end diff --git a/db/schema.rb b/db/schema.rb index c3879f928..8b20ff52d 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: 2024_03_15_025823) do +ActiveRecord::Schema[7.0].define(version: 2024_04_22_200831) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "plpgsql" @@ -234,6 +234,7 @@ t.datetime "created_at", precision: nil t.datetime "updated_at", precision: nil t.text "submission_template" + t.boolean "enable_public_submission", default: true, null: false end create_table "event_users", force: :cascade do |t| @@ -545,6 +546,7 @@ t.integer "week" t.float "amount_paid", default: 0.0 t.string "currency" + t.integer "amount_paid_cents", default: 0 end create_table "ticket_scannings", force: :cascade do |t| diff --git a/spec/controllers/conference_registration_controller_spec.rb b/spec/controllers/conference_registration_controller_spec.rb index a32fe6dbd..1623d9210 100644 --- a/spec/controllers/conference_registration_controller_spec.rb +++ b/spec/controllers/conference_registration_controller_spec.rb @@ -265,27 +265,13 @@ end end - context 'user has purchased a ticket' do - before do - @ticket = create(:ticket, conference: conference) - @purchased_ticket = create(:ticket_purchase, conference: conference, - user: user, - ticket: @ticket) - get :show, params: { conference_id: conference.short_title } - end - - it 'does not assign price of purchased tickets to total_price and purchased tickets to tickets without payment' do - expect(assigns(:total_price)).to eq 0 - end - end - context 'user has not purchased any ticket' do before do get :show, params: { conference_id: conference.short_title } end - it 'assigns 0 dollars to total_price and empty array to tickets variables' do - expect(assigns(:total_price)).to eq 0 + it 'assigns an empty array to tickets variables' do + # expect(assigns(:total_price)).to eq 0 expect(assigns(:tickets)).to match_array [] end end diff --git a/spec/factories/event_types.rb b/spec/factories/event_types.rb index e3801ca14..857b50154 100644 --- a/spec/factories/event_types.rb +++ b/spec/factories/event_types.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # FactoryBot.define do diff --git a/spec/factories/ticket_purchases.rb b/spec/factories/ticket_purchases.rb index 1eb1f347d..9f55a3ca7 100644 --- a/spec/factories/ticket_purchases.rb +++ b/spec/factories/ticket_purchases.rb @@ -4,17 +4,18 @@ # # Table name: ticket_purchases # -# id :bigint not null, primary key -# amount_paid :float default(0.0) -# currency :string -# paid :boolean default(FALSE) -# quantity :integer default(1) -# week :integer -# created_at :datetime -# conference_id :integer -# payment_id :integer -# ticket_id :integer -# user_id :integer +# id :bigint not null, primary key +# amount_paid :float default(0.0) +# amount_paid_cents :integer default(0) +# currency :string +# paid :boolean default(FALSE) +# quantity :integer default(1) +# week :integer +# created_at :datetime +# conference_id :integer +# payment_id :integer +# ticket_id :integer +# user_id :integer # FactoryBot.define do factory :ticket_purchase do diff --git a/spec/models/event_type_spec.rb b/spec/models/event_type_spec.rb index 2c30203c2..8a97d8cfe 100644 --- a/spec/models/event_type_spec.rb +++ b/spec/models/event_type_spec.rb @@ -4,17 +4,18 @@ # # Table name: event_types # -# id :bigint not null, primary key -# color :string -# description :string -# length :integer default(30) -# maximum_abstract_length :integer default(500) -# minimum_abstract_length :integer default(0) -# submission_template :text -# title :string not null -# created_at :datetime -# updated_at :datetime -# program_id :integer +# id :bigint not null, primary key +# color :string +# description :string +# enable_public_submission :boolean default(TRUE), not null +# length :integer default(30) +# maximum_abstract_length :integer default(500) +# minimum_abstract_length :integer default(0) +# submission_template :text +# title :string not null +# created_at :datetime +# updated_at :datetime +# program_id :integer # require 'spec_helper' diff --git a/spec/models/ticket_purchase_spec.rb b/spec/models/ticket_purchase_spec.rb index 6a705336d..9941afcba 100644 --- a/spec/models/ticket_purchase_spec.rb +++ b/spec/models/ticket_purchase_spec.rb @@ -4,17 +4,18 @@ # # Table name: ticket_purchases # -# id :bigint not null, primary key -# amount_paid :float default(0.0) -# currency :string -# paid :boolean default(FALSE) -# quantity :integer default(1) -# week :integer -# created_at :datetime -# conference_id :integer -# payment_id :integer -# ticket_id :integer -# user_id :integer +# id :bigint not null, primary key +# amount_paid :float default(0.0) +# amount_paid_cents :integer default(0) +# currency :string +# paid :boolean default(FALSE) +# quantity :integer default(1) +# week :integer +# created_at :datetime +# conference_id :integer +# payment_id :integer +# ticket_id :integer +# user_id :integer # require 'spec_helper' diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index 36d074afd..f98d879b8 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -83,17 +83,17 @@ subject { ticket.tickets_turnover_total ticket.id } let!(:purchase1) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, quantity: 1, paid: true, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 1, currency: 'USD', paid: true, user: user) end let!(:purchase2) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, quantity: 2, paid: true, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 2, currency: 'USD', paid: true, user: user) end let!(:purchase3) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, quantity: 10, paid: false, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 10, currency: 'USD', paid: false, user: user) end it 'returns turnover as Money with ticket\'s currency' do - expect(subject).to eq Money.new(5_000 * 3, ticket.price_currency) + expect(subject).to eq Money.new(500_000 * 3, ticket.price_currency) end end From 3c73c9528b708c7b4ba68fb68195ad61c9f65045 Mon Sep 17 00:00:00 2001 From: Owen Hu Date: Mon, 22 Apr 2024 16:35:36 -0700 Subject: [PATCH 20/36] remove unused import --- spec/models/commercial_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/models/commercial_spec.rb b/spec/models/commercial_spec.rb index f2d0a749e..2adc17c97 100644 --- a/spec/models/commercial_spec.rb +++ b/spec/models/commercial_spec.rb @@ -15,7 +15,6 @@ # commercialable_id :integer # require 'spec_helper' -require 'uri' describe Commercial do it { is_expected.to validate_presence_of(:url) } From 4389a319fe31e2ccc6c896261880f752b2348780 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Mon, 22 Apr 2024 17:02:55 -0700 Subject: [PATCH 21/36] add upload CSV function --- app/controllers/admin/schedules_controller.rb | 23 +++++++++++-------- app/views/admin/schedules/show.html.haml | 4 ++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index df7b7b884..c7cbf911f 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -69,35 +69,38 @@ def destroy end def upload_csv - Rails.logger.debug "Entered the upload_csv method" @conference = Conference.find_by!(short_title: params[:conference_id]) authorize! :update, @conference - - # Check if the file was included in the params + if params[:schedule] && params[:schedule][:file].present? file = params[:schedule][:file] - begin - CSV.foreach(file.path, headers: true) do |row| + CSV.foreach(file.path, headers: true) do |row| + next if row['Event_ID'].blank? || row['Date'].blank? || row['Start_Time'].blank? || row['Room'].blank? + + begin event_date = Date.strptime(row['Date'], '%m/%d/%y') event_time = Time.parse(row['Start_Time']) event_start_time = DateTime.new(event_date.year, event_date.month, event_date.day, event_time.hour, event_time.min, event_time.sec, event_time.zone) - room = Room.find_or_create_by(name: row['Room']) event = Event.find_by(id: row['Event_ID']) - + if event event.update(start_time: event_start_time, room: room) + else + Rails.logger.warn "Event not found with ID: #{row['Event_ID']}" end + rescue => e + Rails.logger.error "Error processing row: #{row.to_h}, Error: #{e.message}" + next end - flash[:notice] = 'Schedule uploaded successfully!' - rescue => e - flash[:alert] = "Failed to process CSV file: #{e.message}" end + flash[:notice] = 'Schedule uploaded successfully!' else flash[:alert] = 'No file was attached!' end redirect_to admin_conference_schedules_path(@conference) end + private diff --git a/app/views/admin/schedules/show.html.haml b/app/views/admin/schedules/show.html.haml index 3e3a8e837..0b1d0f56a 100644 --- a/app/views/admin/schedules/show.html.haml +++ b/app/views/admin/schedules/show.html.haml @@ -30,8 +30,8 @@ for instance: %pre Event_ID, Start_Time, Date, Room - 1, 10:00, 6/1/2024, Australia - 2, 11:00, 6/2/2024, Brazil + osemdemo, 10:00, 6/1/2024, Australia + osemdemo, 11:00, 6/2/2024, Brazil .modal-footer = f.submit 'Upload', class: 'btn btn-primary' From 8d10eca570600d4f614a3ebaad99328925c14ba3 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Mon, 22 Apr 2024 18:33:56 -0700 Subject: [PATCH 22/36] fixed CI error in controller --- app/models/ticket.rb | 2 +- app/models/ticket_purchase.rb | 7 ++++++- .../admin/physical_tickets/_physical_ticket.html.haml | 2 +- .../controllers/conference_registration_controller_spec.rb | 3 +-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 4786a1920..f2c3997df 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -84,7 +84,7 @@ def tickets_turnover_total(id) ticket = Ticket.find(id) return Money.new(0, 'USD') unless ticket - sum = ticket.ticket_purchases.paid.total + sum = ticket.price_cents * ticket.ticket_purchases.paid.total_quantity Money.new(sum, ticket.price_currency) end diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index 153f14e26..7031ae3fb 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -98,7 +98,12 @@ def self.update_quantity(conference, quantity, ticket, user) # Total amount def self.total - sum('amount_paid_cents * quantity') + sum('amount_paid * quantity') + end + + # Total quantity + def self.total_quantity + sum('quantity') end def pay(payment) diff --git a/app/views/admin/physical_tickets/_physical_ticket.html.haml b/app/views/admin/physical_tickets/_physical_ticket.html.haml index d14f3f0cd..b9cc99a02 100644 --- a/app/views/admin/physical_tickets/_physical_ticket.html.haml +++ b/app/views/admin/physical_tickets/_physical_ticket.html.haml @@ -3,7 +3,7 @@ %td= physical_ticket.ticket.title %td= physical_ticket.ticket.registration_ticket? ? 'Yes' : 'No' %td= physical_ticket.user&.email - %td= humanized_money_with_symbol(physical_ticket.ticket_purchase.price) + %td= humanized_money_with_symbol(physical_ticket.ticket_purchase.purchase_price) %td= physical_ticket.ticket_purchase.currency || 'USD' %td - if physical_ticket.ticket_scannings.present? diff --git a/spec/controllers/conference_registration_controller_spec.rb b/spec/controllers/conference_registration_controller_spec.rb index 1623d9210..ae90ca938 100644 --- a/spec/controllers/conference_registration_controller_spec.rb +++ b/spec/controllers/conference_registration_controller_spec.rb @@ -271,8 +271,7 @@ end it 'assigns an empty array to tickets variables' do - # expect(assigns(:total_price)).to eq 0 - expect(assigns(:tickets)).to match_array [] + expect(assigns(:purchases)).to match_array [] end end end From af0754b450e0554b7a914d9f6b7cec1a63712143 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Tue, 23 Apr 2024 17:56:52 -0700 Subject: [PATCH 23/36] fixed multiple ticket at registration view --- app/views/conference_registrations/show.html.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index 9aa5609b7..15ef7d86a 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -96,7 +96,9 @@ - @total_price_per_purchase_per_currency.select { |(id, curr)| curr == currency }.each do |(ticket_id, curr), total_amount| - purchase = @purchases.find { |p| p.ticket_id == ticket_id && p.currency == curr } %li - = "#{@total_quantity[[ticket_id, currency]]} #{purchase.title} Tickets for " + - title = purchase.title.titleize.gsub(/(?i)\bticket\b/, 'Tickets') + - title = title.include?('Tickets') ? title : "#{title} Tickets" + = "#{@total_quantity[[ticket_id, currency]]} #{title} for " = humanized_money_with_symbol(total_amount) .btn-group{ role: 'group' } = link_to 'View all tickets', From 1b7a9ae3bb7980f1533632e4e2dd23026babbaf0 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Wed, 24 Apr 2024 13:20:54 -0700 Subject: [PATCH 24/36] added testing for conference_registration_controller --- .../conference_registrations_controller.rb | 4 +-- app/models/ticket_purchase.rb | 1 - .../conference_registrations/show.html.haml | 2 +- ...conference_registration_controller_spec.rb | 28 +++++++++++++++++++ spec/models/ticket_purchase_spec.rb | 10 +++++++ 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/app/controllers/conference_registrations_controller.rb b/app/controllers/conference_registrations_controller.rb index 863438a99..b20a0fe84 100644 --- a/app/controllers/conference_registrations_controller.rb +++ b/app/controllers/conference_registrations_controller.rb @@ -30,8 +30,8 @@ def new def show @purchases = current_user.ticket_purchases.by_conference(@conference).paid - summed_per_purchase_per_currency = @purchases.group(:ticket_id, :currency).sum('amount_paid_cents * quantity') - @total_price_per_purchase_per_currency = summed_per_purchase_per_currency.each_with_object({}) do |((ticket_id, currency), amount), hash| + summed_per_ticket_per_currency = @purchases.group(:ticket_id, :currency).sum('amount_paid_cents * quantity') + @total_price_per_ticket_per_currency = summed_per_ticket_per_currency.each_with_object({}) do |((ticket_id, currency), amount), hash| hash[[ticket_id, currency]] = Money.new(amount, currency) end @total_quantity = @purchases.group(:ticket_id, :currency).sum(:quantity) diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index 7031ae3fb..5eced20ec 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -31,7 +31,6 @@ class TicketPurchase < ApplicationRecord delegate :title, to: :ticket delegate :description, to: :ticket - # delegate :price, to: :ticket delegate :price_cents, to: :ticket delegate :price_currency, to: :ticket diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index 15ef7d86a..88e4fac45 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -93,7 +93,7 @@ Total Purchased (#{currency}): = humanized_money_with_symbol(total_price) %ul - - @total_price_per_purchase_per_currency.select { |(id, curr)| curr == currency }.each do |(ticket_id, curr), total_amount| + - @total_price_per_ticket_per_currency.select { |(id, curr)| curr == currency }.each do |(ticket_id, curr), total_amount| - purchase = @purchases.find { |p| p.ticket_id == ticket_id && p.currency == curr } %li - title = purchase.title.titleize.gsub(/(?i)\bticket\b/, 'Tickets') diff --git a/spec/controllers/conference_registration_controller_spec.rb b/spec/controllers/conference_registration_controller_spec.rb index ae90ca938..dfe04003b 100644 --- a/spec/controllers/conference_registration_controller_spec.rb +++ b/spec/controllers/conference_registration_controller_spec.rb @@ -274,6 +274,34 @@ expect(assigns(:purchases)).to match_array [] end end + + context 'when user has purchased tickets' do + let!(:purchase) { create(:ticket_purchase, user: user, conference: conference, quantity: 2, amount_paid_cents: 10_000, currency: 'USD', paid: true, ticket_id: 1) } + let!(:purchase_not_paid) { create(:ticket_purchase, user: user, conference: conference, quantity: 2, amount_paid_cents: 10_000, currency: 'USD') } + let!(:purchase_diff_id) { create(:ticket_purchase, user: user, conference: conference, quantity: 1, amount_paid_cents: 10_000, currency: 'USD', paid: true, ticket_id: 2) } + let!(:purchase_diff_curr) { create(:ticket_purchase, user: user, conference: conference, quantity: 1, amount_paid_cents: 10_000, currency: 'CAD', paid: true, ticket_id: 1) } + + before do + sign_in user + get :show, params: { conference_id: conference.short_title } + end + + it 'assigns @purchases correctly' do + expect(assigns(:purchases)).to contain_exactly(purchase, purchase_diff_id, purchase_diff_curr) + end + + it 'assigns @total_price_per_ticket_per_currency correctly' do + expect(assigns(:total_price_per_ticket_per_currency)).to eq({ [purchase.ticket_id, 'USD'] => Money.new(20_000, 'USD'), [purchase_diff_id.ticket_id, 'USD'] => Money.new(10_000, 'USD'), [purchase_diff_curr.ticket_id, 'CAD'] => Money.new(10_000, 'CAD') }) + end + + it 'assigns @total_quantity correctly' do + expect(assigns(:total_quantity)).to eq({ [purchase.ticket_id, 'USD'] => 2, [purchase_diff_id.ticket_id, 'USD'] => 1, [purchase_diff_curr.ticket_id, 'CAD'] => 1 }) + end + + it 'assigns @total_price_per_currency correctly' do + expect(assigns(:total_price_per_currency)).to eq({ 'USD' => Money.new(30_000, 'USD'), 'CAD' => Money.new(10_000, 'CAD') }) + end + end end describe 'GET #edit' do diff --git a/spec/models/ticket_purchase_spec.rb b/spec/models/ticket_purchase_spec.rb index 9941afcba..9be29cb35 100644 --- a/spec/models/ticket_purchase_spec.rb +++ b/spec/models/ticket_purchase_spec.rb @@ -68,6 +68,16 @@ end end + describe 'monetization' do + let!(:purchase) { create(:ticket_purchase, amount_paid_cents: 1000, currency: 'USD') } + + it 'correctly monotizes amount_paid_cents' do + expect(purchase.purchase_price).to be_a(Money) + expect(purchase.purchase_price.currency.iso_code).to eq('USD') + expect(purchase.purchase_price.fractional).to eq(1000) + end + end + describe 'self#purchase' do let!(:participant) { create(:user) } let!(:ticket_1) { create(:ticket) } From e66a0759a4d522ef68225990907bb6ea071b6f2a Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Wed, 24 Apr 2024 13:58:32 -0700 Subject: [PATCH 25/36] fixed ticket_turnover_total failing model spec --- spec/models/ticket_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index f98d879b8..9b295a039 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -21,7 +21,7 @@ describe Ticket do let(:conference) { create(:conference) } - let(:ticket) { create(:ticket, price: 50, price_currency: 'USD', conference: conference) } + let(:ticket) { create(:ticket, price: 50, price_currency: 'USD', conference: conference, price_cents: 5_000) } let(:user) { create(:user) } describe 'validation' do @@ -83,17 +83,17 @@ subject { ticket.tickets_turnover_total ticket.id } let!(:purchase1) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 1, currency: 'USD', paid: true, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 50, amount_paid_cents: 5_000, quantity: 1, currency: 'USD', paid: true, user: user) end let!(:purchase2) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 2, currency: 'USD', paid: true, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 50, amount_paid_cents: 5_000, quantity: 2, currency: 'USD', paid: true, user: user) end let!(:purchase3) do - create(:ticket_purchase, ticket: ticket, amount_paid: 5_000, amount_paid_cents: 500_000, quantity: 10, currency: 'USD', paid: false, user: user) + create(:ticket_purchase, ticket: ticket, amount_paid: 50, amount_paid_cents: 5_000, quantity: 10, currency: 'USD', paid: false, user: user) end it 'returns turnover as Money with ticket\'s currency' do - expect(subject).to eq Money.new(500_000 * 3, ticket.price_currency) + expect(subject).to eq Money.new(5_000 * 3, ticket.price_currency) end end From aef231a2d947fab9e7d8da7abcda81f8b48079a8 Mon Sep 17 00:00:00 2001 From: tiffanylamm Date: Wed, 24 Apr 2024 14:23:10 -0700 Subject: [PATCH 26/36] spelling mistake --- spec/models/ticket_purchase_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/ticket_purchase_spec.rb b/spec/models/ticket_purchase_spec.rb index 9be29cb35..e5c944a26 100644 --- a/spec/models/ticket_purchase_spec.rb +++ b/spec/models/ticket_purchase_spec.rb @@ -71,7 +71,7 @@ describe 'monetization' do let!(:purchase) { create(:ticket_purchase, amount_paid_cents: 1000, currency: 'USD') } - it 'correctly monotizes amount_paid_cents' do + it 'correctly monetizes amount_paid_cents' do expect(purchase.purchase_price).to be_a(Money) expect(purchase.purchase_price.currency.iso_code).to eq('USD') expect(purchase.purchase_price.fractional).to eq(1000) From 0e228b8eb999ac08e2d3167cc489c999d849e8cb Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sat, 27 Apr 2024 21:39:35 -0700 Subject: [PATCH 27/36] Fix RuboCop offenses in schedules controller --- app/controllers/admin/schedules_controller.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index c7cbf911f..b0194b1fa 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -89,7 +89,7 @@ def upload_csv else Rails.logger.warn "Event not found with ID: #{row['Event_ID']}" end - rescue => e + rescue StandardError => e Rails.logger.error "Error processing row: #{row.to_h}, Error: #{e.message}" next end @@ -101,10 +101,7 @@ def upload_csv redirect_to admin_conference_schedules_path(@conference) end - - private - def schedule_params params.require(:schedule).permit(:track_id) if params[:schedule] end From 645f95aa2510701ac2e22a7dfc518a22c1783638 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sat, 27 Apr 2024 21:58:28 -0700 Subject: [PATCH 28/36] Fix RuboCop offenses in schedules controller2 --- app/controllers/admin/schedules_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index b0194b1fa..066e1128f 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -102,6 +102,7 @@ def upload_csv end private + def schedule_params params.require(:schedule).permit(:track_id) if params[:schedule] end From 384218407bcea9cb782964afd940106bac8fc048 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sat, 27 Apr 2024 22:56:34 -0700 Subject: [PATCH 29/36] Fix RuboCop offenses in schedules controller3 --- app/controllers/admin/schedules_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index 066e1128f..141ace908 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -102,7 +102,7 @@ def upload_csv end private - + def schedule_params params.require(:schedule).permit(:track_id) if params[:schedule] end From 6ba98dd874523c4f141b2e206f3eeeda1b72c0b8 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sat, 27 Apr 2024 23:35:40 -0700 Subject: [PATCH 30/36] Refactored for add event by csv --- app/controllers/admin/schedules_controller.rb | 71 ++++++++++++------- db/schema.rb | 1 - 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index 141ace908..fa9156837 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -4,6 +4,7 @@ module Admin class SchedulesController < Admin::BaseController # By authorizing 'conference' resource, we can ensure there will be no unauthorized access to # the schedule of a conference, which should not be accessed in the first place + before_action :set_conference load_and_authorize_resource :conference, find_by: :short_title load_and_authorize_resource :program, through: :conference, singleton: true load_and_authorize_resource :schedule, through: :program, except: %i[new create] @@ -69,40 +70,62 @@ def destroy end def upload_csv - @conference = Conference.find_by!(short_title: params[:conference_id]) authorize! :update, @conference + return flash[:alert] = 'No file was attached!' unless file_present? - if params[:schedule] && params[:schedule][:file].present? - file = params[:schedule][:file] - CSV.foreach(file.path, headers: true) do |row| - next if row['Event_ID'].blank? || row['Date'].blank? || row['Start_Time'].blank? || row['Room'].blank? - - begin - event_date = Date.strptime(row['Date'], '%m/%d/%y') - event_time = Time.parse(row['Start_Time']) - event_start_time = DateTime.new(event_date.year, event_date.month, event_date.day, event_time.hour, event_time.min, event_time.sec, event_time.zone) - room = Room.find_or_create_by(name: row['Room']) - event = Event.find_by(id: row['Event_ID']) - - if event - event.update(start_time: event_start_time, room: room) - else - Rails.logger.warn "Event not found with ID: #{row['Event_ID']}" - end - rescue StandardError => e - Rails.logger.error "Error processing row: #{row.to_h}, Error: #{e.message}" - next - end - end + if process_csv flash[:notice] = 'Schedule uploaded successfully!' else - flash[:alert] = 'No file was attached!' + flash[:alert] = "Failed to process CSV file." end + redirect_to admin_conference_schedules_path(@conference) end private + def set_conference + @conference = Conference.find_by!(short_title: params[:conference_id]) + end + + def file_present? + params[:schedule] && params[:schedule][:file].present? + end + + def process_csv + file = params[:schedule][:file] + CSV.foreach(file.path, headers: true) do |row| + process_row(row) + end + true + rescue => e + Rails.logger.error "CSV Processing Error: #{e.message}" + false + end + + def process_row(row) + event_date = parse_date(row['Date']) + event_time = parse_time(row['Start_Time']) + event_start_time = combine_datetime(event_date, event_time) + + room = Room.find_or_create_by(name: row['Room']) + event = Event.find_by(id: row['Event_ID']) + + event.update(start_time: event_start_time, room: room) if event + end + + def parse_date(date_str) + Date.strptime(date_str, '%m/%d/%y') + end + + def parse_time(time_str) + Time.parse(time_str) + end + + def combine_datetime(date, time) + DateTime.new(date.year, date.month, date.day, time.hour, time.min, time.sec, time.zone) + end + def schedule_params params.require(:schedule).permit(:track_id) if params[:schedule] end diff --git a/db/schema.rb b/db/schema.rb index 01fbae77e..c31c972f9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -625,7 +625,6 @@ t.boolean "is_disabled", default: false t.string "picture" t.string "timezone" - t.string "default_currency" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true From c847c3a04329a83317820a421d63f18312bf55d4 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sat, 27 Apr 2024 23:41:41 -0700 Subject: [PATCH 31/36] Fix RuboCop offenses in schedules controller --- app/controllers/admin/schedules_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index fa9156837..6e716caaf 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -76,7 +76,7 @@ def upload_csv if process_csv flash[:notice] = 'Schedule uploaded successfully!' else - flash[:alert] = "Failed to process CSV file." + flash[:alert] = 'Failed to process CSV file.' end redirect_to admin_conference_schedules_path(@conference) @@ -98,7 +98,7 @@ def process_csv process_row(row) end true - rescue => e + rescue StandardError => e Rails.logger.error "CSV Processing Error: #{e.message}" false end @@ -111,7 +111,7 @@ def process_row(row) room = Room.find_or_create_by(name: row['Room']) event = Event.find_by(id: row['Event_ID']) - event.update(start_time: event_start_time, room: room) if event + event&.update(start_time: event_start_time, room: room) end def parse_date(date_str) From cf52a84a62ff0d7ee94b1b06580440b7067c49db Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sun, 28 Apr 2024 03:07:56 -0700 Subject: [PATCH 32/36] Fix code style issues --- app/assets/javascripts/osem-schedule.js | 2 +- app/models/commercial.rb | 62 ++++++++++++++++--------- spec/features/event_schedules_spec.rb | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/osem-schedule.js b/app/assets/javascripts/osem-schedule.js index 61e6894bb..c233c877d 100644 --- a/app/assets/javascripts/osem-schedule.js +++ b/app/assets/javascripts/osem-schedule.js @@ -84,7 +84,7 @@ $(document).ready( function() { var now = new Date(); var closestEventId = null; var smallestDiff = Infinity; - var i=0 + var i = 0; $('.event-item').each(function() { diff --git a/app/models/commercial.rb b/app/models/commercial.rb index 42d4ccadf..5ec8f6e98 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -40,34 +40,50 @@ def self.render_from_url(url) end end + # Extracted method to parse the URI and handle errors + def self.parse_uri(url) + URI.parse(url) + rescue URI::InvalidURIError + nil + end + + # New method to determine if the URL is a Snap! project + def self.snap_berkeley_project?(uri) + uri.host == 'snap.berkeley.edu' && uri.path == '/project' + end + + # Extracted method to parse query parameters + def self.parse_query(uri) + URI.decode_www_form(uri.query).to_h + end + + # New method to build the embed URL + def self.build_embed_url(uri, args) + new_query = URI.encode_www_form({ + 'projectname' => args['projectname'], + 'username' => args['username'], + 'showTitle' => 'true', + 'showAuthor' => 'true', + 'editButton' => 'true', + 'pauseButton' => 'true' + }) + URI::HTTPS.build(host: uri.host, path: '/embed', query: new_query).to_s + end + + # Updated generate_snap_embed to use extracted methods def self.generate_snap_embed(url) return url unless url - uri = URI.parse(url) - if uri.host == 'snap.berkeley.edu' && uri.path == '/project' - args = URI.decode_www_form(uri.query).to_h - else - return url - end - if args.key?('username') && args.key?('projectname') - new_query = URI.encode_www_form({ - 'projectname' => args['projectname'], - 'username' => args['username'], - 'showTitle' => 'true', - 'showAuthor' => 'true', - 'editButton' => 'true', - 'pauseButton' => 'true' - }) - new_uri = URI::HTTPS.build( - host: uri.host, - path: '/embed', - query: new_query - ) - return new_uri.to_s - end - url + uri = parse_uri(url) + return url unless uri && snap_berkeley_project?(uri) + + args = parse_query(uri) + return url unless args.key?('username') && args.key?('projectname') + + build_embed_url(uri, args) end + def self.iframe_fallback(url) "".html_safe end diff --git a/spec/features/event_schedules_spec.rb b/spec/features/event_schedules_spec.rb index a166a247f..cc01677a5 100644 --- a/spec/features/event_schedules_spec.rb +++ b/spec/features/event_schedules_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe EventSchedule, js: true do +describe EventSchedule, :js do Timecop.return let(:test_date) { Time.current } let!(:conference) do From b7999bcc18be167585202d452c20033b545e2229 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sun, 28 Apr 2024 03:09:18 -0700 Subject: [PATCH 33/36] Fix code style issues --- app/models/commercial.rb | 62 +++++++++++++++------------------------- 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/app/models/commercial.rb b/app/models/commercial.rb index 5ec8f6e98..42d4ccadf 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -40,50 +40,34 @@ def self.render_from_url(url) end end - # Extracted method to parse the URI and handle errors - def self.parse_uri(url) - URI.parse(url) - rescue URI::InvalidURIError - nil - end - - # New method to determine if the URL is a Snap! project - def self.snap_berkeley_project?(uri) - uri.host == 'snap.berkeley.edu' && uri.path == '/project' - end - - # Extracted method to parse query parameters - def self.parse_query(uri) - URI.decode_www_form(uri.query).to_h - end - - # New method to build the embed URL - def self.build_embed_url(uri, args) - new_query = URI.encode_www_form({ - 'projectname' => args['projectname'], - 'username' => args['username'], - 'showTitle' => 'true', - 'showAuthor' => 'true', - 'editButton' => 'true', - 'pauseButton' => 'true' - }) - URI::HTTPS.build(host: uri.host, path: '/embed', query: new_query).to_s - end - - # Updated generate_snap_embed to use extracted methods def self.generate_snap_embed(url) return url unless url - uri = parse_uri(url) - return url unless uri && snap_berkeley_project?(uri) - - args = parse_query(uri) - return url unless args.key?('username') && args.key?('projectname') - - build_embed_url(uri, args) + uri = URI.parse(url) + if uri.host == 'snap.berkeley.edu' && uri.path == '/project' + args = URI.decode_www_form(uri.query).to_h + else + return url + end + if args.key?('username') && args.key?('projectname') + new_query = URI.encode_www_form({ + 'projectname' => args['projectname'], + 'username' => args['username'], + 'showTitle' => 'true', + 'showAuthor' => 'true', + 'editButton' => 'true', + 'pauseButton' => 'true' + }) + new_uri = URI::HTTPS.build( + host: uri.host, + path: '/embed', + query: new_query + ) + return new_uri.to_s + end + url end - def self.iframe_fallback(url) "".html_safe end From 62ff980dc4a70983bfd59f97d933e2d68f8b5e36 Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Sun, 21 Apr 2024 13:32:05 -0700 Subject: [PATCH 34/36] delete event enable --- app/controllers/admin/events_controller.rb | 14 ++++++++++++++ app/views/admin/events/_proposal.html.haml | 2 ++ 2 files changed, 16 insertions(+) diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb index adf1bde7a..9d401e6fa 100644 --- a/app/controllers/admin/events_controller.rb +++ b/app/controllers/admin/events_controller.rb @@ -182,6 +182,17 @@ def toggle_attendance end end + def destroy + @event = Event.find(params[:id]) + if @event.destroy + flash[:notice] = 'Event successfully deleted.' + redirect_to admin_conference_program_events_path(@conference.short_title) + else + flash[:alert] = 'Event could not be deleted.' + redirect_to admin_conference_program_event_path(@conference.short_title, @event) + end + end + private def event_params @@ -224,5 +235,8 @@ def load_events_with_data votes: [:user] ) end + end + + end diff --git a/app/views/admin/events/_proposal.html.haml b/app/views/admin/events/_proposal.html.haml index ae50c63d2..0fc5aa459 100644 --- a/app/views/admin/events/_proposal.html.haml +++ b/app/views/admin/events/_proposal.html.haml @@ -11,6 +11,8 @@ = link_to 'Preview', conference_program_proposal_path(@conference.short_title, @event.id), class: 'btn btn-mini btn-primary' = link_to 'Registrations', registrations_admin_conference_program_event_path(@conference.short_title, @event), class: 'btn btn-success' = link_to 'Edit', edit_admin_conference_program_event_path(@conference.short_title, @event), class: 'btn btn-mini btn-primary' + = link_to 'Delete', admin_conference_program_event_path(@conference.short_title, @event), method: :delete, data: { confirm: 'Are you sure you want to delete this event?' }, class: 'btn btn-mini btn-danger' + .row .col-md-12 From 8aab77e1bc7744db7644846b6d5539640d37ceee Mon Sep 17 00:00:00 2001 From: Warren Huang Date: Sun, 28 Apr 2024 16:48:24 -0700 Subject: [PATCH 35/36] rubocop styling fix --- app/controllers/admin/events_controller.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb index 9d401e6fa..939b4d967 100644 --- a/app/controllers/admin/events_controller.rb +++ b/app/controllers/admin/events_controller.rb @@ -235,8 +235,5 @@ def load_events_with_data votes: [:user] ) end - end - - end From 1787ba73ddec33cb2beee426090840017c18bf18 Mon Sep 17 00:00:00 2001 From: Owen Yang Date: Sun, 28 Apr 2024 21:34:04 -0700 Subject: [PATCH 36/36] Revert "Revert "187121499 enable default currency"" This reverts commit ca55c9ab919fb59e40135c5712b54a9ead5b1cd1. --- app/controllers/users_controller.rb | 7 ++++++- app/models/currency_conversion.rb | 2 ++ app/models/user.rb | 1 + app/views/users/edit.html.haml | 3 +++ db/schema.rb | 1 + spec/factories/users.rb | 1 + spec/models/user_spec.rb | 1 + 7 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d661a9b3e..5d29ef60d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,6 +2,7 @@ class UsersController < ApplicationController before_action :authenticate_user!, only: :search + before_action :set_currency_options, only: [:edit, :new, :create, :update] load_and_authorize_resource # GET /users/1 @@ -40,7 +41,7 @@ def search def user_params params[:user][:timezone] = params[:user][:timezone].presence || nil - params.require(:user).permit(:name, :biography, :nickname, :affiliation, + params.require(:user).permit(:name, :biography, :nickname, :affiliation, :default_currency, :picture, :picture_cache, :timezone) end @@ -49,5 +50,9 @@ def user_params def load_user @user ||= (params[:id] && params[:id] != 'current' && User.find(params[:id])) || current_user end + # rubocop:enable Naming/MemoizedInstanceVariableName + def set_currency_options + @currency_options = CurrencyConversion::VALID_CURRENCIES.map { |currency| [currency, currency] } + end end diff --git a/app/models/currency_conversion.rb b/app/models/currency_conversion.rb index ffc2ca197..9d25094c6 100644 --- a/app/models/currency_conversion.rb +++ b/app/models/currency_conversion.rb @@ -24,6 +24,8 @@ class CurrencyConversion < ApplicationRecord VALID_CURRENCIES = %w[AUD CAD CHF CNY EUR GBP JPY USD].freeze belongs_to :conference validates :rate, numericality: { greater_than: 0 } + # Ensure from_currency and to_currency are among the VALID_CURRENCIES + validates :from_currency, :to_currency, inclusion: { in: VALID_CURRENCIES } validates :from_currency, uniqueness: { scope: :to_currency }, on: :create def self.convert_currency(conference, amount, from_currency, to_currency) diff --git a/app/models/user.rb b/app/models/user.rb index bcf38b4db..bfa75bb97 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -16,6 +16,7 @@ # confirmed_at :datetime # current_sign_in_at :datetime # current_sign_in_ip :string +# default_currency :string # email :string default(""), not null # email_public :boolean default(FALSE) # encrypted_password :string default(""), not null diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index d1b967620..aff35bd69 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -23,6 +23,9 @@ The timezone setting will update the event schedules to show using the time you selected. Your browser is current set to %span.js-localTimezone + .form-group + = f.label :default_currency, 'Default Currency' + = f.select :default_currency, options_for_select(@currency_options, selected: @user.default_currency), {}, { class: 'form-control' } .form-group = f.label :avatar %br diff --git a/db/schema.rb b/db/schema.rb index 06f91c428..240119034 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -627,6 +627,7 @@ t.boolean "is_disabled", default: false t.string "picture" t.string "timezone" + t.string "default_currency" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 78784fa4f..f9135376c 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -16,6 +16,7 @@ # confirmed_at :datetime # current_sign_in_at :datetime # current_sign_in_ip :string +# default_currency :string # email :string default(""), not null # email_public :boolean default(FALSE) # encrypted_password :string default(""), not null diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a999ef03a..151acca47 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -16,6 +16,7 @@ # confirmed_at :datetime # current_sign_in_at :datetime # current_sign_in_ip :string +# default_currency :string # email :string default(""), not null # email_public :boolean default(FALSE) # encrypted_password :string default(""), not null