diff --git a/.github/workflows/spec.yml b/.github/workflows/spec.yml index 81aecc018..c46ed7704 100644 --- a/.github/workflows/spec.yml +++ b/.github/workflows/spec.yml @@ -42,7 +42,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v1 with: - node-version: '12.x' + node-version: '16.x' - run: sudo apt-get install xvfb - name: Install JavaScript libraries via npm run: npm install diff --git a/.rubocop.yml b/.rubocop.yml index 57d6da91c..b44f547da 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,10 @@ -inherit_from: .rubocop_todo.yml - require: - rubocop-rspec - - rubocop-rails # Currently disabled below. + - rubocop-rails + - rubocop-capybara + - rubocop-performance + +inherit_from: .rubocop_todo.yml inherit_mode: merge: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0f161ba5b..48a9a2252 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,13 +1,35 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2022-08-08 22:16:03 UTC using RuboCop version 1.31.2. +# on 2024-02-13 04:01:02 UTC using RuboCop version 1.60.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. +# Include: **/*.gemfile, **/Gemfile, **/gems.rb +Bundler/OrderedGems: + Exclude: + - 'Gemfile' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: have_no, not_to +Capybara/NegationMatcher: + Exclude: + - 'spec/features/versions_spec.rb' + +# Offense count: 98 +# This cop supports safe autocorrection (--autocorrect). +Capybara/SpecificFinders: + Enabled: false + # Offense count: 13 -# Configuration parameters: IgnoredMethods. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowedMethods, AllowedPatterns. Lint/AmbiguousBlockAssociation: Exclude: - 'spec/controllers/admin/conferences_controller_spec.rb' @@ -25,43 +47,35 @@ Lint/DuplicateBranch: - 'app/helpers/format_helper.rb' - 'app/uploaders/picture_uploader.rb' -# Offense count: 1 -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/features/user_spec.rb' - # Offense count: 4 Lint/IneffectiveAccessModifier: Exclude: - 'app/models/commercial.rb' - 'app/models/conference.rb' -# Offense count: 112 -# Configuration parameters: IgnoredMethods, CountRepeatedAttributes. +# Offense count: 111 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: Max: 72 -# Offense count: 18 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods, inherit_mode. -# IgnoredMethods: refine +# Offense count: 19 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# AllowedMethods: refine Metrics/BlockLength: - Max: 226 - Exclude: - - 'config/routes.rb' + Max: 227 -# Offense count: 14 +# Offense count: 13 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 283 + Max: 270 # Offense count: 26 -# Configuration parameters: IgnoredMethods. +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: - Max: 16 + Max: 15 -# Offense count: 123 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +# Offense count: 127 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Max: 55 @@ -70,8 +84,8 @@ Metrics/MethodLength: Metrics/ModuleLength: Max: 168 -# Offense count: 24 -# Configuration parameters: IgnoredMethods. +# Offense count: 25 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: Max: 17 @@ -83,7 +97,7 @@ Naming/AccessorMethodName: # Offense count: 2 # Configuration parameters: ForbiddenDelimiters. -# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +# ForbiddenDelimiters: (?i-mx:(^|\s)(EO[A-Z]{1}|END)(\s|$)) Naming/HeredocDelimiterNaming: Exclude: - 'spec/factories/users.rb' @@ -91,7 +105,7 @@ Naming/HeredocDelimiterNaming: # Offense count: 2 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. -# AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'app/models/conference.rb' @@ -110,7 +124,7 @@ Naming/PredicateName: # Offense count: 9 # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. # SupportedStyles: snake_case, normalcase, non_integer -# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339 +# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 Naming/VariableNumber: Exclude: - 'app/models/program.rb' @@ -118,6 +132,37 @@ Naming/VariableNumber: - 'spec/models/payment_spec.rb' - 'spec/models/ticket_purchase_spec.rb' +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/Casecmp: + Exclude: + - 'config/environments/production.rb' + +# Offense count: 1 +# Configuration parameters: MinSize. +Performance/CollectionLiteralInLoop: + Exclude: + - 'app/models/conference.rb' + +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/InefficientHashSearch: + Exclude: + - 'app/controllers/admin/versions_controller.rb' + - 'app/helpers/versions_helper.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/MapCompact: + Exclude: + - 'app/datatables/registration_datatable.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/StringInclude: + Exclude: + - 'app/models/commercial.rb' + # Offense count: 32 RSpec/AnyInstance: Exclude: @@ -130,8 +175,24 @@ RSpec/AnyInstance: - 'spec/controllers/proposals_controller_spec.rb' - 'spec/controllers/tracks_controller_spec.rb' +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +RSpec/BeEmpty: + Exclude: + - 'spec/controllers/conference_registration_controller_spec.rb' + - 'spec/models/conference_spec.rb' + +# Offense count: 12 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnabledMethods. +RSpec/Capybara/FeatureMethods: + Exclude: + - 'spec/features/proposals_spec.rb' + - 'spec/features/user_spec.rb' + - 'spec/features/voting_spec.rb' + # Offense count: 338 -# Configuration parameters: Prefixes. +# Configuration parameters: Prefixes, AllowedPatterns. # Prefixes: when, with, without RSpec/ContextWording: Enabled: false @@ -143,7 +204,7 @@ RSpec/ContextWording: RSpec/DescribedClass: Enabled: false -# Offense count: 246 +# Offense count: 248 # Configuration parameters: CountAsOne. RSpec/ExampleLength: Max: 222 @@ -184,11 +245,37 @@ RSpec/FilePath: - 'spec/models/comment_spec.rb' - 'spec/models/openid.rb' +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, each, example +RSpec/HookArgument: + Exclude: + - 'spec/features/voting_spec.rb' + # Offense count: 2 RSpec/IdenticalEqualityAssertion: Exclude: - 'spec/controllers/admin/conferences_controller_spec.rb' +# Offense count: 53 +# Configuration parameters: Max. +RSpec/IndexedLet: + Exclude: + - 'spec/controllers/admin/reports_controller_spec.rb' + - 'spec/controllers/admin/roles_controller_spec.rb' + - 'spec/controllers/schedules_controller_spec.rb' + - 'spec/features/proposals_spec.rb' + - 'spec/features/splashpage_spec.rb' + - 'spec/features/voting_spec.rb' + - 'spec/helpers/conference_helper_spec.rb' + - 'spec/models/conference_spec.rb' + - 'spec/models/event_schedule_spec.rb' + - 'spec/models/ticket_purchase_spec.rb' + - 'spec/models/ticket_spec.rb' + - 'spec/models/user_spec.rb' + - 'spec/services/full_calendar_formatter_spec.rb' + # Offense count: 344 # Configuration parameters: AssignmentOnly. RSpec/InstanceVariable: @@ -209,10 +296,18 @@ RSpec/InstanceVariable: - 'spec/models/track_spec.rb' - 'spec/models/user_spec.rb' -# Offense count: 63 +# Offense count: 64 RSpec/LetSetup: Enabled: false +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +RSpec/MatchArray: + Exclude: + - 'spec/controllers/admin/conferences_controller_spec.rb' + - 'spec/controllers/admin/users_controller_spec.rb' + - 'spec/models/conference_spec.rb' + # Offense count: 12 # Configuration parameters: . # SupportedStyles: have_received, receive @@ -224,17 +319,18 @@ RSpec/MultipleDescribes: Exclude: - 'spec/models/conference_spec.rb' -# Offense count: 297 +# Offense count: 298 RSpec/MultipleExpectations: Max: 97 -# Offense count: 270 +# Offense count: 272 # Configuration parameters: AllowSubject. RSpec/MultipleMemoizedHelpers: Max: 32 -# Offense count: 440 -# Configuration parameters: IgnoreSharedExamples. +# Offense count: 438 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only RSpec/NamedSubject: Exclude: - 'spec/ability/ability_spec.rb' @@ -253,14 +349,53 @@ RSpec/NamedSubject: - 'spec/models/track_spec.rb' # Offense count: 219 +# Configuration parameters: AllowedGroups. RSpec/NestedGroups: Max: 7 +# Offense count: 4 +# Configuration parameters: AllowedPatterns. +# AllowedPatterns: ^expect_, ^assert_ +RSpec/NoExpectationExample: + Exclude: + - 'spec/controllers/admin/conferences_controller_spec.rb' + - 'spec/controllers/admin/registration_periods_controller_spec.rb' + - 'spec/features/proposals_spec.rb' + - 'spec/features/voting_spec.rb' + # Offense count: 1 RSpec/OverwritingSetup: Exclude: - 'spec/controllers/admin/booths_controller_spec.rb' +# Offense count: 11 +RSpec/PendingWithoutReason: + Exclude: + - 'spec/ability/ability_spec.rb' + - 'spec/controllers/admin/conferences_controller_spec.rb' + - 'spec/datatables/user_datatable_spec.rb' + - 'spec/features/proposals_spec.rb' + - 'spec/features/versions_spec.rb' + - 'spec/models/user_spec.rb' + +# Offense count: 12 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Inferences. +RSpec/Rails/InferredSpecType: + Exclude: + - 'spec/controllers/admin/comments_controller_spec.rb' + - 'spec/controllers/admin/programs_controller_spec.rb' + - 'spec/controllers/application_controller_spec.rb' + - 'spec/controllers/conference_registration_controller_spec.rb' + - 'spec/features/omniauth_spec.rb' + - 'spec/helpers/application_helper_spec.rb' + - 'spec/helpers/conference_helper_spec.rb' + - 'spec/helpers/date_time_helper_spec.rb' + - 'spec/helpers/events_helper_spec.rb' + - 'spec/helpers/format_helper_spec.rb' + - 'spec/helpers/users_helper_spec.rb' + - 'spec/routing/routing_spec.rb' + # Offense count: 4 RSpec/RepeatedDescription: Exclude: @@ -277,10 +412,17 @@ RSpec/RepeatedExampleGroupBody: - 'spec/models/conference_spec.rb' # Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). RSpec/ScatteredSetup: Exclude: - 'spec/models/payment_spec.rb' +# Offense count: 32 +# This cop supports safe autocorrection (--autocorrect). +RSpec/SortMetadata: + Exclude: + - 'spec/features/versions_spec.rb' + # Offense count: 9 RSpec/StubbedMock: Exclude: @@ -310,25 +452,26 @@ Security/Open: Exclude: - 'app/pdfs/ticket_pdf.rb' -# Offense count: 11 +# Offense count: 3 # This cop supports unsafe autocorrection (--autocorrect-all). -Style/CaseLikeIf: +Style/ArrayIntersect: Exclude: - - 'app/controllers/admin/roles_controller.rb' - - 'app/controllers/admin/users_controller.rb' - 'app/helpers/application_helper.rb' - - 'app/helpers/versions_helper.rb' - - 'app/models/user.rb' - - 'app/views/admin/booths/booths.xlsx.axlsx' + - 'app/models/admin_ability.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: MinBranchesCount. +Style/CaseLikeIf: + Exclude: - 'app/views/admin/events/events.xlsx.axlsx' - - 'app/views/admin/tracks/tracks.xlsx.axlsx' -# Offense count: 100 +# Offense count: 103 # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false -# Offense count: 41 +# Offense count: 40 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never @@ -341,7 +484,8 @@ Style/GlobalStdStream: Exclude: - 'config/environments/production.rb' -# Offense count: 35 +# Offense count: 36 +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: Enabled: false @@ -366,7 +510,7 @@ Style/IdenticalConditionalBranches: - 'app/controllers/admin/booths_controller.rb' - 'app/controllers/admin/events_controller.rb' -# Offense count: 28 +# Offense count: 32 # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Enabled: false @@ -386,6 +530,13 @@ Style/MapToHash: - 'app/helpers/chart_helper.rb' - 'app/models/conference.rb' +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/MinMaxComparison: + Exclude: + - 'app/helpers/format_helper.rb' + - 'app/models/cfp.rb' + # Offense count: 1 Style/MixinUsage: Exclude: @@ -406,7 +557,7 @@ Style/MutableConstant: # Offense count: 32 # This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle, IgnoredMethods. +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: @@ -435,6 +586,20 @@ Style/OptionalBooleanParameter: - 'app/helpers/format_helper.rb' - 'app/models/event.rb' +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowedCompactTypes. +# SupportedStyles: compact, exploded +Style/RaiseArgs: + EnforcedStyle: compact + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantConstantBase: + Exclude: + - 'config/environments/production.rb' + - 'spec/spec_helper.rb' + # Offense count: 3 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: SafeForConstants. @@ -442,7 +607,13 @@ Style/RedundantFetchBlock: Exclude: - 'config/puma.rb' -# Offense count: 37 +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantStringEscape: + Exclude: + - 'app/models/conference.rb' + +# Offense count: 34 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: @@ -450,8 +621,8 @@ Style/StringConcatenation: # Offense count: 11 # This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowMethodsWithArguments, IgnoredMethods, AllowComments. -# IgnoredMethods: respond_to, define_method +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method, mail, respond_to Style/SymbolProc: Exclude: - 'app/controllers/admin/comments_controller.rb' @@ -461,9 +632,17 @@ Style/SymbolProc: - 'spec/controllers/admin/conferences_controller_spec.rb' - 'spec/support/flash.rb' -# Offense count: 249 +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + EnforcedStyle: percent + MinSize: 5 + +# Offense count: 260 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns. +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. # URISchemes: http, https Layout/LineLength: Max: 267 diff --git a/.tool-versions b/.tool-versions index d420824ab..80e5486ad 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ ruby 3.2.2 -nodejs latest:12 +nodejs 16.20.2 diff --git a/Gemfile b/Gemfile index ce5427ef4..cbae5bbea 100644 --- a/Gemfile +++ b/Gemfile @@ -140,7 +140,9 @@ gem 'leaflet-rails' gem 'gravtastic' # for country selects -gem 'country_select', '< 7' +# TODO-SNAPCON: Verify that this is no longer necessary. +# gem 'country_select', '< 7' +gem 'i18n_data' # as PDF generator gem 'prawn-qrcode' @@ -222,16 +224,13 @@ gem 'selectize-rails' # n+1 query logging gem 'bullet' -# For collecting performance data -gem 'skylight', '~> 5' - -gem 'nokogiri' # memcached binary connector gem 'dalli', require: false # Redis Cache gem 'redis' +# to generate ical files gem 'icalendar' # for making external requests easier @@ -240,10 +239,10 @@ gem 'httparty' # pagination gem 'pagy', '<4.0' -# Use guard for testing in development +# to tame logs +gem 'lograge' + group :development do - # to launch specs when files are modified - gem 'guard-rspec' # to open mails gem 'letter_opener' # view mail at /letter_opener/ @@ -290,18 +289,23 @@ end group :development, :test, :linters do # as debugger gem 'byebug' - # gem 'pry' - # gem 'pry-byebug' - # Linters and static analysis. + # for static code analisys + gem 'rubocop', require: false + gem 'rubocop-rspec', require: false + gem 'rubocop-rails', require: false + gem 'rubocop-capybara', require: false + gem 'rubocop-performance', require: false + gem 'haml_lint' + gem 'faraday-retry', require: false + # TODO-SNAPCON: figure out which haml-lint OR haml_lint is good. gem 'haml-lint', require: false + + # Easily run linters gem 'pronto', require: false gem 'pronto-haml', require: false gem 'pronto-rubocop', require: false - gem 'rubocop-faker', require: false - gem 'rubocop-rails', require: false - gem 'rubocop-rspec', require: false end group :development, :test do @@ -310,5 +314,3 @@ group :development, :test do # to test new rails version gem 'next_rails' end - -gem "jemalloc", "~> 1.0" diff --git a/Gemfile.lock b/Gemfile.lock index 34055e4b6..9ca9cf93e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,7 +26,7 @@ GEM rails-assets-momentjs (2.29.4) rails-assets-spectrum (1.8.0) rails-assets-jquery (>= 1.7.2) - rails-assets-tinycolor (1.4.1) + rails-assets-tinycolor (1.6.0) rails-assets-to-markdown (3.1.1) rails-assets-trianglify (1.2.0) rails-assets-waypoints (4.0.1) @@ -35,47 +35,47 @@ GEM remote: https://rubygems.org/ specs: Ascii85 (1.1.0) - actioncable (7.0.4.2) - actionpack (= 7.0.4.2) - activesupport (= 7.0.4.2) + actioncable (7.0.4.3) + actionpack (= 7.0.4.3) + activesupport (= 7.0.4.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.4.2) - actionpack (= 7.0.4.2) - activejob (= 7.0.4.2) - activerecord (= 7.0.4.2) - activestorage (= 7.0.4.2) - activesupport (= 7.0.4.2) + actionmailbox (7.0.4.3) + actionpack (= 7.0.4.3) + activejob (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.4.2) - actionpack (= 7.0.4.2) - actionview (= 7.0.4.2) - activejob (= 7.0.4.2) - activesupport (= 7.0.4.2) + actionmailer (7.0.4.3) + actionpack (= 7.0.4.3) + actionview (= 7.0.4.3) + activejob (= 7.0.4.3) + activesupport (= 7.0.4.3) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) - actionpack (7.0.4.2) - actionview (= 7.0.4.2) - activesupport (= 7.0.4.2) + actionpack (7.0.4.3) + actionview (= 7.0.4.3) + activesupport (= 7.0.4.3) rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.4.2) - actionpack (= 7.0.4.2) - activerecord (= 7.0.4.2) - activestorage (= 7.0.4.2) - activesupport (= 7.0.4.2) + actiontext (7.0.4.3) + actionpack (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.4.2) - activesupport (= 7.0.4.2) + actionview (7.0.4.3) + activesupport (= 7.0.4.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -85,22 +85,22 @@ GEM activemodel (>= 4.1, < 7.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.0.4.2) - activesupport (= 7.0.4.2) + activejob (7.0.4.3) + activesupport (= 7.0.4.3) globalid (>= 0.3.6) - activemodel (7.0.4.2) - activesupport (= 7.0.4.2) - activerecord (7.0.4.2) - activemodel (= 7.0.4.2) - activesupport (= 7.0.4.2) - activestorage (7.0.4.2) - actionpack (= 7.0.4.2) - activejob (= 7.0.4.2) - activerecord (= 7.0.4.2) - activesupport (= 7.0.4.2) + activemodel (7.0.4.3) + activesupport (= 7.0.4.3) + activerecord (7.0.4.3) + activemodel (= 7.0.4.3) + activesupport (= 7.0.4.3) + activestorage (7.0.4.3) + actionpack (= 7.0.4.3) + activejob (= 7.0.4.3) + activerecord (= 7.0.4.3) + activesupport (= 7.0.4.3) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.4.2) + activesupport (7.0.4.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -109,12 +109,13 @@ GEM activerecord (>= 4.0) activesupport (>= 4.0) awesome_nested_set (>= 3.0) - acts_as_list (1.0.4) + acts_as_list (1.1.0) activerecord (>= 4.2) addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) afm (0.2.2) - ajax-datatables-rails (1.3.1) + ajax-datatables-rails (1.4.0) + rails (>= 5.2) zeitwerk annotate (3.2.0) activerecord (>= 3.2, < 8.0) @@ -122,7 +123,7 @@ GEM archive-zip (0.12.0) io-like (~> 0.3.0) ast (2.4.2) - autoprefixer-rails (10.4.7.0) + autoprefixer-rails (10.4.13.0) execjs (~> 2) awesome_nested_set (3.5.0) activerecord (>= 4.0.0, < 7.1) @@ -140,7 +141,7 @@ GEM activesupport (>= 3.0.0) uniform_notifier (~> 1.11) byebug (11.1.3) - cancancan (3.3.0) + cancancan (3.5.0) capybara (3.39.2) addressable matrix @@ -150,7 +151,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.2) + carrierwave (2.2.4) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -164,7 +165,7 @@ GEM fastimage case_transform (0.2) activesupport - caxlsx (3.2.0) + caxlsx (3.4.1) htmlentities (~> 4.3, >= 4.3.4) marcel (~> 1.0) nokogiri (~> 1.10, >= 1.10.4) @@ -172,25 +173,18 @@ GEM caxlsx_rails (0.6.3) actionpack (>= 3.1) caxlsx (>= 3.0) - chartkick (4.2.0) + chartkick (5.0.2) chronic (0.10.2) chunky_png (1.4.0) - climate_control (1.1.1) - cloudinary (1.23.0) + climate_control (1.2.0) + cloudinary (1.25.0) aws_cf_signer rest-client (>= 2.0.0) cocoon (1.2.15) - coderay (1.1.3) colorize (0.8.1) - concurrent-ruby (1.2.2) + concurrent-ruby (1.2.3) countable-rails (0.0.1) railties (>= 3.1) - countries (4.2.3) - i18n_data (~> 0.16.0) - sixarm_ruby_unaccent (~> 1.1) - country_select (6.1.1) - countries (~> 4.2) - sort_alphabetical (~> 1.1) crack (0.4.5) rexml crass (1.0.6) @@ -235,21 +229,21 @@ GEM cucumber-core (~> 10.1, >= 10.1.0) cucumber-cucumber-expressions (~> 14.0, >= 14.0.0) daemons (1.4.1) - dalli (3.2.3) + dalli (3.2.5) dante (0.2.0) - database_cleaner (2.0.1) - database_cleaner-active_record (~> 2.0.0) - database_cleaner-active_record (2.0.1) + database_cleaner (2.0.2) + database_cleaner-active_record (>= 2, < 3) + database_cleaner-active_record (2.1.0) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) date (3.3.3) - delayed_job (4.1.10) + delayed_job (4.1.11) activesupport (>= 3.0, < 8.0) delayed_job_active_record (4.1.7) activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) - devise (4.8.1) + devise (4.9.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -261,19 +255,18 @@ GEM docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.6) - dotenv-rails (2.7.6) - dotenv (= 2.7.6) + dotenv (2.8.1) + dotenv-rails (2.8.1) + dotenv (= 2.8.1) railties (>= 3.2) erubi (1.12.0) - erubis (2.7.0) execjs (2.8.1) factory_bot (6.2.1) activesupport (>= 5.0.0) factory_bot_rails (6.2.0) factory_bot (~> 6.2.0) railties (>= 5.0.0) - faker (2.21.0) + faker (3.2.0) i18n (>= 1.8.11, < 2) faraday (2.7.4) faraday-net_http (>= 2.0, < 3.1) @@ -281,12 +274,11 @@ GEM faraday-net_http (3.0.2) faraday-retry (2.0.0) faraday (~> 2.0) - fastimage (2.2.6) + fastimage (2.2.7) feature (1.4.0) ffi (1.15.5) - font-awesome-sass (6.1.1) + font-awesome-sass (6.4.0) sassc (~> 2.0) - formatador (1.1.0) geckodriver-helper (0.24.0) archive-zip (~> 0.7) gitlab (4.19.0) @@ -295,33 +287,19 @@ GEM globalid (1.1.0) activesupport (>= 5.0) gravtastic (3.2.6) - guard (2.18.0) - formatador (>= 0.2.4) - listen (>= 2.7, < 4.0) - lumberjack (>= 1.0.12, < 2.0) - nenv (~> 0.1) - notiffany (~> 0.0) - pry (>= 0.13.0) - shellany (~> 0.0) - thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.7.3) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) - haml (5.2.2) - temple (>= 0.8.0) + haml (6.1.1) + temple (>= 0.8.2) + thor tilt haml-lint (0.999.999) haml_lint - haml-rails (2.0.1) + haml-rails (2.1.0) actionpack (>= 5.1) activesupport (>= 5.1) - haml (>= 4.0.6, < 6.0) - html2haml (>= 1.0.1) + haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.40.0) - haml (>= 4.0, < 5.3) + haml_lint (0.45.0) + haml (>= 4.0, < 6.2) parallel (~> 1.10) rainbow rubocop (>= 0.50.0) @@ -329,11 +307,6 @@ GEM hashdiff (1.0.1) hashery (2.1.2) hashie (5.0.0) - html2haml (2.2.0) - erubis (~> 2.7.0) - haml (>= 4.0, < 6) - nokogiri (>= 1.6.0) - ruby_parser (~> 3.5) htmlentities (4.3.4) http-accept (1.7.0) http-cookie (1.0.5) @@ -341,34 +314,34 @@ GEM httparty (0.21.0) mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) - i18n (1.12.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) - i18n_data (0.16.0) + i18n_data (0.17.1) simple_po_parser (~> 1.1) - icalendar (2.7.1) + icalendar (2.8.0) ice_cube (~> 0.16) ice_cube (0.16.4) image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) io-like (0.3.1) - iso-639 (0.3.5) - jemalloc (1.0.1) + iso-639 (0.3.6) jquery-datatables (1.10.20) - jquery-rails (4.5.0) + jquery-rails (4.5.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-ui-rails (6.0.1) railties (>= 3.2.16) - json (2.6.2) - json-schema (3.0.0) + json (2.7.1) + json-schema (4.0.0) addressable (>= 2.8) jsonapi-renderer (0.2.2) - jwt (2.4.1) - launchy (2.5.0) - addressable (~> 2.7) - leaflet-rails (1.7.0) + jwt (2.7.1) + language_server-protocol (3.17.0.3) + launchy (2.5.2) + addressable (~> 2.8) + leaflet-rails (1.9.3) rails (>= 4.2.0) letter_opener (1.8.1) launchy (>= 2.2, < 3) @@ -377,13 +350,14 @@ GEM letter_opener (~> 1.7) railties (>= 5.2) rexml - listen (3.7.1) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.19.1) + lograge (0.12.0) + actionpack (>= 4) + activesupport (>= 4) + railties (>= 4) + request_store (~> 1.0) + loofah (2.22.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - lumberjack (1.2.8) + nokogiri (>= 1.12.0) mail (2.8.1) mini_mime (>= 0.1.1) net-imap @@ -398,9 +372,9 @@ GEM mina (1.2.4) open4 (~> 1.3.4) rake - mini_magick (4.11.0) + mini_magick (4.12.0) mini_mime (1.1.2) - minitest (5.17.0) + minitest (5.22.2) momentjs-rails (2.29.4.1) railties (>= 3.1) monetize (1.12.0) @@ -415,7 +389,6 @@ GEM multi_json (1.15.0) multi_test (0.1.2) multi_xml (0.6.0) - nenv (0.3.0) net-imap (0.3.4) date net-protocol @@ -426,44 +399,40 @@ GEM net-smtp (0.3.3) net-protocol netrc (0.11.0) - next_rails (1.1.0) + next_rails (1.2.4) colorize (>= 0.8.1) - nio4r (2.5.9) + nio4r (2.7.0) nokogiri (1.16.2-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.2-x86_64-darwin) - racc (~> 1.4) nokogiri (1.16.2-x86_64-linux) racc (~> 1.4) - notiffany (0.1.3) - nenv (~> 0.1) - shellany (~> 0.0) - oauth2 (1.4.10) + oauth2 (2.0.9) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) multi_xml (~> 0.5) - rack (>= 1.2, < 3) - octokit (6.0.1) + rack (>= 1.2, < 4) + snaky_hash (~> 2.0) + version_gem (~> 1.1) + octokit (6.1.1) faraday (>= 1, < 3) sawyer (~> 0.9) - omniauth (2.1.0) + omniauth (2.1.1) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection omniauth-facebook (9.0.0) omniauth-oauth2 (~> 1.2) - omniauth-github (2.0.0) + omniauth-github (2.0.1) omniauth (~> 2.0) - omniauth-oauth2 (~> 1.7.1) - omniauth-google-oauth2 (1.0.1) + omniauth-oauth2 (~> 1.8) + omniauth-google-oauth2 (1.1.1) jwt (>= 2.0) - oauth2 (~> 1.1) + oauth2 (~> 2.0.6) omniauth (~> 2.0) - omniauth-oauth2 (~> 1.7.1) - omniauth-oauth2 (1.7.3) + omniauth-oauth2 (~> 1.8.0) + omniauth-oauth2 (1.8.0) oauth2 (>= 1.4, < 3) - omniauth (>= 1.9, < 3) + omniauth (~> 2.0) omniauth-openid (2.0.1) omniauth (>= 1.0, < 3.0) rack-openid (~> 1.4.0) @@ -476,19 +445,20 @@ GEM paper_trail (12.3.0) activerecord (>= 5.2) request_store (~> 1.1) - parallel (1.22.1) - parser (3.1.2.0) + parallel (1.24.0) + parser (3.3.0.5) ast (~> 2.4.1) + racc pdf-core (0.9.0) pdf-inspector (1.3.0) pdf-reader (>= 1.0, < 3.0.a) - pdf-reader (2.10.0) + pdf-reader (2.11.0) Ascii85 (~> 1.0) afm (~> 0.2.1) hashery (~> 2.0) ruby-rc4 ttfunk - pg (1.4.1) + pg (1.5.3) prawn (2.4.0) pdf-core (~> 0.9.0) ttfunk (~> 1.7) @@ -515,35 +485,32 @@ GEM pronto-rubocop (0.11.2) pronto (~> 0.11.0) rubocop (>= 0.63.1, < 2.0) - pry (0.13.1) - coderay (~> 1.1) - method_source (~> 1.0) public_suffix (5.0.3) - puma (6.3.1) + puma (6.4.2) nio4r (~> 2.0) racc (1.7.3) - rack (2.2.7) + rack (2.2.8) rack-openid (1.4.2) rack (>= 1.1.0) ruby-openid (>= 2.1.8) - rack-protection (2.2.0) + rack-protection (3.0.6) rack rack-test (2.1.0) rack (>= 1.3) - rails (7.0.4.2) - actioncable (= 7.0.4.2) - actionmailbox (= 7.0.4.2) - actionmailer (= 7.0.4.2) - actionpack (= 7.0.4.2) - actiontext (= 7.0.4.2) - actionview (= 7.0.4.2) - activejob (= 7.0.4.2) - activemodel (= 7.0.4.2) - activerecord (= 7.0.4.2) - activestorage (= 7.0.4.2) - activesupport (= 7.0.4.2) + rails (7.0.4.3) + actioncable (= 7.0.4.3) + actionmailbox (= 7.0.4.3) + actionmailer (= 7.0.4.3) + actionpack (= 7.0.4.3) + actiontext (= 7.0.4.3) + actionview (= 7.0.4.3) + activejob (= 7.0.4.3) + activemodel (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) bundler (>= 1.15.0) - railties (= 7.0.4.2) + railties (= 7.0.4.3) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -553,97 +520,92 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.5.0) loofah (~> 2.19, >= 2.19.1) - rails-i18n (7.0.5) + rails-i18n (7.0.7) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.0.4.2) - actionpack (= 7.0.4.2) - activesupport (= 7.0.4.2) + railties (7.0.4.3) + actionpack (= 7.0.4.3) + activesupport (= 7.0.4.3) method_source rake (>= 12.2) thor (~> 1.0) zeitwerk (~> 2.5) rainbow (3.1.1) rake (13.0.6) - rb-fsevent (0.11.1) - rb-inotify (0.10.1) - ffi (~> 1.0) - recaptcha (5.10.0) + recaptcha (5.14.0) json - redcarpet (3.5.1) + redcarpet (3.6.0) redis (4.7.1) - regexp_parser (2.8.1) + regexp_parser (2.9.0) request_store (1.5.1) rack (>= 1.4) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) + responders (3.1.0) + actionpack (>= 5.2) + railties (>= 5.2) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.5) - rolify (6.0.0) - rqrcode (2.1.1) + rexml (3.2.6) + rolify (6.0.1) + rqrcode (2.2.0) chunky_png (~> 1.0) rqrcode_core (~> 1.0) rqrcode_core (1.2.0) - rspec (3.11.0) - rspec-core (~> 3.11.0) - rspec-expectations (~> 3.11.0) - rspec-mocks (~> 3.11.0) rspec-activemodel-mocks (1.1.0) activemodel (>= 3.0) activesupport (>= 3.0) rspec-mocks (>= 2.99, < 4.0) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.0) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-mocks (3.11.1) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-rails (5.1.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.11.0) - rubocop (1.31.2) + rspec-support (~> 3.12.0) + rspec-rails (6.0.2) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.12) + rspec-expectations (~> 3.12) + rspec-mocks (~> 3.12) + rspec-support (~> 3.12) + rspec-support (3.12.0) + rubocop (1.60.2) json (~> 2.3) + language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.1.0.0) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.18.0, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.18.0) - parser (>= 3.1.1.0) - rubocop-faker (1.1.0) - faker (>= 2.12.0) - rubocop (>= 0.82.0) - rubocop-rails (2.15.2) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-capybara (2.18.0) + rubocop (~> 1.41) + rubocop-performance (1.17.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.19.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-rspec (2.12.1) - rubocop (~> 1.31) + rubocop (>= 1.33.0, < 2.0) + rubocop-rspec (2.20.0) + rubocop (~> 1.33) + rubocop-capybara (~> 2.17) ruby-oembed (0.16.1) ruby-openid (2.9.2) - ruby-progressbar (1.11.0) + ruby-progressbar (1.13.0) ruby-rc4 (0.1.5) ruby-vips (2.1.4) ffi (~> 1.12) ruby2_keywords (0.0.5) - ruby_parser (3.19.1) - sexp_processor (~> 4.16) rubyzip (2.3.2) rugged (1.5.1) sass-rails (6.0.0) @@ -660,24 +622,19 @@ GEM addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) selectize-rails (0.12.6) - selenium-webdriver (4.8.1) + selenium-webdriver (4.10.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sentry-delayed_job (5.3.1) + sentry-delayed_job (5.9.0) delayed_job (>= 4.0) - sentry-ruby-core (~> 5.3.1) - sentry-rails (5.3.1) + sentry-ruby (~> 5.9.0) + sentry-rails (5.9.0) railties (>= 5.0) - sentry-ruby-core (~> 5.3.1) - sentry-ruby (5.3.1) + sentry-ruby (~> 5.9.0) + sentry-ruby (5.9.0) concurrent-ruby (~> 1.0, >= 1.0.2) - sentry-ruby-core (= 5.3.1) - sentry-ruby-core (5.3.1) - concurrent-ruby - sexp_processor (4.16.1) - shellany (0.0.1) - shoulda-matchers (5.1.0) + shoulda-matchers (5.3.0) activesupport (>= 5.2.0) simple_po_parser (1.1.6) simplecov (0.22.0) @@ -689,20 +646,19 @@ GEM simplecov (~> 0.19) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - sixarm_ruby_unaccent (1.2.0) - skylight (5.3.3) - activesupport (>= 5.2.0) - sort_alphabetical (1.1.0) - unicode_utils (>= 1.2.2) - sprockets (4.1.1) + snaky_hash (2.0.1) + hashie + version_gem (~> 1.1, >= 1.1.1) + sprockets (4.2.1) concurrent-ruby (~> 1.0) - rack (> 1, < 3) + rack (>= 2.2.4, < 4) sprockets-rails (3.4.2) actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.4.4) - ssrf_filter (1.0.7) + sqlite3 (1.6.3-arm64-darwin) + sqlite3 (1.6.3-x86_64-linux) + ssrf_filter (1.1.1) stripe (5.55.0) stripe-ruby-mock (3.1.0.rc3) dante (>= 0.2.0) @@ -711,12 +667,12 @@ GEM sys-uname (1.2.2) ffi (~> 1.1) sysexits (1.2.0) - temple (0.8.2) + temple (0.10.1) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - thor (1.2.1) - tilt (2.0.10) - timecop (0.9.5) + thor (1.2.2) + tilt (2.1.0) + timecop (0.9.6) timeout (0.3.2) transitions (1.3.0) ttfunk (1.7.0) @@ -730,11 +686,11 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.8.2) - unicode-display_width (2.4.2) - unicode_utils (1.4.0) + unicode-display_width (2.5.0) uniform_notifier (1.16.0) unobtrusive_flash (3.3.1) railties + version_gem (1.1.3) warden (1.2.9) rack (>= 2.0.9) web-console (4.2.0) @@ -742,11 +698,11 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webdrivers (5.2.0) + webdrivers (5.3.1) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (~> 4.0) - webmock (3.14.0) + selenium-webdriver (~> 4.0, < 4.11) + webmock (3.18.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -759,12 +715,10 @@ GEM chronic (>= 0.6.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.7) + zeitwerk (2.6.8) PLATFORMS - arm64-darwin-22 arm64-darwin-23 - x86_64-darwin-22 x86_64-linux DEPENDENCIES @@ -790,7 +744,6 @@ DEPENDENCIES cloudinary cocoon countable-rails - country_select (< 7) cucumber-rails cucumber-rails-training-wheels daemons @@ -807,13 +760,13 @@ DEPENDENCIES font-awesome-sass geckodriver-helper gravtastic - guard-rspec haml-lint haml-rails + haml_lint httparty + i18n_data icalendar iso-639 - jemalloc (~> 1.0) jquery-datatables jquery-rails jquery-ui-rails (~> 6.0.1) @@ -821,12 +774,12 @@ DEPENDENCIES leaflet-rails letter_opener letter_opener_web + lograge matrix (~> 0.4) mina mini_magick money-rails next_rails - nokogiri omniauth omniauth-discourse! omniauth-facebook @@ -870,7 +823,9 @@ DEPENDENCIES rqrcode rspec-activemodel-mocks rspec-rails - rubocop-faker + rubocop + rubocop-capybara + rubocop-performance rubocop-rails rubocop-rspec ruby-oembed @@ -881,7 +836,6 @@ DEPENDENCIES sentry-ruby shoulda-matchers simplecov-cobertura - skylight (~> 5) sprockets-rails sqlite3 stripe @@ -900,4 +854,4 @@ RUBY VERSION ruby 3.2.2 BUNDLED WITH - 2.3.26 + 2.5.6 diff --git a/app/assets/javascripts/osem-datepickers.js b/app/assets/javascripts/osem-datepickers.js index e5bbe10e9..e603d15d0 100644 --- a/app/assets/javascripts/osem-datepickers.js +++ b/app/assets/javascripts/osem-datepickers.js @@ -23,17 +23,12 @@ $(function () { format: "YYYY-MM-DD" }); - // start_registration <= end_registration <= end_conference - var end_conference = $('form').data('end-conference'); - $('#registration-period-start-datepicker').datetimepicker({ - format: 'YYYY-MM-DD', - maxDate : end_conference + format: 'YYYY-MM-DD' }); $('#registration-period-end-datepicker').datetimepicker({ - format: 'YYYY-MM-DD', - maxDate : end_conference + format: 'YYYY-MM-DD' }); $("#conference-start-datepicker").on("dp.change",function (e) { diff --git a/app/assets/javascripts/osem.js b/app/assets/javascripts/osem.js index 4701f1b1a..9749a2fa6 100644 --- a/app/assets/javascripts/osem.js +++ b/app/assets/javascripts/osem.js @@ -48,9 +48,8 @@ $(function () { var id = $(this).attr('id'); $('.' + id).collapse('hide'); - $('#' + $(this).val() + '-help.' + id).collapse('show'); - $('#' + $(this).val() + '-instructions.' + id).collapse('show'); - + $(`#event_type_${$(this).val()}-help.${id}`).collapse('show'); + $(`#event_type_${$(this).val()}-instructions.${id}`).collapse('show');w }); $('.dropdown-toggle').dropdown(); @@ -165,8 +164,8 @@ function replace_defaut_submission_text(input_selector, new_text, valid_defaults /* Wait for the DOM to be ready before attaching events to the elements */ $( document ).ready(function() { - /* Set the minimum and maximum proposal abstract and submission text word length */ - $("#event_event_type_id").change(function () { + /* Set the minimum and maximum proposal abstract word length */ + function updateEventTypeRequirements() { var $selected = $("#event_event_type_id option:selected") var max = $selected.data("max-words"); var min = $selected.data("min-words"); @@ -184,8 +183,9 @@ $( document ).ready(function() { $("#abstract-minimum-word-count").text(min); $("#submission-minimum-word-count").text(min); word_count($('#event_abstract').get(0), 'abstract-count', max); - word_count($('#event_submission_text').get(0), 'submission-count', max); - }).trigger('change'); + } + $("#event_event_type_id").change(updateEventTypeRequirements); + updateEventTypeRequirements(); /* Count the proposal abstract length */ $("#event_abstract").on('input', function() { @@ -220,7 +220,6 @@ window.build_dialog = function(selector, content) { // Close it and remove content if it's already open $("#" + selector).modal('hide'); $("#" + selector).remove(); - // Add new content and pops it up - $("body").append("
\n" + content + "
"); + $("body").append(``); $("#" + selector).modal(); } diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 7ea3fda62..2229d983d 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -25,7 +25,7 @@ def verify_user_admin :any) || (current_user.has_cached_role? :organization_admin, :any) || (current_user.has_cached_role? :volunteers_coordinator, :any) || (current_user.has_cached_role? :track_organizer, :any) || current_user.is_admin - raise CanCan::AccessDenied, 'You are not authorized to access this page.' + raise CanCan::AccessDenied.new('You are not authorized to access this page.') end end end diff --git a/app/controllers/admin/rooms_controller.rb b/app/controllers/admin/rooms_controller.rb index 5983e71a8..a2578136a 100644 --- a/app/controllers/admin/rooms_controller.rb +++ b/app/controllers/admin/rooms_controller.rb @@ -50,7 +50,7 @@ def destroy def room_params params.require(:room) .permit(:name, :size, :url, :order, :discussion_url) - .each { |_, value| value.try(:strip!) } + .each_value { |value| value.try(:strip!) } end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b9419da55..672afae83 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -60,7 +60,7 @@ def current_ability end def not_found - raise ActionController::RoutingError, 'Not Found' + raise ActionController::RoutingError.new('Not Found') end skip_authorization_check only: :apple_pay diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ff2e3ea82..d661a9b3e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -15,7 +15,7 @@ def edit; end # PATCH/PUT /users/1 def update if @user.update(user_params) - redirect_to @user, notice: 'User was successfully updated.' + redirect_to user_path(@user), notice: 'User was successfully updated.' else flash.now[:error] = "An error prohibited your profile from being saved: #{@user.errors.full_messages.join('. ')}." render :edit @@ -47,7 +47,7 @@ def user_params # Somewhat of a hack: users/current/edit # rubocop:disable Naming/MemoizedInstanceVariableName def load_user - @user ||= ((params[:id] && params[:id] != 'current' && User.find(params[:id])) || current_user) + @user ||= (params[:id] && params[:id] != 'current' && User.find(params[:id])) || current_user end # rubocop:enable Naming/MemoizedInstanceVariableName end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 31cbca2f9..6edc74c84 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -199,12 +199,10 @@ def get_logo(object) # Timestamps are stored at UTC but in the real timezone. # We must convert then shift the time back to get the correct value. # TODO: just take in an object? - def inyourtz(time, timezone, &block) + def inyourtz(time, timezone, &) time = time.in_time_zone(timezone) time -= time.utc_offset - link_to "https://inyourtime.zone/t?#{time.to_i}", target: '_blank', rel: 'noopener' do - block.call - end + link_to("https://inyourtime.zone/t?#{time.to_i}", target: '_blank', rel: 'noopener', &) end def visible_conference_links diff --git a/app/helpers/format_helper.rb b/app/helpers/format_helper.rb index feadf6fd7..b6b492b4a 100644 --- a/app/helpers/format_helper.rb +++ b/app/helpers/format_helper.rb @@ -3,9 +3,6 @@ require 'redcarpet/render_strip' module FormatHelper - ## - # Includes functions related to formatting (like adding classes, colors) - ## def status_icon(object) case object.state when 'new', 'to_reject', 'to_accept' @@ -80,30 +77,20 @@ def bootstrap_class_for(flash_type) end def label_for(event_state) - result = '' case event_state when 'new' - result = 'label label-primary' - when 'withdrawn' - result = 'label label-danger' - when 'unconfirmed' - result = 'label label-success' - when 'confirmed' - result = 'label label-success' + 'label label-primary' + when 'withdrawn', 'cancelled' + 'label label-danger' + when 'unconfirmed', 'confirmed' + 'label label-success' when 'rejected' - result = 'label label-warning' - when 'canceled' - result = 'label label-danger' + 'label label-warning' end - result end def icon_for_todo(bool) - if bool - 'fa-solid fa-check' - else - 'fa-solid fa-xmark' - end + bool ? 'fa-solid fa-check' : 'fa-solid fa-xmark' end def class_for_todo(bool) @@ -190,7 +177,8 @@ def markdown(text, escape_html = true) safe_links_only: true } markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(render_options), markdown_options) - escape_html ? sanitize(markdown.render(text)) : markdown.render(text).html_safe + rendered = sanitize(markdown.render(text)) + escape_html ? sanitize(rendered, scrubber: Loofah::Scrubbers::NoFollow.new) : rendered.html_safe end def markdown_hint(text = '') diff --git a/app/models/admin_ability.rb b/app/models/admin_ability.rb index fb4d61b84..07e72ec20 100644 --- a/app/models/admin_ability.rb +++ b/app/models/admin_ability.rb @@ -53,7 +53,7 @@ def common_abilities_for_roles(user) # even admin cannot create new users with ICHAIN enabled cannot %i[new create], User if ENV.fetch('OSEM_ICHAIN_ENABLED', nil) == 'true' cannot :revert_object, PaperTrail::Version do |version| - (version.event == 'create' && %w[Conference User Event].include?(version.item_type)) + version.event == 'create' && %w[Conference User Event].include?(version.item_type) end cannot :revert_attribute, PaperTrail::Version do |version| version.event != 'update' || version.item.nil? diff --git a/app/models/conference.rb b/app/models/conference.rb index fcd6443df..964ba3c85 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -45,8 +45,8 @@ class Conference < ApplicationRecord resourcify :roles, dependent: :delete_all default_scope { order('start_date DESC') } - scope :upcoming, (-> { where('end_date >= ?', Date.current) }) - scope :past, (-> { where('end_date < ?', Date.current) }) + scope :upcoming, -> { where('end_date >= ?', Date.current) } + scope :past, -> { where('end_date < ?', Date.current) } belongs_to :organization delegate :code_of_conduct, to: :organization @@ -711,7 +711,7 @@ def notify_on_dates_changed? return false unless saved_change_to_start_date? || saved_change_to_end_date? # do not notify unless the mail content is set up - (email_settings.conference_dates_updated_subject.present? && email_settings.conference_dates_updated_body.present?) + email_settings.conference_dates_updated_subject.present? && email_settings.conference_dates_updated_body.present? end ## @@ -728,7 +728,7 @@ def notify_on_registration_dates_changed? return false unless registration_period.saved_change_to_start_date? || registration_period.saved_change_to_end_date? # do not notify unless the mail content is set up - (email_settings.conference_registration_dates_updated_subject.present? && email_settings.conference_registration_dates_updated_body.present?) + email_settings.conference_registration_dates_updated_subject.present? && email_settings.conference_registration_dates_updated_body.present? end ## @@ -893,11 +893,12 @@ def get_events_per_week_by_state # Completed weeks events_per_week.each do |week, values| + week = Date.parse(week) unless week.respond_to?(:strftime) values.each do |state, value| next unless %i[confirmed unconfirmed].include?(state) result[state.to_s.capitalize] = {} unless result[state.to_s.capitalize] - result[state.to_s.capitalize][DateTime.parse(week).strftime('%W').to_i] = value + result[state.to_s.capitalize][week.strftime('%W').to_i] = value end end diff --git a/app/models/program.rb b/app/models/program.rb index 2c069ce50..3adc2f744 100644 --- a/app/models/program.rb +++ b/app/models/program.rb @@ -189,7 +189,7 @@ def notify_on_schedule_public? return false unless schedule_public # do not notify unless the mail content is set up - (conference.email_settings.program_schedule_public_subject.present? && conference.email_settings.program_schedule_public_body.present?) + conference.email_settings.program_schedule_public_subject.present? && conference.email_settings.program_schedule_public_body.present? end def languages_list @@ -298,9 +298,9 @@ def check_languages_format errors.add(:languages, "can't be repeated") && return unless languages_array.uniq!.nil? # We check if every language is a valid ISO 639-1 language - errors.add(:languages, 'must be ISO 639-1 valid codes') unless languages_array.select do |x| + errors.add(:languages, 'must be ISO 639-1 valid codes') unless languages_array.none? do |x| ISO_639.find(x).nil? - end.empty? + end end ## diff --git a/app/models/user.rb b/app/models/user.rb index 1d50c07ee..bcf38b4db 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -432,7 +432,7 @@ def biography_limit errors.add(:biography, 'is limited to 200 words.') if biography.present? && (biography.split.length > 200) end - def send_devise_notification(notification, *args) - devise_mailer.send(notification, self, *args).deliver_later + def send_devise_notification(notification, *) + devise_mailer.send(notification, self, *).deliver_later end end diff --git a/app/models/venue.rb b/app/models/venue.rb index 324360335..992a027b6 100644 --- a/app/models/venue.rb +++ b/app/models/venue.rb @@ -39,12 +39,11 @@ def address "#{street}, #{city}, #{country_name}" end - # TODO-SNAPCON: (mb) iso_short_name seems to fail in tests only...this makes no sense. + # TODO-SNAPCON: (mb) Fix this to use the country shortname? def country_name return unless country - name = ISO3166::Country[country] - name.try(:iso_short_name) || name.try(:name) + I18nData.countries[country] end def location? @@ -65,7 +64,7 @@ def notify_on_venue_changed? end # do not notify unless the mail content is set up - (conference.email_settings.venue_updated_subject.present? && conference.email_settings.venue_updated_body.present?) + conference.email_settings.venue_updated_subject.present? && conference.email_settings.venue_updated_body.present? end # TODO: create a module to be mixed into model to perform same operation diff --git a/app/serializers/conference_serializer.rb b/app/serializers/conference_serializer.rb index ca7550fc9..32d83dc71 100644 --- a/app/serializers/conference_serializer.rb +++ b/app/serializers/conference_serializer.rb @@ -37,7 +37,9 @@ # class ConferenceSerializer < ActiveModel::Serializer include ApplicationHelper - attributes :short_title, :title, :description, :start_date, :end_date, :picture_url, + include Rails.application.routes.url_helpers + + attributes :short_title, :url, :title, :description, :start_date, :end_date, :picture_url, :difficulty_levels, :event_types, :rooms, :tracks, :date_range, :revision @@ -91,6 +93,10 @@ def tracks end end + def url + url_for(object) + end + def revision object.revision || 0 end diff --git a/app/serializers/event_schedule_serializer.rb b/app/serializers/event_schedule_serializer.rb index 7ee98bb66..086bfd210 100644 --- a/app/serializers/event_schedule_serializer.rb +++ b/app/serializers/event_schedule_serializer.rb @@ -26,8 +26,7 @@ class EventScheduleSerializer < ActiveModel::Serializer attributes :date, :room def date - t = object.start_time - t.blank? ? '' : %( #{I18n.l t, format: :short}#{t.formatted_offset(false)} ) + object.start_time&.change(zone: object.event.program.conference.timezone) end def room diff --git a/app/serializers/event_serializer.rb b/app/serializers/event_serializer.rb index 4bc7441f0..6f853a7b1 100644 --- a/app/serializers/event_serializer.rb +++ b/app/serializers/event_serializer.rb @@ -40,12 +40,16 @@ # class EventSerializer < ActiveModel::Serializer include ActionView::Helpers::TextHelper + include Rails.application.routes.url_helpers - attributes :guid, :title, :length, :scheduled_date, :language, :abstract, :speaker_ids, :type, :room, :track + attributes :guid, :url, :title, :length, :scheduled_date, :language, :abstract, :speaker_ids, :type, :room, :track + + def url + conference_program_proposal_url(object.conference.short_title, object.id) + end def scheduled_date - t = object.time - t.blank? ? '' : %( #{I18n.l t, format: :short}#{t.formatted_offset(false)} ) + object.time&.change(zone: object.program.conference.timezone) end def speaker_ids diff --git a/app/serializers/speaker_serializer.rb b/app/serializers/speaker_serializer.rb index ee7e6dec1..d0585fdf4 100644 --- a/app/serializers/speaker_serializer.rb +++ b/app/serializers/speaker_serializer.rb @@ -2,8 +2,13 @@ class SpeakerSerializer < ActiveModel::Serializer include ActionView::Helpers::TextHelper + include Rails.application.routes.url_helpers - attributes :name, :affiliation, :biography + attributes :url, :name, :affiliation, :biography delegate :name, to: :object + + def url + url_for(object) + end end diff --git a/app/views/admin/booths/index.html.haml b/app/views/admin/booths/index.html.haml index d5c02bdc0..41a8424d3 100644 --- a/app/views/admin/booths/index.html.haml +++ b/app/views/admin/booths/index.html.haml @@ -56,46 +56,48 @@ - if @booths.any? %table.datatable %thead - %th - %b ID - %th - %b Logo - %th - %b Title - %th - %b Submitter - %th - %b Responsibles - %th - %b State - %th - %b Actions - - @booths.each do |booth| %tr - %td - = booth.id - %td - - if booth.logo_link - = image_tag(booth.picture.thumb.url, width: '20%') - %td - = link_to booth.title, admin_conference_booth_path(@conference.short_title, booth) - %td - = link_to booth.submitter.name, admin_user_path(booth.submitter) if booth.submitter - %td - .responsibles - - booth.responsibles.each_with_index do |responsible, i| - = link_to responsible.name, admin_user_path(responsible) - = ", " unless i == booth.responsibles.length - 1 - %td - .btn-group - %button{ type: 'button', class: 'btn btn-link dropdown-toggle', 'data-toggle' => 'dropdown' } - = booth.state.humanize - %span.caret - %ul.dropdown-menu{ role: 'menu' } - = render 'change_state_dropdown', booth: booth + %th + %b ID + %th + %b Logo + %th + %b Title + %th + %b Submitter + %th + %b Responsibles + %th + %b State + %th + %b Actions + %tbody + - @booths.each do |booth| + %tr + %td + = booth.id + %td + - if booth.logo_link + = image_tag(booth.picture.thumb.url, width: '20%') + %td + = link_to booth.title, admin_conference_booth_path(@conference.short_title, booth) + %td + = link_to booth.submitter.name, admin_user_path(booth.submitter) if booth.submitter + %td + .responsibles + - booth.responsibles.each_with_index do |responsible, i| + = link_to responsible.name, admin_user_path(responsible) + = ", " unless i == booth.responsibles.length - 1 %td - = link_to 'Edit', edit_admin_conference_booth_path(@conference.short_title, booth.id), - class: 'btn btn-primary' + .btn-group + %button{ type: 'button', class: 'btn btn-link dropdown-toggle', 'data-toggle' => 'dropdown' } + = booth.state.humanize + %span.caret + %ul.dropdown-menu{ role: 'menu' } + = render 'change_state_dropdown', booth: booth + %td + = link_to 'Edit', edit_admin_conference_booth_path(@conference.short_title, booth.id), + class: 'btn btn-primary' .row .col-md-12.text-right - if can? :create, Booth diff --git a/app/views/admin/cfps/index.html.haml b/app/views/admin/cfps/index.html.haml index b15d16144..21de27a18 100644 --- a/app/views/admin/cfps/index.html.haml +++ b/app/views/admin/cfps/index.html.haml @@ -10,12 +10,13 @@ .col-md-12 %table.table.table-hover#tickets %thead - %th Type - %th Start Date - %th End Date - %th Description - %th Days Left - %th Actions + %tr + %th Type + %th Start Date + %th End Date + %th Description + %th Days Left + %th Actions %tbody - @program.cfps.each do |cfp| %tr diff --git a/app/views/admin/difficulty_levels/index.html.haml b/app/views/admin/difficulty_levels/index.html.haml index ed7b37307..282fdfaec 100644 --- a/app/views/admin/difficulty_levels/index.html.haml +++ b/app/views/admin/difficulty_levels/index.html.haml @@ -8,10 +8,11 @@ .col-md-12 %table.table.table-hover#difficulty_levels %thead - %th Title - %th Description - %th Color - %th Actions + %tr + %th Title + %th Description + %th Color + %th Actions %tbody - @conference.program.difficulty_levels.each do |difficulty_level| %tr diff --git a/app/views/admin/emails/index.html.haml b/app/views/admin/emails/index.html.haml index 41a43825e..e296d824f 100644 --- a/app/views/admin/emails/index.html.haml +++ b/app/views/admin/emails/index.html.haml @@ -22,7 +22,7 @@ .checkbox %label = f.check_box :send_on_registration, data: {name: 'email_settings_registration_subject'}, class: 'send_on_radio' - Send an email when the user registers for the conference? + Send an email to the user when they register for the conference? .form-group = f.label :registration_subject, 'Subject' = f.text_field :registration_subject, class: 'form-control' @@ -38,7 +38,7 @@ .checkbox %label = f.check_box :send_on_submitted_proposal, data: { name: 'email_settings_proposal_submited_subject'}, class: 'send_on_radio' - Send an email when the proposal is submitted? + Send an email to the submitter when the proposal is submitted? .form-group = f.label :submitted_proposal_subject, 'Subject' = f.text_field :submitted_proposal_subject, class: 'form-control' @@ -51,7 +51,7 @@ .checkbox %label = f.check_box :send_on_accepted, data: { name: 'email_settings_accepted_subject' }, class: 'send_on_radio' - Send an email when the proposal is accepted? + Send an email to the submitter when the proposal is accepted? .form-group = f.label :accepted_subject, 'Subject' = f.text_field :accepted_subject, class: 'form-control' @@ -67,7 +67,7 @@ .checkbox %label = f.check_box :send_on_rejected, data: { name: 'email_settings_rejected_subject'}, class: 'send_on_radio' - Send an email when the proposal is rejected? + Send an email to the submitter when the proposal is rejected? .form-group = f.label :rejected_subject, 'Subject' = f.text_field :rejected_subject, class: 'form-control' @@ -83,7 +83,7 @@ .checkbox %label = f.check_box :send_on_confirmed_without_registration, data: {name: 'email_settings_confirmed_without_registration_subject'}, class: 'send_on_radio' - Send an email when a user has a confirmed proposal, but isn't yet registered? + Send an email to the submitter when their proposal is confirmed but they haven't yet registered for the conference? .form-group = f.label :confirmed_without_registration_subject, 'Subject' = f.text_field :confirmed_without_registration_subject, class: 'form-control' @@ -132,7 +132,7 @@ .checkbox %label = f.check_box :send_on_venue_updated, data: { name: 'email_settings_venue_updated_subject'}, class: 'send_on_radio' - Send an email on updating the venue? + Send an email to all participants when the venue is updated? .form-group = f.label :venue_updated_subject, 'Subject' = f.text_field :venue_updated_subject, class: 'form-control' @@ -182,7 +182,7 @@ .checkbox %label = f.check_box :send_on_booths_acceptance - Send an email when the booth is accepted? + Send an email to the submitter when the booth is accepted? .form-group = f.label :booths_acceptance_subject, 'Subject' = f.text_field :booths_acceptance_subject, class: 'form-control' @@ -198,7 +198,7 @@ .checkbox %label = f.check_box :send_on_booths_rejection - Send an email when the booth is rejected? + Send an email to the submitter when the booth is rejected? .form-group = f.label :booths_rejection_subject, 'Subject' = f.text_field :booths_rejection_subject, class: 'form-control' diff --git a/app/views/admin/event_types/index.html.haml b/app/views/admin/event_types/index.html.haml index 015a33975..cac7985c4 100644 --- a/app/views/admin/event_types/index.html.haml +++ b/app/views/admin/event_types/index.html.haml @@ -8,13 +8,14 @@ .col-md-12 %table.table.table-hover#event_types %thead - %th Title - %th Description - %th Instructions - %th Length - %th Abstract Length - %th Color - %th Actions + %tr + %th Title + %th Description + %th Instructions + %th Length + %th Abstract Length + %th Color + %th Actions %tbody - @conference.program.event_types.each do |event_type| %tr diff --git a/app/views/admin/events/_datatable_row.haml b/app/views/admin/events/_datatable_row.haml index 48e98d128..cdf3a9036 100644 --- a/app/views/admin/events/_datatable_row.haml +++ b/app/views/admin/events/_datatable_row.haml @@ -1,7 +1,6 @@ -- cache ['admin', current_user, conference_id, program, event] do +- cache ['admin', conference_id, program, event, current_user] do %tr{ id: "event-#{event.id}" } - %td - = event.id + %td= event.id %td = link_to event.title, diff --git a/app/views/admin/events/_proposal.html.haml b/app/views/admin/events/_proposal.html.haml index f250ea423..ae50c63d2 100644 --- a/app/views/admin/events/_proposal.html.haml +++ b/app/views/admin/events/_proposal.html.haml @@ -1,4 +1,3 @@ --# Must cache with current_user due to voiting. - cache ['admin/event', @conference, @program, @event, current_user] do .row .col-md-12 diff --git a/app/views/admin/events/index.html.haml b/app/views/admin/events/index.html.haml index cab3916ca..46429af29 100644 --- a/app/views/admin/events/index.html.haml +++ b/app/views/admin/events/index.html.haml @@ -28,14 +28,8 @@ .modal-dialog .modal-content .modal-header - %h1 Add materials to events - .text-muted - Upload your file with data in the following format: - %b Event_ID:Commercial_Link - , eg. - %br - %code 11:https://youtube.com/myvideo - + %h1 + Add materials to events .modal-body = form_for('', url: mass_upload_commercials_admin_conference_program_path(@conference.short_title), method: :post) do |f| .form-group @@ -62,51 +56,38 @@ .row .col-md-12 .margin-event-table - %table.datatable.table + %table.datatable %thead - %th - %b ID - %th - %b Title - - if @program.rating_enabled? - %th - %b Rating - %th - %b Submitter - %th - %b Speakers - %th - %b Volunteers - - if @program.languages.present? - %th - %b Language - %th - %b Requires Registration - %th - %b Highlight - - if @program.event_types.any? - %th - %b Type - - if @program.tracks.any? - %th - %b Track - - if @program.difficulty_levels.any? + %tr + %th ID + %th Title + - if @program.rating_enabled? + %th Rating + %th Submitter + %th Speakers + - if @program.languages.present? + %th Language + %th Requires Registration + %th Highlight + %th Type + - if @program.tracks.any? + %th Track + - if @program.difficulty_levels.any? + %th Difficulty + %th State %th - %b Difficulty - %th - %b State - %th - .fa-solid.fa-comment - %th Add Survey - - @events.each do |event| - = render 'datatable_row', - event: event, - conference_id: @conference.short_title, - program: @program, - rating_enabled: @program.rating_enabled?, - show_votes: @program.show_voting?, - max_rating: @program.rating, - event_types: @event_types, - tracks: @tracks, - difficulty_levels: @difficulty_levels, - email_settings: @conference.email_settings + .fa-solid.fa-comment + %th Add Survey + %tbody + - @events.each do |event| + = render 'datatable_row', + event: event, + conference_id: @conference.short_title, + program: @program, + rating_enabled: @program.rating_enabled?, + show_votes: @program.show_voting?, + max_rating: @program.rating, + event_types: @event_types, + tracks: @tracks, + difficulty_levels: @difficulty_levels, + email_settings: @conference.email_settings diff --git a/app/views/admin/events/registrations.html.haml b/app/views/admin/events/registrations.html.haml index f469d4030..bfdab0a29 100644 --- a/app/views/admin/events/registrations.html.haml +++ b/app/views/admin/events/registrations.html.haml @@ -18,12 +18,13 @@ .well %table.datatable#registrations %thead - %th - %th Name - %th Email - %th Created At - %th Attended - %th Attended Conference + %tr + %th + %th Name + %th Email + %th Created At + %th Attended + %th Attended Conference %tbody - @event_registrations.each.with_index(1) do |event_registration, index| %tr diff --git a/app/views/admin/events/show.html.haml b/app/views/admin/events/show.html.haml index f70108388..6cd270117 100644 --- a/app/views/admin/events/show.html.haml +++ b/app/views/admin/events/show.html.haml @@ -20,9 +20,10 @@ .col-md-12 %table.datatable %thead - %th ID - %th Description - %th Actions + %tr + %th ID + %th Description + %th Actions %tbody - @versions.each do |version| = render 'event_version', version: version, event: @event, conference: @conference diff --git a/app/views/admin/organizations/_users_with_org_admin_role.haml b/app/views/admin/organizations/_users_with_org_admin_role.haml index d780babc6..0632afbf0 100644 --- a/app/views/admin/organizations/_users_with_org_admin_role.haml +++ b/app/views/admin/organizations/_users_with_org_admin_role.haml @@ -3,11 +3,12 @@ - if users.present? %table.datatable#users %thead - %th Name - %th Email - - if ( can? :unassign_org_admins, organization ) - %th - Actions + %tr + %th Name + %th Email + - if ( can? :unassign_org_admins, organization ) + %th + Actions %tbody - users.each do |user| %tr diff --git a/app/views/admin/organizations/index.html.haml b/app/views/admin/organizations/index.html.haml index d7ebe7c67..09cf187ea 100644 --- a/app/views/admin/organizations/index.html.haml +++ b/app/views/admin/organizations/index.html.haml @@ -11,11 +11,12 @@ .col-md-12 %table.datatable %thead - %th Name - %th Upcoming Conferences - %th Past Conferences - %th Code of Conduct? - %th Actions + %tr + %th Name + %th Upcoming Conferences + %th Past Conferences + %th Code of Conduct? + %th Actions %tbody - @organizations.each do |organization| %tr{ id: "organization-#{organization.id}" } diff --git a/app/views/admin/physical_tickets/index.html.haml b/app/views/admin/physical_tickets/index.html.haml index b69d089bf..80835f901 100644 --- a/app/views/admin/physical_tickets/index.html.haml +++ b/app/views/admin/physical_tickets/index.html.haml @@ -18,13 +18,14 @@ .col-md-12 %table.datatable#tickets %thead - %th ID - %th Type - %th Registration? - %th User - %th Paid - %th Attedance - %th Actions + %tr + %th ID + %th Type + %th Registration? + %th User + %th Paid + %th Attedance + %th Actions %tbody - @physical_tickets.each do |physical_ticket| = render "physical_ticket", physical_ticket: physical_ticket, diff --git a/app/views/admin/questions/show.html.haml b/app/views/admin/questions/show.html.haml index 2c397d10d..1863e9a92 100644 --- a/app/views/admin/questions/show.html.haml +++ b/app/views/admin/questions/show.html.haml @@ -13,10 +13,11 @@ %table.datatable#question_users %thead - %th Name - %th Username - %th Email - %th Answer + %tr + %th Name + %th Username + %th Email + %th Answer %tbody - @registrations.each do |registration| %tr diff --git a/app/views/admin/reports/_all_events.html.haml b/app/views/admin/reports/_all_events.html.haml index 0eb6b829f..d3e86d1ed 100644 --- a/app/views/admin/reports/_all_events.html.haml +++ b/app/views/admin/reports/_all_events.html.haml @@ -10,15 +10,16 @@ .col-md-12 %table.datatable %thead - %th ID - %th Title - %th Speakers Registered - %th Speakers Biographies - %th Materials - %th Subtitle - %th Difficulty Level - - if @program.tracks.any? - %th Track + %tr + %th ID + %th Title + %th Speakers Registered + %th Speakers Biographies + %th Materials + %th Subtitle + %th Difficulty Level + - if @program.tracks.any? + %th Track %tbody - @events.each do |event| %tr diff --git a/app/views/admin/reports/_events_with_requirements.html.haml b/app/views/admin/reports/_events_with_requirements.html.haml index 662142d77..c4ba2d523 100644 --- a/app/views/admin/reports/_events_with_requirements.html.haml +++ b/app/views/admin/reports/_events_with_requirements.html.haml @@ -9,13 +9,14 @@ .col-md-12 %table.datatable %thead - %th ID - %th Title - %th Speaker(s) - %th Requirements - %th Room - %th Date - %th Time + %tr + %th ID + %th Title + %th Speaker(s) + %th Requirements + %th Room + %th Date + %th Time %tbody - @events_with_requirements.each do |event| %tr diff --git a/app/views/admin/reports/_events_without_commercials.html.haml b/app/views/admin/reports/_events_without_commercials.html.haml index 77020191f..aebcd0e8e 100644 --- a/app/views/admin/reports/_events_without_commercials.html.haml +++ b/app/views/admin/reports/_events_without_commercials.html.haml @@ -9,9 +9,10 @@ .col-md-12 %table.datatable %thead - %th ID - %th Title - %th Speaker(s) + %tr + %th ID + %th Title + %th Speaker(s) %tbody - @events_missing_commercial.each do |event| %tr diff --git a/app/views/admin/reports/_missing_speakers.html.haml b/app/views/admin/reports/_missing_speakers.html.haml index d9b8c5df9..2c1fd239a 100644 --- a/app/views/admin/reports/_missing_speakers.html.haml +++ b/app/views/admin/reports/_missing_speakers.html.haml @@ -9,13 +9,14 @@ .col-md-12 %table.datatable %thead - %th Speaker Name - %th E-Mail - %th Registered? - %th Event - %th Room - %th Date - %th Time + %tr + %th Speaker Name + %th E-Mail + %th Registered? + %th Event + %th Room + %th Date + %th Time %tbody - @missing_event_speakers.each do |event_user| - speaker = event_user.user diff --git a/app/views/admin/resources/index.html.haml b/app/views/admin/resources/index.html.haml index 4d97f1d6c..139754b3d 100644 --- a/app/views/admin/resources/index.html.haml +++ b/app/views/admin/resources/index.html.haml @@ -9,10 +9,11 @@ .col-md-12 %table.datatable %thead - %th Name - %th Left( Left/Total ) - %th Used - %th Actions + %tr + %th Name + %th Left( Left/Total ) + %th Used + %th Actions %tbody - @conference.resources.each do |resource| %tr diff --git a/app/views/admin/roles/index.html.haml b/app/views/admin/roles/index.html.haml index 4990673ea..1982183f5 100644 --- a/app/views/admin/roles/index.html.haml +++ b/app/views/admin/roles/index.html.haml @@ -9,11 +9,12 @@ .col-md-12 %table.table.table-bordered.table-striped.table-hover#roles %thead - %th ID - %th Name - %th Description - %th Users - %th Actions + %tr + %th ID + %th Name + %th Description + %th Users + %th Actions %tbody - @roles.each do |role| %tr diff --git a/app/views/admin/rooms/index.html.haml b/app/views/admin/rooms/index.html.haml index a0a1ec98f..95a28fa37 100644 --- a/app/views/admin/rooms/index.html.haml +++ b/app/views/admin/rooms/index.html.haml @@ -10,11 +10,12 @@ .col-md-12 %table.table.table-hover#rooms %thead - %th Name - %th Capacity - %th Order - %th URL - %th Actions + %tr + %th Name + %th Capacity + %th Order + %th URL + %th Actions %tbody - @rooms.each_with_index do |room, index| %tr diff --git a/app/views/admin/schedules/index.html.haml b/app/views/admin/schedules/index.html.haml index 29c1910e7..8ff86f6e6 100644 --- a/app/views/admin/schedules/index.html.haml +++ b/app/views/admin/schedules/index.html.haml @@ -16,9 +16,10 @@ .col-md-12 %table.table.table-hover %thead - %th Schedule - %th Selected - %th Actions + %tr + %th Schedule + %th Selected + %th Actions %tbody - @schedules.where(track: nil).each do |schedule| %tr @@ -59,10 +60,11 @@ .col-md-12 %table.table.table-hover %thead - %th Schedule - %th Track - %th Selected - %th Actions + %tr + %th Schedule + %th Track + %th Selected + %th Actions %tbody - @schedules.where.not(track: nil).each do |schedule| %tr diff --git a/app/views/admin/sponsors/index.html.haml b/app/views/admin/sponsors/index.html.haml index 95643ada8..8b76e6abb 100644 --- a/app/views/admin/sponsors/index.html.haml +++ b/app/views/admin/sponsors/index.html.haml @@ -9,12 +9,13 @@ .col-md-12 %table.table.table-hover#sponsors %thead - %th Logo - %th Name - %th Description - %th URL - %th Level - %th Actions + %tr + %th Logo + %th Name + %th Description + %th URL + %th Level + %th Actions %tbody - @conference.sponsors.each do |sponsor| %tr diff --git a/app/views/admin/sponsorship_levels/index.html.haml b/app/views/admin/sponsorship_levels/index.html.haml index 8cd280597..d5262abae 100644 --- a/app/views/admin/sponsorship_levels/index.html.haml +++ b/app/views/admin/sponsorship_levels/index.html.haml @@ -9,9 +9,10 @@ .col-md-12 %table.table.table-hover#sponsorship_levels %thead - %th Title - %th Position - %th Actions + %tr + %th Title + %th Position + %th Actions %tbody - @conference.sponsorship_levels.each_with_index do |sponsorship_level, index| %tr diff --git a/app/views/admin/surveys/_survey_replies.html.haml b/app/views/admin/surveys/_survey_replies.html.haml index 8ce5d8094..0d682b9d6 100644 --- a/app/views/admin/surveys/_survey_replies.html.haml +++ b/app/views/admin/surveys/_survey_replies.html.haml @@ -7,8 +7,9 @@ - if survey_question.survey_replies.any? %table.table %thead - %th User Email - %th Reply + %tr + %th User Email + %th Reply %tbody - survey_question.survey_replies.reload.each do |reply| %tr diff --git a/app/views/admin/surveys/index.html.haml b/app/views/admin/surveys/index.html.haml index ff3e9b0bf..64c22aaaf 100644 --- a/app/views/admin/surveys/index.html.haml +++ b/app/views/admin/surveys/index.html.haml @@ -13,13 +13,14 @@ .col-md-12 %table.table.table-hover.datatable#surveys %thead - %th Title - %th # of questions - %th # of submissions - %th When - %th Start Date - %th End Date - %th Actions + %tr + %th Title + %th # of questions + %th # of submissions + %th When + %th Start Date + %th End Date + %th Actions %tbody - @surveys.each_with_index do |survey, index| %tr diff --git a/app/views/admin/tickets/index.html.haml b/app/views/admin/tickets/index.html.haml index ac7f97b51..fc632ac81 100644 --- a/app/views/admin/tickets/index.html.haml +++ b/app/views/admin/tickets/index.html.haml @@ -10,13 +10,14 @@ .col-md-12 %table.datatable#tickets %thead - %th Title - %th Price - %th Sold - %th Turnover - %th Registration Ticket - %th Visible? - %th Actions + %tr + %th Title + %th Price + %th Sold + %th Turnover + %th Registration Ticket + %th Visible? + %th Actions %tbody - @conference.tickets.each do |ticket| %tr diff --git a/app/views/admin/tickets/show.html.haml b/app/views/admin/tickets/show.html.haml index dd2b3eb8b..883a7aaa2 100644 --- a/app/views/admin/tickets/show.html.haml +++ b/app/views/admin/tickets/show.html.haml @@ -20,16 +20,17 @@ .col-md-12 %table.datatable %thead - %th ID - %th Name - %th Quantity - %th E-Mail - %th Affiliation - %th Paid - %th Date - %th - %span.sr-only Delete - ❌ + %tr + %th ID + %th Name + %th Quantity + %th E-Mail + %th Affiliation + %th Paid + %th Date + %th + %span.sr-only Delete + ❌ %tbody - @ticket.buyers.each_with_index do |buyer, index| - purchases = buyer.ticket_purchases.where(ticket_id: @ticket.id) diff --git a/app/views/admin/tracks/index.html.haml b/app/views/admin/tracks/index.html.haml index acdbfe0df..3764e9df4 100644 --- a/app/views/admin/tracks/index.html.haml +++ b/app/views/admin/tracks/index.html.haml @@ -35,16 +35,17 @@ - if @tracks.any? %table.datatable#tracks %thead - %th ID - %th Name - %th Description - %th Room - %th Start Date - %th End Date - %th Submitter - %th Included in Cfp - %th State - %th Actions + %tr + %th ID + %th Name + %th Description + %th Room + %th Start Date + %th End Date + %th Submitter + %th Included in Cfp + %th State + %th Actions %tbody - @tracks.each do |track| %tr diff --git a/app/views/admin/tracks/show.html.haml b/app/views/admin/tracks/show.html.haml index a7bb61a4d..58b88a09b 100644 --- a/app/views/admin/tracks/show.html.haml +++ b/app/views/admin/tracks/show.html.haml @@ -109,11 +109,12 @@ .col-md-12 %table.datatable %thead - %th Title - %th Type - %th Submitter - %th State - %th Time + %tr + %th Title + %th Type + %th Submitter + %th State + %th Time %tbody - @track.events.each_with_index do |event| %tr diff --git a/app/views/admin/users/_event_registrations.html.haml b/app/views/admin/users/_event_registrations.html.haml index 9d8f642b0..762961c71 100644 --- a/app/views/admin/users/_event_registrations.html.haml +++ b/app/views/admin/users/_event_registrations.html.haml @@ -7,10 +7,11 @@ .well %table.datatable#event_registrations %thead - %th ID - %th Conference - %th Title - %th Attended + %tr + %th ID + %th Conference + %th Title + %th Attended %tbody - @user.events_registrations.each do |event_registration| - event = event_registration.event diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml new file mode 100644 index 000000000..51a50069a --- /dev/null +++ b/app/views/admin/users/_form.html.haml @@ -0,0 +1,44 @@ += form_for [:admin, @user] do |f| + %h4 Basic Information + - unless @user.new_record? + .pull-right + %b + Confirmed? + - if can? :toggle_confirmation, @user + = check_box_tag @user.id, @user.id, @user.confirmed?, + url: "#{toggle_confirmation_admin_user_path(@user.id)}?user[to_confirm]=", + class: 'switch-checkbox', + readonly: false + - else + = check_box_tag @user.id, @user.id, @user.confirmed?, + url: "#{toggle_confirmation_admin_user_path(@user.id)}?user[to_confirm]=", + class: 'switch-checkbox', + readonly: true + .checkbox + %label + = f.check_box :is_admin + Is admin + %span.help-block An admin can create a new conference, manage users and make other users admins. + .form-group + = f.label :name + = f.text_field :name, class: 'form-control' + - if @user.new_record? + .form-group + = label_tag :username + = text_field_tag :username, class: 'form-control' + .form-group + = f.label :email, required: true + %abbr{title: 'This field is required'} * + = f.email_field :email, required: true, class: 'form-control' + - if @user.new_record? + .form-group + = f.label :password + = f.password_field :password, class: 'form-control' + .form-group + = f.label :affiliation + = f.text_field :affiliation, class: 'form-control' + .form-group + = f.label :biography + = f.text_area :biography, rows: 10, data: { provide: 'markdown' }, class: 'form-control' + %span.help-block= markdown_hint + = f.submit nil, class: 'btn btn-primary' diff --git a/app/views/admin/users/_submissions.html.haml b/app/views/admin/users/_submissions.html.haml index 81ee01c60..6a9afb629 100644 --- a/app/views/admin/users/_submissions.html.haml +++ b/app/views/admin/users/_submissions.html.haml @@ -6,13 +6,14 @@ .well %table.datatable#submissions %thead - %th ID - %th Conference - %th Title - %th State - %th Type - %th Rating - %th Created At + %tr + %th ID + %th Conference + %th Title + %th State + %th Type + %th Rating + %th Created At %tbody - @user.events.each do |event| %tr diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index 5def87016..729927996 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,7 +1 @@ -.row - .col-md-12 - .page-header - %h1 - Edit User #{@user.nickname} - = form_for(@user) do |f| - = render 'users/form', f: f += render partial: 'form' diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index ebcd8075d..03f5684f0 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -12,15 +12,15 @@ .col-md-12.table-responsive %table.datatable#users{ data: { source: admin_users_path(format: :json) } } %thead - %th{ width: '0' } ID - %th{ width: '0' } Confirmed? - %th{ width: '30%' } Name - %th{ width: '15%' } Email - %th{ width: '15%' } Username - %th{ width: '0' } Conferences Attended - %th{ width: '50%' } Roles - %th{ width: '0' } Actions - %th{ style: 'display: none' } Confirmed? + %tr + %th{ width: '0' } ID + %th{ width: '0' } Confirmed? + %th{ width: '0' } Email + %th{ width: '30%' } Name + %th{ width: '20%' } Conferences Attended + %th{ width: '50%' } Roles + %th{ width: '0' } Actions + %th{ style: 'display: none' } Confirmed? %tbody :javascript diff --git a/app/views/admin/volunteers/_volunteers_table.html.haml b/app/views/admin/volunteers/_volunteers_table.html.haml index 1f085d1ac..56ec989de 100644 --- a/app/views/admin/volunteers/_volunteers_table.html.haml +++ b/app/views/admin/volunteers/_volunteers_table.html.haml @@ -1,13 +1,14 @@ .well %table.table.table-striped.table-bordered.table-hover#volunteerstable %thead - %th First Name - %th Last Name - %th Email - %th Mobile - %th Languages - %th Experience - %th Tshirt Size + %tr + %th First Name + %th Last Name + %th Email + %th Mobile + %th Languages + %th Experience + %th Tshirt Size %tbody - @volunteers.each do |volunteer| %tr diff --git a/app/views/booths/index.html.haml b/app/views/booths/index.html.haml index f7a8361d9..ed5628b5a 100644 --- a/app/views/booths/index.html.haml +++ b/app/views/booths/index.html.haml @@ -8,43 +8,46 @@ .margin-booth-table %table.table.table-striped.table-hover %thead - %th - %b State - %th - %b Logo - %th - %b Title - %th - %b Actions - - @booths.each do |booth| %tr - %td{ style: "padding:20px 8px 20px 8px;" } - - if (booth.state == 'to_accept' || booth.state == 'to_reject') - - show_state = 'new' - - else - - show_state = booth.state - %span{ title: show_state, class: "fa-solid #{status_icon(booth)}" } - %ts - - if booth.logo_link - = image_tag(booth.picture.thumb.url, width: '20%') - %td - = link_to booth.title, conference_booth_path(@conference.short_title, booth) - %td - -if can? :edit, booth - = link_to 'Edit', edit_conference_booth_path(@conference.short_title, booth.id), - class: 'btn btn-default' - - if booth.transition_possible? :withdraw - = link_to 'Withdraw', - withdraw_conference_booth_path(@conference.short_title, booth), - method: :patch, class: 'btn btn-mini btn-warning', id: "withdraw_booth_#{booth.id}", - data: { confirm: 'Are you sure you really want to withdraw this request?' } - - if booth.transition_possible? :confirm - = link_to 'Confirm', - confirm_conference_booth_path(@conference.short_title, booth), - method: :patch, class: 'btn btn-mini btn-success', id: "confirm_booth_#{booth.id}" - - if booth.transition_possible? :restart - = link_to 'Re-submit', - restart_conference_booth_path(@conference.short_title, booth), - method: :patch, class: 'btn btn-mini btn-success', id: "restart_booth_#{booth.id}" + %th + %b State + %th + %b Logo + %th + %b Title + %th + %b Actions + %tbody + - @booths.each do |booth| + %tr + %td{ style: "padding:20px 8px 20px 8px;" } + - if (booth.state == 'to_accept' || booth.state == 'to_reject') + - show_state = 'new' + - else + - show_state = booth.state + %span{ title: show_state, class: "fa #{status_icon(booth)}" } + %td + - if booth.logo_link + = image_tag(booth.picture.thumb.url, width: '20%') + %td + = link_to booth.title, conference_booth_path(@conference.short_title, booth) + %td + -if can? :edit, booth + = link_to 'Edit', edit_conference_booth_path(@conference.short_title, booth.id), + class: 'btn btn-default' + - if booth.transition_possible? :withdraw + = link_to 'Withdraw', + withdraw_conference_booth_path(@conference.short_title, booth), + method: :patch, class: 'btn btn-mini btn-warning', id: "withdraw_booth_#{booth.id}", + data: { confirm: 'Are you sure you really want to withdraw this request?' } + - if booth.transition_possible? :confirm + = link_to 'Confirm', + confirm_conference_booth_path(@conference.short_title, booth), + method: :patch, class: 'btn btn-mini btn-success', id: "confirm_booth_#{booth.id}" + - if booth.transition_possible? :restart + = link_to 'Re-submit', + restart_conference_booth_path(@conference.short_title, booth), + method: :patch, class: 'btn btn-mini btn-success', id: "restart_booth_#{booth.id}" + .pull-right = link_to "Add #{(t'booth').capitalize }", new_conference_booth_path(@conference.short_title), class: 'button btn btn-primary' diff --git a/app/views/physical_tickets/index.html.haml b/app/views/physical_tickets/index.html.haml index e89ceeabc..26cbfda05 100644 --- a/app/views/physical_tickets/index.html.haml +++ b/app/views/physical_tickets/index.html.haml @@ -25,11 +25,12 @@ - if @physical_tickets.present? %table.table.table-bordered.table-striped.table-hover#roles %thead - %th ID - %th Type - %th User - %th Registration? - %th Actions + %tr + %th ID + %th Type + %th User + %th Registration? + %th Actions %tbody - @physical_tickets.each do |physical_ticket| %tr diff --git a/app/views/proposals/_form.html.haml b/app/views/proposals/_form.html.haml index 2b649a20e..150083d4c 100644 --- a/app/views/proposals/_form.html.haml +++ b/app/views/proposals/_form.html.haml @@ -5,6 +5,7 @@ = f.label :title %abbr{title: 'This field is required'} * = f.text_field :title, autofocus: true, required: true, class: 'form-control' + .form-group = f.label :subtitle = f.text_field :subtitle, class: 'form-control' @@ -48,6 +49,10 @@ .form-group = f.label :track_id, 'Track' = f.select :track_id, @program.tracks.confirmed.cfp_active.pluck(:name, :id), { include_blank: '(Please select)' }, { class: 'form-control' } + - @program.tracks.confirmed.cfp_active.each do |track| + .help-block.select-help-text.track-description.collapse{ id: "#{track.id}-help" } + = track.description + - if @program.languages.present? .form-group diff --git a/app/views/proposals/_submission_type_content_form.haml b/app/views/proposals/_submission_type_content_form.haml index 81840e984..04d54aa32 100644 --- a/app/views/proposals/_submission_type_content_form.haml +++ b/app/views/proposals/_submission_type_content_form.haml @@ -6,7 +6,7 @@ = f.select :event_type_id, event_type_select_options(@conference.program.event_types), { include_blank: false }, { class: 'select-help-toggle form-control' } - program.event_types.each do |event_type| - .help-block.event_event_type_id.collapse{ id: "#{event_type.id}-help" } + .help-block.event_event_type_id.collapse{ id: "#{dom_id(event_type)}-help" } %strong Description = markdown(event_type.description) @@ -32,7 +32,7 @@ %p This part of the submission is intended only for the conference committee. - program.event_types.each do |event_type| - .help-block.select-help-text.event_event_type_id.collapse{ id: "#{event_type.id}-instructions" } + .help-block.select-help-text.event_event_type_id.collapse{ id: "#{dom_id(event_type)}-instructions" } - if event_type.submission_instructions.blank? %p Use this space to include any additional inforrmation that is helpful in reviewing your diff --git a/app/views/proposals/_tooltip.html.haml b/app/views/proposals/_tooltip.html.haml index 23fb1c0df..13f3155c2 100644 --- a/app/views/proposals/_tooltip.html.haml +++ b/app/views/proposals/_tooltip.html.haml @@ -1,31 +1,30 @@ - progress_status = event.progress_status %ul.list-unstyled - if can? :create, @conference.registrations.new - %li{class: class_for_todo(progress_status[:registered])} - %span{class: icon_for_todo(progress_status[:registered])} - - if progress_status[:registered] - Speaker(s) registered to the conference - - else - = link_to 'Speaker(s) not registered to the conference', new_conference_conference_registration_path(event.program.conference.short_title) - %li{class: class_for_todo(progress_status[:biographies])} - %span{class: icon_for_todo(progress_status[:biographies])} - - if progress_status[:biographies] - Speakers have filled out their biographies - - elsif current_user.biography.blank? && event.speakers.include?(current_user) - = link_to 'Fill out your biography', edit_user_path(current_user) + %li{'class'=>class_for_todo(progress_status['registered'])} + %span{'class'=>icon_for_todo(progress_status['registered'])} + - if progress_status['registered'] + Speaker(s) registered to the conference - else - Speakers' biographies missing - %li{class: class_for_todo(progress_status[:subtitle])} - %span{class: icon_for_todo(progress_status[:subtitle])} - = link_to 'Add a subtitle', edit_conference_program_proposal_path(event.program.conference.short_title, event) - %li{class: class_for_todo(progress_status[:commercials])} - %span{class: icon_for_todo(progress_status[:commercials])} - = link_to 'Add materials', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content') - - unless progress_status[:track].nil? - %li{class: class_for_todo(progress_status[:track])} - %span{class: icon_for_todo(progress_status[:track])} - = link_to 'Add a track', edit_conference_program_proposal_path(event.program.conference.short_title, event) - - unless progress_status[:difficulty_level].nil? - %li{class: class_for_todo(progress_status[:difficulty_level])} - %span{class: icon_for_todo(progress_status[:difficulty_level])} - = link_to 'Add a difficulty level', edit_conference_program_proposal_path(event.program.conference.short_title, event) + = link_to 'Speaker(s) not registered to the conference', new_conference_conference_registration_path(event.program.conference.short_title) + %li{'class'=>class_for_todo(progress_status['biographies'])} + %span{'class'=>icon_for_todo(progress_status['biographies'])} + - if progress_status['biographies'] + Speakers have filled out their biographies + - elsif current_user.biography.blank? && event.speakers.include?(current_user) + = link_to 'Fill out your biography', edit_user_path(current_user) + - else + Speakers' biographies missing + %li{'class'=>class_for_todo(progress_status['subtitle'])} + %span{'class'=>icon_for_todo(progress_status['subtitle'])} + = link_to 'Add a subtitle', edit_conference_program_proposal_path(event.program.conference.short_title, event) + %li{'class'=>class_for_todo(progress_status['commercials'])} + %span{'class'=>icon_for_todo(progress_status['commercials'])} + = link_to 'Add a commercial', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content') + - unless progress_status['track'].nil? + %li{'class'=>class_for_todo(progress_status['track'])} + %span{'class'=>icon_for_todo(progress_status['track'])} + = link_to 'Add a track', edit_conference_program_proposal_path(event.program.conference.short_title, event) + %li{'class'=>class_for_todo(progress_status['difficulty_level'])} + %span{'class'=>icon_for_todo(progress_status['difficulty_level'])} + = link_to 'Add a difficulty level', edit_conference_program_proposal_path(event.program.conference.short_title, event) diff --git a/app/views/proposals/registrations.html.haml b/app/views/proposals/registrations.html.haml index 3d4ed6f82..527c25274 100644 --- a/app/views/proposals/registrations.html.haml +++ b/app/views/proposals/registrations.html.haml @@ -15,12 +15,13 @@ .well %table.datatable#registrations %thead - %th - %th Name - %th Email - %th Created AT - %th Attended - %th Attended Conference + %tr + %th + %th Name + %th Email + %th Created AT + %th Attended + %th Attended Conference %tbody - @event.events_registrations.each.with_index(1) do |event_registration, index| %tr diff --git a/app/views/shared/_object_changes.html.haml b/app/views/shared/_object_changes.html.haml index b8625de7b..47a3e7018 100644 --- a/app/views/shared/_object_changes.html.haml +++ b/app/views/shared/_object_changes.html.haml @@ -21,41 +21,55 @@ %th Action %tbody - if version.event != 'destroy' - - version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values| - %tr - %td= attribute - - if version.event != 'create' + -# For deleted models we cannot use all of PaperTrail functionalities, so we simplify the output + - if version.item_type == 'Campaign' || version.item_type == 'Target' || version.item_type == 'EventAttachment' + - changeset = version.object_changes.split("\n") + -# object_changes field is now in the format of ["---", "id:", "- ", "- 6", "conference_id:", "- ", "- 2"] + - changeset.shift + - changeset.each_slice(3).each do |attribute_changes| + %tr + -# Remove the dash at the beginning + - attribute_changes.map!{ |x| x.sub(/^- /, '') } + %td= attribute_changes[0] + - if version.event != 'create' + %td= attribute_changes[1] + %td= attribute_changes[2] + - else + - version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values| + %tr + %td= attribute + - if version.event != 'create' + %td + / If the attribute is an associated model, show the value of the record it corresponds to, not just the ID. + / Eg. when the version is of an Event, if the attribute is event_type_id it shows + / Workshop (ID: 116) instead of just 116 + - if attribute.include?('_id') + - model_name = attribute.chomp('_id').camelize + - associated_object = current_or_last_object_state(model_name, values[0]) + + = associated_object.try(:title) || associated_object.try(:name) + = values[0].blank? ? '-' : "(ID: #{values[0]})" + - else + = values[0].blank? ? '-' : values[0] + + - if attribute == 'price_cents' + = "(#{humanized_money_with_symbol previous_version.try(:price)})" %td - / If the attribute is an associated model, show the value of the record it corresponds to, not just the ID. - / Eg. when the version is of an Event, if the attribute is event_type_id it shows - / Workshop (ID: 116) instead of just 116 - if attribute.include?('_id') - model_name = attribute.chomp('_id').camelize - - associated_object = current_or_last_object_state(model_name, values[0]) + - associated_object = current_or_last_object_state(model_name, values[1]) = associated_object.try(:title) || associated_object.try(:name) - = values[0].blank? ? '-' : "(ID: #{values[0]})" + = (values[1].blank? ? '-' : "(ID: #{values[1]})") + - else - = values[0].blank? ? '-' : values[0] + = values[1].blank? ? '-' : values[1] - if attribute == 'price_cents' - = "(#{humanized_money_with_symbol previous_version.try(:price)})" - %td - - if attribute.include?('_id') - - model_name = attribute.chomp('_id').camelize - - associated_object = current_or_last_object_state(model_name, values[1]) - - = associated_object.try(:title) || associated_object.try(:name) - = (values[1].blank? ? '-' : "(ID: #{values[1]})") - - - else - = values[1].blank? ? '-' : values[1] - - - if attribute == 'price_cents' - = "(#{humanized_money_with_symbol version_item.try(:price)})" + = "(#{humanized_money_with_symbol version_item.try(:price)})" - - if can? :revert_attribute, version - %td= link_to 'Revert', admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), class: 'btn btn-sm btn-primary', data: { confirm: "Are you sure you want to revert #{attribute}?" } + - if can? :revert_attribute, version + %td= link_to 'Revert', admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), class: 'btn btn-sm btn-primary', data: { confirm: "Are you sure you want to revert #{attribute}?" } - else - version.reify.attributes.each do |attribute, value| %tr diff --git a/app/views/shared/_select_help_text.html.haml b/app/views/shared/_select_help_text.html.haml new file mode 100644 index 000000000..dcf4a930c --- /dev/null +++ b/app/views/shared/_select_help_text.html.haml @@ -0,0 +1,10 @@ +:ruby + include_blank ||= false + select_id = field_id(f.object_name, local_assigns[:for]) + value = f.object.send(local_assigns[:for]) + +- options.each_with_index do |option, i| + - selected = value.present? ? option.id == value : !include_blank && i == 0 + + %span.help-block.select-help-text.collapse{ id: "#{option.id}-help", class: [select_id, ('in' if selected)] } + = yield option diff --git a/app/views/ticket_purchases/index.html.haml b/app/views/ticket_purchases/index.html.haml index c9255c37b..5f8afede4 100644 --- a/app/views/ticket_purchases/index.html.haml +++ b/app/views/ticket_purchases/index.html.haml @@ -10,11 +10,12 @@ - if @unpaid_ticket_purchases.present? %table.table.table-bordered.table-striped.table-hover#roles %thead - %th ID - %th Type - %th Quantity - %th Date - %th Actions + %tr + %th ID + %th Type + %th Quantity + %th Date + %th Actions %tbody - @unpaid_ticket_purchases.each do |ticket_purchase| %tr diff --git a/config/application.rb b/config/application.rb index 68795fa94..c65e46dd0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -62,9 +62,7 @@ class Application < Rails::Application config.generators.system_tests = nil # This is a nightmare with our current data model, no one ever thought about this. config.active_record.belongs_to_required_by_default = false - - # See note about specifiying allowed classes - # https://github.com/ra ils/rails/blob/v7.0.4/activerecord/CHANGELOG.md#rails-7031-july-12-2022 - config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time, DateTime] + # https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 + config.active_record.yaml_column_permitted_classes = ['Date', 'DateTime', 'Symbol', 'Time'] end end diff --git a/config/environments/development.rb b/config/environments/development.rb index df546d4c1..1512c020b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -56,8 +56,10 @@ # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Set the detault url for action mailer - config.action_mailer.default_url_options = { host: ENV.fetch('OSEM_HOSTNAME', 'localhost:3000') } + # Provide a default host for URLs + Rails.application.routes.default_url_options[:host] = ENV.fetch('OSEM_HOSTNAME', 'localhost:3000') + config.action_controller.default_url_options = Rails.application.routes.default_url_options + config.action_mailer.default_url_options = Rails.application.routes.default_url_options # Access all mails sent at http://localhost:3000/letter_opener config.action_mailer.delivery_method = :letter_opener diff --git a/config/environments/production.rb b/config/environments/production.rb index e0b7d7b31..59431a74d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -92,13 +92,34 @@ # require "syslog/logger" # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") + # Enable lograge + config.lograge.enabled = true + config.lograge.custom_payload do |controller| + # exceptions = ['controller', 'action', 'format', 'id'] + { + # params: event.payload[:params].except(*exceptions), + user: controller.current_user.try(:username) + } + end + config.lograge.custom_options = lambda do |event| + exceptions = %w[controller action format id _method authenticity_token] + { + params: event.payload[:params].except(*exceptions) + } + end + if ENV['RAILS_LOG_TO_STDOUT'].present? logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end - config.action_mailer.default_url_options = { host: ENV.fetch('OSEM_HOSTNAME', 'localhost:3000') } + # Provide a default host for URLs + Rails.application.routes.default_url_options[:host] = ENV.fetch('OSEM_HOSTNAME', 'localhost:3000') + config.action_controller.default_url_options = Rails.application.routes.default_url_options + config.action_mailer.default_url_options = Rails.application.routes.default_url_options + + # Configure outgoing mail config.action_mailer.smtp_settings = { address: ENV.fetch('OSEM_SMTP_ADDRESS', 'localhost'), port: ENV.fetch('OSEM_SMTP_PORT', 25), diff --git a/config/environments/test.rb b/config/environments/test.rb index 4b4ce679c..a7723d22d 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -43,8 +43,12 @@ # Tell Active Support which deprecation messages to disallow. config.active_support.disallowed_deprecation_warnings = [] - # Set the detault url for action mailer - config.action_mailer.default_url_options = { host: 'localhost:3000' } + # Provide a default host for URLs + Rails.application.routes.default_url_options[:host] = 'localhost:3000' + config.action_controller.default_url_options = Rails.application.routes.default_url_options + config.action_mailer.default_url_options = Rails.application.routes.default_url_options + + # Configure outgoing mail config.action_mailer.delivery_method = :test config.after_initialize do diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb index 86c283064..e8d8a1c88 100644 --- a/config/initializers/sentry.rb +++ b/config/initializers/sentry.rb @@ -9,7 +9,7 @@ # To activate performance monitoring, set one of these options. # We recommend adjusting the value in production: - config.traces_sample_rate = 0.5 + config.traces_sample_rate = ENV.fetch('OSEM_SENTRY_TRACES_SAMPLE_RATE', '0.5').to_f # or # config.traces_sampler = lambda do |context| # true diff --git a/spec/controllers/proposals_controller_spec.rb b/spec/controllers/proposals_controller_spec.rb index 4c0433c30..633b3c650 100644 --- a/spec/controllers/proposals_controller_spec.rb +++ b/spec/controllers/proposals_controller_spec.rb @@ -6,7 +6,7 @@ let(:user) { create(:user) } let(:conference) { create(:conference, :with_splashpage, short_title: 'lama101') } let(:event) { create(:event, program: conference.program) } - let(:event_type) { create :event_type } + let(:event_type) { create(:event_type) } context 'user is not signed in' do describe 'GET #new' do diff --git a/spec/factories/event_types.rb b/spec/factories/event_types.rb index 90e32559d..e74b0b363 100644 --- a/spec/factories/event_types.rb +++ b/spec/factories/event_types.rb @@ -21,10 +21,10 @@ factory :event_type do title { 'Example Event Type' } length { 30 } + description { 'Example Event Description\nThis event type is an example.' } minimum_abstract_length { 0 } maximum_abstract_length { 500 } - description { 'Example Event Description' } - submission_instructions { 'Example Event Instructions' } + submission_instructions { 'Example Event Instructions _with_ **markdown**' } color { '#ffffff' } program end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 1bed4989c..78784fa4f 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -99,6 +99,16 @@ end end + factory :cfp_user do + transient do + resource { create(:resource) } + end + + after :create do |user, evaluator| + user.add_role :cfp, evaluator.resource + end + end + trait :disabled do is_disabled { true } end diff --git a/spec/features/event_types_spec.rb b/spec/features/event_types_spec.rb index 302358c99..73267a56f 100644 --- a/spec/features/event_types_spec.rb +++ b/spec/features/event_types_spec.rb @@ -13,7 +13,7 @@ conference_id: conference.short_title ) - within('table#event_types') do + within('table#event_types > tbody') do expect(page.assert_selector('tr', count: 2)).to be true end @@ -33,7 +33,7 @@ # Validations # binding.pry expect(flash).to eq('Event type successfully created.') - within('table#event_types') do + within('table#event_types > tbody') do expect(page.has_content?('Party')).to be true expect(page.has_content?('13042')).to be true expect(page.has_content?('#E4E4E4')).to be true @@ -49,7 +49,7 @@ page.find('#flash') expect(flash).to eq('Event type successfully deleted.') - within('table#event_types') do + within('table#event_types > tbody') do expect(page.assert_selector('tr', count: 2)).to be true expect(page.has_content?('Party')).to be false end diff --git a/spec/features/omniauth_spec.rb b/spec/features/omniauth_spec.rb index 415fbcf57..4ad7e8ac3 100644 --- a/spec/features/omniauth_spec.rb +++ b/spec/features/omniauth_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Openid, type: :feature, js: true do +describe Openid, js: true, type: :feature do shared_examples 'sign in with openid' do it 'has option to log in with Google account' do visit '/accounts/sign_in' diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index 84433726d..2e6b665fd 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -27,7 +27,7 @@ sign_in organizer end - it 'can preview a proposal if it is public', feature: true, js: true do + scenario 'can preview a proposal if it is public', feature: true, js: true do visit admin_conference_program_event_path(conference.short_title, @event) expect(page).to have_selector(:link_or_button, 'Preview') click_link 'Preview' @@ -35,7 +35,7 @@ ignore_query: true) end - it 'cannot preview a proposal if it is not public', feature: true, js: true do + scenario 'cannot preview a proposal if it is not public', feature: true, js: true do event = create(:event, program: conference.program, title: 'Example Proposal') event.public = false event.save! @@ -43,7 +43,16 @@ expect(page).not_to have_selector(:link_or_button, 'Preview') end - it 'rejects a proposal', feature: true, js: true do + scenario 'adds a proposal', feature: true, js: true do + visit admin_conference_program_events_path(conference.short_title) + click_on 'Add Event' + fill_in 'Title', with: 'Organizer-Created Proposal' + fill_in 'Abstract', with: 'This proposal was created by an organizer.' + click_button 'Create Proposal' + expect(flash).to eq('Event was successfully submitted.') + end + + scenario 'rejects a proposal', feature: true, js: true do visit admin_conference_program_events_path(conference.short_title) expect(page).to have_content 'Example Proposal' @@ -66,7 +75,7 @@ expect(@event.state).to eq('unconfirmed') end - it 'restarts review of a proposal', feature: true, js: true do + scenario 'restarts review of a proposal', feature: true, js: true do @event.reject!(@options) visit admin_conference_program_events_path(conference.short_title) expect(page).to have_content 'Example Proposal' @@ -84,7 +93,7 @@ @event.accept!(@options) end - it 'not signed_in user submits proposal' do + scenario 'not signed_in user submits proposal', feature: true, js: true do expected_count_event = Event.count + 1 expected_count_user = User.count + 1 @@ -96,7 +105,15 @@ fill_in 'user_password_confirmation', with: 'testuserpassword' end fill_in 'event_title', with: 'Example Proposal' + + select('Talk', from: 'event[event_type_id]') + expect(page).to have_css( + '#event_type_1-help', + visible: :hidden, + text: EventType.find(1).description + ) select('Example Event Type', from: 'event[event_type_id]') + expect(page).to have_selector '.event_event_type_id', text: 'This event type is an example.' fill_in 'event_abstract', with: 'Lorem ipsum abstract' fill_in 'event_submission_text', with: 'Lorem ipsum submission' @@ -108,7 +125,7 @@ expect(User.count).to eq(expected_count_user) end - it 'edit proposal without cfp' do + scenario 'edit proposal without cfp' do conference = create(:conference) proposal = create(:event, program: conference.program) @@ -119,8 +136,11 @@ expect(page).to have_content 'Proposal Information' end - it 'update a proposal' do + scenario 'update a proposal', js: true do conference = create(:conference) + create(:track, program: conference.program, + name: 'Example Track', + description: 'This track is an *example*.') create(:cfp, program: conference.program) proposal = create(:event, program: conference.program) @@ -129,7 +149,12 @@ visit edit_conference_program_proposal_path(proposal.program.conference.short_title, proposal) fill_in 'event_subtitle', with: 'My event subtitle' + select 'Example Track', from: 'Track' + # TODO-SNAPCON: Renable this after refacotoring proposals form. + # expect(page).to have_css('.track-description', visible: :hidden, text: 'This track is an example.') select('Easy', from: 'event[difficulty_level_id]') + # TODO-SNAPCON: Renable this after refacotoring proposals form. + # expect(page).to have_selector '.in', text: 'Events are understandable for everyone without knowledge of the topic.' click_button 'Update Proposal' page.find('#flash') @@ -142,11 +167,10 @@ visit conference_program_proposals_path(conference.short_title) click_link 'New Proposal' - expect(page).to have_selector(".in[id='#{find_field('event[event_type_id]').value}-help']") # End of animation fill_in 'event_title', with: 'Example Proposal' select('Example Event Type', from: 'event[event_type_id]') - expect(page).to have_selector(".in[id='#{find_field('event[event_type_id]').value}-help']") # End of animation + expect(page).to have_selector '.in', text: 'This event type is an example.' expect(page).to have_text('Example Event Description') fill_in 'event_abstract', with: 'Lorem ipsum abstract' @@ -208,6 +232,7 @@ select(event_type.title, from: 'event[event_type_id]') fill_in 'event_submission_text', with: 'Lorem ipsum example submission text' + # TODO-SNAPCON: Renable this. # accept_confirm do # click_button 'Reset Submission to Template' # end @@ -372,6 +397,7 @@ end it 'only shows 3 events happening now because of pagination' do + Rails.configuration.conference[:events_per_page] = 3 event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, diff --git a/spec/features/roles_spec.rb b/spec/features/roles_spec.rb index b0ed7c8ba..dff041316 100644 --- a/spec/features/roles_spec.rb +++ b/spec/features/roles_spec.rb @@ -48,7 +48,7 @@ let!(:user_with_role) { create(:user, role_ids: [role.id]) } let!(:by_role) { Role.find_by(name: by_role_name, resource: conference) } let!(:user_to_sign_in) { create(:user, role_ids: [by_role.id]) } - let!(:user_with_no_role) { create :user } + let!(:user_with_no_role) { create(:user) } before do sign_in user_to_sign_in @@ -84,7 +84,7 @@ let!(:user_with_role) { create(:user, role_ids: [role.id]) } let!(:by_role) { Role.find_by(name: by_role_name, resource: conference) } let!(:user_to_sign_in) { create(:user, role_ids: [by_role.id]) } - let!(:user_with_no_role) { create :user } + let!(:user_with_no_role) { create(:user) } before do sign_in user_to_sign_in @@ -108,7 +108,7 @@ let!(:organization) { create(:organization) } let!(:org_admin_role) { Role.find_by(name: 'organization_admin', resource: organization) } let!(:organization_admin) { create(:user, role_ids: [org_admin_role.id]) } - let(:user_with_no_role) { create :user } + let(:user_with_no_role) { create(:user) } let!(:other_organization) { create(:organization) } before do @@ -130,7 +130,7 @@ it 'successfully removes role organization_admin' do click_link('Admins', href: admins_admin_organization_path(organization.id)) - first('tr').find('.btn-danger').click + first('tbody > tr').find('.btn-danger').click organization_admin.reload expect(organization_admin.has_cached_role?('organization_admin', organization)).to be false end diff --git a/spec/features/splashpage_spec.rb b/spec/features/splashpage_spec.rb index d0ded3917..ed8ce86bf 100644 --- a/spec/features/splashpage_spec.rb +++ b/spec/features/splashpage_spec.rb @@ -156,14 +156,19 @@ end it 'only shows 3 events happening now because of pagination' do - event_schedule1 = create(:event_schedule, event: scheduled_event1, schedule: selected_schedule, -start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) - event_schedule2 = create(:event_schedule, event: scheduled_event2, schedule: selected_schedule, -start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) - event_schedule3 = create(:event_schedule, event: scheduled_event3, schedule: selected_schedule, -start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) - event_schedule4 = create(:event_schedule, event: scheduled_event4, schedule: selected_schedule, -start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) + Rails.configuration.conference[:events_per_page] = 3 + event_schedule1 = create(:event_schedule, event: scheduled_event1, + schedule: selected_schedule, + start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) + event_schedule2 = create(:event_schedule, event: scheduled_event2, + schedule: selected_schedule, + start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) + event_schedule3 = create(:event_schedule, event: scheduled_event3, + schedule: selected_schedule, + start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) + event_schedule4 = create(:event_schedule, event: scheduled_event4, + schedule: selected_schedule, + start_time: current_time.strftime('%a, %d %b %Y %H:%M:%S')) visit conference_path(conference2.short_title) happening_now = page.find('#happening-now') diff --git a/spec/features/surveys_spec.rb b/spec/features/surveys_spec.rb index 549b168a0..d80ae263f 100644 --- a/spec/features/surveys_spec.rb +++ b/spec/features/surveys_spec.rb @@ -35,10 +35,10 @@ end it 'respond to a survey during registration', feature: true, js: true do - create :registration_period, conference: conference - create :registration, conference: conference, user: attendee + create(:registration_period, conference: conference) + create(:registration, conference: conference, user: attendee) survey = create(:survey, surveyable: conference, target: :during_registration) - create :boolean_mandatory, survey: survey + create(:boolean_mandatory, survey: survey) visit conference_conference_registration_path(conference) expect(find(:link, survey.title).sibling('.fa-solid')[:title]).to eq('Please fill out the survey') diff --git a/spec/features/user_spec.rb b/spec/features/user_spec.rb index 5499af834..0bc07888d 100644 --- a/spec/features/user_spec.rb +++ b/spec/features/user_spec.rb @@ -2,11 +2,25 @@ require 'spec_helper' -describe User do +feature User do + let(:admin) { create(:admin) } + let!(:user) { create(:user) } + shared_examples 'admin ability' do + scenario 'edits a user', feature: true, js: true do + visit admin_users_path + within "tr#user_#{user.id}" do + click_on 'Edit' + end + fill_in 'Name', with: 'Edited Name' + click_button 'Update User' + expect(flash).to include('Updated Edited Name') + end end describe 'admin' do + before { sign_in admin } + it_behaves_like 'admin ability', :admin end end diff --git a/spec/features/voting_spec.rb b/spec/features/voting_spec.rb new file mode 100644 index 000000000..1758de0bd --- /dev/null +++ b/spec/features/voting_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +def have_rating(rating, max) + have_selector('.rating.bright', count: rating) + .and have_selector('.rating:not(.bright)', count: max - rating) +end + +def cast_vote(rating, before:, after:) + # Index shows existing rating but not user’s vote + visit admin_conference_program_events_path(conference.short_title) + within("#event-#{event.id}") do + expect(page).to have_rating(before, 5) + expect(page).to have_text('Not rated') + end + + # Event page shows existing rating but not user’s vote + click_on event.title + within('tr', text: 'Rating') { expect(page).to have_rating(before, 5) } + within('tr', text: 'Your vote') { expect(page).to have_rating(0, 5) } + + # Voting dynamically updates the page + within('tr', text: 'Your vote') { page.find(".rating:nth-of-type(#{rating})").click } + within('tr', text: 'Rating') { expect(page).to have_rating(after, 5) } + within('tr', text: 'Your vote') { expect(page).to have_rating(rating, 5) } + + # Index shows updated rating and vote + visit admin_conference_program_events_path(conference.short_title) + within("#event-#{event.id}") do + expect(page).to have_rating(after, 5) + expect(page).to have_text("You voted: #{rating}/5") + end + + # Re-rendered event page shows updated rating and vote + click_on event.title + within('tr', text: 'Rating') { expect(page).to have_rating(after, 5) } + within('tr', text: 'Your vote') { expect(page).to have_rating(rating, 5) } +end + +feature 'Voting' do + let(:conference) { create(:conference) } + let!(:event) { create(:event, program: conference.program) } + let(:voter1) { create(:cfp_user, resource: conference) } + let(:voter2) { create(:cfp_user, resource: conference) } + + before :each do + conference.program.update_attribute :rating, 5 + end + + scenario 'multiple users casting votes', feature: true, js: true do + sign_in voter1 + cast_vote 3, before: 0, after: 3 + sign_out + + sign_in voter2 + cast_vote 5, before: 3, after: 4 + end +end diff --git a/spec/helpers/format_helper_spec.rb b/spec/helpers/format_helper_spec.rb index 138bd1965..3cd3e7742 100644 --- a/spec/helpers/format_helper_spec.rb +++ b/spec/helpers/format_helper_spec.rb @@ -15,5 +15,18 @@ it 'returns HTML for header markdown' do expect(markdown('# this is my header')).to eq "

this is my header

\n" end + + it 'escapes input HTML' do + expect(markdown('*a*')).to eq "

<em>a</em>

\n" + end + + it 'removes unallowed elements' do + expect(markdown('**', false)).to eq "

a

\n" + end + + it 'sets nofollow on links' do + expect(markdown('[a](https://example.com/)')) + .to eq "

a

\n" + end end end diff --git a/spec/models/resource_spec.rb b/spec/models/resource_spec.rb index 03cf8f874..774812cfb 100644 --- a/spec/models/resource_spec.rb +++ b/spec/models/resource_spec.rb @@ -15,7 +15,7 @@ describe Resource do let(:conference) { create(:conference) } - let(:resource) { create :resource } + let(:resource) { create(:resource) } it { is_expected.to validate_presence_of(:name) } diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index c971a6ee9..412fb9dfe 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -81,13 +81,13 @@ 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, quantity: 1, 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, quantity: 2, 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, quantity: 10, paid: false, user: user) end it 'returns turnover as Money with ticket\'s currency' do diff --git a/spec/serializers/event_schedule_serializer_spec.rb b/spec/serializers/event_schedule_serializer_spec.rb new file mode 100644 index 000000000..9d4cc64e7 --- /dev/null +++ b/spec/serializers/event_schedule_serializer_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe EventScheduleSerializer, type: :serializer do + let(:start) { DateTime.new(2000, 1, 2, 3, 4, 5) } + let(:timezone) { 'Etc/GMT+11' } + let(:conference) do + create(:conference, start_date: start.to_date, + start_hour: start.hour, + timezone: timezone) + end + let(:program) { create(:program, conference: conference) } + let(:event) { create(:event, program: program) } + let(:event_schedule) { create(:event_schedule, event: event, start_time: start) } + let(:serializer) { described_class.new(event_schedule) } + + it 'sets date and room' do + expected_json = { + date: '2000-01-02T03:04:05.000-11:00', + room: event_schedule.room.guid + }.to_json + + expect(serializer.to_json).to eq expected_json + end +end diff --git a/spec/serializers/event_serializer_spec.rb b/spec/serializers/event_serializer_spec.rb index 0aef5b796..1844c65ea 100644 --- a/spec/serializers/event_serializer_spec.rb +++ b/spec/serializers/event_serializer_spec.rb @@ -40,16 +40,23 @@ # require 'spec_helper' describe EventSerializer, type: :serializer do - let(:event) { create(:event, title: 'Some Talk', abstract: 'Lorem ipsum dolor sit amet') } + let(:conference) { create(:conference, timezone: 'UTC') } + let(:program) { create(:program, conference: conference) } + let(:event) do + create(:event, program: program, + title: 'Some Talk', + abstract: 'Lorem ipsum dolor sit amet') + end let(:serializer) { EventSerializer.new(event) } context 'event does not have date, room and tracks assigned' do it 'sets guid, title, length, abstract and type' do expected_json = { guid: event.guid, + url: "http://localhost:3000/conferences/#{event.conference.short_title}/program/proposals/#{event.id}", title: 'Some Talk', length: 30, - scheduled_date: '', + scheduled_date: nil, language: nil, abstract: 'Lorem ipsum dolor sit amet', speaker_ids: event.speaker_ids, @@ -77,9 +84,10 @@ it 'sets guid, title, length, abstract, type, date, language, speakers, room and track' do expected_json = { guid: event.guid, + url: "http://localhost:3000/conferences/#{event.conference.short_title}/program/proposals/#{event.id}", title: 'Some Talk', length: 30, - scheduled_date: ' 2014-03-04T09:00:00+0000 ', + scheduled_date: '2014-03-04T09:00:00.000Z', language: 'English', abstract: 'Lorem ipsum dolor sit amet', speaker_ids: [speaker.id], diff --git a/spec/serializers/speaker_serializer_spec.rb b/spec/serializers/speaker_serializer_spec.rb index 9971efe78..3f85b772f 100644 --- a/spec/serializers/speaker_serializer_spec.rb +++ b/spec/serializers/speaker_serializer_spec.rb @@ -8,6 +8,7 @@ context 'speaker does not have biography' do it 'sets name and affiliation' do expected_json = { + url: "http://localhost:3000/users/#{speaker.id}", name: 'John Doe', affiliation: 'JohnDoesInc', biography: nil @@ -22,6 +23,7 @@ it 'sets name, affiliation and biography' do expected_json = { + url: "http://localhost:3000/users/#{speaker.id}", name: 'John Doe', affiliation: 'JohnDoesInc', biography: 'Doest of all Jon Does' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0fa89ba08..99a75f488 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -117,6 +117,11 @@ # end # end + # Expect configured host instead of `test.host` (see https://stackoverflow.com/q/15414847) + config.before(:each, type: :controller) do + @request.host = Rails.application.routes.default_url_options[:host] + end + # use the config to use # t('some.locale.key') instead of always having to type I18n.t config.include AbstractController::Translation diff --git a/spec/support/external_request.rb b/spec/support/external_request.rb index b68b6dff7..45f0a5e03 100644 --- a/spec/support/external_request.rb +++ b/spec/support/external_request.rb @@ -5,6 +5,9 @@ driver_urls = Webdrivers::Common.subclasses.map do |driver| Addressable::URI.parse(driver.base_url).host end +# Local chromedriver pings GitHub. :( +driver_urls << 'googlechromelabs.github.io' +driver_urls << 'edgedl.me.gvt1.com' # The fuck, Google? WebMock.disable_net_connect!(allow_localhost: true, allow: [*driver_urls, /stripe.com/]) RSpec.configure do |config| diff --git a/spec/support/schemas/conference.json b/spec/support/schemas/conference.json index 26e2c907e..81fc14081 100644 --- a/spec/support/schemas/conference.json +++ b/spec/support/schemas/conference.json @@ -3,6 +3,7 @@ "type" : "object", "required" : [ "short_title", + "url", "title", "description", "start_date", @@ -19,6 +20,9 @@ "short_title": { "type": "string" }, + "url": { + "type": "string" + }, "title": { "type": "string" },