diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..a3778efa --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,15 @@ +**I'm submitting a ..** +- [ ] Bug Report +- [ ] Feature Request + +**Current behavior:** + + +**Expected correct behavior:** + + +**Steps to reproduce:** + + +**Other information:** + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..501ce4df --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ +**Checklist** + +- [ ] I have read the [Contribution & Best practices Guide](https://github.com/openSUSE/osem/blob/master/CONTRIBUTING.md). +- [ ] My branch is up-to-date with the upstream `master` branch. +- [ ] The tests pass locally with my changes. +- [ ] I have added tests that prove my fix is effective or that my feature works(if appropriate). +- [ ] I have added necessary documentation (if appropriate). + +**Short description of what this resolves/which [issues](https://github.com/openSUSE/osem/issues) does this fix?:** + + + +- + +**Changes proposed in this pull request:** + + + +- diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index b79ddc17..54b6d85d 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -121,20 +121,9 @@ linters: - "app/views/conference_registrations/_registration_info.html.haml" - "app/views/conference_registrations/_volunteer.html.haml" - "app/views/conference_registrations/show.html.haml" - - "app/views/conferences/_booths.html.haml" - - "app/views/conferences/_call_for_paper.html.haml" - "app/views/conferences/_conference_details.html.haml" - "app/views/conferences/_gallery.html.haml" - - "app/views/conferences/_lodging.html.haml" - - "app/views/conferences/_program.html.haml" - - "app/views/conferences/_registration.html.haml" - - "app/views/conferences/_schedule_splashpage.html.haml" - - "app/views/conferences/_sponsors.html.haml" - - "app/views/conferences/_tickets.html.haml" - - "app/views/conferences/_venue.html.haml" - - "app/views/conferences/_venue_map.html.haml" - "app/views/conferences/index.html.haml" - - "app/views/conferences/show.html.haml" - "app/views/devise/confirmations/new.html.haml" - "app/views/devise/ichain_sessions/new.html.haml" - "app/views/devise/ichain_sessions/new_test.html.haml" diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a91f2ae9..a4542c19 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,42 @@ 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: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. @@ -386,7 +407,15 @@ 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' + - 'spec/models/program_spec.rb' + +# Offense count: 488 Style/Documentation: Enabled: false @@ -419,14 +448,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 +473,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 +481,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 +495,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 +524,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 +576,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 +591,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 +605,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 +630,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 +675,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 +714,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/CONTRIBUTING.md b/CONTRIBUTING.md index 5193725d..bef64aab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,7 +82,7 @@ You can read through current enabled rules in `.rubocop.yml` file. Explanations Additionally you can read through the [ruby style-guide](https://github.com/bbatsov/ruby-style-guide) to better understand core principles. ### Test Suite -We are using [rspec](http://rspec.info/)+[capybara](http://jnicklas.github.io/capybara/)+[factory girl](https://github.com/thoughtbot/factory_girl) as a test suite. You can run it locally +We are using [rspec](http://rspec.info/)+[capybara](http://teamcapybara.github.io/capybara/)+[factory girl](https://github.com/thoughtbot/factory_girl) as a test suite. You can run it locally ```shell vagrant exec bundle exec rspec diff --git a/Dockerfile b/Dockerfile index 4cc5c04c..6cf50964 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,10 @@ RUN chown -R osem.root /osem/ && \ # data directory is used to cache the secret key in a file ENV DATA_DIR /data RUN install -d -m 0770 -o osem -g root $DATA_DIR -VOLUME ["$DATA_DIR"] +# data persistence for uploaded files (logos, other pictures, etc) +RUN mkdir 0775 -p /osem/tmp/cache /osem/tmp/uploads/ && \ + chown -R osem.osem /osem/tmp/ +VOLUME ["$DATA_DIR", "/osem/tmp/uploads/", "/osem/public/system/"] USER osem EXPOSE 9292 diff --git a/Gemfile b/Gemfile index 22dc5f6e..e624a1f7 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' @@ -174,7 +179,7 @@ gem 'acts_as_list' gem 'bootstrap-switch-rails', '~> 3.0.0' # for parsing OEmbed data -gem 'ruby-oembed' +gem 'ruby-oembed', '~>0.12.0' # for uploading images to the cloud gem 'cloudinary' @@ -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" @@ -205,14 +214,17 @@ gem 'selectize-rails' # CVE-2017-9049, CVE-2017-9050 gem 'nokogiri', '>= 1.8.1' +# memcached binary connector +gem 'dalli' + # 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 @@ -227,11 +239,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 @@ -246,6 +258,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 dc730e82..0f64b0e8 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) @@ -142,9 +145,10 @@ GEM safe_yaml (~> 1.0.0) currencies (0.4.2) daemons (1.1.9) + dalli (2.7.6) 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 +170,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 +184,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) @@ -287,9 +293,10 @@ GEM multi_json (1.12.1) multi_xml (0.5.5) multipart-post (2.0.0) - mysql2 (0.4.9) + mysql2 (0.4.10) nenv (0.3.0) netrc (0.11.0) + nio4r (2.1.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) notiffany (0.1.1) @@ -324,9 +331,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 +360,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 +398,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 +433,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 +473,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-oembed (0.12.0) 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 +514,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 +548,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 +569,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 +587,7 @@ DEPENDENCIES bootstrap-switch-rails (~> 3.0.0) bootstrap3-datetimepicker-rails (~> 3.0.2) byebug - cancancan + cancancan (~> 2.0) capybara carrierwave carrierwave-bombshelter @@ -582,6 +598,7 @@ DEPENDENCIES country_select coveralls daemons + dalli database_cleaner delayed_job_active_record devise @@ -589,8 +606,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 @@ -621,7 +639,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! @@ -633,17 +652,19 @@ 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) - ruby-oembed + rubocop (~> 0.51.0) + ruby-oembed (~> 0.12.0) sass-rails (>= 4.0.2) selectize-rails shoulda-matchers @@ -663,4 +684,4 @@ DEPENDENCIES whenever BUNDLED WITH - 1.15.4 + 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..6dc89f43 100644 --- a/app/assets/javascripts/osem-datepickers.js +++ b/app/assets/javascripts/osem-datepickers.js @@ -79,13 +79,28 @@ $(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); + if (!$('#registration-period-end-datepicker').val()) { + $('#registration-period-end-datepicker').data("DateTimePicker").setDate(e.date); + } }); $("#registration-period-end-datepicker").on("dp.change",function (e) { $('#registration-period-start-datepicker').data("DateTimePicker").setMaxDate(e.date); diff --git a/app/assets/stylesheets/breakpoints.css.scss b/app/assets/stylesheets/breakpoints.css.scss index b2025e39..d3dbc799 100644 --- a/app/assets/stylesheets/breakpoints.css.scss +++ b/app/assets/stylesheets/breakpoints.css.scss @@ -2,20 +2,20 @@ @if $class == xs { @media (max-width: 767px) { @content; } } - + @else if $class == sm { - @media (min-width: 750px) { @content; } + @media (min-width: 768px) and (max-width: 991px) { @content; } } - + @else if $class == md { - @media (min-width: 992px) { @content; } + @media (min-width: 992px) and (max-width: 1199px) { @content; } } - + @else if $class == lg { @media (min-width: 1200px) { @content; } } - + @else { @warn "Breakpoint mixin supports: xs, sm, md, lg"; } -} \ No newline at end of file +} 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/commercials_controller.rb b/app/controllers/admin/commercials_controller.rb index f13b4322..3c694246 100644 --- a/app/controllers/admin/commercials_controller.rb +++ b/app/controllers/admin/commercials_controller.rb @@ -49,6 +49,26 @@ module Admin end end + ## + # Received a file from user + # Reads file and creates commercial for event + # File content example: + # EventID:MyURL + def mass_upload + errors = Commercial.read_file(params[:file]) if params[:file] + + if errors.all? { |_k, v| v.blank? } + flash[:notice] = 'Successfully added commercials.' + else + errors_text = '' + errors_text << 'Unable to find event with ID: ' + errors[:no_event].join(', ') + '. ' if errors[:no_event].any? + errors_text << 'There were some errors: ' + errors[:validation_errors].join('. ') if errors[:validation_errors].any? + + flash[:error] = errors_text + end + redirect_to :back + end + private def commercial_params diff --git a/app/controllers/admin/conferences_controller.rb b/app/controllers/admin/conferences_controller.rb index 8f8f2959..921a23d1 100644 --- a/app/controllers/admin/conferences_controller.rb +++ b/app/controllers/admin/conferences_controller.rb @@ -155,7 +155,7 @@ module Admin # Set line color using a hash function @tickets = [] - @tickets_data.keys.each do |title| + @tickets_data.each_key do |title| @tickets.append(short_title: title, color: "\##{Digest::MD5.hexdigest(title)[0..5]}") end diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb index accfb281..164e0407 100644 --- a/app/controllers/admin/events_controller.rb +++ b/app/controllers/admin/events_controller.rb @@ -124,6 +124,15 @@ module Admin def cancel update_state(:cancel, 'Event canceled!') + selected_schedule = @event.program.selected_schedule + event_schedule = EventSchedule.unscoped.where(event: @event).find_by(schedule: selected_schedule) if selected_schedule + Rails.logger.debug "schedule: #{selected_schedule.inspect} and event_schedule #{event_schedule.inspect}" + if selected_schedule && event_schedule + event_schedule.enabled = false + event_schedule.save + else + @event.event_schedules.destroy_all + end end def reject 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/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 e8809b28..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] diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index f141529d..4b01ca29 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -9,19 +9,58 @@ class ConferencesController < ApplicationController end def show - @conference = if params[:id] - Conference.find_by_short_title(params[:id]) - else - load_conference_by_domain - end - authorize! :show, @conference - @program = @conference.program + # load conference with header content + @conference = Conference.unscoped.eager_load( + :splashpage, + :program, + :registration_period, + :contact, + venue: :commercial + ).find_by(conference_finder_conditions) + authorize! :show, @conference # TODO: reduce the 10 queries performed here + + splashpage = @conference.splashpage + if splashpage.include_cfp + cfps = @conference.program.cfps + @call_for_events = cfps.find { |call| call.cfp_type == 'events' } + if @call_for_events.try(:open?) + @event_types = @conference.event_types.pluck(:title) + @track_names = @conference.confirmed_tracks.pluck(:name).sort + end + @call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' } + end + if splashpage.include_program + @highlights = @conference.highlighted_events.eager_load(:speakers) + if splashpage.include_tracks + @tracks = @conference.confirmed_tracks.eager_load( + :room + ).order('tracks.name') + end + if splashpage.include_booths + @booths = @conference.confirmed_booths.order('title') + end + end + if splashpage.include_registrations || splashpage.include_tickets + @tickets = @conference.tickets.order('price_cents') + end + if splashpage.include_lodgings + @lodgings = @conference.lodgings.order('name') + end + if splashpage.include_sponsors + @sponsorship_levels = @conference.sponsorship_levels.eager_load( + :sponsors + ).order('sponsorship_levels.position ASC', 'sponsors.name') + end end private - def load_conference_by_domain - Conference.find_by(custom_domain: request.domain) + def conference_finder_conditions + if params[:id] + { short_title: params[:id] } + else + { custom_domain: request.domain } + end end def respond_to_options diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 66052310..7ea81dc0 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -91,6 +91,15 @@ class ProposalsController < ApplicationController begin @event.withdraw + selected_schedule = @event.program.selected_schedule + event_schedule = @event.event_schedules.find_by(schedule: selected_schedule) if selected_schedule + Rails.logger.debug "schedule: #{selected_schedule.inspect} and event_schedule #{event_schedule.inspect}" + if selected_schedule && event_schedule + event_schedule.enabled = false + event_schedule.save + else + @event.event_schedules.destroy_all + end rescue Transitions::InvalidTransition redirect_to :back, error: "Event can't be withdrawn" return 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 ed7ce011..1d0400cd 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -11,6 +11,11 @@ module Users def handle(provider) auth_hash = request.env['omniauth.auth'] + unless auth_hash.info.email.present? + flash[:error] = "Email field is missing in your #{provider} account" + redirect_to new_user_registration_path + return + end 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, diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b5e2892e..f0311c7a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -56,17 +56,7 @@ module ApplicationHelper end def tracks(conference) - all = conference.program.tracks.confirmed.cfp_active.pluck(:name) - first = all[0...-1] - last = all[-1] - ts = '' - if all.length > 1 - ts << first.join(', ') - ts << " and #{last}" - else - ts = all.join - end - return ts + conference.confirmed_tracks.collect(&:name).to_sentence end def difficulty_levels(conference) @@ -80,7 +70,7 @@ module ApplicationHelper else ts = all.join end - return ts + ts end def unread_notifications(user) @@ -99,7 +89,7 @@ module ApplicationHelper end def normalize_array_length(hashmap, length) - hashmap.each do |_, value| + hashmap.each_value do |value| if value.length < length value.fill(value[-1], value.length...length) end @@ -151,8 +141,8 @@ module ApplicationHelper hint: 'The people responsible for the booth. You can only select existing users.' end - def event_types(conference) - conference.program.event_types.map { |et| et.title.pluralize }.to_sentence + def event_types_sentence(conference) + conference.event_types.map { |et| et.title.pluralize }.to_sentence end def sign_in_path @@ -191,4 +181,19 @@ module ApplicationHelper title: 'Open Source Event Manager' ) end + + # returns the url to be used for logo on basis of sponsorship level position + def get_logo(object) + if object.try(:sponsorship_level) + if object.sponsorship_level.position == 1 + object.picture.first.url + elsif object.sponsorship_level.position == 2 + object.picture.second.url + else + object.picture.others.url + end + else + object.picture.large.url + end + end end diff --git a/app/helpers/conference_helper.rb b/app/helpers/conference_helper.rb new file mode 100644 index 00000000..481461dc --- /dev/null +++ b/app/helpers/conference_helper.rb @@ -0,0 +1,17 @@ +module ConferenceHelper + # Return true if only call_for_papers or call_for_tracks is open + def one_call_open(*calls) + calls.one? { |call| call.try(:open?) } + end + + # URL for sponsorship emails + def sponsorship_mailto(conference) + [ + 'mailto:', + conference.contact.sponsor_email, + '?subject=', + url_encode(conference.short_title), + '%20Sponsorship' + ].join + 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/sponsors_helper.rb b/app/helpers/sponsors_helper.rb deleted file mode 100644 index 4a21c9cd..00000000 --- a/app/helpers/sponsors_helper.rb +++ /dev/null @@ -1,12 +0,0 @@ -module SponsorsHelper - # returns the url to be used for logo on basis of sponsorship level position - def get_logo(sponsor) - if sponsor.sponsorship_level.position == 1 - sponsor.picture.first.url - elsif sponsor.sponsorship_level.position == 2 - sponsor.picture.second.url - else - sponsor.picture.others.url - 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/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..ad9597e4 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -1,11 +1,11 @@ -class Commercial < ActiveRecord::Base +class Commercial < ApplicationRecord require 'oembed' belongs_to :commercialable, polymorphic: true has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } - validates :url, presence: true + validates :url, presence: true, uniqueness: { scope: :commercialable } validates :url, format: URI::regexp(%w(http https)) validate :valid_url @@ -20,6 +20,29 @@ class Commercial < ActiveRecord::Base end end + def self.read_file(file) + errors = {} + errors[:no_event] = [] + errors[:validation_errors] = [] + + file.read.each_line do |line| + # Get the event id (text before :) + id = line.match(/:/).pre_match.to_i + # Get the commercial url (text after :) + url = line.match(/:/).post_match + event = Event.find_by(id: id) + + # Go to next event, if the event is not found + errors[:no_event] << id && next unless event + + commercial = event.commercials.new(url: url) + unless commercial.save + errors[:validation_errors] << "Could not create commercial for event with ID #{event.id} (" + commercial.errors.full_messages.to_sentence + ')' + end + end + errors + end + private def valid_url diff --git a/app/models/conference.rb b/app/models/conference.rb index c56161f2..9adac888 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 @@ -33,6 +33,7 @@ class Conference < ActiveRecord::Base end has_many :resources, dependent: :destroy has_many :booths, dependent: :destroy + has_many :confirmed_booths, -> { where(state: 'confirmed') }, class_name: 'Booth' has_many :lodgings, dependent: :destroy has_many :registrations, dependent: :destroy @@ -45,7 +46,15 @@ class Conference < ActiveRecord::Base has_many :campaigns, dependent: :destroy has_many :commercials, as: :commercialable, dependent: :destroy has_many :subscriptions, dependent: :destroy - + has_one :call_for_events, -> { where(cfp_type: 'events') }, through: :program, source: :cfps + has_one :call_for_booths, -> { where(cfp_type: 'booths') }, through: :program, source: :cfps + has_one :call_for_tracks, -> { where(cfp_type: 'tracks') }, through: :program, source: :cfps + has_many :confirmed_tracks, -> { where(state: 'confirmed') }, through: :program, source: :tracks + has_many :highlighted_events, + -> { where(state: :confirmed, is_highlight: true) }, + through: :program, + source: :events + has_many :event_types, through: :program accepts_nested_attributes_for :venue accepts_nested_attributes_for :tickets, allow_destroy: true accepts_nested_attributes_for :sponsorship_levels, allow_destroy: true @@ -710,7 +719,7 @@ class Conference < ActiveRecord::Base # * +True+ -> If the registration limit has been reached or exceeded # * +False+ -> If the registration limit hasn't been exceeded def registration_limit_exceeded? - registration_limit > 0 && registrations.count + program.speakers.confirmed.count - program.speakers.confirmed.registered(program.conference).count >= registration_limit + registration_limit > 0 && registrations.count + program.speakers.confirmed.unregistered(program.conference).count >= registration_limit end # Returns an hexadecimal color given a collection. The returned color changed 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 360421f5..943572eb 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 } @@ -197,6 +197,14 @@ class Event < ActiveRecord::Base send(transition) end save + # If the event was previously scheduled, and then withdrawn or cancelled + # its event_schedule will have enabled set to false + # If the event is now confirmed again, we want it to be available for scheduling + Rails.logger.debug "transition is #{transition}" + if transition == :confirm + Rails.logger.debug "schedules #{EventSchedule.unscoped.where(event: self, enabled: false)}" + EventSchedule.unscoped.where(event: self, enabled: false).destroy_all + end rescue Transitions::InvalidTransition => e alert = "Update state failed. #{e.message}" end diff --git a/app/models/event_schedule.rb b/app/models/event_schedule.rb index 57edbec0..9d59713d 100644 --- a/app/models/event_schedule.rb +++ b/app/models/event_schedule.rb @@ -1,4 +1,5 @@ -class EventSchedule < ActiveRecord::Base +class EventSchedule < ApplicationRecord + default_scope { where(enabled: true) } belongs_to :schedule belongs_to :event belongs_to :room @@ -33,7 +34,7 @@ class EventSchedule < ActiveRecord::Base # Returns event schedules that are scheduled in the same room and start_time as event # def intersecting_event_schedules - room.event_schedules.where(start_time: start_time, schedule: schedule).where.not(id: id) + EventSchedule.unscoped.where(room: room, start_time: start_time, schedule: schedule).where.not(id: id) end def replacement? 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..b0f45f0c 100644 --- a/app/models/openid.rb +++ b/app/models/openid.rb @@ -1,6 +1,6 @@ -class Openid < ActiveRecord::Base +class Openid < ApplicationRecord belongs_to :user - validates :provider, :uid, presence: true + validates :provider, :uid, :email, presence: true # Searches for openid based on provider and uid. # Returns found openid or a new openid. 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 addda157..14554786 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 @@ -51,6 +51,10 @@ class Program < ActiveRecord::Base def registered(conference) joins(:registrations).where('registrations.conference_id = ?', conference.id) end + + def unregistered(conference) + self - registered(conference) + end end accepts_nested_attributes_for :event_types, allow_destroy: true @@ -165,7 +169,7 @@ class Program < ActiveRecord::Base # * +False+ -> If there is not any event for the given date def any_event_for_this_date?(date) parsed_date = DateTime.parse("#{date} 00:00").utc - EventSchedule.where(schedule: selected_schedule).where(start_time: parsed_date..(parsed_date + 1)).any? + EventSchedule.where(schedule: selected_schedule).where(start_time: parsed_date..(parsed_date + 1.day)).any? 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 13646c9f..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 @@ -61,7 +61,7 @@ class Ticket < ActiveRecord::Base end def tickets_turnover_total(id) - tickets = TicketPurchase.where(ticket_id: id) + tickets = TicketPurchase.where(ticket_id: id).paid tickets.inject(0){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } end diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index 71b44d18..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 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..d062529a 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) @@ -45,8 +45,8 @@ class User < ActiveRecord::Base attr_accessor :login has_many :event_users, dependent: :destroy - has_many :events, -> { uniq }, through: :event_users - has_many :presented_events, -> { joins(:event_users).where(event_users: {event_role: 'speaker'}).uniq }, through: :event_users, source: :event + has_many :events, -> { distinct }, through: :event_users + has_many :presented_events, -> { joins(:event_users).where(event_users: {event_role: 'speaker'}).distinct }, through: :event_users, source: :event has_many :registrations, dependent: :destroy do def for_conference conference where(conference: conference).first @@ -216,7 +216,7 @@ class User < ActiveRecord::Base end def proposals(conference) - events.where('program_id = ? AND event_users.event_role=?', conference.program.id, 'submitter') + events.where('program_id = ? AND (event_users.event_role=? OR event_users.event_role=?)', conference.program.id, 'submitter', 'speaker') end def proposal_count(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/pdfs/ticket_pdf.rb b/app/pdfs/ticket_pdf.rb index 9a09f9fe..d21a1e27 100644 --- a/app/pdfs/ticket_pdf.rb +++ b/app/pdfs/ticket_pdf.rb @@ -1,3 +1,5 @@ +require 'open-uri' + class TicketPdf < Prawn::Document def initialize(conference, user, physical_ticket, ticket_layout, file_name) super(page_layout: ticket_layout, page_size: 'A4', filename: file_name) @@ -43,11 +45,17 @@ class TicketPdf < Prawn::Document def draw_second_square move_up 150 if @conference.picture? - if 7 * @conference.picture.image[:width] > 12 * @conference.picture.image[:height] - image "#{Rails.root}/public#{@conference.picture_url}", at: [@mid_horizontal + 30, cursor], width: 120 - else - image "#{Rails.root}/public#{@conference.picture_url}", at: [@mid_horizontal + 30, cursor], height: 70 - end + conference_image = case @conference.picture.ticket.url[0, 4] + when 'http', 'ftp:' # CDNs + open(@conference.picture.ticket.url) + when '/sys' # local storage + open([ + Rails.root, + '/public', + @conference.picture.ticket.url + ].join) + end + image conference_image, at: [@mid_horizontal + 30, cursor] else image "#{Rails.root}/public/img/osem-logo.png", at: [@mid_horizontal + 30, cursor], height: 70 end diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index b17f0d76..41bcab7b 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -52,10 +52,6 @@ class PictureUploader < CarrierWave::Uploader::Base "system/#{object_class_name}/#{mounted_as}/#{model.id}" end - def image - @image ||= MiniMagick::Image.open(file.file) - end - # Create different versions of your uploaded files: version :large do process resize_to_fit: [300, 300] @@ -80,6 +76,11 @@ class PictureUploader < CarrierWave::Uploader::Base process resize_and_pad: [320, 120, 'white'] end + version :ticket, if: :conference? + version :ticket do + process resize_and_pad: [120, 70] + end + # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list @@ -95,4 +96,8 @@ class PictureUploader < CarrierWave::Uploader::Base def sponsor?(_picture) object_class_name == 'sponsors' end + + def conference?(_picture) + object_class_name == 'conferences' + end end diff --git a/app/views/admin/booths/show.html.haml b/app/views/admin/booths/show.html.haml index 6ed823e5..02d44609 100644 --- a/app/views/admin/booths/show.html.haml +++ b/app/views/admin/booths/show.html.haml @@ -1,7 +1,8 @@ .row .col-md-12 %h3 - = image_tag(@booth.picture.thumb.url, size: '20%', alt: '') + - if @booth.logo_link + = image_tag( @booth.picture.thumb.url, size: '20%', alt: '') = @booth.title .btn-group.pull-right = link_to 'Edit', edit_admin_conference_booth_path(@conference.short_title, @booth), class: 'btn btn-mini btn-primary' diff --git a/app/views/admin/campaigns/_form.html.haml b/app/views/admin/campaigns/_form.html.haml index 6b826300..71aa075e 100644 --- a/app/views/admin/campaigns/_form.html.haml +++ b/app/views/admin/campaigns/_form.html.haml @@ -11,7 +11,7 @@ .col-md-8 = semantic_form_for(@campaign, url: (@campaign.new_record? ? admin_conference_campaigns_path : admin_conference_campaign_path(@conference.short_title, @campaign))) do |f| = f.inputs do - = f.input :name + = f.input :name, input_html: { autofocus: true } = f.inputs name: 'UTM Parameters' do = f.input :utm_campaign, label: 'Campaign', hint: 'Groups all of the content from one campaign. E.g. 20percentpromocode' = f.input :utm_source, label: 'Source', hint: 'Which website is sending you traffic. E.g. Facebook, google+, blog' diff --git a/app/views/admin/cfps/_events_cfp.html.haml b/app/views/admin/cfps/_events_cfp.html.haml index f4557bb4..686f292e 100644 --- a/app/views/admin/cfps/_events_cfp.html.haml +++ b/app/views/admin/cfps/_events_cfp.html.haml @@ -21,7 +21,7 @@ %dt Event types: %dd - = event_types(@conference) + = event_types_sentence(@conference) %dt Tracks: %dd diff --git a/app/views/admin/cfps/index.html.haml b/app/views/admin/cfps/index.html.haml index fb075eae..1b80f411 100644 --- a/app/views/admin/cfps/index.html.haml +++ b/app/views/admin/cfps/index.html.haml @@ -7,7 +7,7 @@ - if @program.cfps .row .col-md-12 - %table.table.table-hover.datatable#tickets + %table.table.table-hover#tickets %thead %th Type %th Start Date @@ -27,7 +27,7 @@ = cfp.end_date.strftime('%A, %B %-d. %Y') %td %p - = markdown(truncate(cfp.description)) + = truncate(cfp.description) %td = pluralize(cfp.remaining_days, 'day') %td diff --git a/app/views/admin/commercials/index.html.haml b/app/views/admin/commercials/index.html.haml index 32779e2c..095ddad2 100644 --- a/app/views/admin/commercials/index.html.haml +++ b/app/views/admin/commercials/index.html.haml @@ -14,7 +14,7 @@ .row .col-md-6 = semantic_form_for(@commercial, url: admin_conference_commercials_path(conference_id: @conference.short_title)) do |f| - = f.input :url, label: 'URL', as: :string, input_html: { required: 'required' }, + = f.input :url, label: 'URL', as: :string, input_html: { required: 'required', autofocus: true }, hint: 'Just paste the url of your video/photo provider. YouTube, Vimeo, SpeakerDeck, SlideShare, Instagram, Flickr.' = f.action :submit, as: :button, button_html: { class: 'btn btn-primary pull-right', disabled: true } %hr diff --git a/app/views/admin/conferences/_doughnut_chart.html.haml b/app/views/admin/conferences/_doughnut_chart.html.haml index f4a8f0ba..6ad75cef 100644 --- a/app/views/admin/conferences/_doughnut_chart.html.haml +++ b/app/views/admin/conferences/_doughnut_chart.html.haml @@ -1,6 +1,6 @@ .text-center %h4 #{title} - %canvas.doughnut_chart{ id: "dough_#{title}", 'data-chart' => data.to_json } + %canvas.doughnut_chart{ id: "dough_#{title.parameterize.underscore}", 'data-chart' => data.to_json } - if data - data.each do |key, value| %span{ 'style' => "border-bottom: 3px solid #{value['color']}" } #{key}: #{value['value']} @@ -8,7 +8,7 @@ :javascript $(document).ready( function(){ - var d = $("#dough_#{title}"); + var d = $("#dough_#{title.parameterize.underscore}"); var dt = d.get(0).getContext('2d'); $(window).resize( respondCanvas ); diff --git a/app/views/admin/contacts/edit.html.haml b/app/views/admin/contacts/edit.html.haml index 872977b0..db06dd7e 100644 --- a/app/views/admin/contacts/edit.html.haml +++ b/app/views/admin/contacts/edit.html.haml @@ -8,7 +8,7 @@ .col-md-8 = semantic_form_for(@contact, url: admin_conference_contact_path(@conference.short_title), html: {multipart: true}) do |f| = f.inputs name: 'Mail' do - = f.input :email, hint: 'Contact email address for your conference. Will be used as reply-to address in emails sent out by the system.' + = f.input :email, input_html: { autofocus: true }, hint: 'Contact email address for your conference. Will be used as reply-to address in emails sent out by the system.' = f.input :sponsor_email, hint: 'This will appear in the sponsor segment of the splash for the sponsors to contact to the organizers' = f.inputs name: 'Social Media' do = f.input :social_tag, hint: "The hashtag you'll use on Twitter and Google+. Don't include the '#' sign!'" diff --git a/app/views/admin/difficulty_levels/_form.html.haml b/app/views/admin/difficulty_levels/_form.html.haml index fa47a88b..f28ab7e3 100644 --- a/app/views/admin/difficulty_levels/_form.html.haml +++ b/app/views/admin/difficulty_levels/_form.html.haml @@ -9,7 +9,7 @@ .row .col-md-8 = semantic_form_for(@difficulty_level, url: (@difficulty_level.new_record? ? admin_conference_program_difficulty_levels_path : admin_conference_program_difficulty_level_path(@conference.short_title, @difficulty_level))) do |f| - = f.input :title, required: true + = f.input :title, input_html: { autofocus: true }, required: true = f.input :description, input_html: {rows: 3, class: 'span6'} = f.input :color, input_html: {size: 6, type: 'color'} %p.text-right diff --git a/app/views/admin/event_types/_form.html.haml b/app/views/admin/event_types/_form.html.haml index 51a0ad99..29fac398 100644 --- a/app/views/admin/event_types/_form.html.haml +++ b/app/views/admin/event_types/_form.html.haml @@ -9,7 +9,7 @@ .row .col-md-12 = semantic_form_for(@event_type, url: (@event_type.new_record? ? admin_conference_program_event_types_path : admin_conference_program_event_type_path(@conference.short_title, @event_type))) do |f| - = f.input :title + = f.input :title, input_html: { autofocus: true } = f.input :length, input_html: {size: 3, type: 'number', step: @event_type.program.schedule_interval, min: @event_type.program.schedule_interval} = f.input :description = f.input :minimum_abstract_length, input_html: {size: 3} 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/events/index.html.haml b/app/views/admin/events/index.html.haml index f8b58b63..be7abe05 100644 --- a/app/views/admin/events/index.html.haml +++ b/app/views/admin/events/index.html.haml @@ -4,37 +4,60 @@ %h1 Events = "(#{@events.length})" if @events.any? - .pull-right + + .btn-group.pull-right + %button.btn.btn-primary{ 'data-toggle' => 'modal', 'data-target' => '#mass-commercials-modal', title: 'Mass import of commercials for events' } + Add Commercials + - if can? :create, Event - =link_to 'Add Event', new_admin_conference_program_event_path(@conference.short_title), class: 'button btn btn-default btn-info' + = link_to 'Add Event', new_admin_conference_program_event_path(@conference.short_title), class: 'button btn btn-default btn-info' + - if can? :read, Event .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 Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all') - %li= link_to 'Confirmed Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'confirmed') - %li= link_to 'All Events with Comments', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all_with_comments') - .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_events_path(@conference.short_title, format: :csv, event_export_option: 'all') - %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'confirmed') - %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all_with_comments') - .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_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all') - %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'confirmed') - %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all_with_comments') + %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 Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all') + %li= link_to 'Confirmed Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'confirmed') + %li= link_to 'All Events with Comments', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all_with_comments') + .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_events_path(@conference.short_title, format: :csv, event_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'confirmed') + %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all_with_comments') + .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_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'confirmed') + %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all_with_comments') + %p.text-muted All the submissions of your speakers + +.modal#mass-commercials-modal + .modal-dialog + .modal-content + .modal-header + %h1 Add commercials to events + .text-muted + Upload your file with data in the following format: + %b Event_ID:Commercial_Link + , eg. + %br + %b 11:https://youtube.com/myvideo + + .modal-body + = semantic_form_for '', url: mass_upload_commercials_admin_conference_program_path(@conference.short_title), method: :post do |f| + = f.input 'file', as: :file + .modal-footer + = f.submit 'Add', class: 'btn btn-primary' .row .col-md-4 = render partial: 'admin/conferences/doughnut_chart', locals: { title: 'Events state', data: @event_distribution } 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/programs/_form.html.haml b/app/views/admin/programs/_form.html.haml index 035093f0..9b42e2b0 100644 --- a/app/views/admin/programs/_form.html.haml +++ b/app/views/admin/programs/_form.html.haml @@ -9,7 +9,7 @@ = f.input :schedule_fluid, label: 'Allow submitters to change their event after it is scheduled' = f.input :rating, hint: 'Enter the number of different rating levels you want to have for voting on proposals. Enter 0 if you do not want to vote on proposals.' = f.input :languages, hint: "Enter the languages allowed for events as values of #{link_to('ISO 639-1', 'http://www.loc.gov/standards/iso639-2/php/code_list.php', target: "_blank")} language codes separated with commas. The first language would be the default language. Leave it blank if you do not want to specify languages.".html_safe - = f.input :schedule_interval, hint: "It is the minimal time interval of your schedule. The value should be 5, 6, 10, 12, 15, 20, 30 or 60. Warning! Some events could be unscheduled when changing this value." + = f.input :schedule_interval, input_html: { autofocus: true }, hint: "It is the minimal time interval of your schedule. The value should be 5, 6, 10, 12, 15, 20, 30 or 60. Warning! Some events could be unscheduled when changing this value." = f.input :blind_voting, hint: 'Enable this feature if you do not want to show voting results and voters prior to user submitting a vote. For the feature to work you need to set the voting dates below as well' = f.input :voting_start_date, as: :string, input_html: { id: 'datetimepicker-voting_start_date', readonly: true, value: (f.object.voting_start_date.to_formatted_s(:db_without_seconds) unless f.object.voting_start_date.nil?) } = f.input :voting_end_date, as: :string, input_html: { id: 'datetimepicker-voting_start_date', readonly: true, value: (f.object.voting_end_date.to_formatted_s(:db_without_seconds) unless f.object.voting_end_date.nil?) } diff --git a/app/views/admin/programs/show.html.haml b/app/views/admin/programs/show.html.haml index 47e50fb6..eceb21c5 100644 --- a/app/views/admin/programs/show.html.haml +++ b/app/views/admin/programs/show.html.haml @@ -22,7 +22,7 @@ %dt Event types: %dd - = event_types(@conference) + = event_types_sentence(@conference) %dt Tracks: %dd diff --git a/app/views/admin/reports/_all_events.html.haml b/app/views/admin/reports/_all_events.html.haml index 98f405ea..cca8968a 100644 --- a/app/views/admin/reports/_all_events.html.haml +++ b/app/views/admin/reports/_all_events.html.haml @@ -5,7 +5,7 @@ All Events = "(#{@events.length})" %p.text-muted - All submissions and the information that they are mssing + All submissions and the information that they are missing .col-md-12 %table.table.table-striped.table-bordered.table-hover.datatable diff --git a/app/views/admin/resources/_form.html.haml b/app/views/admin/resources/_form.html.haml index ef999104..ce5f25b0 100644 --- a/app/views/admin/resources/_form.html.haml +++ b/app/views/admin/resources/_form.html.haml @@ -8,7 +8,7 @@ .row .col-md-8 = semantic_form_for(@resource, :url => (@resource.new_record? ? admin_conference_resources_path : admin_conference_resource_path(@conference.short_title, @resource))) do |f| - = f.input :name + = f.input :name, input_html: { autofocus: true } = f.input :description, input_html: { rows: 5, data: { provide: 'markdown-editable' } } = f.input :used = f.input :quantity diff --git a/app/views/admin/roles/_form.html.haml b/app/views/admin/roles/_form.html.haml index 2204ef89..860f43a9 100644 --- a/app/views/admin/roles/_form.html.haml +++ b/app/views/admin/roles/_form.html.haml @@ -10,6 +10,6 @@ = semantic_form_for @role, url: @url do |f| .row .col-md-5 - = f.input :description + = f.input :description, input_html: { autofocus: true } = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/roles/show.html.haml b/app/views/admin/roles/show.html.haml index b264bc5f..b8796121 100644 --- a/app/views/admin/roles/show.html.haml +++ b/app/views/admin/roles/show.html.haml @@ -24,7 +24,7 @@ = u.label 'Add user by email: ' .input-group - = u.input :email, label: false, placeholder: "User's email" + = u.input :email, input_html: { autofocus: true }, label: false, placeholder: "User's email" .input-group-btn = u.submit 'Add', id: 'user-add', class: 'btn btn-primary' diff --git a/app/views/admin/rooms/_form.html.haml b/app/views/admin/rooms/_form.html.haml index eec272cd..90de99e0 100644 --- a/app/views/admin/rooms/_form.html.haml +++ b/app/views/admin/rooms/_form.html.haml @@ -9,7 +9,7 @@ .row .col-md-8 = semantic_form_for(@room, url: (@room.new_record? ? admin_conference_venue_rooms_path : admin_conference_venue_room_path(@conference.short_title, @room))) do |f| - = f.input :name, input_html: { autofocus: true} + = f.input :name, input_html: { autofocus: true } = f.input :size, label: 'Capacity', input_html: {size: 5} %p.text-right = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/splashpages/_form.html.haml b/app/views/admin/splashpages/_form.html.haml index c1897745..1d15b38c 100644 --- a/app/views/admin/splashpages/_form.html.haml +++ b/app/views/admin/splashpages/_form.html.haml @@ -2,21 +2,46 @@ .col-md-12 .page-header %h1 Splashpage -.row - .col-md-8 - = semantic_form_for(@splashpage, url: admin_conference_splashpage_path(@conference.short_title)) do |f| + += semantic_form_for(@splashpage, url: admin_conference_splashpage_path(@conference.short_title)) do |f| + .row + .col-md-12 = f.inputs name: 'Components' do - = f.input :include_tracks, label: 'Display tracks', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_tracks) } - = f.input :include_program, label: 'Display program', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_program) } - = f.input :include_cfp, label: 'Display call for papers information on splashpage, while cfp is open', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_cfp) } - = f.input :include_venue, label: 'Display venue', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_venue) } - = f.input :include_registrations, label: 'Display the registration period', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_registrations) } - = f.input :include_tickets, label: 'Display tickets', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_tickets) } - = f.input :include_lodgings, label: 'Display the lodgings', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_lodgings) } - = f.input :include_sponsors, label: 'Display sponsors', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_sponsors) } - = f.input :include_booths, label: 'Display confirmed booths', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_booths) } - = f.input :include_social_media, label: 'Display social media', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_social_media) } + %ul.fa-ul + %li + = f.input :include_cfp, label: 'Display call for papers and call for tracks, while open', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_cfp) } + %li + = f.input :include_program, label: 'Display the program', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_program) } + + %ul.fa-ul + %li + = f.input :include_tracks, label: 'Include confirmed tracks', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_tracks) } + %li + = f.input :include_booths, label: 'Include confirmed booths', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_booths) } + + %li + = f.input :include_registrations, label: 'Display the registration period', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_registrations) } + + %li + = f.input :include_tickets, label: 'Display tickets', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_tickets) } + + %li + = f.input :include_venue, label: 'Display the venue', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_venue) } + + %li + = f.input :include_lodgings, label: 'Display the lodgings', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_lodgings) } + + %li + = f.input :include_sponsors, label: 'Display sponsors', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_sponsors) } + + %li + = f.input :include_social_media, label: 'Display social media links', input_html: { checked: params[:action] == 'new' || @splashpage.try(:include_social_media) } + = f.inputs name: 'Access' do - = f.input :public, label: 'Make splash page public?' + %ul.fa-ul + %li + = f.input :public, label: 'Make splash page public?' + .row + .col-md-12 %p.text-right - = f.submit 'Save Splashpage', class: 'btn btn-primary' + = f.submit 'Save Changes', class: 'btn btn-primary' diff --git a/app/views/admin/splashpages/show.html.haml b/app/views/admin/splashpages/show.html.haml index c185b119..ec625385 100644 --- a/app/views/admin/splashpages/show.html.haml +++ b/app/views/admin/splashpages/show.html.haml @@ -8,92 +8,47 @@ with all the information for your conference - if @splashpage .row - .col-md-8 - %dl.dl-horizontal - %dt - Include Tracks: - %dd - - if @splashpage.include_tracks - Yes - - else - No - %dt - Include Program: - %dd - - if @splashpage.include_program - Yes - - else - No - %dt - Include CFP: - %dd - - if @splashpage.include_cfp - Yes - - else - No - %dt - Include Venue: - %dd - -if @splashpage.include_venue - Yes - -else - No - %dt - Include Registrations: - %dd - - if @splashpage.include_registrations - Yes - - else - No - %dt - Include Tickets: - %dd - - if @splashpage.include_tickets - Yes - - else - No - %dt - Include Lodgins - %dd - -if @splashpage.include_lodgings - Yes - -else - No - %dt - Include Sponsors: - %dd - - if @splashpage.include_sponsors - Yes - - else - No - %dt - Include Booths - %dd - - if @splashpage.include_booths - Yes - - else - No - %dt - Include Social Media: - %dd - - if @splashpage.include_social_media - Yes - - else - No - %dt - Public - %dd - - if @splashpage.public - Yes - - else - No + .col-md-12 + %ul.fa-ul + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_cfp?}" } + Display call for papers and call for tracks, while open + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_program?}" } + Display the program + %ul.fa-ul + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_program?}" } + Include confirmed tracks + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_booths?}" } + Include confirmed booths + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_registrations?}" } + Display the registration period + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_tickets?}" } + Display tickets + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_venue?}" } + Display the venue + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_lodgings?}" } + Display the lodgings + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_sponsors?}" } + Display sponsors + %li + %i{ class: "fa-li #{icon_for_todo @splashpage.include_social_media?}" } + Display social media links + .row .col-md-12 - - if can? :update, @splashpage - = link_to 'Edit', edit_admin_conference_splashpage_path, class: 'btn btn-primary' - - if can? :destroy, @splashpage - = link_to 'Delete', admin_conference_splashpage_path, - method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' + - if can? :update, @splashpage + = link_to 'Edit', edit_admin_conference_splashpage_path, class: 'btn btn-primary' + - if can? :destroy, @splashpage + = link_to 'Delete', admin_conference_splashpage_path, + method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' - else .row .col-md-12.text-right diff --git a/app/views/admin/sponsors/_form.html.haml b/app/views/admin/sponsors/_form.html.haml index ba24f9f3..c465fc48 100644 --- a/app/views/admin/sponsors/_form.html.haml +++ b/app/views/admin/sponsors/_form.html.haml @@ -9,7 +9,7 @@ .row .col-md-8 = semantic_form_for(@sponsor, url: (@sponsor.new_record? ? admin_conference_sponsors_path : admin_conference_sponsor_path(@conference.short_title, @sponsor))) do |f| - = f.input :name + = f.input :name, input_html: { autofocus: true } = f.input :description = image_tag f.object.picture.thumb.url if f.object.picture? = f.input :picture diff --git a/app/views/admin/sponsors/index.html.haml b/app/views/admin/sponsors/index.html.haml index 1c8f1077..d2fc512c 100644 --- a/app/views/admin/sponsors/index.html.haml +++ b/app/views/admin/sponsors/index.html.haml @@ -19,7 +19,8 @@ - @conference.sponsors.each do |sponsor| %tr %td - = image_tag(sponsor.picture.thumb.url, width: '20%') + - if sponsor.picture? + = image_tag(sponsor.picture.thumb.url, width: '20%') %td = sponsor.name %td diff --git a/app/views/admin/sponsorship_levels/_form.html.haml b/app/views/admin/sponsorship_levels/_form.html.haml index 60848928..ae819a71 100644 --- a/app/views/admin/sponsorship_levels/_form.html.haml +++ b/app/views/admin/sponsorship_levels/_form.html.haml @@ -9,6 +9,6 @@ .row .col-md-8 = semantic_form_for(@sponsorship_level, url: (@sponsorship_level.new_record? ? admin_conference_sponsorship_levels_path : admin_conference_sponsorship_level_path(@conference.short_title, @sponsorship_level))) do |f| - = f.input :title + = f.input :title, input_html: { autofocus: true } %p.text-right = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/targets/_form.html.haml b/app/views/admin/targets/_form.html.haml index 1e81989b..df22922e 100644 --- a/app/views/admin/targets/_form.html.haml +++ b/app/views/admin/targets/_form.html.haml @@ -9,7 +9,7 @@ .col-md-8 = semantic_form_for(@target, url: (@target.new_record? ? admin_conference_targets_path : admin_conference_target_path(@conference.short_title, @target))) do |f| = f.input :due_date, as: :string, input_html: { class: 'target-due-date-datepicker'}, label: 'Until when do you want to have ' - = f.input :target_count, label: 'this amount of ' + = f.input :target_count, input_html: { autofocus: true }, label: 'this amount of ' = f.input :unit, as: :select, label: 'Unit', class: 'form-control', collection: Target.units.values, include_blank: false %p.text-right = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/tickets/_form.html.haml b/app/views/admin/tickets/_form.html.haml index 319f7996..f66cea51 100644 --- a/app/views/admin/tickets/_form.html.haml +++ b/app/views/admin/tickets/_form.html.haml @@ -9,8 +9,8 @@ .row .col-md-8 = semantic_form_for(@ticket, url: (@ticket.new_record? ? admin_conference_tickets_path : admin_conference_ticket_path(@conference.short_title, @ticket))) do |f| - = f.input :title - = f.input :description, input_html: { rows: 5, data: { provide: "markdown-editable" } } + = f.input :title, input_html: { autofocus: true } + = 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', 'CHF'], include_blank: false = f.input :registration_ticket, hint: 'A registration ticket is with which user register for the conference.' diff --git a/app/views/admin/tracks/_form.html.haml b/app/views/admin/tracks/_form.html.haml index 9109e4f5..36ff5734 100644 --- a/app/views/admin/tracks/_form.html.haml +++ b/app/views/admin/tracks/_form.html.haml @@ -9,12 +9,12 @@ .row .col-md-12 = semantic_form_for(@track, url: (@track.new_record? ? admin_conference_program_tracks_path(@conference.short_title) : admin_conference_program_track_path(@conference.short_title, @track))) do |f| - = f.input :name + = f.input :name, input_html: { autofocus: true } = f.input :short_name, hint: "A short and unique handle for the track, using only letters, numbers, underscores, and dashes. This will be used to identify the track in URLs etc. Example: 'my_awesome_track'", input_html: { required: 'required', pattern: '[a-zA-Z0-9_-]+', title: 'Only letters, numbers, underscores, and dashes.' } = f.input :color, input_html: {size: 6, type: 'color'}, required: true = 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', required: @track.self_organized_and_accepted_or_confirmed? } = f.input :end_date, as: :string, input_html: { id: 'registration-period-end-datepicker', readonly: 'readonly', required: @track.self_organized_and_accepted_or_confirmed? } - - if @conference.venue.try(:rooms) + - if @conference.venue.try(:rooms).present? = f.input :room, as: :select, collection: (@conference.venue.rooms).map {|room| ["#{room.name}", room.id]}, include_blank: true, label: 'Room', input_html: { class: 'select-help-toggle', required: @track.self_organized_and_accepted_or_confirmed? } - else %b 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 6b182c2f..0df93aa9 100644 --- a/app/views/admin/versions/_object_desc_and_link.html.haml +++ b/app/views/admin/versions/_object_desc_and_link.html.haml @@ -234,6 +234,12 @@ = link_to_organization(version.conference_id) - else (Organization Deleted) + - elsif version.item_type == 'Commercial' + - commercial = current_or_last_object_state(version.item_type, version.item_id) + - commercialable = current_or_last_object_state(commercial.commercialable_type, commercial.commercialable_id) + - unless commercial.commercialable_type == 'Conference' + in conference + = link_to_conference(version.conference_id) - else in conference = link_to_conference(version.conference_id) diff --git a/app/views/booths/_form.html.haml b/app/views/booths/_form.html.haml index 55a51432..4f5b6018 100644 --- a/app/views/booths/_form.html.haml +++ b/app/views/booths/_form.html.haml @@ -2,7 +2,7 @@ .row .col-md-8 = semantic_form_for(@booth, url: @url, html: { multipart: true }) do |f| - = f.input :title, as: :string, autofocus: true, required: true + = f.input :title, as: :string, input_html: { autofocus: true }, required: true = f.input :description, input_html: { rows: 5, data: { provide: 'markdown-editable' } }, required: true, hint: 'This field becomes public upon request acceptance' = f.input :reasoning, input_html: { rows: 5, data: { provide: 'markdown-editable' } }, required: true, diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index a50cf198..83efbd60 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -104,7 +104,9 @@ = 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" + .btn-group + = link_to 'View all tickets', conference_physical_tickets_path(@conference.short_title), class: "btn btn-success" + = link_to 'Get more tickets', conference_tickets_path(@conference.short_title), class: "btn btn-default" - else You haven't bought any tickets. = link_to 'Please get some tickets to support us!', conference_tickets_path(@conference.short_title) diff --git a/app/views/conferences/_booths.haml b/app/views/conferences/_booths.haml new file mode 100644 index 00000000..da14526e --- /dev/null +++ b/app/views/conferences/_booths.haml @@ -0,0 +1,15 @@ +.row + .col-md-12 + %h3.text-center Booths +.row.row-centered + - booths.each do |booth| + .col-md-2.col-sm-2.col-centered.col-top.booth + %a.thumbnail{ href: '#', + data: { toggle: 'modal', target: "#modal-booth-#{booth.id}" } } + - if booth.picture? + = image_tag get_logo(booth), + class: ['img-responsive', 'img-rounded'], + title: booth.title + - else + .caption + %h3.text-center= booth.title diff --git a/app/views/conferences/_booths.html.haml b/app/views/conferences/_booths.html.haml deleted file mode 100644 index b40af9b8..00000000 --- a/app/views/conferences/_booths.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#booths' } Booths - -.container - .row - .col-md-12.text-center - %h2 Booths - - @conference.booths.confirmed.each_slice(3).with_index do |slice, index_for_row| - .row.row-centered - - slice.each.with_index do |booth, index_for_column| - .col-md-4.col-sm-4.col-xs-10.col-centered.col-top - .thumbnail - - if booth.logo_link - = link_to booth.website_url, class: 'thumbnail' do - = image_tag booth.picture.large.url - .caption - %h3.text-center - = booth.title - %p.text-center.text-muted - = link_to "#show_descrition_#{index_for_row}_#{index_for_column}", "data-toggle"=>"collapse" do - learn more - .collapse{ id: "show_descrition_#{index_for_row}_#{index_for_column}" } - = markdown(booth.description) diff --git a/app/views/conferences/_call_for_content.haml b/app/views/conferences/_call_for_content.haml new file mode 100644 index 00000000..ab24f407 --- /dev/null +++ b/app/views/conferences/_call_for_content.haml @@ -0,0 +1,16 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#call' } Call For Content + +%section#call + .container + .row + - if one_call_open(call_for_events, call_for_tracks) + .col-md-3.col-sm-3.hidden-xs   + - if call_for_events.try(:open?) + = render 'call_for_papers', conference_id: conference.short_title, + call: call_for_events, event_types: event_types, tracks: tracks + .col-md-2.col-sm-2   + - if call_for_tracks.try(:open?) + = render 'call_for_tracks', conference_id: conference.short_title, + call: call_for_tracks diff --git a/app/views/conferences/_call_for_paper.html.haml b/app/views/conferences/_call_for_paper.html.haml deleted file mode 100644 index 289c3d9e..00000000 --- a/app/views/conferences/_call_for_paper.html.haml +++ /dev/null @@ -1,43 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#callforpapers' } Call For Papers - -.container - .row - .col-md-12.text-center - %h2 - Call for Papers - %p.lead - We are ready to accept your proposals for sessions! - .row - .col-md-6.col-md-offset-3.col-sm-10.col-sm-offset-1 - %p - - if @conference.program.event_types.any? - You can submit proposals for - %span.notranslate - = "#{event_types(@conference)}." - - if @conference.program.tracks.any? - Proposals should fit in one of the - %span.notranslate - = "#{pluralize(@conference.program.tracks.count, 'track')}:" - = "#{tracks(@conference)}." - The submission period has begun - %em.notranslate - = @conference.program.cfp.start_date.strftime('%A, %B %-d. %Y') - and closes - %em.notranslate - = @conference.program.cfp.end_date.strftime('%A, %B %-d. %Y.') - - if @conference.program.cfp_open? - That means you have only - %b.notranslate= pluralize(@conference.program.cfp.remaining_days, 'day') - left! - Remember - %span.notranslate - = @conference.short_title - will only be as good as the sessions you present. Submit early, submit often! - - else - The submission period is closed. - .row - .col-md-12.text-center - %p.cta-button - = link_to "Submit your paper now", conference_program_proposals_path(@conference.short_title), class: 'btn btn-success btn-lg text-center' diff --git a/app/views/conferences/_call_for_papers.haml b/app/views/conferences/_call_for_papers.haml new file mode 100644 index 00000000..3bf0f295 --- /dev/null +++ b/app/views/conferences/_call_for_papers.haml @@ -0,0 +1,27 @@ +- cache [conference_id, call, event_types, tracks, '#splash#callforpapers'] do + .col-md-5.col-sm-5.text-center + %h2 + Call for Papers + %p.lead + We are now accepting proposals for sessions! + %p + - if event_types.any? + You can submit proposals for + %span.notranslate + = event_types.map(&:pluralize).to_sentence + '.' + - if tracks.any? + Proposals should fit in one of the + %span.notranslate + = pluralize(tracks.length, 'track') + ':' + = tracks.to_sentence + '.' + The submission period is open + %em.notranslate + = date_string(call.start_date, call.end_date) + '.' + %b + You have + = pluralize(call.remaining_days, 'day') + left! + %p.cta-button + = link_to "Submit your proposal now", + conference_program_proposals_path(conference_id), + class: 'btn btn-success btn-lg text-center' diff --git a/app/views/conferences/_call_for_tracks.haml b/app/views/conferences/_call_for_tracks.haml new file mode 100644 index 00000000..7eb80fa6 --- /dev/null +++ b/app/views/conferences/_call_for_tracks.haml @@ -0,0 +1,19 @@ +- cache [conference_id, call, '#splash#callfortracks'] do + .col-md-5.col-sm-5.text-center + %h2 + Call for Tracks + %p.lead + We are now accepting custom track requests! + %p + Would you like to host a mini-summit, sub-conference, or hack space? + The submission period for track requests is open + %em + = date_string(call.start_date, call.end_date) + '.' + %b + You have + = pluralize(call.remaining_days, 'day') + left! + %p.cta-button + = link_to("Submit your request for track", + conference_program_tracks_path(conference_id), + class: 'btn btn-success btn-lg text-center') diff --git a/app/views/conferences/_call_for_tracks.html.haml b/app/views/conferences/_call_for_tracks.html.haml deleted file mode 100644 index 1abeb956..00000000 --- a/app/views/conferences/_call_for_tracks.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#callfortracks' } Call For Tracks - -.container - .row - .col-md-12.text-center - %h2 - Call for Tracks - %p.lead - We are ready to accept requests for tracks! - .row - .col-md-6.col-md-offset-3.col-sm-10.col-sm-offset-1 - %p - The submission period for track requests has begun - %em.notranslate - = @conference.program.cfps.for_tracks.start_date.strftime('%A, %B %-d. %Y') - and closes - %em.notranslate - = @conference.program.cfps.for_tracks.end_date.strftime('%A, %B %-d. %Y.') - - if @conference.program.cfps.for_tracks.try(:open?) - That means you have only - %b.notranslate= pluralize(@conference.program.cfps.for_tracks.remaining_days, 'day') - left! - - else - The submission period for track requests is closed. - .row - .col-md-12.text-center - %p.cta-button - = link_to "Submit your request for track", conference_program_tracks_path(@conference.short_title), class: 'btn btn-success btn-lg text-center' diff --git a/app/views/conferences/_footer.html.haml b/app/views/conferences/_footer.haml similarity index 100% rename from app/views/conferences/_footer.html.haml rename to app/views/conferences/_footer.haml diff --git a/app/views/conferences/_header.haml b/app/views/conferences/_header.haml new file mode 100644 index 00000000..08ad1e94 --- /dev/null +++ b/app/views/conferences/_header.haml @@ -0,0 +1,35 @@ +- cache [conference, venue, '#splash#header'] do + #banner + .container + .row + .col-md-8.col-md-offset-2#header + .row + .col-md-4 + - if conference.picture? + = image_tag(conference.picture_url, + class: 'img-responsive img-center', + id: 'splash-logo') + .col-md-8 + %h1 + = conference.title + %h3 + - if conference.start_date && conference.end_date + %span.date.text-nowrap + = date_string(conference.start_date, conference.end_date) + - if conference.venue + %span.venue.text-nowrap + - if venue.website + = sanitize link_to(venue.name, venue.website) + - else + = venue.city + - if venue.country_name != 'US' + • + = venue.country_name + + - unless conference.description.blank? + %section#about + .container + .row + .col-md-8.col-md-offset-2 + %h3.text-center + = markdown(conference.description) diff --git a/app/views/conferences/_highlights.haml b/app/views/conferences/_highlights.haml new file mode 100644 index 00000000..1949f4a2 --- /dev/null +++ b/app/views/conferences/_highlights.haml @@ -0,0 +1,19 @@ +.row + .col-md-12 + %h3.text-center + Program Highlights +.row + .col-md-12 + .row.row-centered + - highlights.each do |event| + - speaker = event.speakers_ordered.first + .col-md-3.col-sm-3.col-centered.col-top.highlights + = link_to(conference_program_proposal_path(conference_id, + event), + class: 'thumbnail') do + = image_tag speaker.gravatar_url(size: 300), + class: ['img-responsive', 'img-circle'], + title: speaker.name + .caption + %h3.text-center= speaker.name + %h4.text-center= event.title diff --git a/app/views/conferences/_lodging.haml b/app/views/conferences/_lodging.haml new file mode 100644 index 00000000..724e78ca --- /dev/null +++ b/app/views/conferences/_lodging.haml @@ -0,0 +1,41 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#lodging' } Lodging + +- cache [venue, lodgings, '#splash#lodging'] do + %section#lodging + .container + .row + .col-md-12.text-center + %h2 + Where to stay + - if venue + in + = venue.city + %p.lead + We recommend the following accommodations for your visit. + + .row.row-centered + - lodgings.each do |lodging| + .col-md-4.col-sm-4.col-centered.col-top + .thumbnail + - if lodging.picture? + - if lodging.website_link.present? + = link_to(lodging.website_link, class: 'thumbnail') do + = image_tag lodging.picture.large.url, + class: 'img-responsive img-lodging' + - else + = image_tag lodging.picture.large.url, + class: 'img-responsive img-lodging' + - else + %p.text-center + - if lodging.website_link.present? + = link_to(lodging.website_link, class: 'thumbnail') do + %i.fa.fa-home.fa-5x + - else + %i.fa.fa-home.fa-5x + .caption + %h3.text-center + = lodging.name + - if lodging.description.present? + = markdown(lodging.description) diff --git a/app/views/conferences/_lodging.html.haml b/app/views/conferences/_lodging.html.haml deleted file mode 100644 index 561e2421..00000000 --- a/app/views/conferences/_lodging.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#lodging' } Lodging - -.container - .row - .col-md-12.text-center - %h2 - Where to stay - - if @conference.venue - in - = @conference.venue.city - %p.lead - We recommend these affordable lodging accommodations for your visit. - - .row.row-centered{ style:"display: flex; flex-wrap: wrap" } - - @conference.lodgings.each do |lodging| - .col-md-4.col-sm-4.col-centered.col-top{ style:"display:flex;" } - .thumbnail - - if lodging.picture? - -if lodging.website_link.present? - = link_to(lodging.website_link, class: 'thumbnail') do - = image_tag lodging.picture.large.url, class: 'img-responsive img-lodging' - - else - = image_tag lodging.picture.large.url, class: 'img-responsive img-lodging' - - else - %p.text-center - -if lodging.website_link.present? - = link_to(lodging.website_link, class: 'thumbnail') do - %i.fa.fa-home.fa-5x - - else - %i.fa.fa-home.fa-5x - .caption - %h3.text-center - = lodging.name - -if lodging.description.present? - = markdown(lodging.description) diff --git a/app/views/conferences/_modal_description.haml b/app/views/conferences/_modal_description.haml new file mode 100644 index 00000000..7fe4173b --- /dev/null +++ b/app/views/conferences/_modal_description.haml @@ -0,0 +1,23 @@ +- content_for :modals do + - cache [object, '#modal'] do + .modal.fade{ id: "modal-#{object.class.name.downcase}-#{object.id}" } + .modal-dialog + .modal-content + .modal-header + %button.close{ data: { dismiss: 'modal' } } + %i.fa.fa-close + %h3.modal-title + = object.try(:title) || object.try(:name) + .modal-body + %p.logo + = link_to object.website_url || '#', target: '_blank' do + - img_classes = ['img-responsive center-block'] + - if object.is_a? Sponsor + - img_classes << ['img-sponsor', + "img-sponsor-#{object.sponsorship_level.position}"] + - if object.picture? + = image_tag get_logo(object), class: img_classes + %p.description + = object.description + .modal-footer + = link_to nil, object.website_url, target: '_blank' diff --git a/app/views/conferences/_program.haml b/app/views/conferences/_program.haml new file mode 100644 index 00000000..2ab2ef70 --- /dev/null +++ b/app/views/conferences/_program.haml @@ -0,0 +1,38 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#program' } Program + +- cache [conference, highlights, tracks, booths, '#splash#program'] do + %section#program + .container + .row + .col-md-12 + %p.lead.text-center + %span.notranslate + = conference.title + has the most awesome program ever! + + - unless highlights.blank? + = render 'highlights', conference_id: conference.short_title, + highlights: highlights + + - if conference.splashpage.include_tracks + - unless tracks.blank? + = render 'tracks', tracks: tracks + + - if conference.splashpage.include_booths + - unless booths.blank? + = render 'booths', booths: booths + + - if conference.program.try(:schedule_public?) + .row + .col-md-12 + %p.cta-button.text-center + = link_to(conference_schedule_path(conference.short_title), + class: 'btn btn-success btn-lg') do + Full Schedule + +- unless booths.blank? + - booths.each do |booth| + - content_for :modals do + = render 'modal_description', object: booth diff --git a/app/views/conferences/_program.html.haml b/app/views/conferences/_program.html.haml deleted file mode 100644 index f07816a4..00000000 --- a/app/views/conferences/_program.html.haml +++ /dev/null @@ -1,40 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#callforpapers' } Call For Papers - -.container - .row - .col-md-12.text-center - %h2 - Call for Papers - %p.lead - We are ready to accept your proposals for sessions! - .row - .col-md-6.col-md-offset-3.col-sm-10.col-sm-offset-1 - %p - - if @conference.program.event_types.any? - You can submit proposals for - = "#{event_types(@conference)}." - - if @conference.tracks.any? - Proposals should fit in one of the - = "#{pluralize(@conference.tracks.count, 'track')}:" - = "#{tracks(@conference)}." - The submission period has begun - %em - = @program.cfp.start_date.strftime('%A, %B %-d. %Y') - and closes - %em - = @program.cfp.end_date.strftime('%A, %B %-d. %Y.') - - if @conference.cfp_open? - That means you have only - %b= pluralize(@program.cfp.remaining_days, 'day') - left! - Remember - = @conference.short_title - will only be as good as the sessions you present. Submit early, submit often! - - else - The submission period is closed. - .row - .col-md-12.text-center - %p.cta-button - = link_to "Submit your paper now", conference_proposals_path(@conference.short_title), class: 'btn btn-success btn-lg text-center' diff --git a/app/views/conferences/_registration.haml b/app/views/conferences/_registration.haml new file mode 100644 index 00000000..d789cbf2 --- /dev/null +++ b/app/views/conferences/_registration.haml @@ -0,0 +1,33 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#registration' } Registration + +- cache [conference, registration_period, tickets, '#splash#registration'] do + %section#registration + .container + .row + .col-md-12.text-center + %h1 Registration + - if conference.registration_limit_exceeded? + %p + Sorry, the conference registration limit has exceeded + - elsif tickets.empty? + %p.lead + Going to + = conference.short_title + is free of charge. + %p + We only ask you to register yourself before + = date_string(registration_period.end_date) + so we can plan for the right amount of people. + %p.cta-button + - else + %p + The registration period is open + = date_string(registration_period.start_date, + registration_period.end_date) + - if conference.registration_open? + %p.cta-button + = link_to('Register Now', + new_conference_conference_registration_path(conference_id), + class: 'btn btn-lg btn-success') diff --git a/app/views/conferences/_registration.html.haml b/app/views/conferences/_registration.html.haml deleted file mode 100644 index 5614bdba..00000000 --- a/app/views/conferences/_registration.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#registration' } Registration - -.container - .row - .col-md-12.text-center - %h1 Registration - - - if @conference.registration_limit_exceeded? - %p - Sorry, the conference registration limit has exceeded - - else - - if @conference.tickets.empty? - %p.lead - Going to - = @conference.short_title - is free of charge. - %p - We only ask you to register yourself until - = @conference.registration_period.end_date.strftime('%A, %B %-d. %Y') - so we can plan for the right amount of people. - %p.cta-button - - else - %p - The registration period ends on - = @conference.registration_period.end_date.strftime('%A, %B %-d. %Y') - %p.cta-button - = link_to(new_conference_conference_registration_path(@conference.short_title), class: 'btn btn-lg btn-success') do - Register Now diff --git a/app/views/conferences/_schedule_splashpage.html.haml b/app/views/conferences/_schedule_splashpage.html.haml deleted file mode 100644 index 790582cb..00000000 --- a/app/views/conferences/_schedule_splashpage.html.haml +++ /dev/null @@ -1,57 +0,0 @@ -.container - .row - .col-md-12 - %h2.text-center - Program - %p.lead.text-center - %span.notranslate - = @conference.short_title - has the most awesome program ever! - - if @conference.splashpage and @conference.program.tracks.any? and @conference.splashpage.include_tracks - See rock-star speakers cover the topics of - - if @conference.splashpage and @conference.splashpage.include_tracks - - @conference.program.tracks.confirmed.each_slice(3) do |slice| - .row.row-centered - - slice.each do |track| - .col-md-4.col-sm-4.col-centered.col-top.track - %h4.text-center - = track.name - = markdown(track.description) - - if track.start_date - %br - From: #{track.start_date.strftime('%A, %B %-d. %Y')} - - if track.end_date - %br - To: #{track.end_date.strftime('%A, %B %-d. %Y')} - - if track.room - %br - In: #{track.room.name} - - - if @conference.program and @conference.program.schedule_public - .row - .col-md-12 - %p.cta-button.text-center - = link_to(conference_schedule_path(@conference.short_title), class: 'btn btn-default btn-lg') do - Full Schedule - - - %h3.text-center - Don't miss out! - %br - - if @conference.program.events.highlights.any? - .row - .col-md-12 - - @conference.program.events.highlights.each_slice(2) do |slice| - .row.row-centered - - slice.each do |event| - .col-md-6.col-centered.col-top.highlights - %p.text-center - %b= event.title - %h5.text-center - = markdown truncate(event.abstract, length: 500, separator: ' ') - = link_to "Read More", conference_program_proposal_path(@conference.short_title, event) - - = content_for :splash_nav do - %li - =link_to('#program', class: 'smoothscroll') do - Program diff --git a/app/views/conferences/_social_media.haml b/app/views/conferences/_social_media.haml new file mode 100644 index 00000000..32cf1b16 --- /dev/null +++ b/app/views/conferences/_social_media.haml @@ -0,0 +1,20 @@ +- cache [contact, '#splash#social'] do + %section#social-media + .container + .row + .col-md-12.text-center + - unless contact.facebook.blank? + = link_to "#{ contact.facebook }" do + %i.fa.fa-facebook-square.fa-4x + - unless contact.twitter.blank? + = link_to "#{ contact.twitter }" do + %i.fa.fa-twitter.fa-4x + - unless contact.instagram.blank? + = link_to "#{ contact.instagram }" do + %i.fa.fa-instagram.fa-4x + - unless contact.googleplus.blank? + = link_to "#{ contact.googleplus }" do + %i.fa.fa-google-plus-square.fa-4x + - unless contact.email.blank? + = mail_to "#{ contact.email }" do + %i.fa.fa-envelope-o.fa-4x diff --git a/app/views/conferences/_social_media.html.haml b/app/views/conferences/_social_media.html.haml deleted file mode 100644 index b072423f..00000000 --- a/app/views/conferences/_social_media.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -.container - .row - .col-md-12.text-center - - unless @conference.contact.facebook.blank? - = link_to "#{ @conference.contact.facebook }" do - %i.fa.fa-facebook-square.fa-4x - - unless @conference.contact.twitter.blank? - = link_to "#{ @conference.contact.twitter }" do - %i.fa.fa-twitter.fa-4x - - unless @conference.contact.instagram.blank? - = link_to "#{ @conference.contact.instagram }" do - %i.fa.fa-instagram.fa-4x - - unless @conference.contact.googleplus.blank? - = link_to "#{ @conference.contact.googleplus }" do - %i.fa.fa-google-plus-square.fa-4x - - unless @conference.contact.email.blank? - = mail_to "#{ @conference.contact.email }" do - %i.fa.fa-envelope-o.fa-4x diff --git a/app/views/conferences/_sponsors.haml b/app/views/conferences/_sponsors.haml new file mode 100644 index 00000000..8f4d55c6 --- /dev/null +++ b/app/views/conferences/_sponsors.haml @@ -0,0 +1,36 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#sponsors' } Sponsors + +- cache [conference, sponsorship_levels, '#splash#sponsors'] do + %section#sponsors + .container + - sponsorship_levels.each do |sponsorship_level| + - if sponsorship_level.sponsors.any? + .row.text-center + %h3 + = sponsorship_level.title + = 'Sponsor'.pluralize(sponsorship_level.sponsors.length) + .row.row-centered + - sponsorship_level.sponsors.each do |sponsor| + .col-md-4.col-sm-4.col-centered.col-top + %a{ href: '#', data: { toggle: 'modal', + target: "#modal-sponsor-#{sponsor.id}" } } + - if sponsor.logo_file_name + = image_tag get_logo(sponsor), + class: ['img-responsive', 'img-sponsor', + "img-sponsor-#{sponsorship_level.position}"], + title: sponsor.name + - else + %h4.text-center= sponsor.name + + .row + .col-md-12 + %h3.text-center + Want to sponsor? + = link_to(sponsorship_mailto(conference)) do + Contact us! + +- sponsorship_levels.collect(&:sponsors).flatten.each do |sponsor| + - content_for :modals do + = render 'modal_description', object: sponsor diff --git a/app/views/conferences/_sponsors.html.haml b/app/views/conferences/_sponsors.html.haml deleted file mode 100644 index aa7921b5..00000000 --- a/app/views/conferences/_sponsors.html.haml +++ /dev/null @@ -1,41 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#sponsors' } Sponsors - -.container - .row - .col-md-12.text-center - %h2 Sponsors - - @conference.sponsorship_levels.each do |sponsorship_level| - -if sponsorship_level.sponsors.any? - - sponsorship_level.sponsors.each_slice(3) do |slice| - .row.row-centered - - slice.each do |sponsor| - .col-md-4.col-sm-4.col-centered.col-top - %a{ href: '#', data: { toggle: 'modal', target: "#modal_#{sponsor.id}" } } - = image_tag get_logo(sponsor), class: "img-responsive img-sponsor img-sponsor-#{sponsorship_level.position}" - - .modal.fade{ id: "modal_#{sponsor.id}" } - .modal-dialog - .modal-content - .modal-header - %button.close{ data: { dismiss: 'modal' } } - x - .modal-title - = sponsor.name - .modal-body.text-center - .logo - = link_to sponsor.website_url, target: '_blank' do - = image_tag get_logo(sponsor), class: "img-responsive img-sponsor img-sponsor-#{sponsorship_level.position}" - .description - = sponsor.description - .modal-footer - = link_to nil, "#{sponsor.website_url}", target: '_blank' - -if @conference.contact and !@conference.contact.sponsor_email.blank? - .row - .col-md-12 - %p.text-muted.text-center - %small - Want to sponsor #{@conference.short_title}? - = link_to("mailto: #{@conference.contact.sponsor_email}?subject=#{@conference.short_title}%20Sponsorship") do - Please contact us! diff --git a/app/views/conferences/_tickets.haml b/app/views/conferences/_tickets.haml new file mode 100644 index 00000000..0a927593 --- /dev/null +++ b/app/views/conferences/_tickets.haml @@ -0,0 +1,24 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#tickets' } Tickets + +- cache [conference, tickets, '#splash#tickets'] do + %section#tickets + .container + .row + .col-md-12.text-center + %h2 + Support + = conference.title + .row.row-centered + - tickets.each do |ticket| + .col-md-3.col-sm-3.col-centered.col-top + = link_to(conference_tickets_path(conference.short_title), + class: 'thumbnail') do + .caption + %h3.text-center + = ticket.title + = markdown(ticket.description) + %button.btn-block.btn.btn-lg.btn-success + %i.fa.fa-ticket.fa-fw + = humanized_money_with_symbol(ticket.price) diff --git a/app/views/conferences/_tickets.html.haml b/app/views/conferences/_tickets.html.haml deleted file mode 100644 index 8a202295..00000000 --- a/app/views/conferences/_tickets.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -.container - .row - .col-md-12.text-center - %h2 - Support - =@conference.short_title - %p.lead - To support our event you can get these tickets - - @conference.tickets.each_slice(4) do |slice| - .row.row-centered - - slice.each do |ticket| - .col-md-3.col-centered.col-top.col-sm-3 - .thumbnail - %p.text-center - %i.fa.fa-ticket.fa-5x - .caption - %h3.text-center - = ticket.title - -if ticket.description.present? - = markdown(ticket.description) - %p.text-center - = link_to(conference_tickets_path(@conference.short_title), class: 'btn btn-success') do - Get Ticket - = humanized_money_with_symbol ticket.price - diff --git a/app/views/conferences/_tracks.haml b/app/views/conferences/_tracks.haml new file mode 100644 index 00000000..7742778f --- /dev/null +++ b/app/views/conferences/_tracks.haml @@ -0,0 +1,16 @@ +.row + .col-md-12 + %h3.text-center Tracks +.row.row-centered + - tracks.each do |track| + .col-md-3.col-sm-3.col-centered.col-top.track + .thumbnail + .caption + %h3.text-center + = track.name + %p.text-center + - if track.start_date && track.end_date + = date_string(track.start_date, track.end_date) + - if track.room + In #{track.room.name} + = markdown truncate(track.description, length: 200, separator: ' ') diff --git a/app/views/conferences/_venue.haml b/app/views/conferences/_venue.haml new file mode 100644 index 00000000..fbdcde48 --- /dev/null +++ b/app/views/conferences/_venue.haml @@ -0,0 +1,43 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#venue' } Venue + +%section#venue + - if venue.location? + = render '/conferences/venue_map', venue: venue + - else + - cache [venue, commercial, '#splash#venue'] do + .container + .row + .col-md-6 + .thumbnail#venue-pic + - if commercial + .flexvideo{ id: "resource-content-#{commercial.id}" } + = render 'shared/media_item', + commercial: commercial + - elsif venue.picture? + = image_tag venue.picture.url, + title: venue.name, class: "img-responsive" + - else + %p.text-center + %span.fa.fa-university.fa-5x + .caption + %h3.text-center + = venue.name + - unless venue.description.blank? + = markdown(venue.description) + .col-md-6 + %h2 + = venue.city + \/ + = venue.country_name + %address + = venue.street + %br + = venue.postalcode + ',' + = venue.city + %br + = venue.country_name + - if venue.website + %br + = sanitize link_to(h(venue.website), h(venue.website)) diff --git a/app/views/conferences/_venue.html.haml b/app/views/conferences/_venue.html.haml deleted file mode 100644 index 4436b0fe..00000000 --- a/app/views/conferences/_venue.html.haml +++ /dev/null @@ -1,35 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#venue' } Venue --if @conference.venue.location? - = render '/conferences/venue_map' --else - .container - .row - .col-md-6 - .thumbnail#venue-pic - - if @conference.venue.commercial.present? and @conference.venue.commercial.persisted? - .flexvideo{ id: "resource-content-#{@conference.venue.commercial.id}"} - = render partial: 'shared/media_item', locals: { commercial: @conference.venue.commercial } - - elsif @conference.venue.picture? - = image_tag @conference.venue.picture.url, alt: @conference.venue.name, class:"img-responsive" - - else - %p.text-center - %span.fa.fa-university.fa-5x - .caption - %h3.text-center - = @conference.venue.name - - unless @conference.venue.description.blank? - = markdown(@conference.venue.description) - .col-md-6 - %h2 - = "#{@conference.venue.city} / #{@conference.venue.country_name}" - %address - = @conference.venue.street - %br - = "#{@conference.venue.postalcode}, #{@conference.venue.city}" - %br - = @conference.venue.country_name - - if @conference.venue.website - %br - =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.haml similarity index 55% rename from app/views/conferences/_venue_map.html.haml rename to app/views/conferences/_venue_map.haml index 9f34117f..07f387bc 100644 --- a/app/views/conferences/_venue_map.html.haml +++ b/app/views/conferences/_venue_map.haml @@ -1,16 +1,29 @@ -#map{style: "height: 500px;" } +#map{ style: "height: 500px;" } - content_for(:script_body) do + - marker = escape_javascript(render '/conferences/venue_map_marker', + venue: venue) :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([#{h(@conference.venue.latitude)}, #{h(@conference.venue.longitude)}], 11); + var map = L.map('map', { scrollWheelZoom: false }).setView( + [ + #{venue.latitude.to_f + 0.05}, + #{h(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', + 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([#{h @conference.venue.latitude}, #{h @conference.venue.longitude}]).addTo(map) - .bindPopup("#{escape_javascript(render '/conferences/venue_map_marker', venue: @conference.venue)}") + // add a marker in the given location, attach some popup content to it + // and open the popup + L.marker([ + #{h venue.latitude}, + #{h venue.longitude} + ]).addTo(map) + .bindPopup("#{marker}") .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.haml similarity index 100% rename from app/views/conferences/_venue_map_marker.html.haml rename to app/views/conferences/_venue_map_marker.haml diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index dd6b2d62..ea99b419 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -11,88 +11,64 @@ = @conference.title #splash - - if @conference.splashpage - #banner - .container - .row - .col-md-8.col-md-offset-2#header - .row - .col-md-4 - = image_tag(@conference.picture_url, class: 'img-responsive img-center', id: 'splash-logo') if @conference.picture? - .col-md-8 - %h1 - = @conference.title - %p.lead - - if @conference.venue - = "#{@conference.venue.city} / #{@conference.venue.country_name}" - - if @conference.start_date && @conference.end_date - %br - = date_string(@conference.start_date, @conference.end_date) + -# header/description + = render 'header', conference: @conference, venue: @conference.venue - - unless @conference.description.blank? - %section#about - .container - .row - .col-md-8.col-md-offset-2 - %h3.text-center - = markdown(@conference.description) + -# calls for content, or program + - if @conference.splashpage.include_cfp + = render 'call_for_content', conference: @conference, + call_for_events: @call_for_events, call_for_tracks: @call_for_tracks, + event_types: @event_types, tracks: @track_names - - if @conference.registration_open? and @conference.splashpage.include_registrations - %section#registration - = render 'registration' + - if @conference.splashpage.include_program + = render 'program', conference: @conference, tracks: @tracks, + highlights: @highlights, booths: @booths - - if @conference.splashpage.include_program - %section#program - = render 'schedule_splashpage' + -# attendance/registration + - if @conference.splashpage.include_registrations + - if @conference.registration_open? + = render 'registration', conference: @conference, + registration_period: @conference.registration_period, + tickets: @tickets, conference_id: @conference.short_title + - if @conference.splashpage.include_tickets && @conference.tickets.any? + = render 'tickets', conference: @conference, tickets: @tickets - - if @conference.program.cfp_open? and @conference.splashpage.include_cfp - %section#callforpapers - = render 'call_for_paper' + -# geo + - if @conference.splashpage.include_venue && @conference.venue + = render 'venue', conference: @conference, venue: @conference.venue, + commercial: @conference.venue.commercial + - if @conference.splashpage.include_lodgings && @conference.lodgings.any? + = render 'lodging', venue: @conference.venue, lodgings: @lodgings - - if @conference.program.cfps.for_tracks.try(:open?) && @conference.splashpage.include_cfp - %section#callfortracks - = render 'call_for_tracks' + -# sponsorship + - if @conference.splashpage.include_sponsors + = render 'sponsors', conference: @conference, + sponsorship_levels: @sponsorship_levels - - if @conference.venue and @conference.splashpage.include_venue - %section#venue - = render 'venue' + -# footer + - if @conference.splashpage.include_social_media + - if @conference.contact.has_social_media? + = render 'social_media', contact: @conference.contact + = render 'footer' - - if @conference.lodgings.any? and @conference.splashpage.include_lodgings - %section#lodging - = render 'lodging' + = yield :modals - - if @conference.tickets.any? and @conference.splashpage.include_tickets and @conference.pending? - %section#tickets - = render 'tickets' - - - if @conference.booths.confirmed.any? and @conference.splashpage.include_booths - %section#booths - = render 'booths' - - - if @conference.sponsors.any? and @conference.splashpage.include_sponsors - %section#sponsors - = render 'sponsors' - - - if @conference.contact.has_social_media? and @conference.splashpage.include_social_media - %section#social-media - = render 'social_media' - - // grmbl - = render 'footer' - -- content_for :script_head do - :javascript - var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic(); - var triangle_colors = triangle_tcs.map(function(t) { return t.toHexString(); }); - $(function () { - $(document).ready(function() { - var triangle_width = document.body.clientWidth; - var triangle_height = ($( "#banner" ).height() + 200 ); - var pattern = Trianglify({ width: triangle_width, - height: triangle_height, - cell_size: 100, - x_colors: triangle_colors - }); - $('#banner').css('background-image', 'url("' + pattern.png() + '")'); +- cache [@conference.color, '#splash#inlinejs'] do + - content_for :script_head do + :javascript + var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic(); + var triangle_colors = triangle_tcs.map(function(t) { + return t.toHexString(); + }); + $(function () { + $(document).ready(function() { + var triangle_width = document.body.clientWidth; + var triangle_height = ($( "#banner" ).height() + 200 ); + var pattern = Trianglify({ width: triangle_width, + height: triangle_height, + cell_size: 100, + x_colors: triangle_colors + }); + $('#banner').css('background-image', 'url("' + pattern.png() + '")'); + }); }); - }); 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/_admin_sidebar_index.html.haml b/app/views/layouts/_admin_sidebar_index.html.haml index 9a3d19f3..f828fe85 100644 --- a/app/views/layouts/_admin_sidebar_index.html.haml +++ b/app/views/layouts/_admin_sidebar_index.html.haml @@ -27,6 +27,11 @@ = link_to(admin_users_path) do %span.fa.fa-user Users + - if can? :index, Organization + %li + = link_to(admin_organizations_path) do + %span.fa.fa-users + Organizations - if can? :index, PaperTrail::Version %li = link_to(admin_revision_history_path) do diff --git a/app/views/layouts/_user_menu.html.haml b/app/views/layouts/_user_menu.html.haml index 10d4c386..dc645a11 100644 --- a/app/views/layouts/_user_menu.html.haml +++ b/app/views/layouts/_user_menu.html.haml @@ -7,7 +7,7 @@ = link_to(edit_user_path(current_user.id)) do %span.fa.fa-user Edit Profile --if @conference and @conference.program +-if @conference && @conference.program %li = link_to(conference_program_proposals_path(@conference.short_title)) do %span.fa.fa-comment @@ -16,7 +16,7 @@ = link_to(conference_program_tracks_path(@conference.short_title)) do %span.fa.fa-road My Tracks --if @conference && @conference.program && (@conference.program.cfps.for_booths.try(:open?) || current_user.booths.where(conference_id: @conference.id).count > 0) +-if @conference && (@conference.call_for_booths.try(:open?) || current_user.booths.where(conference_id: @conference.id).count > 0) %li = link_to (conference_booths_path(@conference.short_title)) do %span.fa.fa-shopping-bag @@ -41,7 +41,7 @@ =link_to(new_admin_conference_path) do %span.fa.fa-plus New Conference - -if @conference and @conference.id and can? :show, @conference + -if @conference && @conference.id && can?(:show, @conference) %li = link_to(admin_conference_path(@conference.short_title)) do %span.fa.fa-cog diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index ee88a24c..aa155bcb 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -43,5 +43,5 @@ You can run, copy, distribute, study, change and improve it. The source code and the developers are on =link_to "github.", "https://github.com/openSUSE/osem" - = content_for(:script_body) + = yield :script_body = piwik_tracking_tag diff --git a/app/views/organizations/index.html.haml b/app/views/organizations/index.html.haml index bc5a4d5e..c8743363 100644 --- a/app/views/organizations/index.html.haml +++ b/app/views/organizations/index.html.haml @@ -8,7 +8,7 @@ - @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 diff --git a/app/views/physical_tickets/show.html.haml b/app/views/physical_tickets/show.html.haml index 40513ae8..7dbc44da 100644 --- a/app/views/physical_tickets/show.html.haml +++ b/app/views/physical_tickets/show.html.haml @@ -31,12 +31,7 @@ = @user.email .col-md-5.col-md-offset-2.box.well - if @conference.picture? - - width = @conference.picture.image[:width] - - height = @conference.picture.image[:height] - - if 10 * width > 15 * height - = image_tag(@conference.picture_url, width: '150') - - else - = image_tag(@conference.picture_url, height: '100') + = image_tag(@conference.picture.ticket.url, class: 'img-responsive') - else = image_tag('/img/osem-logo.png', class: 'img-responsive') %p.text-left diff --git a/app/views/proposals/_encouragement_text.html.haml b/app/views/proposals/_encouragement_text.html.haml index 48fcd045..ad9f01ea 100644 --- a/app/views/proposals/_encouragement_text.html.haml +++ b/app/views/proposals/_encouragement_text.html.haml @@ -1,7 +1,7 @@ %p.lead - if @program.event_types.any? You can submit proposals for - = "#{event_types(@conference)}." + = "#{event_types_sentence(@conference)}." - if @program.tracks.confirmed.cfp_active.any? Proposals should fit in one of the = "#{pluralize(@program.tracks.confirmed.cfp_active.count, 'track')}:" diff --git a/app/views/proposals/_proposal_form.html.haml b/app/views/proposals/_proposal_form.html.haml index 4b66240c..1b642d94 100644 --- a/app/views/proposals/_proposal_form.html.haml +++ b/app/views/proposals/_proposal_form.html.haml @@ -1,6 +1,6 @@ = semantic_form_for(@event, url: @url) do |f| = f.inputs name: 'Proposal Information' do - = f.input :title, as: :string, required: true + = f.input :title, as: :string, input_html: { autofocus: true }, required: true = f.input :subtitle, as: :string diff --git a/app/views/proposals/show.html.haml b/app/views/proposals/show.html.haml index 19f9371f..99f2d49e 100644 --- a/app/views/proposals/show.html.haml +++ b/app/views/proposals/show.html.haml @@ -36,8 +36,10 @@ .col-md-8 %h4 = link_to speaker.name, user_path(speaker.id) + %br - if speaker.email_public? - = "(#{speaker.email})" + = mail_to "#{ speaker.email }" do + %i.fa.fa-envelope-o.fa-2x - if speaker.affiliation? .text-muted from diff --git a/app/views/schedules/show.xml.haml b/app/views/schedules/show.xml.haml index 541377ad..f42ad801 100644 --- a/app/views/schedules/show.xml.haml +++ b/app/views/schedules/show.xml.haml @@ -9,10 +9,10 @@ %timeslot_duration= length_timestamp(@conference.program.schedule_interval) - if @events_xml.any? - - @events_xml.keys.each.with_index(1) do |day, index| + - @events_xml.each_key.with_index(1) do |day, index| %day{ date: day, index: index } - events_in_rooms = @events_xml[day].group_by(&:room) - - events_in_rooms.keys.each do |room| + - events_in_rooms.each_key do |room| %room{ name: room.name } - events_in_rooms[room].each do |event| %event{ guid: event.guid, id: event.id } 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 06a642dd..f23739ed 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -54,6 +54,7 @@ elif [[ "$ID" == "centos" || "$VERSION" == "7" ]]; then 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 + pushd /vagrant fi echo -e "\ninstalling your bundle...\n" @@ -64,7 +65,7 @@ if [ ! -f /vagrant/config/database.yml ] && [ -f /vagrant/config/database.yml.ex echo -e "\nSetting up your database from config/database.yml...\n" cp config/database.yml.example config/database.yml if [ ! -f db/development.sqlite3 ] && [ ! -f db/test.sqlite3 ]; then - bundle exec rake db:setup + su - vagrant -c "cd /vagrant/; bundle exec rake db:setup" else echo -e "\n\nWARNING: You have already have a development/test database." echo -e "WARNING: Please make sure this database works in this vagrant box!\n\n" 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/database.yml.example b/config/database.yml.example index 51a4dd45..f47361d5 100644 --- a/config/database.yml.example +++ b/config/database.yml.example @@ -9,6 +9,35 @@ development: pool: 5 timeout: 5000 +## PostgreSQL +## gem install pg +## +## Ensure the postgres gem is defined in your Gemfile +## gem 'pg' +## Update with your database name and login credentials +# development: +# adapter: postgresql +# encoding: unicode +# database: database_name +# pool: 5 +# username: username +# password: password + +## MySQL +## gem install mysql2 +## +## Ensure the mysql gem is defined in your Gemfile +## gem 'mysql2' +## Update with your database name and login credentials +# development: +# adapter: mysql2 +# encoding: utf8 +# database: database_name +# pool: 5 +# username: username +# password: password +# socket: /tmp/mysql.sock + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. diff --git a/config/environments/development.rb b/config/environments/development.rb index 2557e892..4bff137e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -12,6 +12,8 @@ Osem::Application.configure do # since you don't have to restart the web server when you make code changes. config.cache_classes = false + config.cache_store = :memory_store, { size: 64.megabytes } + # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false diff --git a/config/environments/production.rb b/config/environments/production.rb index 4e2c2e79..11a8c06b 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 @@ -46,6 +46,14 @@ Osem::Application.configure do # Use a different cache store in production # config.cache_store = :mem_cache_store + if ENV["MEMCACHEDCLOUD_SERVERS"] + config.cache_store = :dalli_store, ENV["MEMCACHEDCLOUD_SERVERS"].split(','), { + username: ENV["MEMCACHEDCLOUD_USERNAME"], + password: ENV["MEMCACHEDCLOUD_PASSWORD"] + } + else + config.cache_store = :memory_store, { size: 64.megabytes } + end # Enable serving of images, stylesheets, and JavaScripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" 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 52d3dfb2..7afe067d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,6 +98,7 @@ Osem::Application.routes.draw do end resources :event_types resources :difficulty_levels + post 'mass_upload_commercials' => 'commercials#mass_upload' resources :events do member do patch :toggle_attendance 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/20140701123203_add_events_per_week_to_conference.rb b/db/migrate/20140701123203_add_events_per_week_to_conference.rb index 36bbf40d..2b4d3342 100644 --- a/db/migrate/20140701123203_add_events_per_week_to_conference.rb +++ b/db/migrate/20140701123203_add_events_per_week_to_conference.rb @@ -77,7 +77,7 @@ class AddEventsPerWeekToConference < ActiveRecord::Migration hash.each do |week, values| if previous - values.each do |state, _value| + values.each_key do |state| hash[week][state] += previous[state] end end diff --git a/db/migrate/20170212145523_add_enabled_to_event_schedules.rb b/db/migrate/20170212145523_add_enabled_to_event_schedules.rb new file mode 100644 index 00000000..d89505fe --- /dev/null +++ b/db/migrate/20170212145523_add_enabled_to_event_schedules.rb @@ -0,0 +1,5 @@ +class AddEnabledToEventSchedules < ActiveRecord::Migration + def change + add_column :event_schedules, :enabled, :boolean, default: true + 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/migrate/20171130172334_rebuild_conference_pictures.rb b/db/migrate/20171130172334_rebuild_conference_pictures.rb new file mode 100644 index 00000000..a8d74bce --- /dev/null +++ b/db/migrate/20171130172334_rebuild_conference_pictures.rb @@ -0,0 +1,9 @@ +class RebuildConferencePictures < ActiveRecord::Migration + def up + Conference.all.each do |conference| + conference.picture.recreate_versions! + end + end + + def down; end +end diff --git a/db/schema.rb b/db/schema.rb index bdf3ad65..43602f9b 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: 20170924190528) do +ActiveRecord::Schema.define(version: 20171130172334) 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: 20170924190528) 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" @@ -89,12 +86,11 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -130,10 +126,9 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -164,10 +159,9 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -223,13 +217,13 @@ ActiveRecord::Schema.define(version: 20170924190528) do t.datetime "start_time" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "enabled", default: true + 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 @@ -327,10 +321,9 @@ ActiveRecord::Schema.define(version: 20170924190528) 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 @@ -344,10 +337,9 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -416,11 +408,10 @@ ActiveRecord::Schema.define(version: 20170924190528) 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 @@ -433,11 +424,10 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -540,12 +530,11 @@ ActiveRecord::Schema.define(version: 20170924190528) 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 @@ -579,21 +568,18 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -634,12 +620,11 @@ ActiveRecord::Schema.define(version: 20170924190528) 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" @@ -659,10 +644,9 @@ ActiveRecord::Schema.define(version: 20170924190528) 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/docker/init.sh b/docker/init.sh index 3a2031f3..6a29044f 100644 --- a/docker/init.sh +++ b/docker/init.sh @@ -37,6 +37,9 @@ dockerize -wait tcp://$DATABASE_HOST:$DATABASE_PORT -timeout 60s true if [ $(echo "show tables;" | mysql --host $DATABASE_HOST --port $DATABASE_PORT $MYSQL_DATABASE | wc -l) -le 1 ]; then echo ">>> Initializing database..." bundle exec rake db:schema:load + + echo ">>> Seed database..." + bundle exec rake db:seed fi echo ">>> Upgrading database..." 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/users/omniauth_callbacks_controller_spec.rb b/spec/controllers/users/omniauth_callbacks_controller_spec.rb new file mode 100644 index 00000000..c67e6ac9 --- /dev/null +++ b/spec/controllers/users/omniauth_callbacks_controller_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Users::OmniauthCallbacksController do + context 'email is not there in auth hash' do + before do + stub_env_for_omniauth + get :google + end + + it { expect(flash[:error]).to eq('Email field is missing in your google account') } + end +end + +def stub_env_for_omniauth + request.env['devise.mapping'] = Devise.mappings[:user] + env = OmniAuth::AuthHash.new( + provider: 'google', + uid: 'google-test-uid-1', + info: { + name: 'google user', + email: nil, + username: 'user_google' + }, + credentials: { + token: 'google_mock_token', + secret: 'google_mock_secret' + } + ) + request.env['omniauth.auth'] = env + @controller.stub(:env).and_return(env) +end diff --git a/spec/factories/commercials.rb b/spec/factories/commercials.rb index 2578d1cd..7fa052a7 100644 --- a/spec/factories/commercials.rb +++ b/spec/factories/commercials.rb @@ -2,7 +2,7 @@ FactoryGirl.define do factory :commercial do - url 'https://www.youtube.com/watch?v=BTTygyxuGj8' + sequence(:url) { |n| "https://www.youtube.com/watch?v=4VrhlyIgo3M&factory=#{n}" } factory :conference_commercial do association :commercialable, factory: :conference diff --git a/spec/factories/conferences.rb b/spec/factories/conferences.rb index 1e4d8551..31f72344 100644 --- a/spec/factories/conferences.rb +++ b/spec/factories/conferences.rb @@ -5,7 +5,7 @@ FactoryGirl.define do title { Faker::Book.title } short_title { SecureRandom.urlsafe_base64(4) } timezone { Faker::Address.time_zone } - start_date { Date.today } + start_date { Date.current } end_date { 6.days.from_now } start_hour 9 end_hour 20 diff --git a/spec/factories/event_users.rb b/spec/factories/event_users.rb index 78bcd10d..5d1574a9 100644 --- a/spec/factories/event_users.rb +++ b/spec/factories/event_users.rb @@ -4,7 +4,7 @@ FactoryGirl.define do factory :event_user do user - Hash[EventUser::ROLES].values.each do |role| + Hash[EventUser::ROLES].each_value do |role| factory role do event_role role end diff --git a/spec/factories/openid.rb b/spec/factories/openid.rb new file mode 100644 index 00000000..6950c718 --- /dev/null +++ b/spec/factories/openid.rb @@ -0,0 +1,10 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :openid do + provider { Faker::Internet.domain_word } + email { Faker::Internet.email } + uid { SecureRandom.hex } + user + end +end diff --git a/spec/features/commercials_spec.rb b/spec/features/commercials_spec.rb index 65efa0b6..d460a725 100644 --- a/spec/features/commercials_spec.rb +++ b/spec/features/commercials_spec.rb @@ -98,7 +98,8 @@ feature Commercial do scenario 'does not update a commercial of an event with invalid data', feature: true, versioning: true, js: true do commercial = create(:commercial, commercialable_id: event.id, - commercialable_type: 'Event') + commercialable_type: 'Event', + url: 'https://www.youtube.com/watch?v=BTTygyxuGj8') visit edit_conference_program_proposal_path(conference.short_title, event.id) click_link 'Commercials' fill_in "commercial_url_#{commercial.id}", with: 'invalid_commercial_url' diff --git a/spec/features/splashpage_spec.rb b/spec/features/splashpage_spec.rb index d33c6c85..006df419 100644 --- a/spec/features/splashpage_spec.rb +++ b/spec/features/splashpage_spec.rb @@ -13,7 +13,7 @@ feature Splashpage do visit admin_conference_splashpage_path(conference.short_title) click_link 'Create Splashpage' - click_button 'Save Splashpage' + click_button 'Save Changes' expect(flash).to eq('Splashpage successfully created.') expect(current_path).to eq(admin_conference_splashpage_path(conference.short_title)) @@ -28,7 +28,7 @@ feature Splashpage do click_link 'Edit' check('Make splash page public') - click_button 'Save Splashpage' + click_button 'Save Changes' expect(flash).to eq('Splashpage successfully updated.') expect(current_path).to eq(admin_conference_splashpage_path(conference.short_title)) diff --git a/spec/features/versions_spec.rb b/spec/features/versions_spec.rb index 1bf114a0..62536019 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 @@ -233,18 +233,18 @@ feature 'Version' do scenario 'display changes in splashpages', feature: true, versioning: true, js: true do visit admin_conference_splashpage_path(conference.short_title) click_link 'Create Splashpage' - click_button 'Save Splashpage' + click_button 'Save Changes' click_link 'Edit' - uncheck('Display program') - uncheck('Display call for papers information on splashpage, while cfp is open') - uncheck('Display venue') + uncheck('Display the program') + uncheck('Display call for papers and call for tracks, while open') + uncheck('Display the venue') uncheck('Display tickets') uncheck('Display the lodgings') uncheck('Display sponsors') - uncheck('Display social media') + uncheck('Display social media links') check('Make splash page public?') - click_button 'Save Splashpage' + click_button 'Save Changes' splashpage_id = conference.splashpage.id click_link 'Delete' @@ -343,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 6cd71d2a..ff0fbfa2 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe ApplicationHelper, type: :helper do - let(:conference) { create(:conference) } + let(:conference) { create(:full_conference) } let(:event) { create(:event, program: conference.program) } + let(:sponsor) { create(:sponsor) } describe '#date_string' do it 'when conference lasts 1 day' do @@ -66,12 +67,53 @@ describe ApplicationHelper, type: :helper do end it 'should use the environment variable' do - ENV['OSEM_NAME'] = Faker::Company.name - expect(nav_root_link_for(nil)).to match ENV['OSEM_NAME'] + 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 conference.organization.name + expect(nav_root_link_for(conference)).to match h(conference.organization.name) + end + end + end + + describe '#get_logo' do + context 'first sponsorship_level' do + before do + first_sponsorship_level = create(:sponsorship_level, position: 1) + sponsor.update_attributes(sponsorship_level: first_sponsorship_level) + end + + it 'returns correct url' do + expect(get_logo(sponsor)).to match %r{.*(\bfirst/#{sponsor.logo_file_name}\b)} + end + end + + context 'second sponsorship_level' do + before do + second_sponsorship_level = create(:sponsorship_level, position: 2) + sponsor.update_attributes(sponsorship_level: second_sponsorship_level) + end + + it 'returns correct url' do + expect(get_logo(sponsor)).to match %r{.*(\bsecond/#{sponsor.logo_file_name}\b)} + end + end + + context 'other sponsorship_level' do + before do + other_sponsorship_level = create(:sponsorship_level, position: 3) + sponsor.update_attributes(sponsorship_level: other_sponsorship_level) + end + + it 'returns correct url' do + expect(get_logo(sponsor)).to match %r{.*(\bothers/#{sponsor.logo_file_name}\b)} + end + end + + context 'non-sponsor' do + it 'returns correct url' do + expect(get_logo(conference)).to match %r{.*(\blarge/#{conference.logo_file_name}\b)} end end end diff --git a/spec/helpers/conference_helper_spec.rb b/spec/helpers/conference_helper_spec.rb new file mode 100644 index 00000000..09e38e69 --- /dev/null +++ b/spec/helpers/conference_helper_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe ConferenceHelper, type: :helper do + let!(:conference) { create(:conference) } + let!(:contact) { create(:contact, conference: conference) } + + describe '#one_call_open' do + it 'is falsey if neither call is open' do + expect(one_call_open(*conference.program.cfps)).to be_falsey + end + + it 'is truthy if call_for_papers is open' do + create( + :cfp, + program: conference.program, + cfp_type: 'events', + start_date: conference.start_date, + end_date: conference.end_date + ) + expect(one_call_open(*conference.program.cfps)).to be_truthy + end + + it 'is truthy if call_for_tracks is open' do + create( + :cfp, + program: conference.program, + cfp_type: 'tracks', + start_date: conference.start_date, + end_date: conference.end_date + ) + + expect(one_call_open(*conference.program.cfps)).to be_truthy + end + + it 'is falsey if both calls are open' do + create( + :cfp, + program: conference.program, + cfp_type: 'events', + start_date: conference.start_date, + end_date: conference.end_date + ) + create( + :cfp, + program: conference.program, + cfp_type: 'tracks', + start_date: conference.start_date, + end_date: conference.end_date + ) + + expect(one_call_open(*conference.program.cfps)).to be_falsey + end + end + + describe '#sponsorship_mailto' do + it 'constructs a mailto URL' do + expect(sponsorship_mailto(conference)).to match 'mailto:' + end + + it 'points to the conference sponsor address' do + expect(sponsorship_mailto(conference)).to match contact.sponsor_email + end + + it 'includes a conference identifier' do + expect(sponsorship_mailto(conference)).to match conference.short_title + end + end +end diff --git a/spec/helpers/sponsor_helper_spec.rb b/spec/helpers/sponsor_helper_spec.rb deleted file mode 100644 index c6ce08ce..00000000 --- a/spec/helpers/sponsor_helper_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'spec_helper' - -describe SponsorsHelper, type: :helper do - let(:sponsor) { create(:sponsor) } - - describe '#get_logo' do - context 'first sponsorship_level' do - before do - first_sponsorship_level = create(:sponsorship_level, position: 1) - sponsor.update_attributes(sponsorship_level: first_sponsorship_level) - end - - it 'returns correct url' do - expect(get_logo(sponsor)).to match %r{.*(\bfirst/#{sponsor.logo_file_name}\b)} - end - end - - context 'second sponsorship_level' do - before do - second_sponsorship_level = create(:sponsorship_level, position: 2) - sponsor.update_attributes(sponsorship_level: second_sponsorship_level) - end - - it 'returns correct url' do - expect(get_logo(sponsor)).to match %r{.*(\bsecond/#{sponsor.logo_file_name}\b)} - end - end - - context 'other sponsorship_level' do - before do - other_sponsorship_level = create(:sponsorship_level, position: 3) - sponsor.update_attributes(sponsorship_level: other_sponsorship_level) - end - - it 'returns correct url' do - expect(get_logo(sponsor)).to match %r{.*(\bothers/#{sponsor.logo_file_name}\b)} - end - end - end -end diff --git a/spec/models/conference_spec.rb b/spec/models/conference_spec.rb index 26070134..0af13eed 100755 --- a/spec/models/conference_spec.rb +++ b/spec/models/conference_spec.rb @@ -1704,4 +1704,8 @@ describe Conference do it { is_expected.to eq [past_conference1, past_conference2] } end + + it 'should have a picture format for tickets' do + expect(create(:conference).picture.ticket.url) + end end diff --git a/spec/models/openid.rb b/spec/models/openid.rb new file mode 100644 index 00000000..42b6a74f --- /dev/null +++ b/spec/models/openid.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Openid do + subject { create(:openid) } + + describe 'validation' do + it { is_expected.to validate_presence_of(:provider) } + it { is_expected.to validate_presence_of(:uid) } + it { is_expected.to validate_presence_of(:email) } + end + + describe 'association' do + it { is_expected.to belong_to(:user) } + end +end diff --git a/spec/models/program_spec.rb b/spec/models/program_spec.rb index 62e576f4..a4b7e44f 100644 --- a/spec/models/program_spec.rb +++ b/spec/models/program_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Program do subject { create(:program) } - let!(:conference) { create(:conference, end_date: Date.today + 3) } + let!(:conference) { create(:conference, end_date: Date.current + 3) } let!(:program) { conference.program } describe 'association' do @@ -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 @@ -240,6 +241,54 @@ describe Program do end end + describe '#any_event_for_this_date?' do + + let(:event){ create(:event, program: program) } + + context 'when no schedule is selected for the conference' do + let(:schedule) { create(:schedule, program: program) } + let!(:event_schedule) { create(:event_schedule, event: event, schedule: schedule, start_time: DateTime.parse("#{Date.current + 1} 10:00").utc) } + + it 'returns false irrespective of any date' do + expect(program.any_event_for_this_date?(Date.current + 1)).to eq false + end + + it 'returns false if date passed is empty' do + expect(program.any_event_for_this_date?('')).to eq false + end + + it 'returns false if date passed is nil' do + expect(program.any_event_for_this_date?(nil)).to eq false + end + end + + context 'when schedule is selected for the conference' do + let(:schedule) { create(:schedule, program: program) } + let!(:event_schedule) { create(:event_schedule, event: event, schedule: schedule, start_time: DateTime.parse("#{Date.current + 1} 10:00").utc) } + + before :each do + program.selected_schedule = event_schedule.schedule + program.save! + end + + it 'returns true if there is any event for this date' do + expect(program.any_event_for_this_date?(Date.current + 1)).to eq true + end + + it 'returns false if there is no event for this date' do + expect(program.any_event_for_this_date?(Date.current + 2)).to eq false + end + + it 'returns false if date passed is empty' do + expect(program.any_event_for_this_date?('')).to eq false + end + + it 'returns false if date passed is nil' do + expect(program.any_event_for_this_date?(nil)).to eq false + end + end + end + describe '#cfp' do it 'returns the cfp for events' do create(:cfp, cfp_type: 'events', program: program, end_date: Date.current + 1) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e742b993..b5b63089 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -345,24 +345,34 @@ describe User do end describe 'proposals methods' do - let(:submitter) { create(:submitter, user: user) } + let(:submitter) { create(:user) } + let(:speaker) { create(:user) } let(:event1) { create(:event, program: conference.program) } let(:event2) { create(:event, program: conference.program) } before do - event1.event_users << create(:event_user, user: user, event_role: 'submitter') - event2.event_users << create(:event_user, user: user, event_role: 'submitter') + event1.event_users << create(:event_user, user: submitter, event_role: 'submitter') + event2.event_users << create(:event_user, user: submitter, event_role: 'submitter') + event1.event_users << create(:event_user, user: speaker, event_role: 'speaker') end describe '#proposals' do it 'returns events submitted by user' do - expect(user.proposals(conference)).to match [event1, event2] + expect(submitter.proposals(conference)).to match [event1, event2] + end + + it 'returns events in which user is a speaker' do + expect(speaker.proposals(conference)).to match [event1] end end describe '#proposal_count' do it 'returns number of events submitted by user' do - expect(user.proposal_count(conference)).to eq 2 + expect(submitter.proposal_count(conference)).to eq 2 + end + + it 'returns number of events in which the user is a speaker' do + expect(speaker.proposal_count(conference)).to eq 1 end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d9283117..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