diff --git a/.gitignore b/.gitignore index 75a1bdc6..ce3e7f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ pickle-email-*.html .env.local docker-compose.env docker-compose.yml +.DS_Store +.byebug_history diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a91f2ae9..7664f6c3 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,19 +1,11 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2017-07-14 12:03:16 +0000 using RuboCop version 0.49.1. +# on 2017-11-27 22:40:12 +0530 using RuboCop version 0.51.0. # 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: 15 -# Cop supports --auto-correct. -# Configuration parameters: Include, TreatCommentsAsGroupSeparators. -# Include: **/Gemfile, **/gems.rb -Bundler/OrderedGems: - Exclude: - - 'Gemfile' - # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. @@ -46,7 +38,7 @@ Layout/EmptyLineAfterMagicComment: Exclude: - 'spec/models/conference_spec.rb' -# Offense count: 104 +# Offense count: 109 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: empty_lines, no_empty_lines @@ -151,7 +143,7 @@ Layout/MultilineHashBraceLayout: Layout/MultilineMethodCallBraceLayout: Enabled: false -# Offense count: 55 +# Offense count: 53 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: aligned, indented, indented_relative_to_receiver @@ -192,10 +184,11 @@ Layout/SpaceAroundOperators: Exclude: - 'lib/tasks/data.rake' -# Offense count: 416 +# Offense count: 463 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle, SupportedStyles, SupportedStylesForEmptyBraces. # SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space Layout/SpaceBeforeBlockBraces: Enabled: false @@ -205,20 +198,13 @@ Layout/SpaceBeforeComma: Exclude: - 'lib/tasks/data_demo.rake' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment. -Layout/SpaceBeforeFirstArg: - Exclude: - - 'spec/controllers/admin/roles_controller_spec.rb' - # Offense count: 1 # Cop supports --auto-correct. Layout/SpaceBeforeSemicolon: Exclude: - 'Guardfile' -# Offense count: 51 +# Offense count: 54 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters. # SupportedStyles: space, no_space @@ -293,6 +279,13 @@ Lint/IneffectiveAccessModifier: - 'app/models/conference.rb' # Offense count: 2 +Lint/RescueWithoutErrorClass: + Exclude: + - 'app/controllers/users/omniauth_callbacks_controller.rb' + - 'lib/tasks/migrate_config.rake' + +# Offense count: 2 +# Cop supports --auto-correct. Lint/ScriptPermission: Exclude: - 'Guardfile' @@ -305,49 +298,41 @@ Lint/UnusedBlockArgument: Exclude: - 'lib/tasks/user.rake' -# Offense count: 114 +# Offense count: 136 Metrics/AbcSize: Max: 86 -# Offense count: 233 +# Offense count: 258 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: Max: 471 -# Offense count: 23 +# Offense count: 28 Metrics/CyclomaticComplexity: - Max: 12 - Exclude: - - 'app/models/track.rb' + Max: 14 -# Offense count: 2353 +# Offense count: 2774 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 619 -# Offense count: 120 +# Offense count: 133 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 56 - Exclude: - - 'app/models/admin_ability.rb' -# Offense count: 3 +# Offense count: 4 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 159 - Exclude: - - 'app/helpers/format_helper.rb' - -# Offense count: 15 -Metrics/PerceivedComplexity: - Max: 16 - Exclude: - - 'app/models/track.rb' + Max: 171 # Offense count: 20 -Style/AccessorMethodName: +Metrics/PerceivedComplexity: + Max: 16 + +# Offense count: 20 +Naming/AccessorMethodName: Exclude: - 'app/controllers/admin/events_controller.rb' - 'app/controllers/application_controller.rb' @@ -356,6 +341,51 @@ Style/AccessorMethodName: - 'app/models/target.rb' - 'app/models/user.rb' +# Offense count: 2 +# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'Gemfile' + - 'Vagrantfile' + +# Offense count: 2 +# Configuration parameters: Blacklist. +# Blacklist: END, (?-mix:EO[A-Z]{1}) +Naming/HeredocDelimiterNaming: + Exclude: + - 'spec/factories/users.rb' + - 'spec/models/user_spec.rb' + +# Offense count: 2 +# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros. +# NamePrefix: is_, has_, have_ +# NamePrefixBlacklist: is_, has_, have_ +# NameWhitelist: is_a? +# MethodDefinitionMacros: define_method, define_singleton_method +Naming/PredicateName: + Exclude: + - 'spec/**/*' + - 'app/models/comment.rb' + - 'app/models/contact.rb' + +# Offense count: 2 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: snake_case, normalcase, non_integer +Naming/VariableNumber: + Exclude: + - 'spec/models/ticket_purchase_spec.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect. +Performance/HashEachMethods: + Exclude: + - 'app/controllers/admin/conferences_controller.rb' + - 'app/helpers/application_helper.rb' + - 'db/migrate/20140701123203_add_events_per_week_to_conference.rb' + - 'spec/factories/event_users.rb' + # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. @@ -386,7 +416,14 @@ Style/ConditionalAssignment: - 'db/migrate/20140610165551_migrate_data_person_to_user.rb' - 'db/migrate/20140820124117_undo_wrong_migration20140801080705_add_users_to_events.rb' -# Offense count: 464 +# Offense count: 9 +Style/DateTime: + Exclude: + - 'app/models/conference.rb' + - 'app/models/program.rb' + - 'spec/models/conference_spec.rb' + +# Offense count: 488 Style/Documentation: Enabled: false @@ -419,14 +456,13 @@ Style/EmptyMethod: - 'db/migrate/20130216122155_set_registration_defaults_to_false.rb' # Offense count: 2 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. -# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS -Style/FileName: +# Cop supports --auto-correct. +Style/Encoding: Exclude: - - 'Gemfile' - - 'Vagrantfile' + - 'app/uploaders/picture_uploader.rb' + - 'spec/models/conference_spec.rb' -# Offense count: 24 +# Offense count: 32 # Configuration parameters: MinBodyLength. Style/GuardClause: Enabled: false @@ -445,7 +481,6 @@ Style/HashSyntax: # Configuration parameters: MaxLineLength. Style/IfUnlessModifier: Exclude: - - 'app/controllers/admin/booths_controller.rb' - 'app/controllers/admin/events_controller.rb' - 'app/controllers/api/v1/events_controller.rb' - 'app/controllers/conference_registrations_controller.rb' @@ -454,7 +489,6 @@ Style/IfUnlessModifier: - 'app/models/commercial.rb' - 'app/models/conference.rb' - 'app/models/email_settings.rb' - - 'app/models/ticket_purchase.rb' - 'app/models/user.rb' - 'db/migrate/20151031092713_change_conference_id_to_venue_id_in_rooms.rb' - 'lib/tasks/events_registrations.rake' @@ -469,7 +503,7 @@ Style/LineEndConcatenation: - 'spec/features/conference_spec.rb' - 'spec/features/registration_periods_spec.rb' -# Offense count: 6 +# Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline @@ -498,12 +532,14 @@ Style/MutableConstant: # Offense count: 4 # Cop supports --auto-correct. +# Configuration parameters: Whitelist. +# Whitelist: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with Style/NestedParenthesizedCalls: Exclude: - 'spec/features/conference_spec.rb' - 'spec/models/conference_spec.rb' -# Offense count: 26 +# Offense count: 27 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. # SupportedStyles: skip_modifier_ifs, always @@ -548,6 +584,12 @@ Style/OptionalArguments: Exclude: - 'app/models/event.rb' +# Offense count: 1 +# Cop supports --auto-correct. +Style/OrAssignment: + Exclude: + - 'app/controllers/schedules_controller.rb' + # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AllowSafeAssignment. @@ -557,7 +599,7 @@ Style/ParenthesesAroundCondition: - 'app/controllers/application_controller.rb' - 'app/helpers/format_helper.rb' -# Offense count: 14 +# Offense count: 15 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: @@ -571,20 +613,9 @@ Style/PercentLiteralDelimiters: - 'app/models/contact.rb' - 'app/models/registration.rb' - 'app/models/subscription.rb' + - 'app/models/track.rb' - 'app/uploaders/picture_uploader.rb' - 'spec/models/program_spec.rb' - - 'app/models/track.rb' - -# Offense count: 2 -# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist. -# NamePrefix: is_, has_, have_ -# NamePrefixBlacklist: is_, has_, have_ -# NameWhitelist: is_a? -Style/PredicateName: - Exclude: - - 'spec/**/*' - - 'app/models/comment.rb' - - 'app/models/contact.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -607,16 +638,6 @@ Style/RedundantParentheses: Exclude: - 'app/controllers/admin/base_controller.rb' -# Offense count: 9 -# Cop supports --auto-correct. -# Configuration parameters: AllowMultipleReturnValues. -Style/RedundantReturn: - Exclude: - - 'app/helpers/application_helper.rb' - - 'app/helpers/format_helper.rb' - - 'app/helpers/paths_helper.rb' - - 'app/helpers/users_helper.rb' - # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. @@ -662,7 +683,7 @@ Style/StringLiteralsInInterpolation: Exclude: - 'lib/tasks/dump_db.rake' -# Offense count: 73 +# Offense count: 79 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, MinSize, SupportedStyles. # SupportedStyles: percent, brackets @@ -701,17 +722,3 @@ Style/TrailingCommaInLiteral: - 'Guardfile' - 'db/migrate/20140701123203_add_events_per_week_to_conference.rb' - 'spec/models/conference_spec.rb' - -# Offense count: 3 -# Cop supports --auto-correct. -Style/UnneededInterpolation: - Exclude: - - 'app/helpers/format_helper.rb' - - 'spec/controllers/admin/conferences_controller_spec.rb' - -# Offense count: 2 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: snake_case, normalcase, non_integer -Style/VariableNumber: - Exclude: - - 'spec/models/ticket_purchase_spec.rb' diff --git a/.travis.yml b/.travis.yml index 6650fbf9..88c50189 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_script: - cp config/database.yml.travis config/database.yml - cp config/secrets.yml.example config/secrets.yml - mysql -u root -e 'create database osem_test;' - - RAILS_ENV=test bundle exec rake db:migrate --trace + - RAILS_ENV=test bundle exec rake db:schema:load --trace script: - "./travis_script.sh $TEST_SUITE" env: diff --git a/Dockerfile b/Dockerfile index dab432ca..4cc5c04c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,12 @@ RUN cd /usr/bin && \ tar -xf dockerize.tar.gz && \ rm dockerize.tar.gz +# dumb-init for a proper PID 1 +RUN cd /tmp && \ + wget https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_1.2.0_amd64.deb && \ + rm dumb-init_1.2.0_amd64.deb + # explicitly add Gemfile and install dependencies using bundler to make use of # Docker's caching WORKDIR /osem/ @@ -25,12 +31,13 @@ RUN bundle install --without test development # add OSEM files and prepare them for use inside a Docker container COPY . /osem/ -RUN chown osem.osem /osem/ -R && \ +RUN chown -R osem.root /osem/ && \ + chmod -R g=u /osem/ && \ mv /osem/config/database.yml.docker /osem/config/database.yml # data directory is used to cache the secret key in a file ENV DATA_DIR /data -RUN install -d -m 0700 -o osem $DATA_DIR +RUN install -d -m 0770 -o osem -g root $DATA_DIR VOLUME ["$DATA_DIR"] USER osem @@ -42,4 +49,7 @@ COPY docker/init.sh /init.sh # from a webserver ENV RAILS_SERVE_STATIC_FILES 1 +# Runs "/usr/bin/dumb-init -- /my/script --with --args" +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + CMD ["bash", "/init.sh"] diff --git a/Gemfile b/Gemfile index 7f25aa46..79bbdb3f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,10 @@ if Gem::Version.new(Bundler::VERSION) < Gem::Version.new('1.8.4') end # as web framework -gem 'rails', '~> 4.2.8' +gem 'rails', '~> 5.0.5' + +# Use Puma as the app server +gem 'puma', '~> 3.0' # enables serving assets in production and setting your logger to standard out # both of which are required to run an application on a twelve-factor provider @@ -27,11 +30,11 @@ gem 'paper_trail' # for upload management gem 'carrierwave' -gem 'mini_magick' gem 'carrierwave-bombshelter' +gem 'mini_magick' # for internationalizing -gem 'rails-i18n', '~> 4.0.0' +gem 'rails-i18n', '~> 5.0.0' # as authentification framework gem 'devise' @@ -40,12 +43,15 @@ gem 'devise_ichain_authenticatable' # for openID authentication gem 'omniauth' gem 'omniauth-facebook' -gem 'omniauth-openid' -gem 'omniauth-google-oauth2' gem 'omniauth-github' +gem 'omniauth-google-oauth2' +gem 'omniauth-openid' + +# Bot-filtering +gem 'recaptcha', require: 'recaptcha/rails' # as authorization framework -gem 'cancancan' +gem 'cancancan', '~> 2.0' # for roles gem 'rolify' @@ -57,8 +63,8 @@ gem 'unobtrusive_flash', '>=3' gem 'transitions', :require => %w( transitions active_record/transitions ) # for comments -gem 'awesome_nested_set', '~> 3.1.3' gem 'acts_as_commentable_with_threading' +gem 'awesome_nested_set', '~> 3.1.3' # as templating language gem 'haml-rails' @@ -70,11 +76,11 @@ gem 'sass-rails', '>= 4.0.2' gem 'uglifier', '>= 1.3.0' # as the front-end framework -gem 'bootstrap-sass', '~> 3.3.4.1' gem 'autoprefixer-rails' -gem 'formtastic-bootstrap' -gem 'formtastic', '~> 3.1.1' +gem 'bootstrap-sass', '~> 3.3.4.1' gem 'cocoon' +gem 'formtastic', '~> 3.1.5' +gem 'formtastic-bootstrap' # as the JavaScript library gem 'jquery-rails' @@ -105,8 +111,8 @@ source 'https://rails-assets.org' do gem 'rails-assets-waypoints' # for markdown editors gem 'rails-assets-bootstrap-markdown' - gem 'rails-assets-to-markdown' gem 'rails-assets-markdown' + gem 'rails-assets-to-markdown' end # as date picker @@ -126,9 +132,9 @@ gem 'gravtastic' gem 'country_select' # as PDF generator +gem 'prawn-qrcode', '~> 0.2.2.1' gem 'prawn_rails' gem 'rqrcode' -gem 'prawn-qrcode', '~> 0.2.2.1' # to render XLS spreadsheets gem 'axlsx', git: 'https://github.com/randym/axlsx.git' @@ -154,12 +160,11 @@ gem 'rdoc-generator-fivefish' # for visitor tracking gem 'ahoy_matey' -gem 'activeuuid' gem 'piwik_analytics', '~> 1.0.1' # for recurring jobs -gem 'whenever', :require => false gem 'delayed_job_active_record' +gem 'whenever', :require => false # to run scripts gem 'daemons' @@ -182,6 +187,10 @@ gem 'cloudinary' # for setting app configuration in the environment gem 'dotenv-rails' +# configurable toggles for functionality +# https://github.com/mgsnova/feature +gem 'feature' + # For countable.js gem "countable-rails", "~> 0.0.1" @@ -200,14 +209,19 @@ gem 'sprockets-rails' # for multiple speakers select on proposal/event forms gem 'selectize-rails' +# Nokogiri < 1.8.1 is subject to: +# CVE-2017-0663, CVE-2017-7375, CVE-2017-7376, CVE-2017-9047, CVE-2017-9048, +# CVE-2017-9049, CVE-2017-9050 +gem 'nokogiri', '>= 1.8.1' + # Use guard and spring for testing in development group :development do # to launch specs when files are modified gem 'guard-rspec' - gem 'spring-commands-rspec' gem 'haml_lint', '~> 0.24.0' + gem 'spring-commands-rspec' # for static code analisys - gem 'rubocop', '~> 0.49.0', require: false + gem 'rubocop', '~> 0.51.0', require: false # as database gem 'sqlite3' # to open mails @@ -222,11 +236,11 @@ end group :test do # as test framework - gem 'rspec-rails', '~> 3.5', '>= 3.5.2' - gem 'database_cleaner' gem 'capybara' - gem 'poltergeist' + gem 'database_cleaner' gem 'phantomjs', :require => 'phantomjs/poltergeist' + gem 'poltergeist' + gem 'rspec-rails', '~> 3.5', '>= 3.5.2' # for measuring test coverage gem 'coveralls', require: false # for describing models @@ -241,6 +255,8 @@ group :test do gem 'stripe-ruby-mock' # For validating JSON schemas gem 'json-schema' + # For using 'assigns' in tests + gem 'rails-controller-testing' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index c6b4faa8..1023f255 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,62 +12,65 @@ GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: - actionmailer (4.2.9) - actionpack (= 4.2.9) - actionview (= 4.2.9) - activejob (= 4.2.9) + actioncable (5.0.5) + actionpack (= 5.0.5) + nio4r (>= 1.2, < 3.0) + websocket-driver (~> 0.6.1) + actionmailer (5.0.5) + actionpack (= 5.0.5) + actionview (= 5.0.5) + activejob (= 5.0.5) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.9) - actionview (= 4.2.9) - activesupport (= 4.2.9) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.0.5) + actionview (= 5.0.5) + activesupport (= 5.0.5) + rack (~> 2.0) + rack-test (~> 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.9) - activesupport (= 4.2.9) + actionview (5.0.5) + activesupport (= 5.0.5) builder (~> 3.1) erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) active_model_serializers (0.9.4) activemodel (>= 3.2) - activejob (4.2.9) - activesupport (= 4.2.9) - globalid (>= 0.3.0) - activemodel (4.2.9) - activesupport (= 4.2.9) - builder (~> 3.1) - activerecord (4.2.9) - activemodel (= 4.2.9) - activesupport (= 4.2.9) - arel (~> 6.0) - activesupport (4.2.9) + activejob (5.0.5) + activesupport (= 5.0.5) + globalid (>= 0.3.6) + activemodel (5.0.5) + activesupport (= 5.0.5) + activerecord (5.0.5) + activemodel (= 5.0.5) + activesupport (= 5.0.5) + arel (~> 7.0) + activesupport (5.0.5) + concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - activeuuid (0.6.1) - activerecord (>= 3.1) - uuidtools acts_as_commentable_with_threading (1.2.0) activerecord (>= 3.0) activesupport (>= 3.0) awesome_nested_set (>= 2.0) - acts_as_list (0.4.0) + acts_as_list (0.9.7) activerecord (>= 3.0) addressable (2.5.1) public_suffix (~> 2.0, >= 2.0.2) - ahoy_matey (1.0.0) + ahoy_matey (1.6.0) addressable - browser (>= 0.4.0) + browser (~> 2.0) geocoder - referer-parser + rack-attack (< 6) + railties + referer-parser (>= 0.3.0) request_store + safely_block (>= 0.1.1) user_agent_parser uuidtools - arel (6.0.4) + arel (7.1.4) ast (2.3.0) autoprefixer-rails (7.1.1) execjs @@ -86,10 +89,10 @@ GEM bootstrap-switch-rails (3.0.2) bootstrap3-datetimepicker-rails (3.0.3) momentjs-rails (>= 2.8.1) - browser (0.6.0) + browser (2.5.1) builder (3.2.3) byebug (9.0.6) - cancancan (1.13.1) + cancancan (2.0.0) capybara (2.6.2) addressable mime-types (>= 1.16) @@ -144,7 +147,7 @@ GEM daemons (1.1.9) dante (0.2.0) database_cleaner (1.3.0) - debug_inspector (0.0.2) + debug_inspector (0.0.3) delayed_job (4.1.3) activesupport (>= 3.0, < 5.2) delayed_job_active_record (4.1.2) @@ -166,6 +169,7 @@ GEM dotenv-rails (2.2.1) dotenv (= 2.2.1) railties (>= 3.2, < 5.2) + errbase (0.0.3) erubis (2.7.0) execjs (2.6.0) factory_girl (4.5.0) @@ -179,15 +183,16 @@ GEM multipart-post (>= 1.2, < 3) fastimage (2.0.0) addressable (~> 2) + feature (1.4.0) ffi (1.9.18) font-awesome-rails (4.7.0.2) railties (>= 3.2, < 5.2) formatador (0.2.5) - formtastic (3.1.3) + formtastic (3.1.5) actionpack (>= 3.2.13) formtastic-bootstrap (3.1.1) formtastic (>= 3.0) - geocoder (1.2.2) + geocoder (1.4.4) globalid (0.4.0) activesupport (>= 4.2.0) gravtastic (3.2.6) @@ -270,7 +275,7 @@ GEM open4 (~> 1.3.4) rake mini_magick (4.5.1) - mini_portile2 (2.2.0) + mini_portile2 (2.3.0) minitest (5.10.2) momentjs-rails (2.8.1) railties (>= 3.1) @@ -290,8 +295,9 @@ GEM mysql2 (0.4.9) nenv (0.3.0) netrc (0.11.0) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) + nio4r (2.1.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) @@ -324,9 +330,9 @@ GEM activerecord (>= 3.0, < 6.0) activesupport (>= 3.0, < 6.0) request_store (~> 1.1) - parallel (1.11.2) - parser (2.4.0.0) - ast (~> 2.2) + parallel (1.12.0) + parser (2.4.0.2) + ast (~> 2.3) pdf-core (0.2.5) phantomjs (2.1.1.0) piwik_analytics (1.0.2) @@ -353,23 +359,27 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) public_suffix (2.0.5) - rack (1.6.8) + puma (3.10.0) + rack (2.0.3) + rack-attack (5.0.1) + rack rack-openid (1.3.1) rack (>= 1.1.0) ruby-openid (>= 2.1.8) rack-test (0.6.3) rack (>= 1.0) - rails (4.2.9) - actionmailer (= 4.2.9) - actionpack (= 4.2.9) - actionview (= 4.2.9) - activejob (= 4.2.9) - activemodel (= 4.2.9) - activerecord (= 4.2.9) - activesupport (= 4.2.9) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.9) - sprockets-rails + rails (5.0.5) + actioncable (= 5.0.5) + actionmailer (= 5.0.5) + actionpack (= 5.0.5) + actionview (= 5.0.5) + activejob (= 5.0.5) + activemodel (= 5.0.5) + activerecord (= 5.0.5) + activesupport (= 5.0.5) + bundler (>= 1.3.0) + railties (= 5.0.5) + sprockets-rails (>= 2.0.0) rails-assets-bootstrap (3.3.6) rails-assets-jquery (>= 1.9.1, < 3) rails-assets-bootstrap-markdown (2.10.0) @@ -387,30 +397,32 @@ GEM rails-assets-to-markdown (1.3.0) rails-assets-trianglify (0.4.0) rails-assets-waypoints (4.0.0) - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.8) - activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - rails-i18n (4.0.8) + rails-i18n (5.0.4) i18n (~> 0.7) - railties (~> 4.0) + railties (~> 5.0) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging rails_serve_static_assets (0.0.4) rails_stdout_logging (0.0.3) - railties (4.2.9) - actionpack (= 4.2.9) - activesupport (= 4.2.9) + railties (5.0.5) + actionpack (= 5.0.5) + activesupport (= 5.0.5) + method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.2.2) rake - rake (12.0.0) + rake (12.3.0) rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) @@ -420,8 +432,10 @@ GEM loggability (~> 0.12) rdoc (~> 5.0) yajl-ruby (~> 1.3) + recaptcha (4.6.2) + json redcarpet (3.2.3) - referer-parser (0.2.1) + referer-parser (0.3.0) request_store (1.1.0) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) @@ -458,19 +472,21 @@ GEM rspec-mocks (~> 3.6.0) rspec-support (~> 3.6.0) rspec-support (3.6.0) - rubocop (0.49.1) + rubocop (0.51.0) parallel (~> 1.10) parser (>= 2.3.3.1, < 3.0) powerpack (~> 0.1) - rainbow (>= 1.99.1, < 3.0) + rainbow (>= 2.2.2, < 3.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) ruby-oembed (0.8.14) ruby-openid (2.5.0) - ruby-progressbar (1.8.1) + ruby-progressbar (1.9.0) ruby_dep (1.5.0) rubyzip (1.2.1) safe_yaml (1.0.4) + safely_block (0.2.0) + errbase sass (3.2.19) sass-rails (5.0.6) railties (>= 4.0.0, < 6) @@ -497,10 +513,10 @@ GEM sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (2.3.3) - actionpack (>= 3.0) - activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) sqlite3 (1.3.9) stripe (1.43.0) rest-client (~> 1.4) @@ -531,11 +547,11 @@ GEM unicode_utils (1.4.0) unobtrusive_flash (3.1.0) railties - user_agent_parser (2.1.5) + user_agent_parser (2.4.0) uuidtools (2.1.5) warden (1.2.4) rack (>= 1.0) - web-console (2.2.1) + web-console (2.3.0) activemodel (>= 4.0) binding_of_caller (>= 0.7.2) railties (>= 4.0) @@ -552,14 +568,13 @@ GEM chronic (>= 0.6.3) xpath (2.0.0) nokogiri (~> 1.3) - yajl-ruby (1.3.0) + yajl-ruby (1.3.1) PLATFORMS ruby DEPENDENCIES active_model_serializers - activeuuid acts_as_commentable_with_threading acts_as_list ahoy_matey @@ -571,7 +586,7 @@ DEPENDENCIES bootstrap-switch-rails (~> 3.0.0) bootstrap3-datetimepicker-rails (~> 3.0.2) byebug - cancancan + cancancan (~> 2.0) capybara carrierwave carrierwave-bombshelter @@ -589,8 +604,9 @@ DEPENDENCIES dotenv-rails factory_girl_rails faker + feature font-awesome-rails - formtastic (~> 3.1.1) + formtastic (~> 3.1.5) formtastic-bootstrap gravtastic guard-rspec @@ -609,6 +625,7 @@ DEPENDENCIES mini_magick money-rails mysql2 + nokogiri (>= 1.8.1) omniauth omniauth-facebook omniauth-github @@ -620,7 +637,8 @@ DEPENDENCIES poltergeist prawn-qrcode (~> 0.2.2.1) prawn_rails - rails (~> 4.2.8) + puma (~> 3.0) + rails (~> 5.0.5) rails-assets-bootstrap-markdown! rails-assets-date.format! rails-assets-holderjs! @@ -632,16 +650,18 @@ DEPENDENCIES rails-assets-to-markdown! rails-assets-trianglify! rails-assets-waypoints! - rails-i18n (~> 4.0.0) + rails-controller-testing + rails-i18n (~> 5.0.0) rails_12factor rdoc-generator-fivefish + recaptcha redcarpet responders (~> 2.0) rolify rqrcode rspec-activemodel-mocks rspec-rails (~> 3.5, >= 3.5.2) - rubocop (~> 0.49.0) + rubocop (~> 0.51.0) ruby-oembed sass-rails (>= 4.0.2) selectize-rails @@ -662,4 +682,4 @@ DEPENDENCIES whenever BUNDLED WITH - 1.15.1 + 1.16.0 diff --git a/INSTALL.md b/INSTALL.md index 29dc5cec..ea47fd93 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -42,7 +42,7 @@ There are two configurations to deploy OSEM with Docker: *evaluation mode* and * If you want to evaluate OSEM to see if it fits your needs, the default configuration in `docker-compose.env` will work perfectly fine for you. For convenience reasons, `docker-compose.yml` already contains a [MailHog](https://github.com/mailhog/MailHog) service configuration. MailHog -is going to catch every email sent by OSEM and displays them on a special web service. Thus, it eliminitates the need to set up an SMTP server just to try out OSEM. +is going to catch every email sent by OSEM and displays them on a special web service. Thus, it eliminates the need to set up an SMTP server just to try out OSEM. Just point your browser to http://localhost:8025 to get access to registration confirmation links etc. Run `docker-compose up --build` to start the services. On first run, it will take a few minutes to initialize the database. Thus, wait a few minutes before you open up @@ -105,6 +105,7 @@ There are a couple of environment variables you can set to configure OSEM. Check | CLOUDINARY_URL | *string* | Configure your cloudinary.com cloud name and api key/secret | STRIPE_PUBLISHABLE_KEY | *string* | Publishable Key for Stripe Gateway | STRIPE_SECRET_KEY | *string* | Secret Key for Stripe Gateway +| OSEM_REDIS_URL | *string* | Redis server URL e.g. redis://localhost:6379/1 ### Online Ticket Payments We use [Stripe](https://stripe.com) for accepting your ticket payments securely over the web. diff --git a/app/assets/javascripts/osem-datepickers.js b/app/assets/javascripts/osem-datepickers.js index ff0b6860..84533b49 100644 --- a/app/assets/javascripts/osem-datepickers.js +++ b/app/assets/javascripts/osem-datepickers.js @@ -79,11 +79,23 @@ $(function () { $("#conference-start-datepicker").on("dp.change",function (e) { $('#conference-end-datepicker').data("DateTimePicker").setMinDate(e.date); + if (!$('#conference-end-datepicker').val()) { + $('#conference-end-datepicker').data("DateTimePicker").setDate(e.date); + } }); + + $("#conference-start-datepicker").change(function (e) { + $('#conference-start-datepicker').val()?$('#conference-end-datepicker').data("DateTimePicker").setMinDate(e.date):$('#conference-end-datepicker').data("DateTimePicker").setMinDate(null); + }); + $("#conference-end-datepicker").on("dp.change",function (e) { $('#conference-start-datepicker').data("DateTimePicker").setMaxDate(e.date); }); + $("#conference-end-datepicker").change(function (e) { + $('#conference-end-datepicker').val()?$('#conference-start-datepicker').data("DateTimePicker").setMaxDate(e.date):$('#conference-start-datepicker').data("DateTimePicker").setMaxDate(null); + }); + $("#registration-period-start-datepicker").on("dp.change",function (e) { $('#registration-period-end-datepicker').data("DateTimePicker").setMinDate(e.date); }); diff --git a/app/assets/javascripts/osem-tickets.js b/app/assets/javascripts/osem-tickets.js index 51881055..3f559c38 100644 --- a/app/assets/javascripts/osem-tickets.js +++ b/app/assets/javascripts/osem-tickets.js @@ -11,7 +11,7 @@ function update_price($this){ $('.total_row').each(function( index ) { total += parseFloat($(this).text()); }); - $('#total_price').text(total); + $('#total_price').text(total.toFixed(2)); } $( document ).ready(function() { diff --git a/app/assets/stylesheets/osem.css.scss b/app/assets/stylesheets/osem.css.scss index 79768c5d..bbcabc44 100644 --- a/app/assets/stylesheets/osem.css.scss +++ b/app/assets/stylesheets/osem.css.scss @@ -1,3 +1,5 @@ +@import "bootstrap/mixins"; + html { position: relative; min-height: 100%; @@ -104,3 +106,12 @@ p.comment-body { .qr-image{ margin-left: 120px; } + +.g-recaptcha { + @include clearfix; + padding-bottom: 12px; + + div { + float: right; + } +} diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 631dd4d8..ab9719bd 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -1,6 +1,6 @@ module Admin class BaseController < ApplicationController - before_filter :verify_user_admin + before_action :verify_user_admin private diff --git a/app/controllers/admin/booths_controller.rb b/app/controllers/admin/booths_controller.rb index 102eb10b..e41d11d3 100644 --- a/app/controllers/admin/booths_controller.rb +++ b/app/controllers/admin/booths_controller.rb @@ -3,7 +3,24 @@ module Admin load_and_authorize_resource :conference, find_by: :short_title load_and_authorize_resource through: :conference - def index; end + def index + @file_name = "booths_for_#{@conference.short_title}" + @booth_export_option = params[:booth_export_option] + respond_to do |format| + format.html + # Explicity call #to_json to avoid the use of EventSerializer + format.json { render json: Booth.where(state: :confirmed, program: @program).to_json } + format.xlsx do + response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.xlsx\"" + render 'booths' + end + format.pdf { render 'booths' } + format.csv do + response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.csv\"" + render 'booths' + end + end + end def show; end diff --git a/app/controllers/admin/cfps_controller.rb b/app/controllers/admin/cfps_controller.rb index da2723b7..18b493eb 100644 --- a/app/controllers/admin/cfps_controller.rb +++ b/app/controllers/admin/cfps_controller.rb @@ -55,7 +55,7 @@ module Admin private def cfp_params - params.require(:cfp).permit(:start_date, :end_date, :cfp_type) + params.require(:cfp).permit(:start_date, :end_date, :description, :cfp_type) end end end diff --git a/app/controllers/admin/conferences_controller.rb b/app/controllers/admin/conferences_controller.rb index d8c101d1..8f8f2959 100644 --- a/app/controllers/admin/conferences_controller.rb +++ b/app/controllers/admin/conferences_controller.rb @@ -193,6 +193,7 @@ module Admin def edit @conferences = Conference.all @date_string = date_string(@conference.start_date, @conference.end_date) + @affected_event_count = @conference.program.events.scheduled(@conference.program.selected_schedule_id).count respond_to do |format| format.html format.json { render json: @conference.to_json } diff --git a/app/controllers/admin/registrations_controller.rb b/app/controllers/admin/registrations_controller.rb index 2afb8f6a..475c18c8 100644 --- a/app/controllers/admin/registrations_controller.rb +++ b/app/controllers/admin/registrations_controller.rb @@ -2,7 +2,7 @@ module Admin class RegistrationsController < Admin::BaseController load_and_authorize_resource :conference, find_by: :short_title load_and_authorize_resource :registration, through: :conference - before_filter :set_user, except: [:index] + before_action :set_user, except: [:index] def index authorize! :show, Registration.new(conference_id: @conference.id) diff --git a/app/controllers/admin/tracks_controller.rb b/app/controllers/admin/tracks_controller.rb index 7352ee35..4692f9a1 100644 --- a/app/controllers/admin/tracks_controller.rb +++ b/app/controllers/admin/tracks_controller.rb @@ -7,7 +7,25 @@ module Admin # Show flash message with ajax calls after_action :prepare_unobtrusive_flash, only: :toggle_cfp_inclusion - def index; end + def index + @file_name = "tracks_for_#{@conference.short_title}" + @track_export_option = params[:track_export_option] + + respond_to do |format| + format.html + # Explicity call #to_json to avoid the use of EventSerializer + format.json { render json: Track.where(state: :confirmed, program: @program).to_json } + format.xlsx do + response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.xlsx\"" + render 'tracks' + end + format.pdf { render 'tracks' } + format.csv do + response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.csv\"" + render 'tracks' + end + end + end def show respond_to do |format| diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f1a31894..7421a0f0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,10 +1,10 @@ class ApplicationController < ActionController::Base - before_filter :set_paper_trail_whodunnit + before_action :set_paper_trail_whodunnit include ApplicationHelper add_flash_types :error - protect_from_forgery with: :exception - before_filter :get_conferences - before_filter :store_location + protect_from_forgery with: :exception, prepend: true + before_action :get_conferences + before_action :store_location # Ensure every controller authorizes resource or skips authorization (skip_authorization_check) check_authorization unless: :devise_controller? diff --git a/app/controllers/conference_registrations_controller.rb b/app/controllers/conference_registrations_controller.rb index c2037318..f2751a31 100644 --- a/app/controllers/conference_registrations_controller.rb +++ b/app/controllers/conference_registrations_controller.rb @@ -1,5 +1,5 @@ class ConferenceRegistrationsController < ApplicationController - before_filter :authenticate_user!, except: [:new, :create] + before_action :authenticate_user!, except: [:new, :create] load_resource :conference, find_by: :short_title authorize_resource :conference_registrations, class: Registration, except: [:new, :create] before_action :set_registration, only: [:edit, :update, :destroy, :show] @@ -27,8 +27,9 @@ class ConferenceRegistrationsController < ApplicationController end def show - @total_price = Ticket.total_price(@conference, current_user, paid: true) + @total_price = Ticket.total_price_user(@conference, current_user, paid: true) @tickets = current_user.ticket_purchases.by_conference(@conference).paid + @total_price_per_ticket = @tickets.group(:ticket_id).sum('amount_paid * quantity') @ticket_payments = @tickets.group_by(&:ticket_id) @total_quantity = @tickets.group(:ticket_id).sum(:quantity) end diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 3d549dfa..2ebbdeeb 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -4,4 +4,10 @@ class OrganizationsController < ApplicationController def index @organizations = Organization.all end + + def conferences + @current = @organization.conferences.upcoming.reorder(start_date: :asc) + @antiquated = @organization.conferences.past + render '/conferences/index' + end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index e141084c..e020d217 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,5 +1,5 @@ class RegistrationsController < Devise::RegistrationsController - before_action :configure_permitted_parameters, if: :devise_controller? + prepend_before_action :check_captcha, only: [:create] def edit @openids = Openid.where(user_id: current_user.id).order(:provider) @@ -21,14 +21,34 @@ class RegistrationsController < Devise::RegistrationsController edit_user_registration_path(resource) end - def configure_permitted_parameters - devise_parameter_sanitizer.permit(:account_update) do |u| - u - .permit(:email, :password, :password_confirmation, :current_password, :username, :email_public) - end - devise_parameter_sanitizer.permit(:sign_up) do |u| - u - .permit(:email, :password, :password_confirmation, :name, :username) + private + + def sign_up_params + params.require(:user).permit( + :email, + :password, + :password_confirmation, + :name, + :username + ) + end + + def account_update_params + params.require(:user).permit( + :email, + :password, + :password_confirmation, + :current_password, + :username, + :email_public + ) + end + + def check_captcha + unless Feature.inactive?(:recaptcha) || verify_recaptcha + self.resource = resource_class.new sign_up_params + resource.validate # Look for any other validation errors besides Recaptcha + respond_with_navigational(resource) { render :new } end end end diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb index 76d5c74a..d5111835 100644 --- a/app/controllers/subscriptions_controller.rb +++ b/app/controllers/subscriptions_controller.rb @@ -1,5 +1,5 @@ class SubscriptionsController < ApplicationController - before_filter :authenticate_user! + before_action :authenticate_user! load_resource :conference, find_by: :short_title load_and_authorize_resource only: [:create, :destroy], through: :conference diff --git a/app/controllers/ticket_purchases_controller.rb b/app/controllers/ticket_purchases_controller.rb index 3eb8b68d..dbf4755e 100644 --- a/app/controllers/ticket_purchases_controller.rb +++ b/app/controllers/ticket_purchases_controller.rb @@ -1,5 +1,5 @@ class TicketPurchasesController < ApplicationController - before_filter :authenticate_user! + before_action :authenticate_user! load_resource :conference, find_by: :short_title authorize_resource :conference_registrations, class: Registration authorize_resource diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 55c73fc0..94893c27 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -1,9 +1,9 @@ class TicketsController < ApplicationController - before_filter :authenticate_user! + before_action :authenticate_user! load_resource :conference, find_by: :short_title load_resource :ticket, through: :conference authorize_resource :conference_registrations, class: Registration - before_filter :check_load_resource, only: :index + before_action :check_load_resource, only: :index def index; end diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index cf6eb6a8..ed7ce011 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -11,13 +11,13 @@ module Users def handle(provider) auth_hash = request.env['omniauth.auth'] - uid = auth_hash[:uid] + username = auth_hash.info.email.split('@')[0] openid = Openid.find_for_oauth(auth_hash) # Get or create openid # If openid exists and is associated with a user, sign in with associated user, # even if the email of the associated user and the email of the provided openid are different unless (user = openid.user) user = User.find_for_auth(auth_hash, current_user) # Get or create users - user.username = "#{uid}@#{provider}" if user.username.blank? + user.username = "#{username}@#{provider}" if user.username.blank? end begin diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6174500e..b1e249ba 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -66,7 +66,7 @@ module ApplicationHelper else ts = all.join end - return ts + ts end def difficulty_levels(conference) @@ -80,7 +80,7 @@ module ApplicationHelper else ts = all.join end - return ts + ts end def unread_notifications(user) @@ -163,6 +163,12 @@ module ApplicationHelper end end + def rescheduling_hint(affected_event_count) + if affected_event_count > 0 + "You have #{affected_event_count} scheduled #{'event'.pluralize(affected_event_count)}. Changing the conference hours will unschedule those scheduled outside the conference hours." + end + end + ## # ====Gets # a conference object @@ -171,4 +177,18 @@ module ApplicationHelper def hidden_if_conference_over(conference) 'hidden' if Date.today > conference.end_date end + + def nav_root_link_for(conference) + link_text = ( + conference.try(:organization).try(:name) || + ENV['OSEM_NAME'] || + 'OSEM' + ) + link_to( + link_text, + root_path, + class: 'navbar-brand', + title: 'Open Source Event Manager' + ) + end end diff --git a/app/helpers/format_helper.rb b/app/helpers/format_helper.rb index 65578ba6..a41c584e 100644 --- a/app/helpers/format_helper.rb +++ b/app/helpers/format_helper.rb @@ -101,17 +101,17 @@ module FormatHelper def icon_for_todo(bool) if bool - return 'fa fa-check' + 'fa fa-check' else - return 'fa fa-times' + 'fa fa-times' end end def class_for_todo(bool) if bool - return 'todolist-ok' + 'todolist-ok' else - return 'todolist-missing' + 'todolist-missing' end end @@ -122,7 +122,7 @@ module FormatHelper plural || singular.pluralize end - "#{word}" + word end # Returns black or white deppending on what of them contrast more with the diff --git a/app/helpers/paths_helper.rb b/app/helpers/paths_helper.rb index df01ab2f..46e82900 100644 --- a/app/helpers/paths_helper.rb +++ b/app/helpers/paths_helper.rb @@ -5,9 +5,9 @@ module PathsHelper def active_nav_li(link) if current_page?(link) - return 'active' + 'active' else - return '' + '' end end end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 50becf0c..763a44c9 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -18,7 +18,7 @@ module UsersHelper providers << provider if !ENV["OSEM_#{provider.upcase}_KEY"].blank? && !ENV["OSEM_#{provider.upcase}_SECRET"].blank? end - return providers.uniq + providers.uniq end # Receives a hash, generated from User model, function get_roles diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 00000000..a009ace5 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/app/jobs/conference_cfp_update_mail_job.rb b/app/jobs/conference_cfp_update_mail_job.rb index f732c068..7138bd59 100644 --- a/app/jobs/conference_cfp_update_mail_job.rb +++ b/app/jobs/conference_cfp_update_mail_job.rb @@ -1,4 +1,4 @@ -class ConferenceCfpUpdateMailJob < ActiveJob::Base +class ConferenceCfpUpdateMailJob < ApplicationJob queue_as :default def perform(conference) diff --git a/app/jobs/conference_date_update_mail_job.rb b/app/jobs/conference_date_update_mail_job.rb index e8eeae12..4218d22f 100644 --- a/app/jobs/conference_date_update_mail_job.rb +++ b/app/jobs/conference_date_update_mail_job.rb @@ -1,4 +1,4 @@ -class ConferenceDateUpdateMailJob < ActiveJob::Base +class ConferenceDateUpdateMailJob < ApplicationJob queue_as :default def perform(conference) diff --git a/app/jobs/conference_registration_date_update_mail_job.rb b/app/jobs/conference_registration_date_update_mail_job.rb index 9015d8af..ed7ee084 100644 --- a/app/jobs/conference_registration_date_update_mail_job.rb +++ b/app/jobs/conference_registration_date_update_mail_job.rb @@ -1,4 +1,4 @@ -class ConferenceRegistrationDateUpdateMailJob < ActiveJob::Base +class ConferenceRegistrationDateUpdateMailJob < ApplicationJob queue_as :default def perform(conference) diff --git a/app/jobs/conference_schedule_update_mail_job.rb b/app/jobs/conference_schedule_update_mail_job.rb index a6c73eca..02d03352 100644 --- a/app/jobs/conference_schedule_update_mail_job.rb +++ b/app/jobs/conference_schedule_update_mail_job.rb @@ -1,4 +1,4 @@ -class ConferenceScheduleUpdateMailJob < ActiveJob::Base +class ConferenceScheduleUpdateMailJob < ApplicationJob queue_as :default def perform(conference) diff --git a/app/jobs/conference_venue_update_mail_job.rb b/app/jobs/conference_venue_update_mail_job.rb index 2aa960d1..30203639 100644 --- a/app/jobs/conference_venue_update_mail_job.rb +++ b/app/jobs/conference_venue_update_mail_job.rb @@ -1,4 +1,4 @@ -class ConferenceVenueUpdateMailJob < ActiveJob::Base +class ConferenceVenueUpdateMailJob < ApplicationJob queue_as :default def perform(conference) diff --git a/app/jobs/event_comment_mail_job.rb b/app/jobs/event_comment_mail_job.rb index 28564a1d..36bc9294 100644 --- a/app/jobs/event_comment_mail_job.rb +++ b/app/jobs/event_comment_mail_job.rb @@ -1,4 +1,4 @@ -class EventCommentMailJob < ActiveJob::Base +class EventCommentMailJob < ApplicationJob queue_as :default def perform(comment) diff --git a/app/models/ability.rb b/app/models/ability.rb index 04f56e51..018df0f7 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -15,7 +15,7 @@ class Ability # Abilities for not signed in users (guests) def not_signed_in - can [:index], Organization + can [:index, :conferences], Organization can [:index], Conference can [:show], Conference do |conference| conference.splashpage && conference.splashpage.public == true diff --git a/app/models/ahoy/event.rb b/app/models/ahoy/event.rb index a70e7e41..74758c47 100644 --- a/app/models/ahoy/event.rb +++ b/app/models/ahoy/event.rb @@ -1,5 +1,5 @@ module Ahoy - class Event < ActiveRecord::Base + class Event < ApplicationRecord self.table_name = 'ahoy_events' belongs_to :visit diff --git a/app/models/answer.rb b/app/models/answer.rb index 31dee54b..6d1bca3c 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -1,4 +1,4 @@ -class Answer < ActiveRecord::Base +class Answer < ApplicationRecord has_many :qanswers has_many :questions, through: :qanswers diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 00000000..10a4cba8 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/booth.rb b/app/models/booth.rb index 4e42d839..e64a230a 100644 --- a/app/models/booth.rb +++ b/app/models/booth.rb @@ -1,4 +1,4 @@ -class Booth < ActiveRecord::Base +class Booth < ApplicationRecord include ActiveRecord::Transitions has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/booth_request.rb b/app/models/booth_request.rb index 438b4167..f57c712e 100644 --- a/app/models/booth_request.rb +++ b/app/models/booth_request.rb @@ -1,4 +1,4 @@ -class BoothRequest < ActiveRecord::Base +class BoothRequest < ApplicationRecord belongs_to :booth belongs_to :user diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 28cddbbd..103274a0 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -1,4 +1,4 @@ -class Campaign < ActiveRecord::Base +class Campaign < ApplicationRecord validates :name, :utm_campaign, presence: true has_many :targets, dependent: :nullify diff --git a/app/models/cfp.rb b/app/models/cfp.rb index 17b37809..5105a6bd 100644 --- a/app/models/cfp.rb +++ b/app/models/cfp.rb @@ -1,6 +1,6 @@ # cannot delete program if there are events submitted -class Cfp < ActiveRecord::Base +class Cfp < ApplicationRecord TYPES = %w(events booths tracks).freeze has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/comment.rb b/app/models/comment.rb index 4bb90719..535eea57 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,4 @@ -class Comment < ActiveRecord::Base +class Comment < ApplicationRecord acts_as_nested_set scope: %i(commentable_id commentable_type) validates :body, presence: true validates :user, presence: true diff --git a/app/models/commercial.rb b/app/models/commercial.rb index a2245d07..0976fe44 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -1,4 +1,4 @@ -class Commercial < ActiveRecord::Base +class Commercial < ApplicationRecord require 'oembed' belongs_to :commercialable, polymorphic: true diff --git a/app/models/conference.rb b/app/models/conference.rb index 034e755b..b12137d8 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -1,4 +1,4 @@ -class Conference < ActiveRecord::Base +class Conference < ApplicationRecord include RevisionCount require 'uri' serialize :events_per_week, Hash @@ -496,7 +496,7 @@ class Conference < ActiveRecord::Base if tickets && ticket_purchases tickets.each do |ticket| result[ticket.title] = { - 'value' => ApplicationController.helpers.humanized_money(ticket.tickets_turnover).delete(',').to_i, + 'value' => ApplicationController.helpers.humanized_money(ticket.tickets_turnover_total(ticket.id)).delete(',').to_i, 'color' => "\##{Digest::MD5.hexdigest(ticket.title)[0..5]}" } end diff --git a/app/models/contact.rb b/app/models/contact.rb index 3f8216df..799c8748 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -1,4 +1,4 @@ -class Contact < ActiveRecord::Base +class Contact < ApplicationRecord has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id } belongs_to :conference diff --git a/app/models/difficulty_level.rb b/app/models/difficulty_level.rb index b5d971a7..e81ce026 100644 --- a/app/models/difficulty_level.rb +++ b/app/models/difficulty_level.rb @@ -1,4 +1,4 @@ -class DifficultyLevel < ActiveRecord::Base +class DifficultyLevel < ApplicationRecord belongs_to :program has_many :events, dependent: :nullify diff --git a/app/models/email_settings.rb b/app/models/email_settings.rb index 6210cf9d..2c593b96 100644 --- a/app/models/email_settings.rb +++ b/app/models/email_settings.rb @@ -1,4 +1,4 @@ -class EmailSettings < ActiveRecord::Base +class EmailSettings < ApplicationRecord belongs_to :conference has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/event.rb b/app/models/event.rb index c6de2d45..34c217f3 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,4 +1,4 @@ -class Event < ActiveRecord::Base +class Event < ApplicationRecord include ActiveRecord::Transitions include RevisionCount has_paper_trail on: [:create, :update], ignore: [:updated_at, :guid, :week], meta: { conference_id: :conference_id } @@ -204,11 +204,12 @@ class Event < ActiveRecord::Base end def speaker_names - result = Set.new - speakers.each do |speaker| - result.add(speaker.name) - end - result.to_a.to_sentence + speakers.map(&:name).join(', ') + end + + # Returns emails of all the speaker belongs to a particular event + def speaker_emails + speakers.map(&:email).join(', ') end ## diff --git a/app/models/event_schedule.rb b/app/models/event_schedule.rb index 57edbec0..cb5d1675 100644 --- a/app/models/event_schedule.rb +++ b/app/models/event_schedule.rb @@ -1,4 +1,4 @@ -class EventSchedule < ActiveRecord::Base +class EventSchedule < ApplicationRecord belongs_to :schedule belongs_to :event belongs_to :room diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 47da514f..8e4b4497 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -1,4 +1,4 @@ -class EventType < ActiveRecord::Base +class EventType < ApplicationRecord belongs_to :program has_many :events, dependent: :restrict_with_error diff --git a/app/models/event_user.rb b/app/models/event_user.rb index 70d9ca91..6feb9521 100644 --- a/app/models/event_user.rb +++ b/app/models/event_user.rb @@ -1,4 +1,4 @@ -class EventUser < ActiveRecord::Base +class EventUser < ApplicationRecord # TODO: Do we need these roles? ROLES = [%w[Speaker speaker], %w[Submitter submitter], %w[Moderator moderator]] diff --git a/app/models/events_registration.rb b/app/models/events_registration.rb index fcebd69f..6539064e 100644 --- a/app/models/events_registration.rb +++ b/app/models/events_registration.rb @@ -1,4 +1,4 @@ -class EventsRegistration < ActiveRecord::Base +class EventsRegistration < ApplicationRecord belongs_to :registration belongs_to :event diff --git a/app/models/lodging.rb b/app/models/lodging.rb index 21e4a8b0..50feaf41 100644 --- a/app/models/lodging.rb +++ b/app/models/lodging.rb @@ -1,4 +1,4 @@ -class Lodging < ActiveRecord::Base +class Lodging < ApplicationRecord belongs_to :conference has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/openid.rb b/app/models/openid.rb index 2fc1c245..2b954f8b 100644 --- a/app/models/openid.rb +++ b/app/models/openid.rb @@ -1,4 +1,4 @@ -class Openid < ActiveRecord::Base +class Openid < ApplicationRecord belongs_to :user validates :provider, :uid, presence: true diff --git a/app/models/organization.rb b/app/models/organization.rb index 0354df5b..21d0989b 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -1,4 +1,4 @@ -class Organization < ActiveRecord::Base +class Organization < ApplicationRecord resourcify :roles, dependent: :delete_all has_paper_trail diff --git a/app/models/payment.rb b/app/models/payment.rb index e9386a35..3938dcb6 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -1,4 +1,4 @@ -class Payment < ActiveRecord::Base +class Payment < ApplicationRecord has_many :ticket_purchases belongs_to :user belongs_to :conference diff --git a/app/models/physical_ticket.rb b/app/models/physical_ticket.rb index 689d118a..e98646b0 100644 --- a/app/models/physical_ticket.rb +++ b/app/models/physical_ticket.rb @@ -1,4 +1,4 @@ -class PhysicalTicket < ActiveRecord::Base +class PhysicalTicket < ApplicationRecord belongs_to :ticket_purchase has_one :ticket, through: :ticket_purchase has_one :conference, through: :ticket_purchase diff --git a/app/models/program.rb b/app/models/program.rb index 612d8154..4f0298f4 100644 --- a/app/models/program.rb +++ b/app/models/program.rb @@ -1,6 +1,6 @@ # cannot delete program if there are events submitted -class Program < ActiveRecord::Base +class Program < ApplicationRecord has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id } belongs_to :conference @@ -42,7 +42,8 @@ class Program < ActiveRecord::Base has_many :event_schedules, through: :events has_many :event_users, through: :events - has_many :speakers, -> { distinct }, through: :event_users, source: :user do + has_many :program_events_speakers, -> {where(event_role: 'speaker')}, through: :events, source: :event_users + has_many :speakers, -> { distinct }, through: :program_events_speakers, source: :user do def confirmed joins(:events).where(events: { state: :confirmed }) end diff --git a/app/models/qanswer.rb b/app/models/qanswer.rb index 730d98e7..2e581131 100644 --- a/app/models/qanswer.rb +++ b/app/models/qanswer.rb @@ -1,4 +1,4 @@ -class Qanswer < ActiveRecord::Base +class Qanswer < ApplicationRecord belongs_to :question belongs_to :answer, dependent: :delete diff --git a/app/models/question.rb b/app/models/question.rb index 4d8a33d0..0c7456a9 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,4 +1,4 @@ -class Question < ActiveRecord::Base +class Question < ApplicationRecord belongs_to :question_type has_and_belongs_to_many :conferences diff --git a/app/models/question_type.rb b/app/models/question_type.rb index df063568..84fd1a80 100644 --- a/app/models/question_type.rb +++ b/app/models/question_type.rb @@ -1,3 +1,3 @@ -class QuestionType < ActiveRecord::Base +class QuestionType < ApplicationRecord has_many :questions end diff --git a/app/models/registration.rb b/app/models/registration.rb index 7003dfd7..1198324e 100644 --- a/app/models/registration.rb +++ b/app/models/registration.rb @@ -1,4 +1,4 @@ -class Registration < ActiveRecord::Base +class Registration < ApplicationRecord belongs_to :user belongs_to :conference diff --git a/app/models/registration_period.rb b/app/models/registration_period.rb index fb9e6225..9aa82444 100644 --- a/app/models/registration_period.rb +++ b/app/models/registration_period.rb @@ -1,4 +1,4 @@ -class RegistrationPeriod < ActiveRecord::Base +class RegistrationPeriod < ApplicationRecord belongs_to :conference has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/resource.rb b/app/models/resource.rb index ce6e7b94..77363cfb 100644 --- a/app/models/resource.rb +++ b/app/models/resource.rb @@ -1,4 +1,4 @@ -class Resource < ActiveRecord::Base +class Resource < ApplicationRecord belongs_to :conference validates :name, :used, :quantity, presence: true validates :used, :quantity, numericality: { greater_than_or_equal_to: 0, only_integer: true } diff --git a/app/models/role.rb b/app/models/role.rb index c827d0dd..fcbac932 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,4 +1,4 @@ -class Role < ActiveRecord::Base +class Role < ApplicationRecord belongs_to :resource, polymorphic: true has_many :users_roles has_many :users, through: :users_roles diff --git a/app/models/room.rb b/app/models/room.rb index 8a50551d..718704de 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -1,4 +1,4 @@ -class Room < ActiveRecord::Base +class Room < ApplicationRecord include RevisionCount belongs_to :venue has_many :event_schedules, dependent: :destroy diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 082d0af0..3bd1f1fa 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -1,4 +1,4 @@ -class Schedule < ActiveRecord::Base +class Schedule < ApplicationRecord belongs_to :program belongs_to :track has_many :event_schedules, dependent: :destroy diff --git a/app/models/splashpage.rb b/app/models/splashpage.rb index 15447aa9..388831ba 100644 --- a/app/models/splashpage.rb +++ b/app/models/splashpage.rb @@ -1,4 +1,4 @@ -class Splashpage < ActiveRecord::Base +class Splashpage < ApplicationRecord belongs_to :conference has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } diff --git a/app/models/sponsor.rb b/app/models/sponsor.rb index df687f20..d54d95c7 100644 --- a/app/models/sponsor.rb +++ b/app/models/sponsor.rb @@ -1,4 +1,4 @@ -class Sponsor < ActiveRecord::Base +class Sponsor < ApplicationRecord belongs_to :sponsorship_level belongs_to :conference diff --git a/app/models/sponsorship_level.rb b/app/models/sponsorship_level.rb index da411859..f742e41b 100644 --- a/app/models/sponsorship_level.rb +++ b/app/models/sponsorship_level.rb @@ -1,4 +1,4 @@ -class SponsorshipLevel < ActiveRecord::Base +class SponsorshipLevel < ApplicationRecord validates :title, presence: true belongs_to :conference acts_as_list scope: :conference diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 984c46f3..9d78975a 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -1,4 +1,4 @@ -class Subscription < ActiveRecord::Base +class Subscription < ApplicationRecord belongs_to :conference belongs_to :user diff --git a/app/models/target.rb b/app/models/target.rb index 6581c48d..55365a6a 100644 --- a/app/models/target.rb +++ b/app/models/target.rb @@ -1,4 +1,4 @@ -class Target < ActiveRecord::Base +class Target < ApplicationRecord include ActionView::Helpers::TextHelper default_scope { order('due_date ASC') } diff --git a/app/models/ticket.rb b/app/models/ticket.rb index ce527472..b49cf1b9 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -1,4 +1,4 @@ -class Ticket < ActiveRecord::Base +class Ticket < ApplicationRecord belongs_to :conference has_many :ticket_purchases, dependent: :destroy has_many :buyers, -> { distinct }, through: :ticket_purchases, source: :user @@ -55,12 +55,18 @@ class Ticket < ActiveRecord::Base result ? result : Money.new(0, 'USD') end - def tickets_sold - ticket_purchases.paid.sum(:quantity) + def self.total_price_user(conference, user, paid: false) + tickets = TicketPurchase.where(conference: conference, user: user, paid: paid) + tickets.inject(0){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } end - def tickets_turnover - tickets_sold * price + def tickets_turnover_total(id) + tickets = TicketPurchase.where(ticket_id: id).paid + tickets.inject(0){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } + end + + def tickets_sold + ticket_purchases.paid.sum(:quantity) end private diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index 97fa9957..15de3785 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -1,4 +1,4 @@ -class TicketPurchase < ActiveRecord::Base +class TicketPurchase < ApplicationRecord belongs_to :ticket belongs_to :user belongs_to :conference @@ -52,7 +52,8 @@ class TicketPurchase < ActiveRecord::Base purchase = new(ticket_id: ticket.id, conference_id: conference.id, user_id: user.id, - quantity: quantity) + quantity: quantity, + amount_paid: ticket.price) purchase.pay(nil) if ticket.price_cents.zero? end purchase diff --git a/app/models/ticket_scanning.rb b/app/models/ticket_scanning.rb index 350d4f9b..27536c86 100644 --- a/app/models/ticket_scanning.rb +++ b/app/models/ticket_scanning.rb @@ -1,4 +1,4 @@ -class TicketScanning < ActiveRecord::Base +class TicketScanning < ApplicationRecord belongs_to :physical_ticket before_create :mark_user_present diff --git a/app/models/track.rb b/app/models/track.rb index 02d49f8c..01755c0e 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -1,4 +1,4 @@ -class Track < ActiveRecord::Base +class Track < ApplicationRecord include ActiveRecord::Transitions include RevisionCount diff --git a/app/models/user.rb b/app/models/user.rb index 231e1c11..4510aece 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -4,7 +4,7 @@ end class UserDisabled < StandardError end -class User < ActiveRecord::Base +class User < ApplicationRecord rolify has_many :physical_tickets, through: :ticket_purchases do def by_conference(conference) diff --git a/app/models/users_role.rb b/app/models/users_role.rb index 3a3afaba..f233e995 100644 --- a/app/models/users_role.rb +++ b/app/models/users_role.rb @@ -1,4 +1,4 @@ -class UsersRole < ActiveRecord::Base +class UsersRole < ApplicationRecord belongs_to :role belongs_to :user diff --git a/app/models/vchoice.rb b/app/models/vchoice.rb index cc09574a..b258c34d 100644 --- a/app/models/vchoice.rb +++ b/app/models/vchoice.rb @@ -1,4 +1,4 @@ -class Vchoice < ActiveRecord::Base +class Vchoice < ApplicationRecord belongs_to :vday belongs_to :vposition diff --git a/app/models/vday.rb b/app/models/vday.rb index 33de4ba7..bd122291 100644 --- a/app/models/vday.rb +++ b/app/models/vday.rb @@ -1,4 +1,4 @@ -class Vday < ActiveRecord::Base +class Vday < ApplicationRecord belongs_to :conference has_many :vchoices diff --git a/app/models/venue.rb b/app/models/venue.rb index 76d7de5e..6a758242 100644 --- a/app/models/venue.rb +++ b/app/models/venue.rb @@ -1,4 +1,4 @@ -class Venue < ActiveRecord::Base +class Venue < ApplicationRecord belongs_to :conference has_one :commercial, as: :commercialable, dependent: :destroy has_many :rooms, dependent: :destroy diff --git a/app/models/visit.rb b/app/models/visit.rb index 4ae9bb97..76b1981b 100644 --- a/app/models/visit.rb +++ b/app/models/visit.rb @@ -1,4 +1,4 @@ -class Visit < ActiveRecord::Base +class Visit < ApplicationRecord has_many :ahoy_events, class_name: 'Ahoy::Event' belongs_to :user end diff --git a/app/models/vote.rb b/app/models/vote.rb index 5b0e3fe7..9e1c572f 100644 --- a/app/models/vote.rb +++ b/app/models/vote.rb @@ -1,4 +1,4 @@ -class Vote < ActiveRecord::Base +class Vote < ApplicationRecord belongs_to :user belongs_to :event diff --git a/app/models/vposition.rb b/app/models/vposition.rb index 8a7dbdf9..38ef27fe 100644 --- a/app/models/vposition.rb +++ b/app/models/vposition.rb @@ -1,4 +1,4 @@ -class Vposition < ActiveRecord::Base +class Vposition < ApplicationRecord belongs_to :conference has_many :vchoices diff --git a/app/views/admin/booths/_all_booths.csv.haml b/app/views/admin/booths/_all_booths.csv.haml new file mode 100644 index 00000000..7a6f10fd --- /dev/null +++ b/app/views/admin/booths/_all_booths.csv.haml @@ -0,0 +1,19 @@ +- headers = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] += CSV.generate_line ['All booths'] += CSV.generate_line headers +- @booths.each do |booth| + = CSV.generate_line([booth.id, + booth.title, + booth.description, + booth.reasoning, + booth.submitter.name, + booth.submitter_relationship, + booth.website_url, + booth.state]).html_safe diff --git a/app/views/admin/booths/_all_booths.pdf.prawn b/app/views/admin/booths/_all_booths.pdf.prawn new file mode 100644 index 00000000..168397e8 --- /dev/null +++ b/app/views/admin/booths/_all_booths.pdf.prawn @@ -0,0 +1,26 @@ +prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf| + booths_array = [] + header_array = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] + booths_array << header_array + @booths.each do |booth| + row = [] + row << booth.id + row << booth.title + row << booth.description + row << booth.reasoning + row << booth.submitter.name + row << booth.submitter_relationship + row << booth.website_url + row << booth.state + booths_array << row + end + pdf.text "#{@conference.short_title} booths", font_size: 25, align: :center + pdf.table booths_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [45,70,153,152,70,80,105,45] +end diff --git a/app/views/admin/booths/_all_booths.xlsx.axlsx b/app/views/admin/booths/_all_booths.xlsx.axlsx new file mode 100644 index 00000000..bd1cc1db --- /dev/null +++ b/app/views/admin/booths/_all_booths.xlsx.axlsx @@ -0,0 +1,27 @@ +wb.add_worksheet(name: 'all booths') do |sheet| + bold_style = wb.styles.add_style(b: true) + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] + + sheet.add_row row, style: bold_style + @booths.each do |booth| + row = [] + row << booth.id + row << booth.title + row << booth.description + row << booth.reasoning + row << booth.submitter.name + row << booth.submitter_relationship + row << booth.website_url + row << booth.state + sheet.add_row row , style: wrap_text + sheet.column_widths 10,20,35,35,20,30,35,10 + end +end diff --git a/app/views/admin/booths/_confirmed_booths.csv.haml b/app/views/admin/booths/_confirmed_booths.csv.haml new file mode 100644 index 00000000..b5d17eb4 --- /dev/null +++ b/app/views/admin/booths/_confirmed_booths.csv.haml @@ -0,0 +1,19 @@ +- headers = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] += CSV.generate_line ['All booths'] += CSV.generate_line headers +- @booths.confirmed.each do |booth| + = CSV.generate_line([booth.id, + booth.title, + booth.description, + booth.reasoning, + booth.submitter.name, + booth.submitter_relationship, + booth.website_url, + booth.state]).html_safe diff --git a/app/views/admin/booths/_confirmed_booths.pdf.prawn b/app/views/admin/booths/_confirmed_booths.pdf.prawn new file mode 100644 index 00000000..a9750ab9 --- /dev/null +++ b/app/views/admin/booths/_confirmed_booths.pdf.prawn @@ -0,0 +1,26 @@ +prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf| + booths_array = [] + header_array = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] + booths_array << header_array + @booths.confirmed.each do |booth| + row = [] + row << booth.id + row << booth.title + row << booth.description + row << booth.reasoning + row << booth.submitter.name + row << booth.submitter_relationship + row << booth.website_url + row << booth.state + booths_array << row + end + pdf.text "#{@conference.short_title} booths", font_size: 25, align: :center + pdf.table booths_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [45,70,153,152,70,80,105,45] +end diff --git a/app/views/admin/booths/_confirmed_booths.xlsx.axlsx b/app/views/admin/booths/_confirmed_booths.xlsx.axlsx new file mode 100644 index 00000000..2dc10013 --- /dev/null +++ b/app/views/admin/booths/_confirmed_booths.xlsx.axlsx @@ -0,0 +1,27 @@ +wb.add_worksheet(name: 'all booths') do |sheet| + bold_style = wb.styles.add_style(b: true) + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Booth ID', + 'Title', + 'Description', + 'Reasoning', + 'Submitter Name', + 'Submitter Relationship', + 'Website Url', + 'State'] + sheet.add_row row, style: bold_style + + @booths.confirmed.each do |booth| + row = [] + row << booth.id + row << booth.title + row << booth.description + row << booth.reasoning + row << booth.submitter.name + row << booth.submitter_relationship + row << booth.website_url + row << booth.state + sheet.add_row row , style: wrap_text + sheet.column_widths 10,20,35,35,20,30,35,10 + end +end diff --git a/app/views/admin/booths/booths.csv.haml b/app/views/admin/booths/booths.csv.haml new file mode 100644 index 00000000..27d1d354 --- /dev/null +++ b/app/views/admin/booths/booths.csv.haml @@ -0,0 +1,4 @@ +- if @booth_export_option == 'confirmed' + = render 'confirmed_booths' +- elsif @booth_export_option == 'all' + = render 'all_booths' diff --git a/app/views/admin/booths/booths.pdf.prawn b/app/views/admin/booths/booths.pdf.prawn new file mode 100644 index 00000000..5c8f9bd2 --- /dev/null +++ b/app/views/admin/booths/booths.pdf.prawn @@ -0,0 +1,5 @@ +if @booth_export_option == 'confirmed' + render 'confirmed_booths' +elsif @booth_export_option == 'all' + render 'all_booths' +end diff --git a/app/views/admin/booths/booths.xlsx.axlsx b/app/views/admin/booths/booths.xlsx.axlsx new file mode 100644 index 00000000..5fe084db --- /dev/null +++ b/app/views/admin/booths/booths.xlsx.axlsx @@ -0,0 +1,7 @@ +wb = xlsx_package.workbook +xlsx_package.use_autowidth = true +if @booth_export_option == 'confirmed' + render partial: 'confirmed_booths', locals: { wb: wb } +elsif @booth_export_option == 'all' + render partial: 'all_booths', locals: { wb: wb } +end diff --git a/app/views/admin/booths/index.html.haml b/app/views/admin/booths/index.html.haml index 428895e5..431b6dfc 100644 --- a/app/views/admin/booths/index.html.haml +++ b/app/views/admin/booths/index.html.haml @@ -3,6 +3,30 @@ .page-header %h1 Booths + .pull-right + - if can? :read, Booth + .btn-group + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export PDF + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All Booths', admin_conference_booths_path(@conference.short_title, format: :pdf, booth_export_option: 'all') + %li= link_to 'Confirmed Booths', admin_conference_booths_path(@conference.short_title, format: :pdf, booth_export_option: 'confirmed') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export CSV + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_booths_path(@conference.short_title, format: :csv, booth_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_booths_path(@conference.short_title, format: :csv, booth_export_option: 'confirmed') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export XLS + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_booths_path(@conference.short_title, format: :xlsx, booth_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_booths_path(@conference.short_title, format: :xlsx, booth_export_option: 'confirmed') = "(#{@booths.length})" if @booths.any? %p.text-muted All the booth requests diff --git a/app/views/admin/cfps/_booths_cfp.html.haml b/app/views/admin/cfps/_booths_cfp.html.haml index 7cdc6db4..2b82f813 100644 --- a/app/views/admin/cfps/_booths_cfp.html.haml +++ b/app/views/admin/cfps/_booths_cfp.html.haml @@ -11,6 +11,10 @@ %dd = @cfp.end_date.strftime('%A, %B %e. %Y') %dt - Days Left: + Description +%dd + = markdown(@cfp.description) +%dt + Days Left %dd = pluralize(@cfp.remaining_days, 'day') diff --git a/app/views/admin/cfps/_events_cfp.html.haml b/app/views/admin/cfps/_events_cfp.html.haml index f06aa6ca..f4557bb4 100644 --- a/app/views/admin/cfps/_events_cfp.html.haml +++ b/app/views/admin/cfps/_events_cfp.html.haml @@ -10,6 +10,10 @@ End Date: %dd#end_date = @cfp.end_date.strftime('%A, %B %-d. %Y') +%dt + Description: +%dd#description + = markdown(@cfp.description) %dt Days Left: %dd diff --git a/app/views/admin/cfps/_form.html.haml b/app/views/admin/cfps/_form.html.haml index a02f3a02..b42a76e1 100644 --- a/app/views/admin/cfps/_form.html.haml +++ b/app/views/admin/cfps/_form.html.haml @@ -8,5 +8,6 @@ = f.input :start_date, as: :string, input_html: { id: 'registration-period-start-datepicker', start_date: @conference.start_date, end_date: @conference.end_date, readonly: 'readonly' } = f.input :end_date, as: :string, input_html: { id: 'registration-period-end-datepicker', readonly: 'readonly' } = f.input :cfp_type, as: :select, collection: (@cfp.new_record? ? @program.remaining_cfp_types : [@cfp.cfp_type] + @program.remaining_cfp_types).map {|type| ["#{type.capitalize}", type]}, include_blank: false, label: 'Type', input_html: { class: 'select-help-toggle' } + = f.input :description, input_html: {rows: 2, data: { provide: 'markdown-editable' } }, hint: markdown_hint %p.text-right = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/cfps/_tracks_cfp.html.haml b/app/views/admin/cfps/_tracks_cfp.html.haml index bcc2df43..20926758 100644 --- a/app/views/admin/cfps/_tracks_cfp.html.haml +++ b/app/views/admin/cfps/_tracks_cfp.html.haml @@ -10,6 +10,10 @@ End Date: %dd#end_date = @cfp.end_date.strftime('%A, %B %-d. %Y') +%dt + Description: +%dd#description + = markdown(@cfp.description) %dt Days Left: %dd diff --git a/app/views/admin/cfps/index.html.haml b/app/views/admin/cfps/index.html.haml index 0067229c..09c208cf 100644 --- a/app/views/admin/cfps/index.html.haml +++ b/app/views/admin/cfps/index.html.haml @@ -12,6 +12,7 @@ %th Type %th Start Date %th End Date + %th Description %th Days Left %th Actions %tbody @@ -24,6 +25,9 @@ = cfp.start_date.strftime('%A, %B %-d. %Y') %td = cfp.end_date.strftime('%A, %B %-d. %Y') + %td + %p + = truncate(cfp.description) %td = pluralize(cfp.remaining_days, 'day') %td diff --git a/app/views/admin/conferences/edit.html.haml b/app/views/admin/conferences/edit.html.haml index 26ae198f..ac90610d 100644 --- a/app/views/admin/conferences/edit.html.haml +++ b/app/views/admin/conferences/edit.html.haml @@ -22,11 +22,11 @@ = f.input :timezone, as: :time_zone, hint: 'The conference time zone' = f.input :start_date, as: :string, input_html: { id: 'conference-start-datepicker', readonly: 'readonly' } = f.input :end_date, as: :string, input_html: { id: 'conference-end-datepicker', readonly: 'readonly' } - = f.input :start_hour, input_html: {size: 2, type: 'number', min: 0, max: 23} - = f.input :end_hour, input_html: {size: 2, type: 'number', min: 1, max: 24} + = f.input :start_hour, input_html: {size: 2, type: 'number', min: 0, max: 23}, hint: rescheduling_hint(@affected_event_count) + = f.input :end_hour, input_html: {size: 2, type: 'number', min: 1, max: 24}, hint: rescheduling_hint(@affected_event_count) = f.inputs name: 'Registrations' do = f.input :registration_limit, as: :number, in: 0..9999, hint: 'Limit the number of registrations to the conference (0 no limit). Please note that the registration limit doesn\'t apply to speakers of confirmed events (they will still be able to register even if it has been reached). You currently have ' + pluralize(@conference.registrations.count, 'registration') = f.inputs name: 'Booths' do = f.input :booth_limit, as: :number, in: 0..9999, hint: 'Booth limit is the maximum number of booths that you can accept for this conference. By setting this number (0 no limit) you can be sure that you are not going to accept more booths than the conference can accommodate. You currently have ' + pluralize(@conference.booths.accepted.count, 'accepted booth') +'.' - = f.action :submit, as: :button, button_html: {class: 'btn btn-primary'} + = f.action :submit, as: :button, button_html: { class: 'btn btn-primary', data: { confirm: 'Are you sure you want to proceed?' } } diff --git a/app/views/admin/events/_all_events.csv.haml b/app/views/admin/events/_all_events.csv.haml index 9423c4ee..c7bff3be 100644 --- a/app/views/admin/events/_all_events.csv.haml +++ b/app/views/admin/events/_all_events.csv.haml @@ -4,6 +4,7 @@ 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -12,8 +13,15 @@ = CSV.generate_line ['All Events'] = CSV.generate_line headers - @events.each do |event| - = CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''), - event.submitter.name, event.speaker_names, event.event_type.title, + = CSV.generate_line([event.id, + event.title, + event.abstract, + (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")}#{event.time.strftime("%I:%M%p")} " : ''), + event.submitter.name, + event.speaker_names, + event.speaker_emails, + event.event_type.title, (event.track.present? ? event.track.name : ''), (event.difficulty_level.present? ? event.difficulty_level.title : ''), - (event.room.present? ? event.room.name : ''), event.state]).html_safe + (event.room.present? ? event.room.name : ''), + event.state]).html_safe diff --git a/app/views/admin/events/_all_events.pdf.prawn b/app/views/admin/events/_all_events.pdf.prawn index e53a1018..3f1c0d78 100644 --- a/app/views/admin/events/_all_events.pdf.prawn +++ b/app/views/admin/events/_all_events.pdf.prawn @@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') @@ -30,5 +32,5 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: end pdf.text "#{@conference.short_title} Events", font_size: 25, align: :center - pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1} + pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45] end diff --git a/app/views/admin/events/_all_events.xlsx.axlsx b/app/views/admin/events/_all_events.xlsx.axlsx index 66232784..3197cf38 100644 --- a/app/views/admin/events/_all_events.xlsx.axlsx +++ b/app/views/admin/events/_all_events.xlsx.axlsx @@ -1,6 +1,18 @@ wb.add_worksheet(name: 'all events') do |sheet| bold_style = wb.styles.add_style(b: true) - row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State'] + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Event ID', + 'Title', + 'Abstract', + 'Start time', + 'Submitter', + 'Speaker', + 'Speaker Email', + 'Event Type', + 'Track', + 'Difficulty Level', + 'Room', + 'State'] sheet.add_row row, style: bold_style @events.each do |event| @@ -11,11 +23,13 @@ wb.add_worksheet(name: 'all events') do |sheet| row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') row << (event.room.present? ? event.room.name : '') row << event.state - sheet.add_row row + sheet.add_row row , style: wrap_text + sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10 end end diff --git a/app/views/admin/events/_all_with_comments.csv.haml b/app/views/admin/events/_all_with_comments.csv.haml index cdf79339..315da41e 100644 --- a/app/views/admin/events/_all_with_comments.csv.haml +++ b/app/views/admin/events/_all_with_comments.csv.haml @@ -4,6 +4,7 @@ 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -16,8 +17,17 @@ - all_comments = '' - event.root_comments.each do |comment| - all_comments << "#{comment.created_at.strftime("%Y-%m-%d")} #{comment.created_at.strftime("%I:%M%p")} #{comment.user.name}: #{comment.body}\n" - = CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''), - event.submitter.name, event.speaker_names, event.event_type.title, + = CSV.generate_line([event.id, + event.title, + event.abstract, + (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")}#{event.time.strftime("%I:%M%p")} " : ''), + event.submitter.name, + event.speaker_names, + event.speaker_emails, + event.event_type.title, (event.track.present? ? event.track.name : ''), (event.difficulty_level.present? ? event.difficulty_level.title : ''), - (event.room.present? ? event.room.name : ''), event.state, all_comments]).html_safe + (event.room.present? ? event.room.name : ''), + event.state, + all_comments]).html_safe + diff --git a/app/views/admin/events/_all_with_comments.pdf.prawn b/app/views/admin/events/_all_with_comments.pdf.prawn index 2df27759..ccc9b773 100644 --- a/app/views/admin/events/_all_with_comments.pdf.prawn +++ b/app/views/admin/events/_all_with_comments.pdf.prawn @@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') @@ -31,7 +33,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: pdf.text "#{@conference.short_title} Events", font_size: 25, align: :center pdf.move_down 10 - pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1, position: :center} + pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1, position: :center},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45] pdf.start_new_page pdf.text "#{@conference.short_title} Comments", font_size: 25, align: :center pdf.move_down 20 diff --git a/app/views/admin/events/_all_with_comments.xlsx.axlsx b/app/views/admin/events/_all_with_comments.xlsx.axlsx index 038dfea5..fd798ca5 100644 --- a/app/views/admin/events/_all_with_comments.xlsx.axlsx +++ b/app/views/admin/events/_all_with_comments.xlsx.axlsx @@ -1,8 +1,20 @@ wb.use_shared_strings = true wb.add_worksheet(name: 'events with comments') do |sheet| - bold_style = wb.styles.add_style(b: true ) + bold_style = wb.styles.add_style(b: true) cell_style = wb.styles.add_style(alignment: { wrap_text: true, vertical: :top }) -row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State', 'Comments'] + row = ['Event ID', + 'Title', + 'Abstract', + 'Start time', + 'Submitter', + 'Speaker', + 'Speaker Email', + 'Event Type', + 'Track', + 'Difficulty Level', + 'Room', + 'State', + 'Comments'] sheet.add_row row, style: bold_style @events.each do |event| @@ -17,6 +29,7 @@ row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'E row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') @@ -24,5 +37,6 @@ row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'E row << event.state row << all_comments.strip sheet.add_row row, style: cell_style + sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10 end end diff --git a/app/views/admin/events/_confirmed_events.csv.haml b/app/views/admin/events/_confirmed_events.csv.haml index 4edbbaa3..2a61c352 100644 --- a/app/views/admin/events/_confirmed_events.csv.haml +++ b/app/views/admin/events/_confirmed_events.csv.haml @@ -4,6 +4,7 @@ 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -12,8 +13,15 @@ = CSV.generate_line ["Confirmed Events"] = CSV.generate_line headers - @events.confirmed.each do |event| - = CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''), - event.submitter.name, event.speaker_names, event.event_type.title, + = CSV.generate_line([event.id, + event.title, + event.abstract, + (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''), + event.submitter.name, + event.speaker_names, + event.speaker_emails, + event.event_type.title, (event.track.present? ? event.track.name : ''), (event.difficulty_level.present? ? event.difficulty_level.title : ''), - (event.room.present? ? event.room.name : ''), event.state]).html_safe + (event.room.present? ? event.room.name : ''), + event.state]).html_safe diff --git a/app/views/admin/events/_confirmed_events.pdf.prawn b/app/views/admin/events/_confirmed_events.pdf.prawn index ea838b94..8bef8883 100644 --- a/app/views/admin/events/_confirmed_events.pdf.prawn +++ b/app/views/admin/events/_confirmed_events.pdf.prawn @@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: 'Start time', 'Submitter', 'Speaker', + 'Speaker Email', 'Event Type', 'Track', 'Difficulty Level', @@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') @@ -30,6 +32,6 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: end pdf.text "#{@conference.short_title} Confirmed Events", font_size: 25, align: :center - pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1} + pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45] end diff --git a/app/views/admin/events/_confirmed_events.xlsx.axlsx b/app/views/admin/events/_confirmed_events.xlsx.axlsx index 34c40b36..a1c8c886 100644 --- a/app/views/admin/events/_confirmed_events.xlsx.axlsx +++ b/app/views/admin/events/_confirmed_events.xlsx.axlsx @@ -1,6 +1,18 @@ wb.add_worksheet(name: 'confirmed events') do |sheet| bold_style = wb.styles.add_style(b: true) - row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State'] + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Event ID', + 'Title', + 'Abstract', + 'Start time', + 'Submitter', + 'Speaker', + 'Speaker Email', + 'Event Type', + 'Track', + 'Difficulty Level', + 'Room', + 'State'] sheet.add_row row, style: bold_style @events.confirmed.each do |event| @@ -11,11 +23,13 @@ wb.add_worksheet(name: 'confirmed events') do |sheet| row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '') row << event.submitter.name row << event.speaker_names + row << event.speaker_emails row << event.event_type.title row << (event.track.present? ? event.track.name : '') row << (event.difficulty_level.present? ? event.difficulty_level.title : '') row << (event.room.present? ? event.room.name : '') row << event.state - sheet.add_row row + sheet.add_row row , style: wrap_text + sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10 end end diff --git a/app/views/admin/events/_proposal.html.haml b/app/views/admin/events/_proposal.html.haml index 15894f26..063bb20a 100644 --- a/app/views/admin/events/_proposal.html.haml +++ b/app/views/admin/events/_proposal.html.haml @@ -165,7 +165,7 @@ %td= markdown(@event.abstract) %tr %td - %b Description + %b Requirements %td= simple_format(@event.description) - if @conference.program && @conference.program.rating && @conference.program.rating > 0 diff --git a/app/views/admin/lodgings/_form.html.haml b/app/views/admin/lodgings/_form.html.haml index fa91bd24..9081951e 100644 --- a/app/views/admin/lodgings/_form.html.haml +++ b/app/views/admin/lodgings/_form.html.haml @@ -9,7 +9,7 @@ .row .col-md-8 = semantic_form_for(@lodging, url: (@lodging.new_record? ? admin_conference_lodgings_path : admin_conference_lodging_path(@conference.short_title, @lodging))) do |f| - = f.input :name + = f.input :name, input_html: { autofocus: true} = f.input :website_link = f.input :description, input_html: { rows: 5, cols: 20, data: { provide: 'markdown-editable' } }, hint: markdown_hint - if @lodging.picture? diff --git a/app/views/admin/organizations/_form.html.haml b/app/views/admin/organizations/_form.html.haml index c83facbb..048d13e4 100644 --- a/app/views/admin/organizations/_form.html.haml +++ b/app/views/admin/organizations/_form.html.haml @@ -3,7 +3,7 @@ = f.input :name, as: :string, required: true = f.input :description, as: :text, input_html: { rows: 10 }, placeholder: 'Decribe about your organization..' = image_tag f.object.picture.thumb.url if f.object.picture? - - if @organization.picture + - if @organization.picture? = image_tag(@organization.picture.thumb.url, width: '20%') = f.input :picture %p.text-right diff --git a/app/views/admin/physical_tickets/_physical_ticket.html.haml b/app/views/admin/physical_tickets/_physical_ticket.html.haml new file mode 100644 index 00000000..ff4dd185 --- /dev/null +++ b/app/views/admin/physical_tickets/_physical_ticket.html.haml @@ -0,0 +1,16 @@ +%tr + %td= physical_ticket.id + %td= physical_ticket.ticket.title + %td= physical_ticket.user.email + %td= humanized_money_with_symbol physical_ticket.ticket_purchase.amount_paid + %td + .btn-group + = link_to 'Show', + conference_physical_ticket_path(conference.short_title, + physical_ticket.token), + class: 'btn btn-primary' + = link_to 'Generate PDF', + conference_physical_ticket_path(conference.short_title, + physical_ticket.token, + format: :pdf), + class: 'button btn btn-default btn-info' diff --git a/app/views/admin/physical_tickets/index.html.haml b/app/views/admin/physical_tickets/index.html.haml index 96c5911f..8b26a965 100644 --- a/app/views/admin/physical_tickets/index.html.haml +++ b/app/views/admin/physical_tickets/index.html.haml @@ -21,23 +21,11 @@ %th ID %th Type %th User + %th Paid %th Actions %tbody - @physical_tickets.each do |physical_ticket| - %tr - %td= physical_ticket.id - %td= physical_ticket.ticket.title - %td= physical_ticket.user.email - %td - .btn-group - = link_to 'Show', - conference_physical_ticket_path(@conference.short_title, - physical_ticket.token), - class: 'btn btn-primary' - = link_to 'Generate PDF', - conference_physical_ticket_path(@conference.short_title, - physical_ticket.token, - format: :pdf), - class: 'button btn btn-default btn-info' + = render "physical_ticket", physical_ticket: physical_ticket, + conference: @conference - else %h5 No Tickets sold! diff --git a/app/views/admin/schedules/show.html.haml b/app/views/admin/schedules/show.html.haml index 9009fcbb..258b4d87 100644 --- a/app/views/admin/schedules/show.html.haml +++ b/app/views/admin/schedules/show.html.haml @@ -40,11 +40,23 @@ .tab-pane{ class: "#{ (@dates.first == date) ? 'active' : '' }", id: "#{date}" } = render partial: 'day_tab', locals: { date: date } - else - .h3 - No Rooms! - %small - = link_to 'Create rooms', admin_conference_venue_rooms_path - before creating the schedule. + - if @venue.try(:rooms).present? + .text-right + - if can? :create, @program.schedules.new + = link_to 'Add Schedule', admin_conference_schedules_path(@conference.short_title), + method: :post, class: 'btn btn-primary' + - elsif @venue + .h3 + No Rooms! + %small + = link_to 'Create rooms', admin_conference_venue_rooms_path + before creating the schedule. + - else + .h3 + No Venue! + %small + = link_to 'Create a venue with rooms', new_admin_conference_venue_path + before creating the schedule. :javascript $(document).ready( function() { diff --git a/app/views/admin/tickets/_form.html.haml b/app/views/admin/tickets/_form.html.haml index 11aff78d..319f7996 100644 --- a/app/views/admin/tickets/_form.html.haml +++ b/app/views/admin/tickets/_form.html.haml @@ -12,7 +12,7 @@ = f.input :title = f.input :description, input_html: { rows: 5, data: { provide: "markdown-editable" } } = f.input :price - = f.input :price_currency, as: :select, class: 'form-control', collection: ['USD', 'EUR', 'GBP', 'INR', 'CNY'], include_blank: false + = f.input :price_currency, as: :select, class: 'form-control', collection: ['USD', 'EUR', 'GBP', 'INR', 'CNY', 'CHF'], include_blank: false = f.input :registration_ticket, hint: 'A registration ticket is with which user register for the conference.' %p.text-right = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/tickets/index.html.haml b/app/views/admin/tickets/index.html.haml index 42154ae7..71698bb2 100644 --- a/app/views/admin/tickets/index.html.haml +++ b/app/views/admin/tickets/index.html.haml @@ -27,7 +27,7 @@ %td = ticket.tickets_sold %td - = humanized_money_with_symbol ticket.tickets_turnover + = humanized_money_with_symbol ticket.tickets_turnover_total(ticket.id) %td = ticket.registration_ticket? ? 'Yes' : 'No' %td diff --git a/app/views/admin/tracks/_all_tracks.csv.haml b/app/views/admin/tracks/_all_tracks.csv.haml new file mode 100644 index 00000000..a2361231 --- /dev/null +++ b/app/views/admin/tracks/_all_tracks.csv.haml @@ -0,0 +1,21 @@ +- headers = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'Start Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] += CSV.generate_line ['All Tracks'] += CSV.generate_line headers +- @tracks.each do |track| + = CSV.generate_line([track.id, + track.name, + track.description, + track.try(:room).try(:name), + track.start_date, + track.end_date, + track.try(:submitter).try(:name), + track.cfp_active? ? 'Yes' : 'No', + track.state]).html_safe diff --git a/app/views/admin/tracks/_all_tracks.pdf.prawn b/app/views/admin/tracks/_all_tracks.pdf.prawn new file mode 100644 index 00000000..885c4d28 --- /dev/null +++ b/app/views/admin/tracks/_all_tracks.pdf.prawn @@ -0,0 +1,28 @@ +prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf| + tracks_array = [] + header_array = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'End Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] + tracks_array << header_array + @tracks.each do |track| + row = [] + row << track.id + row << track.name.to_s + row << track.description.to_s + row << track.try(:room).try(:name) + row << track.start_date.to_s + row << track.end_date.to_s + row << track.try(:submitter).try(:name) + row << (track.cfp_active? ? 'Yes' : 'No') + row << track.state + tracks_array << row + end + pdf.text "#{@conference.short_title} tracks", font_size: 25, align: :center + pdf.table tracks_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,70,230,65,55,55,90,65,50] +end diff --git a/app/views/admin/tracks/_all_tracks.xlsx.axlsx b/app/views/admin/tracks/_all_tracks.xlsx.axlsx new file mode 100644 index 00000000..d1397193 --- /dev/null +++ b/app/views/admin/tracks/_all_tracks.xlsx.axlsx @@ -0,0 +1,29 @@ +wb.add_worksheet(name: 'all tracks') do |sheet| + bold_style = wb.styles.add_style(b: true) + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'End Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] + sheet.add_row row, style: bold_style + + @tracks.each do |track| + row = [] + row << track.id + row << track.name.to_s + row << track.description.to_s + row << track.try(:room).try(:name) + row << track.start_date.to_s + row << track.end_date.to_s + row << track.try(:submitter).try(:name) + row << (track.cfp_active? ? 'Yes' : 'No') + row << track.state + sheet.add_row row , style: wrap_text + sheet.column_widths 10,20,50,20,12,12,20,15,10 + end +end diff --git a/app/views/admin/tracks/_confirmed_tracks.csv.haml b/app/views/admin/tracks/_confirmed_tracks.csv.haml new file mode 100644 index 00000000..b2bd3f85 --- /dev/null +++ b/app/views/admin/tracks/_confirmed_tracks.csv.haml @@ -0,0 +1,21 @@ +- headers = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'Start Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] += CSV.generate_line ['Confirmed Tracks'] += CSV.generate_line headers +- @tracks.confirmed.each do |track| + = CSV.generate_line([track.id, + track.name, + track.description, + track.try(:room).try(:name), + track.start_date, + track.end_date, + track.try(:submitter).try(:name), + track.cfp_active? ? 'Yes' : 'No', + track.state]).html_safe diff --git a/app/views/admin/tracks/_confirmed_tracks.pdf.prawn b/app/views/admin/tracks/_confirmed_tracks.pdf.prawn new file mode 100644 index 00000000..290014a8 --- /dev/null +++ b/app/views/admin/tracks/_confirmed_tracks.pdf.prawn @@ -0,0 +1,28 @@ +prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf| + tracks_array = [] + header_array = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'End Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] + tracks_array << header_array + @tracks.confirmed.each do |track| + row = [] + row << track.id + row << track.name.to_s + row << track.description.to_s + row << track.try(:room).try(:name) + row << track.start_date.to_s + row << track.end_date.to_s + row << track.try(:submitter).try(:name) + row << (track.cfp_active? ? 'Yes' : 'No') + row << track.state + tracks_array << row + end + pdf.text "#{@conference.short_title} tracks", font_size: 25, align: :center + pdf.table tracks_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,70,230,65,55,55,90,65,50] +end diff --git a/app/views/admin/tracks/_confirmed_tracks.xlsx.axlsx b/app/views/admin/tracks/_confirmed_tracks.xlsx.axlsx new file mode 100644 index 00000000..673b985c --- /dev/null +++ b/app/views/admin/tracks/_confirmed_tracks.xlsx.axlsx @@ -0,0 +1,29 @@ +wb.add_worksheet(name: 'all tracks') do |sheet| + bold_style = wb.styles.add_style(b: true) + wrap_text = wb.styles.add_style alignment: {wrap_text: true} + row = ['Track ID', + 'Name', + 'Description', + 'Room', + 'Start Date', + 'End Date', + 'Submitter Name', + 'Included in Cfp', + 'State'] + sheet.add_row row, style: bold_style + + @tracks.confirmed.each do |track| + row = [] + row << track.id + row << track.name.to_s + row << track.description.to_s + row << track.try(:room).try(:name) + row << track.start_date.to_s + row << track.end_date.to_s + row << track.try(:submitter).try(:name) + row << (track.cfp_active? ? 'Yes' : 'No') + row << track.state + sheet.add_row row , style: wrap_text + sheet.column_widths 10,20,50,20,12,12,20,15,10 + end +end diff --git a/app/views/admin/tracks/index.html.haml b/app/views/admin/tracks/index.html.haml index b814ac8e..a5f5c9a0 100644 --- a/app/views/admin/tracks/index.html.haml +++ b/app/views/admin/tracks/index.html.haml @@ -2,7 +2,32 @@ .row .col-md-12 .page-header - %h1 Tracks + %h1 + Tracks + .pull-right + - if can? :read, Track + .btn-group + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export PDF + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All Tracks', admin_conference_program_tracks_path(@conference.short_title, format: :pdf, track_export_option: 'all') + %li= link_to 'Confirmed Tracks', admin_conference_program_tracks_path(@conference.short_title, format: :pdf, track_export_option: 'confirmed') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export CSV + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_program_tracks_path(@conference.short_title, format: :csv, track_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_tracks_path(@conference.short_title, format: :csv, track_export_option: 'confirmed') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export XLS + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_program_tracks_path(@conference.short_title, format: :xlsx, track_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_tracks_path(@conference.short_title, format: :xlsx, track_export_option: 'confirmed') %p.text-muted Categorize events in your conference .row diff --git a/app/views/admin/tracks/tracks.csv.haml b/app/views/admin/tracks/tracks.csv.haml new file mode 100644 index 00000000..a94811fe --- /dev/null +++ b/app/views/admin/tracks/tracks.csv.haml @@ -0,0 +1,4 @@ +- if @track_export_option == 'confirmed' + = render 'confirmed_tracks' +- elsif @track_export_option == 'all' + = render 'all_tracks' diff --git a/app/views/admin/tracks/tracks.pdf.prawn b/app/views/admin/tracks/tracks.pdf.prawn new file mode 100644 index 00000000..c74b3cbb --- /dev/null +++ b/app/views/admin/tracks/tracks.pdf.prawn @@ -0,0 +1,5 @@ +if @track_export_option == 'confirmed' + render 'confirmed_tracks' +elsif @track_export_option == 'all' + render 'all_tracks' +end diff --git a/app/views/admin/tracks/tracks.xlsx.axlsx b/app/views/admin/tracks/tracks.xlsx.axlsx new file mode 100644 index 00000000..6a84da9b --- /dev/null +++ b/app/views/admin/tracks/tracks.xlsx.axlsx @@ -0,0 +1,6 @@ +wb = xlsx_package.workbook +if @track_export_option == 'confirmed' + render partial: 'confirmed_tracks', locals: { wb: wb } +elsif @track_export_option == 'all' + render partial: 'all_tracks', locals: { wb: wb } +end diff --git a/app/views/admin/venues/_form.html.haml b/app/views/admin/venues/_form.html.haml index 7dd08a2c..6674305b 100644 --- a/app/views/admin/venues/_form.html.haml +++ b/app/views/admin/venues/_form.html.haml @@ -15,6 +15,12 @@ = semantic_form_for(@venue, url: admin_conference_venue_path(@conference.short_title)) do |f| = f.inputs :name, :website = f.input :description, input_html: { rows: 5, cols: 20, data: { provide: 'markdown-editable' } }, hint: markdown_hint + = f.label 'Venue Logo' + %br + - if @venue.picture? + = image_tag @venue.picture.thumb.url + = f.input :picture, label: false, hint: 'This will be displayed on the venue are of the splash page.' + = f.hidden_field :picture_cache = f.inputs :street, :postalcode, :city, :country, :latitude, :longitude = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/versions/_object_desc_and_link.html.haml b/app/views/admin/versions/_object_desc_and_link.html.haml index a924a4cf..6b182c2f 100644 --- a/app/views/admin/versions/_object_desc_and_link.html.haml +++ b/app/views/admin/versions/_object_desc_and_link.html.haml @@ -12,14 +12,17 @@ - role = Role.find_by(id: users_role.role_id) if users_role role - if role.name == 'organization_admin' - -# organization_admin belongs to organization and not conferences - - organization = Organization.find(version.conference_id) - = link_if_alive version, role.name, + - if Organization.find_by(id: version.conference_id) + -# organization_admin belongs to organization and not conferences + - organization = Organization.find_by(id: version.conference_id) + = link_if_alive version, role.name, admins_admin_organization_path(organization), organization + - else + (Deleted Organization) - else - conference = Conference.find_by(id: version.conference_id) - conference_short_title = conference.try(:short_title) || current_or_last_object_state('Conference', version.conference_id).try(:short_title) || ' ' - = link_if_alive version, role.try(:name), admin_conference_role_path(role.try(:name) || ' ', conference_short_title), conference + = link_if_alive version, role.try(:name), admin_conference_role_path(conference_short_title,role.try(:name) || ' '), conference = version.event == 'create' ? 'to' : 'from' user @@ -140,10 +143,13 @@ - role = current_or_last_object_state(version.item_type, version.item_id) - role_name = role.try(:name) || PaperTrail::Version.where(item_type: 'Role', item_id: version.item_id).last.changeset[:name].second - if role_name == 'organization_admin' - -# organization_admin belongs to organization and not conferences - - organization = Organization.find(version.conference_id) - = link_if_alive version, role_name, + - if Organization.find_by(id: version.conference_id) + -# organization_admin belongs to organization and not conferences + - organization = Organization.find_by(id: version.conference_id) + = link_if_alive version, role.name, admins_admin_organization_path(organization), organization + - else + (Role Deleted) - else - conference = Conference.find_by(id: version.conference_id) - conference_short_title = conference.try(:short_title) || current_or_last_object_state('Conference', version.conference_id).try(:short_title) || ' ' @@ -202,9 +208,7 @@ - when 'DifficultyLevel' difficulty level - difficulty_level = current_or_last_object_state(version.item_type, version.item_id) - = link_if_alive version, difficulty_level.title, - admin_conference_program_difficulty_level_path(conference_short_title, version.item_id), - conference + = link_if_alive version, difficulty_level.title,admin_conference_program_difficulty_levels_path(conference_short_title), conference - when 'Splashpage' = link_if_alive version, 'splashpage', @@ -224,7 +228,12 @@ - unless %w(Conference Subscription Registration User Organization).include?(version.item_type) - if (version.item_type == 'Role' && role_name == 'organization_admin') || (version.item_type == 'UsersRole' && role.name == 'organization_admin') in organization - = link_to_organization(version.conference_id) + - if Organization.find_by(id: version.conference_id) + -# organization_admin belongs to organization and not conferences + - organization = Organization.find_by(id: version.conference_id) + = link_to_organization(version.conference_id) + - else + (Organization Deleted) - else in conference = link_to_conference(version.conference_id) diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index 83d6d89c..a50cf198 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -101,7 +101,7 @@ = word_pluralize(@total_quantity[ticket_id], 'Ticket') for = tickets.first.price.symbol - = humanized_money tickets.first.price + = humanized_money @total_price_per_ticket[ticket_id] %br - if @tickets.any? = link_to 'Get more tickets', conference_tickets_path(@conference.short_title), class: "btn btn-default" diff --git a/app/views/conferences/_venue.html.haml b/app/views/conferences/_venue.html.haml index 62af90c7..4436b0fe 100644 --- a/app/views/conferences/_venue.html.haml +++ b/app/views/conferences/_venue.html.haml @@ -32,4 +32,4 @@ = @conference.venue.country_name - if @conference.venue.website %br - =link_to @conference.venue.website, @conference.venue.website + =link_to(h(@conference.venue.website), h(@conference.venue.website)).html_safe diff --git a/app/views/conferences/_venue_map.html.haml b/app/views/conferences/_venue_map.html.haml index b58b3053..9f34117f 100644 --- a/app/views/conferences/_venue_map.html.haml +++ b/app/views/conferences/_venue_map.html.haml @@ -1,17 +1,16 @@ #map{style: "height: 500px;" } -- popup = "

#{@conference.venue.name}


#{@conference.venue.street}
#{@conference.venue.city}
#{@conference.venue.country_name}" - content_for(:script_body) do :javascript // create a map in the "map" div, set the view to a given place and zoom - var map = L.map('map', { scrollWheelZoom: false }).setView([#{@conference.venue.latitude}, #{@conference.venue.longitude}], 11); + var map = L.map('map', { scrollWheelZoom: false }).setView([#{h(@conference.venue.latitude)}, #{h(@conference.venue.longitude)}], 11); // add an OpenStreetMap tile layer L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', maxZoom: 18 }).addTo(map); // add a marker in the given location, attach some popup content to it and open the popup - L.marker([#{@conference.venue.latitude}, #{@conference.venue.longitude}]).addTo(map) - .bindPopup("#{popup}") + L.marker([#{h @conference.venue.latitude}, #{h @conference.venue.longitude}]).addTo(map) + .bindPopup("#{escape_javascript(render '/conferences/venue_map_marker', venue: @conference.venue)}") .openPopup(); // Turn scrollwheel on when user clicks map.on('focus', function(e) { diff --git a/app/views/conferences/_venue_map_marker.html.haml b/app/views/conferences/_venue_map_marker.html.haml new file mode 100644 index 00000000..c5f78345 --- /dev/null +++ b/app/views/conferences/_venue_map_marker.html.haml @@ -0,0 +1,13 @@ +- if venue.picture? + = image_tag venue.picture.thumb.url, + alt: venue.name, + class: 'img-responsive pull-right' +%h3= venue.name +%p + = venue.street + %br + = venue.city + %br + = venue.country_name +- if venue.website + %p.text-center.clearfix= sanitize(link_to venue.website, venue.website) diff --git a/app/views/conferences/index.html.haml b/app/views/conferences/index.html.haml index 032db5c3..a3735478 100644 --- a/app/views/conferences/index.html.haml +++ b/app/views/conferences/index.html.haml @@ -4,7 +4,7 @@ .page-header %h2 Upcoming Conferences - @current.each do |conference| - = render partial: 'conference_details', locals: { conference: conference } + = render '/conferences/conference_details', conference: conference -if @antiquated and @antiquated.any? .row .col-md-12 @@ -17,7 +17,7 @@ %i.fa.fa-chevron-down{ style: 'display: none' } #antiquated.collapse - @antiquated.each do |conference| - = render partial: 'conference_details', locals: { conference: conference} + = render '/conferences/conference_details', conference: conference -content_for :script_body do :javascript diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index f94b8ee4..dd6b2d62 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -82,7 +82,7 @@ - content_for :script_head do :javascript - var triangle_tcs = tinycolor("#{@conference.color}").monochromatic(); + var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic(); var triangle_colors = triangle_tcs.map(function(t) { return t.toHexString(); }); $(function () { $(document).ready(function() { diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index aa9c4db4..64aaa99e 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -12,6 +12,8 @@ = f.input :name, input_html: { required: true }, hint: 'This is your real name' = f.input :password, input_html: { required: true } = f.input :password_confirmation, input_html: { required: true } + - Feature.with(:recaptcha) do + = recaptcha_tags %p.text-right = f.action :submit, as: :button, label: 'Sign Up', button_html: { class: 'btn btn-success' } diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml index 9995123b..f7d5fa30 100644 --- a/app/views/layouts/_navigation.html.haml +++ b/app/views/layouts/_navigation.html.haml @@ -13,10 +13,8 @@ %span.icon-bar %span.icon-bar %span.icon-bar - - if conference.nil? || conference.new_record? - = link_to (ENV['OSEM_NAME'] || 'OSEM'), root_path, class: 'navbar-brand', title: 'Open Source Event Manager' - - else - = link_to conference.organization.name, organizations_path, class: 'navbar-brand', title: 'Open Source Event Manager' + = nav_root_link_for conference + .collapse.navbar-collapse#main-nav - if content_for :splash_nav %ul.nav.navbar-nav#splash-nav diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index c1a6ce78..ee88a24c 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -9,15 +9,16 @@ = javascript_include_tag "application" = csrf_meta_tags - :javascript - window.liveSettings = { - api_key: "#{ENV['OSEM_TRANSIFEX_APIKEY']}", - picker: "bottom-right", - detectlang: true, - autocollect: true - }; = content_for(:script_head) - = javascript_include_tag "//cdn.transifex.com/live.js" + - if ENV['OSEM_TRANSIFEX_APIKEY'] + :javascript + window.liveSettings = { + api_key: "#{ENV['OSEM_TRANSIFEX_APIKEY']}", + picker: "bottom-right", + detectlang: true, + autocollect: true + }; + = javascript_include_tag "//cdn.transifex.com/live.js" = yield(:head) %body diff --git a/app/views/organizations/index.html.haml b/app/views/organizations/index.html.haml index b2794bd8..c8743363 100644 --- a/app/views/organizations/index.html.haml +++ b/app/views/organizations/index.html.haml @@ -8,9 +8,11 @@ - @organizations.each do |organization| .col-md-4 .thumbnail - = image_tag(organization.picture.thumb.url, width: '20%') + = image_tag(organization.picture.thumb.url, width: '20%') if organization.picture? .caption %h4 = organization.name - %button.btn.btn-success Conferences + = link_to 'Conferences', + conferences_organization_path(organization), + class: 'btn btn-success' / = link_to 'Edit', edit_organization_path(organization), class: 'btn btn-mini btn-default' diff --git a/app/views/proposals/_tooltip.html.haml b/app/views/proposals/_tooltip.html.haml index 168d2d26..b10b5a7a 100644 --- a/app/views/proposals/_tooltip.html.haml +++ b/app/views/proposals/_tooltip.html.haml @@ -1,11 +1,12 @@ - progress_status = event.progress_status %ul.list-unstyled - %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) + - 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'] diff --git a/app/views/proposals/index.html.haml b/app/views/proposals/index.html.haml index 06154d47..e40eb30e 100644 --- a/app/views/proposals/index.html.haml +++ b/app/views/proposals/index.html.haml @@ -6,6 +6,14 @@ %span.notranslate = @conference.title + + - if @program.cfp_open? + - if @program.cfp.description.present? + .row + .col-md-12 + = markdown(@program.cfp.description) + + .row .col-md-12 = render partial: 'encouragement_text' @@ -48,14 +56,14 @@ The more information you add to your proposal, the more likely it is that the conference organizers accept your proposal. %br It will also be more likely that visitors find your proposal interesting enough to attend. + - if can? :create, @conference.registrations.new + %p + %strong + Why do I need to register to the conference? + %p + Knowing the number of visitors for the conference helps the organizers plan better. - %p - %strong - Why do I need to register to the conference? - %p - Knowing the number of visitors for the conference helps the organizers plan better. - - %table.table.table-striped + %table.table.table-striped#events - @events.each do |event| %tr %td{style: "padding:20px 8px 20px 8px;"} @@ -74,13 +82,20 @@ %td.col-md-2{style: "padding:20px 8px 20px 8px;"} = link_to 'Complete your proposal', 'javascript: void(0)', "type"=>"button", "data-trigger"=>"focus", "data-toggle"=>"popover", "title"=>"Your todo list", "data-content"=>"#{render partial: 'tooltip', locals: { event: event} }" - - - progress_percentage = event.calculate_progress - .progress - %div{class: "progress-bar #{event_progress_color(progress_percentage)}", style: "width:#{progress_percentage}%;"} - = event.progress_status.reject{ |_key, value| value || value.nil? }.length - left - + - if can? :create, @conference.registrations.new + - progress_percentage = event.calculate_progress + .progress + %div{class: "progress-bar #{event_progress_color(progress_percentage)}", style: "width:#{progress_percentage}%;"} + = event.progress_status.reject{ |_key, value| value || value.nil? }.length + left + - else + :ruby + progress_list = event.progress_status + progress_percentage = (100 * progress_list.values.count(true) / (progress_list.values.compact.count-1)).to_s + .progress + %div{class: "progress-bar #{event_progress_color(progress_percentage)}", style: "width:#{progress_percentage}%;"} + = event.progress_status.reject{ |_key, value| value || value.nil? }.length-1 + left %td.col-md-3{style: "padding:20px 0px 20px 0px;"} .pull-right - if event.transition_possible? :confirm diff --git a/app/views/proposals/new.html.haml b/app/views/proposals/new.html.haml index 25a78786..0f699559 100644 --- a/app/views/proposals/new.html.haml +++ b/app/views/proposals/new.html.haml @@ -3,6 +3,11 @@ .col-md-12 .page-header %h1 New Proposal + - if @program.cfp_open? + - if @program.cfp.description.present? + .row + .col-md-12 + = markdown(@program.cfp.description) .row .col-md-12 = render partial: 'encouragement_text' diff --git a/app/views/proposals/show.html.haml b/app/views/proposals/show.html.haml index c181e283..19f9371f 100644 --- a/app/views/proposals/show.html.haml +++ b/app/views/proposals/show.html.haml @@ -36,7 +36,8 @@ .col-md-8 %h4 = link_to speaker.name, user_path(speaker.id) - = "(#{speaker.email})" + - if speaker.email_public? + = "(#{speaker.email})" - if speaker.affiliation? .text-muted from diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 00000000..9ca6ce2b --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby.ruby2.4 +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rake b/bin/rake new file mode 100755 index 00000000..c5376b0f --- /dev/null +++ b/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby.ruby2.4 +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 00000000..e87a485f --- /dev/null +++ b/bin/setup @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby.ruby2.4 +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/update b/bin/update new file mode 100755 index 00000000..b19460d7 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby.ruby2.4 +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bootstrap.sh b/bootstrap.sh index 92a8d746..06a642dd 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,10 @@ #!/bin/bash + +# set env os release variables +. /etc/os-release + +if [[ "$ID" == "opensuse" ]]; then + pushd /vagrant echo -e "\ninstalling required software packages...\n" @@ -14,6 +20,42 @@ echo 'install: --no-format-executable' >> /etc/gemrc echo -e "\ninstalling bundler...\n" gem.ruby2.4 install bundler +elif [[ "$ID" == "centos" || "$VERSION" == "7" ]]; then + _YELLOW='\033[1;33m' # yellow color + _LRED='\033[1;31m' # Light red color + _NO_COLOUR='\033[0m' # no color + + printf "${_YELLOW}CEntOS-7 Setup${_NO_COLOUR}\n" + + printf "${_YELLOW}installing ruby-2.4${_NO_COLOUR}\n" + yum install -q -y https://github.com/feedforce/ruby-rpm/releases/download/2.4.2/ruby-2.4.2-1.el7.centos.x86_64.rpm + if [[ ! "$?" -eq 0 ]]; then + printf "${_LRED}Error trying to install ruby-2.4${_NO_COLOUR}\n" + fi + + printf "${_YELLOW}installing ruby-2.4 gems dependencies${_NO_COLOUR}\n" + gem install bundler + if [[ ! "$?" -eq 0 ]]; then + printf "${_LRED}Error trying to install ruby-2.4 bundler${_NO_COLOUR}\n" + fi + + printf "${_YELLOW}installing nodejs repo${_NO_COLOUR}\n" + curl -sL https://rpm.nodesource.com/setup_9.x | bash - > /dev/null + + printf "${_YELLOW}installing nodejs and devel tools${_NO_COLOUR}\n" + yum install -q -y git make gcc gcc-c++ libxml2-devel libxslt-devel nodejs screen mariadb mariadb-devel sqlite-devel ImageMagick bzip2 + + # for production: bundle install --without test development + printf "${_YELLOW}Opening firewall port: 3000${_NO_COLOUR}\n" + iptables -I INPUT -p tcp --dport 3000 -j ACCEPT + + printf "${_YELLOW}installing phantomjs${_NO_COLOUR}\n" + curl -L --silent https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 -o /tmp/phantomjs-2.1.1-linux-x86_64.tar.bz2 + tar jxvf /tmp/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C /tmp/ phantomjs-2.1.1-linux-x86_64/bin/phantomjs + mv /tmp/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin + +fi + echo -e "\ninstalling your bundle...\n" su - vagrant -c "cd /vagrant/; bundle install --quiet" diff --git a/config/application.rb b/config/application.rb index 07ba40f3..4e3844ad 100644 --- a/config/application.rb +++ b/config/application.rb @@ -60,9 +60,6 @@ module Osem # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' - # Errors raised within `after_rollback`/`after_commit` propagate normally - # like in other Active Record callbacks. - config.active_record.raise_in_transactional_callbacks = true config.active_job.queue_adapter = :delayed_job end end diff --git a/config/boot.rb b/config/boot.rb index 5e5f0c1f..30f5120d 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,3 @@ -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 00000000..e9bac116 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,9 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV['OSEM_REDIS_URL'] %> diff --git a/config/deploy.rb b/config/deploy.rb index 5a9090fb..9b76c176 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -3,7 +3,7 @@ require 'mina/rails' require 'mina/git' set :domain, 'proxy-opensuse.suse.de' -set :port, 2214 +set :port, 2252 set :user, 'osem' set :deploy_to, '/srv/www/vhosts/opensuse.org/events' set :repository, 'https://github.com/openSUSE/osem.git' @@ -42,7 +42,7 @@ task deploy: :environment do #invoke :notify_errbit to :launch do - queue "sudo /etc/init.d/apache2 restart" + queue "sudo /usr/bin/systemctl restart apache2" queue "cd #{deploy_to}/current && RAILS_ENV=production bin/delayed_job start" end diff --git a/config/environments/production.rb b/config/environments/production.rb index 4e2c2e79..cf598a16 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -15,7 +15,7 @@ Osem::Application.configure do config.eager_load = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_files = false + config.public_file_server.enabled = false # Compress JavaScripts and CSS config.assets.compress = true @@ -33,7 +33,7 @@ Osem::Application.configure do # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true + config.force_ssl = !!ENV['FORCE_SSL'] # See everything in the log (default is :info) config.log_level = :info diff --git a/config/environments/test.rb b/config/environments/test.rb index 68c74dab..225ae26f 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -8,8 +8,8 @@ Osem::Application.configure do config.cache_classes = true # Configure static asset server for tests with Cache-Control for performance - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + config.public_file_server.enabled = true + config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } # Do not eager load code on boot. config.eager_load = false diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 00000000..51639b67 --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,6 @@ +# Be sure to restart your server when you modify this file. + +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 00000000..01ef3e66 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,11 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. +# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 00000000..1389e86a --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :marshal diff --git a/config/initializers/feature.rb b/config/initializers/feature.rb new file mode 100644 index 00000000..415d84f7 --- /dev/null +++ b/config/initializers/feature.rb @@ -0,0 +1,10 @@ +require 'feature' + +repo = Feature::Repository::SimpleRepository.new + +# configure features here +unless(ENV['RECAPTCHA_SITE_KEY'].blank? || ENV['RECAPTCHA_SECRET_KEY'].blank?) + repo.add_active_feature :recaptcha +end + +Feature.set_repository repo diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 00000000..4a994e1e --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 5d8d9be2..ac033bf9 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,15 +1,16 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end -# + # These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections do |inflect| +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.acronym 'RESTful' # end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 72aca7e4..dc189968 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -2,4 +2,3 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf -# Mime::Type.register_alias "text/html", :iphone diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb new file mode 100644 index 00000000..cbf423a8 --- /dev/null +++ b/config/initializers/new_framework_defaults.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +Rails.application.config.action_controller.raise_on_unfiltered_parameters = true + +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = false + +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = false + +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = false + +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = false + +# Do not halt callback chains when a callback returns false. Previous versions had true. +ActiveSupport.halt_callback_chains_on_return_false = true diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..fa11fb8f --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,47 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum, this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests, default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +preload_app! + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted this block will be run, if you are using `preload_app!` +# option you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, Ruby +# cannot share connections between processes. +# +on_worker_boot do + ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +end + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb index 99f716e4..33a92a48 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -149,7 +149,11 @@ Osem::Application.routes.draw do get '/revision_history/:id/revert_object' => 'versions#revert_object', as: 'revision_history_revert_object' get '/revision_history/:id/revert_attribute' => 'versions#revert_attribute', as: 'revision_history_revert_attribute' end - resources :organizations, only: [:index] + resources :organizations, only: [:index] do + member do + get :conferences + end + end resources :conferences, only: [:index, :show] do resources :booths do member do @@ -165,7 +169,6 @@ Osem::Application.routes.draw do member do get :registrations patch '/withdraw' => 'proposals#withdraw' - get :registrations patch '/confirm' => 'proposals#confirm' patch '/restart' => 'proposals#restart' end diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 00000000..c9119b40 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/db/migrate/20170905110034_add_description_to_cfps.rb b/db/migrate/20170905110034_add_description_to_cfps.rb new file mode 100644 index 00000000..a4976ee2 --- /dev/null +++ b/db/migrate/20170905110034_add_description_to_cfps.rb @@ -0,0 +1,5 @@ +class AddDescriptionToCfps < ActiveRecord::Migration + def change + add_column :cfps, :description, :text + end +end diff --git a/db/migrate/20170924190528_add_amount_paid_to_ticket_purchases.rb b/db/migrate/20170924190528_add_amount_paid_to_ticket_purchases.rb new file mode 100644 index 00000000..5e732d4c --- /dev/null +++ b/db/migrate/20170924190528_add_amount_paid_to_ticket_purchases.rb @@ -0,0 +1,5 @@ +class AddAmountPaidToTicketPurchases < ActiveRecord::Migration + def change + add_column :ticket_purchases, :amount_paid, :float, default: 0 + end +end diff --git a/db/migrate/20171118113113_change_visit_id_type_of_ahoy_events_to_integer.rb b/db/migrate/20171118113113_change_visit_id_type_of_ahoy_events_to_integer.rb new file mode 100644 index 00000000..61415970 --- /dev/null +++ b/db/migrate/20171118113113_change_visit_id_type_of_ahoy_events_to_integer.rb @@ -0,0 +1,5 @@ +class ChangeVisitIdTypeOfAhoyEventsToInteger < ActiveRecord::Migration[5.0] + def change + change_column :ahoy_events, :visit_id, :integer, limit: nil + end +end diff --git a/db/schema.rb b/db/schema.rb index 82f5923d..de53720a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -11,20 +10,19 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170816203325) do +ActiveRecord::Schema.define(version: 20171118113113) do create_table "ahoy_events", force: :cascade do |t| - t.uuid "visit_id", limit: 16 + t.integer "visit_id" t.integer "user_id" t.string "name" t.text "properties" t.datetime "time" + t.index ["time"], name: "index_ahoy_events_on_time" + t.index ["user_id"], name: "index_ahoy_events_on_user_id" + t.index ["visit_id"], name: "index_ahoy_events_on_visit_id" end - add_index "ahoy_events", ["time"], name: "index_ahoy_events_on_time" - add_index "ahoy_events", ["user_id"], name: "index_ahoy_events_on_user_id" - add_index "ahoy_events", ["visit_id"], name: "index_ahoy_events_on_visit_id" - create_table "answers", force: :cascade do |t| t.string "title" t.datetime "created_at" @@ -37,11 +35,10 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.string "role" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["booth_id"], name: "index_booth_requests_on_booth_id" + t.index ["user_id"], name: "index_booth_requests_on_user_id" end - add_index "booth_requests", ["booth_id"], name: "index_booth_requests_on_booth_id" - add_index "booth_requests", ["user_id"], name: "index_booth_requests_on_user_id" - create_table "booths", force: :cascade do |t| t.string "title" t.text "description" @@ -68,12 +65,13 @@ ActiveRecord::Schema.define(version: 20170816203325) do end create_table "cfps", force: :cascade do |t| - t.date "start_date", null: false - t.date "end_date", null: false + t.date "start_date", null: false + t.date "end_date", null: false t.datetime "created_at" t.datetime "updated_at" t.integer "program_id" t.string "cfp_type" + t.text "description" end create_table "comments", force: :cascade do |t| @@ -88,12 +86,11 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.integer "parent_id" t.integer "lft" t.integer "rgt" + t.index ["commentable_id"], name: "index_comments_on_commentable_id" + t.index ["commentable_type"], name: "index_comments_on_commentable_type" + t.index ["user_id"], name: "index_comments_on_user_id" end - add_index "comments", ["commentable_id"], name: "index_comments_on_commentable_id" - add_index "comments", ["commentable_type"], name: "index_comments_on_commentable_type" - add_index "comments", ["user_id"], name: "index_comments_on_user_id" - create_table "commercials", force: :cascade do |t| t.string "commercial_id" t.string "commercial_type" @@ -129,10 +126,9 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.integer "ticket_layout", default: 0 t.string "custom_domain" t.integer "booth_limit", default: 0 + t.index ["organization_id"], name: "index_conferences_on_organization_id" end - add_index "conferences", ["organization_id"], name: "index_conferences_on_organization_id" - create_table "conferences_questions", id: false, force: :cascade do |t| t.integer "conference_id" t.integer "question_id" @@ -163,10 +159,9 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.string "queue" t.datetime "created_at" t.datetime "updated_at" + t.index ["priority", "run_at"], name: "delayed_jobs_priority" end - add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority" - create_table "difficulty_levels", force: :cascade do |t| t.string "title" t.text "description" @@ -222,13 +217,12 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.datetime "start_time" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["event_id", "schedule_id"], name: "index_event_schedules_on_event_id_and_schedule_id", unique: true + t.index ["event_id"], name: "index_event_schedules_on_event_id" + t.index ["room_id"], name: "index_event_schedules_on_room_id" + t.index ["schedule_id"], name: "index_event_schedules_on_schedule_id" end - add_index "event_schedules", ["event_id", "schedule_id"], name: "index_event_schedules_on_event_id_and_schedule_id", unique: true - add_index "event_schedules", ["event_id"], name: "index_event_schedules_on_event_id" - add_index "event_schedules", ["room_id"], name: "index_event_schedules_on_room_id" - add_index "event_schedules", ["schedule_id"], name: "index_event_schedules_on_schedule_id" - create_table "event_types", force: :cascade do |t| t.string "title", null: false t.integer "length", default: 30 @@ -326,10 +320,9 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "token" + t.index ["token"], name: "index_physical_tickets_on_token", unique: true end - add_index "physical_tickets", ["token"], name: "index_physical_tickets_on_token", unique: true - create_table "programs", force: :cascade do |t| t.integer "conference_id" t.integer "rating", default: 0 @@ -343,10 +336,9 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.datetime "voting_end_date" t.integer "selected_schedule_id" t.integer "schedule_interval", default: 15, null: false + t.index ["selected_schedule_id"], name: "index_programs_on_selected_schedule_id" end - add_index "programs", ["selected_schedule_id"], name: "index_programs_on_selected_schedule_id" - create_table "qanswers", force: :cascade do |t| t.integer "question_id" t.integer "answer_id" @@ -415,11 +407,10 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.string "description" t.integer "resource_id" t.string "resource_type" + t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" + t.index ["name"], name: "index_roles_on_name" end - add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" - add_index "roles", ["name"], name: "index_roles_on_name" - create_table "rooms", force: :cascade do |t| t.string "guid", null: false t.string "name", null: false @@ -432,11 +423,10 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "track_id" + t.index ["program_id"], name: "index_schedules_on_program_id" + t.index ["track_id"], name: "index_schedules_on_track_id" end - add_index "schedules", ["program_id"], name: "index_schedules_on_program_id" - add_index "schedules", ["track_id"], name: "index_schedules_on_track_id" - create_table "splashpages", force: :cascade do |t| t.integer "conference_id" t.boolean "public" @@ -504,6 +494,7 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.integer "user_id" t.integer "payment_id" t.integer "week" + t.float "amount_paid", default: 0.0 end create_table "ticket_scannings", force: :cascade do |t| @@ -538,12 +529,11 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.date "end_date" t.text "relevance" t.integer "selected_schedule_id" + t.index ["room_id"], name: "index_tracks_on_room_id" + t.index ["selected_schedule_id"], name: "index_tracks_on_selected_schedule_id" + t.index ["submitter_id"], name: "index_tracks_on_submitter_id" end - add_index "tracks", ["room_id"], name: "index_tracks_on_room_id" - add_index "tracks", ["selected_schedule_id"], name: "index_tracks_on_selected_schedule_id" - add_index "tracks", ["submitter_id"], name: "index_tracks_on_submitter_id" - create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false @@ -577,21 +567,18 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.boolean "is_admin", default: false t.string "username" t.boolean "is_disabled", default: false - t.string "token" + t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + t.index ["username"], name: "index_users_on_username", unique: true end - add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true - add_index "users", ["email"], name: "index_users_on_email", unique: true - add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - add_index "users", ["username"], name: "index_users_on_username", unique: true - create_table "users_roles", force: :cascade do |t| t.integer "role_id" t.integer "user_id" + t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id" end - add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id" - create_table "vchoices", force: :cascade do |t| t.integer "vday_id" t.integer "vposition_id" @@ -632,12 +619,11 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.text "object_changes" t.datetime "created_at" t.integer "conference_id" + t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" end - add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" - create_table "visits", force: :cascade do |t| - t.uuid "visitor_id", limit: 16 + t.binary "visitor_id", limit: 16 t.string "ip" t.text "user_agent" t.text "referrer" @@ -657,10 +643,9 @@ ActiveRecord::Schema.define(version: 20170816203325) do t.string "utm_content" t.string "utm_campaign" t.datetime "started_at" + t.index ["user_id"], name: "index_visits_on_user_id" end - add_index "visits", ["user_id"], name: "index_visits_on_user_id" - create_table "votes", force: :cascade do |t| t.integer "event_id" t.integer "rating" diff --git a/docker-compose.env.example b/docker-compose.env.example index 2aedbe73..905ff612 100644 --- a/docker-compose.env.example +++ b/docker-compose.env.example @@ -19,10 +19,10 @@ DATABASE_PORT=3306 # having to create a .env file: # https://github.com/openSUSE/osem/blob/master/dotenv.example -OSEM_NAME=Dockerized OSEM -OSEM_HOSTNAME=http://localhost:9292 -OSEM_ERRBIT_HOST=localhost -SECRET_KEY_BASE=changemechangemechangeme +OSEM_NAME="Dockerized OSEM" +OSEM_HOSTNAME="http://localhost:9292" +OSEM_ERRBIT_HOST="localhost" +SECRET_KEY_BASE=changemechangemechangeme" # these settings work for the MailHog server that is enabled by default in # docker-compose.yml @@ -31,9 +31,10 @@ SECRET_KEY_BASE=changemechangemechangeme # your users are going to see the HTTP status 500 page # you should comment out or remove the mailhog service from docker-compose.yml, # too -OSEM_EMAIL_ADDRESS=osem@mailhog -OSEM_SMTP_AUTHENTICATION=login -OSEM_SMTP_ADDRESS=mailhog -OSEM_SMTP_PORT=1025 -OSEM_SMTP_USERNAME=mailhog -OSEM_SMTP_PASSWORD=mailhog +OSEM_EMAIL_ADDRESS="osem@mailhog" +OSEM_SMTP_AUTHENTICATION="login" +OSEM_SMTP_ADDRESS="mailhog" +OSEM_SMTP_PORT="1025" +OSEM_SMTP_USERNAME="mailhog" +OSEM_SMTP_PASSWORD="mailhog" + diff --git a/dotenv.example b/dotenv.example index 77c28e4c..e0e3f519 100644 --- a/dotenv.example +++ b/dotenv.example @@ -63,3 +63,13 @@ OSEM_SMTP_OPENSSL_VERIFY_MODE="" # Enable the usage of the devise ichain plugin OSEM_ICHAIN_ENABLED=false + +# enable this to force SSL +# FORCE_SSL="1" + +# ReCAPTCHA keys +RECAPTCHA_SITE_KEY="" +RECAPTCHA_SECRET_KEY="" + +# The url of the redis server +OSEM_REDIS_URL='redis://localhost:6379/1' diff --git a/spec/controllers/admin/conferences_controller_spec.rb b/spec/controllers/admin/conferences_controller_spec.rb index 009e40ba..ff9d676b 100644 --- a/spec/controllers/admin/conferences_controller_spec.rb +++ b/spec/controllers/admin/conferences_controller_spec.rb @@ -56,8 +56,8 @@ describe Admin::ConferencesController do conference.reload expect(flash[:error]) .to eq("Updating conference failed. Short title can't be blank.") - expect(conference.title).to eq("#{conference.title}") - expect(conference.short_title).to eq("#{conference.short_title}") + expect(conference.title).to eq(conference.title) + expect(conference.short_title).to eq(conference.short_title) end it 're-renders the #show template' do diff --git a/spec/controllers/conference_registration_controller_spec.rb b/spec/controllers/conference_registration_controller_spec.rb index 9afaaed8..a6f1503c 100644 --- a/spec/controllers/conference_registration_controller_spec.rb +++ b/spec/controllers/conference_registration_controller_spec.rb @@ -252,7 +252,7 @@ describe ConferenceRegistrationsController, type: :controller do end it 'does not assign price of purchased tickets to total_price and purchased tickets to tickets without payment' do - expect(assigns(:total_price)).to eq Money.new(0, 'USD') + expect(assigns(:total_price)).to eq 0 end end @@ -262,7 +262,7 @@ describe ConferenceRegistrationsController, type: :controller do end it 'assigns 0 dollars to total_price and empty array to tickets variables' do - expect(assigns(:total_price)).to eq Money.new(0, 'USD') + expect(assigns(:total_price)).to eq 0 expect(assigns(:tickets)).to match_array [] end end diff --git a/spec/controllers/organizations_controller_spec.rb b/spec/controllers/organizations_controller_spec.rb index 2916fdea..eb0109a1 100644 --- a/spec/controllers/organizations_controller_spec.rb +++ b/spec/controllers/organizations_controller_spec.rb @@ -2,6 +2,26 @@ require 'spec_helper' describe OrganizationsController do let!(:organization) { create(:organization) } + let!(:conference) do + create( + :conference, + splashpage: create(:splashpage, public: true), + venue: create(:venue), + organization: organization + ) + end + let!(:antiquated_conference) do + create( + :conference, + splashpage: create(:splashpage, public: true), + venue: create(:venue), + organization: organization, + start_date: 2.weeks.ago, + end_date: 1.week.ago + ) + end + + let!(:other_conference) { create(:conference) } let!(:user) { create(:user) } describe 'GET #index' do @@ -12,4 +32,27 @@ describe OrganizationsController do it { expect(response).to render_template('index') } end + + describe 'GET #conferences' do + before :each do + get :conferences, id: organization.id + end + + it 'loads the organization' do + expect(assigns(:organization)).to eq organization + end + + it 'includes organization conferences' do + expect(assigns(:current)).to include conference + end + + it 'does not include conferences outside organization' do + expect(assigns(:current)).not_to include other_conference + expect(assigns(:antiquated)).not_to include other_conference + end + + it 'includes antiquated organization conferences' do + expect(assigns(:antiquated)).to include antiquated_conference + end + end end diff --git a/spec/factories/cfps.rb b/spec/factories/cfps.rb index 6b061d53..ea59a8c1 100644 --- a/spec/factories/cfps.rb +++ b/spec/factories/cfps.rb @@ -5,7 +5,7 @@ FactoryGirl.define do start_date { 1.day.ago } end_date { 2.days.from_now } cfp_type 'events' - + description 'This is a test description' program end end diff --git a/spec/features/organization_spec.rb b/spec/features/organization_spec.rb index 6fcf590b..72948c2d 100644 --- a/spec/features/organization_spec.rb +++ b/spec/features/organization_spec.rb @@ -48,4 +48,12 @@ feature Organization do it_behaves_like 'successfully updates an organization' end + + context 'anonymously' do + scenario 'index should link to conferences list' do + visit organizations_path + + expect(page).to have_link('Conferences', href: "/organizations/#{organization.id}/conferences") + end + end end diff --git a/spec/features/splashpage_spec.rb b/spec/features/splashpage_spec.rb index ee9b63d5..d33c6c85 100644 --- a/spec/features/splashpage_spec.rb +++ b/spec/features/splashpage_spec.rb @@ -62,14 +62,18 @@ feature Splashpage do end end - context 'public splashpage already created' do + context 'navigation' do let!(:splashpage) { create(:splashpage, conference: conference, public: true)} - scenario 'should have organization name', feature: true, js: true do - sign_in participant - visit conference_path(conference.short_title) + context 'multiple organizations' do + let!(:additional_organization) { create(:organization) } - expect(page).to have_text(conference.organization.name) + scenario 'should have organization name', feature: true, js: true do + sign_in participant + visit conference_path(conference.short_title) + + expect(page).to have_text(conference.organization.name) + end end end end diff --git a/spec/features/sponsor_spec.rb b/spec/features/sponsor_spec.rb index c6b5009e..b12ee90d 100644 --- a/spec/features/sponsor_spec.rb +++ b/spec/features/sponsor_spec.rb @@ -36,7 +36,14 @@ feature Sponsor do end # Remove sponsor - click_link 'Delete' + visit admin_conference_sponsors_path( + conference_id: conference.short_title + ) + within('table#sponsors') do + page.accept_confirm do + click_link 'Delete' + end + end expect(flash).to eq('Sponsor successfully deleted.') expect(page).to_not have_selector('table#sponsors') end diff --git a/spec/features/tracks_spec.rb b/spec/features/tracks_spec.rb index 934f28ba..f753abc2 100644 --- a/spec/features/tracks_spec.rb +++ b/spec/features/tracks_spec.rb @@ -36,8 +36,11 @@ feature Track do expected = expect do visit admin_conference_program_tracks_path(conference_id: conference.short_title) - - click_link 'Delete' + within('#tracks', visible: true) do + page.accept_confirm do + find_link('Delete').click + end + end end expected.to change { Track.count }.by(-1) @@ -53,7 +56,9 @@ feature Track do expected = expect do visit admin_conference_program_tracks_path(conference_id: conference.short_title) - click_link 'Edit' + within('#tracks', visible: true) do + find_link('Edit').trigger('click') + end fill_in 'track_name', with: 'Distribution' fill_in 'track_short_name', with: 'Distribution' diff --git a/spec/features/versions_spec.rb b/spec/features/versions_spec.rb index 0db2d1f9..37ad4e15 100644 --- a/spec/features/versions_spec.rb +++ b/spec/features/versions_spec.rb @@ -148,7 +148,7 @@ feature 'Version' do visit admin_revision_history_path expect(page).to have_text("Someone (probably via the console) created new ticket Gold with ID #{ticket_id} in conference #{conference.short_title}") - expect(page).to have_text("Someone (probably via the console) updated price cents and description of ticket Gold with ID #{ticket_id} in conference #{conference.short_title}") + expect(page).to have_text("Someone (probably via the console) updated description and price cents of ticket Gold with ID #{ticket_id} in conference #{conference.short_title}") expect(page).to have_text("Someone (probably via the console) deleted ticket Gold with ID #{ticket_id} in conference #{conference.short_title}") end @@ -193,7 +193,9 @@ feature 'Version' do click_link 'Reject event' visit conference_program_proposals_path(conference_id: conference.short_title) - click_link 'Re-Submit' + within('#events') do + click_link 'Re-Submit' + end visit admin_conference_program_events_path(conference.short_title) click_button 'New' @@ -341,7 +343,7 @@ feature 'Version' do conference.email_settings.update_attributes(registration_subject: 'xxxxx', registration_body: 'yyyyy', accepted_subject: 'zzzzz') visit admin_revision_history_path - expect(page).to have_text("Someone (probably via the console) updated registration subject, registration body and accepted subject + expect(page).to have_text("Someone (probably via the console) updated registration body, registration subject and accepted subject of email settings in conference #{conference.short_title}") end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 139a5cf9..6626ed87 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -58,5 +58,21 @@ describe ApplicationHelper, type: :helper do expect(concurrent_events(event).present?).to eq false end end + + describe 'navigation title link' do + it 'should default to OSEM' do + ENV.delete('OSEM_NAME') + expect(nav_root_link_for(nil)).to match 'OSEM' + end + + it 'should use the environment variable' do + ENV['OSEM_NAME'] = Faker::Company.name + "'" + expect(nav_root_link_for(nil)).to match h(ENV['OSEM_NAME']) + end + + it 'should use the conference organization name' do + expect(nav_root_link_for(conference)).to match h(conference.organization.name) + end + end end end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 0a84aedd..158e1db3 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -362,7 +362,7 @@ describe Event do new_event.submitter = submitter new_event.speakers = [speaker1, speaker2] - expect(new_event.speaker_names).to eq 'user speaker 1 and user speaker 2' + expect(new_event.speaker_names).to eq 'user speaker 1, user speaker 2' end end end diff --git a/spec/models/program_spec.rb b/spec/models/program_spec.rb index 1c8eabd9..ccb1bfbc 100644 --- a/spec/models/program_spec.rb +++ b/spec/models/program_spec.rb @@ -15,8 +15,8 @@ describe Program do it { is_expected.to have_many(:events).dependent(:destroy) } it { is_expected.to have_many(:event_schedules).through(:events) } it { is_expected.to have_many(:event_users).through(:events) } - it { is_expected.to have_many(:speakers).through(:event_users).source(:user) } - + it { is_expected.to have_many(:program_events_speakers).through(:events).source(:event_users) } + it { is_expected.to have_many(:speakers).through(:program_events_speakers).source(:user) } it { is_expected.to accept_nested_attributes_for(:event_types) } it { is_expected.to accept_nested_attributes_for(:tracks) } it { is_expected.to accept_nested_attributes_for(:difficulty_levels) } @@ -204,6 +204,7 @@ describe Program do program.schedule_interval = 10 program.save! + program.reload expect(program.event_types.pluck(:length).sort).to eq [10, 20, 30] end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fc56e829..704b8e08 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,10 @@ require 'phantomjs' # makes it easier to control when PaperTrail is enabled during testing. require 'paper_trail/frameworks/rspec' +# Make htmlescape() available +require 'erb' +include ERB::Util + # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are # run as spec files by default. This means that files in spec/support that end @@ -59,7 +63,7 @@ RSpec.configure do |config| Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, phantomjs: Phantomjs.path, js_errors: false) + Capybara::Poltergeist::Driver.new(app, phantomjs: Phantomjs.path, js_errors: false, window_size: [1920, 1080]) end # Includes helpers and connect them to specific types of tests @@ -82,6 +86,14 @@ RSpec.configure do |config| # Types of tests (controller, feature, model) will # be inferred from subfolder name config.infer_spec_type_from_file_location! + + # Enable this if you like to see what you're debugging + # config.after(:example) do |example| + # if example.exception + # save_and_open_screenshot + # save_and_open_page + # end + # end end OmniAuth.config.test_mode = true