diff --git a/.gitignore b/.gitignore index cc90ddb..61d62ed 100644 --- a/.gitignore +++ b/.gitignore @@ -47,10 +47,6 @@ rerun.txt pickle-email-*.html .project -# Ignore Gemfile.lock so that we always get the most up to date gems -# We'll be testing in 'preview' to avoid clashes -Gemfile.lock - # Ignore Redis' dataset snapshot dump.rdb diff --git a/Gemfile b/Gemfile index 851267c..aa555a9 100644 --- a/Gemfile +++ b/Gemfile @@ -10,93 +10,106 @@ gem 'rack-mini-profiler' gem 'haml' gem 'nokogiri', '~> 1.6.8.rc2' +gem 'tzinfo-data' +gem 'sass' +gem 'sass-rails' +gem 'uglifier', '>= 1.3.0' +# replace this once these changes are merged in sorcery +gem 'sorcery', git: 'https://github.com/tg90nor/sorcery.git', branch: 'make-facebook-provider-use-json-token-parser' +gem 'carrierwave' +gem 'carrierwave-imageoptimizer' +gem 'mini_magick' +gem 'activerecord-session_store' +gem 'premailer-rails' +gem 'sidekiq' +gem 'letter_opener' +gem 'launchy' + if Dir.exists?('../lingua_franca') - gem 'lingua_franca', :path => '../lingua_franca' + gem 'lingua_franca', path: '../lingua_franca' else - gem 'lingua_franca', :git => 'git://github.com/lingua-franca/lingua_franca.git' + gem 'lingua_franca', git: 'https://github.com/lingua-franca/lingua_franca.git', :branch => '2017' end -gem 'tzinfo-data' -gem 'sass' -gem 'sass-rails' +if Dir.exists?('../marmara') + gem 'marmara', path: '../marmara' +else + gem 'marmara', git: 'https://github.com/lingua-franca/marmara.git' +end -if Dir.exists?('../bumbleberry') - gem 'bumbleberry', :path => "../bumbleberry" +if Dir.exists?('../bikecollectives_core') + gem 'bikecollectives_core', path: '../bikecollectives_core' else - gem 'bumbleberry', :git => 'git://github.com/bumbleberry/bumbleberry.git' + gem 'bikecollectives_core', git: 'https://github.com/bikebike/bikecollectives_core.git' end -if Dir.exists?('../paypal-express') - gem 'paypal-express', :path => "../paypal-express" +if Dir.exists?('../bumbleberry') + gem 'bumbleberry', path: '../bumbleberry' else - gem 'paypal-express', :git => 'git://github.com/bikebike/paypal-express.git' + gem 'bumbleberry', git: 'https://github.com/bumbleberry/bumbleberry.git' end -gem 'uglifier', '>= 1.3.0' -gem 'sorcery', '>= 0.8.1' -gem 'oauth2', '~> 0.8.0' -gem 'carrierwave' -gem 'carrierwave-imageoptimizer' -gem 'mini_magick' + +# gem 'paper_trail', '~> 3.0.5' + +# Bike!Bike! specific stuff +gem 'paypal-express', git: 'https://github.com/ianfleeton/paypal-express' gem 'geocoder' -gem 'paper_trail', '~> 3.0.5' gem 'sitemap_generator' -gem 'activerecord-session_store' gem 'sass-json-vars' -gem 'premailer-rails' gem 'redcarpet' -gem 'sidekiq' -gem 'letter_opener' -gem 'launchy' -gem 'to_spreadsheet', :git => 'git://github.com/glebm/to_spreadsheet.git' - -group :test do - gem 'rspec' - gem 'rspec-rails' -end +gem 'to_spreadsheet', git: 'https://github.com/glebm/to_spreadsheet.git' group :development do - gem 'better_errors' - gem 'binding_of_caller' - gem 'meta_request' - - gem 'capistrano', '~> 3.1' - gem 'capistrano-rails', '~> 1.1' - gem 'capistrano-faster-assets', '~> 1.0' - - gem 'eventmachine', :github => 'krzcho/eventmachine', :branch => 'master' - gem 'thin'# , :github => 'krzcho/thin', :branch => 'master' + gem 'better_errors' + gem 'binding_of_caller' + gem 'meta_request' + + gem 'capistrano', '~> 3.1' + gem 'capistrano-rails', '~> 1.1' + gem 'capistrano-faster-assets', '~> 1.0' + + gem 'eventmachine', git: 'https://github.com/krzcho/eventmachine', :branch => 'master' + gem 'thin'# , :github => 'krzcho/thin', :branch => 'master' + gem 'rubocop', require: false + gem 'haml-lint', require: false end group :test do - gem 'gherkin3', '>= 3.1.0' - gem 'cucumber' - gem 'cucumber-core' - gem 'cucumber-rails' - - gem 'poltergeist' - gem 'guard-rspec' - gem 'factory_girl_rails' - gem 'coveralls', require: false - gem 'selenium-webdriver' - gem 'simplecov', require: false - gem 'webmock', require: false - gem 'database_cleaner' - gem 'mocha' + gem 'rspec' + gem 'rspec-rails' + gem 'gherkin3', '>= 3.1.0' + gem 'cucumber' + gem 'cucumber-core' + gem 'cucumber-rails', require: false + gem 'guard-cucumber' + + gem 'poltergeist' + gem 'capybara-email' + # gem 'capybara-webkit' + gem 'guard-rspec' + gem 'factory_girl_rails' + gem 'coveralls', require: false + gem 'selenium-webdriver' + gem 'simplecov', require: false + gem 'webmock', require: false + gem 'database_cleaner' + gem 'mocha' end group :staging, :production, :preview do - gem 'rails_12factor' + gem 'rails_12factor' end group :production, :preview do - gem 'unicorn' - gem 'daemon-spawn' - gem 'daemons' + gem 'unicorn', require: false + gem 'daemon-spawn' + gem 'daemons' end platforms 'mswin', 'mingw' do - group :test do - gem 'wdm', '>= 0.1.0' - end + group :test do + gem 'wdm', '>= 0.1.0' + gem 'win32console', require: false + end end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..e52b085 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,633 @@ +GIT + remote: https://github.com/glebm/to_spreadsheet.git + revision: 4c08455646dd18de51cc1ec05717fbb240c78a68 + specs: + to_spreadsheet (1.0.6) + axlsx + chronic + nokogiri + rails + responders + +GIT + remote: https://github.com/ianfleeton/paypal-express + revision: 629749621de4c65dd6651649f98410315520fb3d + specs: + paypal-express (0.8.1) + activesupport (>= 2.3) + attr_required (>= 0.0.5) + rest-client + +GIT + remote: https://github.com/krzcho/eventmachine + revision: 651a35ee9df9826e048c3b3721e2c6b415c5a328 + branch: master + specs: + eventmachine (1.2.1) + +GIT + remote: https://github.com/tg90nor/sorcery.git + revision: 79b69a87ce168c47fab76921874aa7e8cb727002 + branch: make-facebook-provider-use-json-token-parser + specs: + sorcery (0.10.3) + bcrypt (~> 3.1) + oauth (~> 0.4, >= 0.4.4) + oauth2 (~> 1.0, >= 0.8.0) + +PATH + remote: ../bikecollectives_core + specs: + bikecollectives_core (0.1.0) + activerecord-session_store + carrierwave + carrierwave-imageoptimizer + haml + launchy + letter_opener + mini_magick + pg + premailer-rails + rails (~> 4.2.0) + redcarpet + sass + sass-json-vars + sass-rails + sidekiq + uglifier (>= 1.3.0) + +PATH + remote: ../bumbleberry + specs: + bumbleberry (0.0.1) + blockspring + cairo + railties + rsvg2 + sass-json-vars + sass-rails + +PATH + remote: ../lingua_franca + specs: + lingua_franca (0.0.1) + diffy + forgery + http_accept_language + i18n + rails (~> 4.2.0.rc2) + rails-i18n + rubyzip + +PATH + remote: ../marmara + specs: + marmara (1.0.2) + css_parser (>= 1.5.0.pre) + +GEM + remote: http://rubygems.org/ + specs: + actionmailer (4.2.0) + actionpack (= 4.2.0) + actionview (= 4.2.0) + activejob (= 4.2.0) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.0) + actionview (= 4.2.0) + activesupport (= 4.2.0) + rack (~> 1.6.0) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + actionview (4.2.0) + activesupport (= 4.2.0) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + activejob (4.2.0) + activesupport (= 4.2.0) + globalid (>= 0.3.0) + activemodel (4.2.0) + activesupport (= 4.2.0) + builder (~> 3.1) + activerecord (4.2.0) + activemodel (= 4.2.0) + activesupport (= 4.2.0) + arel (~> 6.0) + activerecord-session_store (1.0.0) + actionpack (>= 4.0, < 5.1) + activerecord (>= 4.0, < 5.1) + multi_json (~> 1.11, >= 1.11.2) + rack (>= 1.5.2, < 3) + railties (>= 4.0, < 5.1) + activesupport (4.2.0) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.1) + public_suffix (~> 2.0, >= 2.0.2) + airbrussh (1.1.2) + sshkit (>= 1.6.1, != 1.7.0) + arel (6.0.4) + ast (2.3.0) + attr_required (1.0.1) + axlsx (2.0.1) + htmlentities (~> 4.3.1) + nokogiri (>= 1.4.1) + rubyzip (~> 1.0.0) + bcrypt (3.1.11-x64-mingw32) + bcrypt (3.1.11-x86-mingw32) + better_errors (2.1.1) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + rack (>= 0.9.0) + binding_of_caller (0.7.2) + debug_inspector (>= 0.0.1) + blockspring (0.1.4) + rest-client (> 1.6.7) + builder (3.2.3) + cairo (1.15.5-x64-mingw32) + pkg-config (>= 1.1.5) + cairo (1.15.5-x86-mingw32) + pkg-config (>= 1.1.5) + callsite (0.0.11) + capistrano (3.8.0) + airbrussh (>= 1.0.0) + i18n + rake (>= 10.0.0) + sshkit (>= 1.9.0) + capistrano-bundler (1.2.0) + capistrano (~> 3.1) + sshkit (~> 1.2) + capistrano-faster-assets (1.0.2) + capistrano (>= 3.1) + capistrano-rails (1.2.3) + capistrano (~> 3.1) + capistrano-bundler (~> 1.1) + capybara (2.13.0) + addressable + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + capybara-email (2.5.0) + capybara (~> 2.4) + mail + carrierwave (1.0.0) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) + carrierwave-imageoptimizer (1.4.0) + carrierwave (>= 0.8, < 2.0) + image_optimizer (~> 1.6) + childprocess (0.6.3) + ffi (~> 1.0, >= 1.0.11) + chronic (0.10.2) + cliver (0.3.2) + coderay (1.1.1) + concurrent-ruby (1.0.5) + connection_pool (2.2.1) + coveralls (0.8.20) + json (>= 1.8, < 3) + simplecov (~> 0.14.1) + term-ansicolor (~> 1.3) + thor (~> 0.19.4) + tins (~> 1.6) + crack (0.4.3) + safe_yaml (~> 1.0.0) + css_parser (1.5.0.pre2) + addressable + cucumber (2.4.0) + builder (>= 2.1.2) + cucumber-core (~> 1.5.0) + cucumber-wire (~> 0.0.1) + diff-lcs (>= 1.1.3) + gherkin (~> 4.0) + multi_json (>= 1.7.5, < 2.0) + multi_test (>= 0.1.2) + cucumber-core (1.5.0) + gherkin (~> 4.0) + cucumber-rails (1.4.5) + capybara (>= 1.1.2, < 3) + cucumber (>= 1.3.8, < 4) + mime-types (>= 1.16, < 4) + nokogiri (~> 1.5) + railties (>= 3, < 5.1) + cucumber-wire (0.0.1) + daemon-spawn (0.4.2) + daemons (1.2.4) + database_cleaner (1.5.3) + debug_inspector (0.0.2) + diff-lcs (1.3) + diffy (3.2.0) + docile (1.1.5) + domain_name (0.5.20170404) + unf (>= 0.0.5, < 1.0.0) + erubis (2.7.0) + execjs (2.7.0) + factory_girl (4.8.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) + railties (>= 3.0.0) + faraday (0.11.0) + multipart-post (>= 1.2, < 3) + ffi (1.9.18-x64-mingw32) + ffi (1.9.18-x86-mingw32) + forgery (0.6.0) + formatador (0.2.5) + gdk_pixbuf2 (3.1.1-x64-mingw32) + gio2 (= 3.1.1) + gdk_pixbuf2 (3.1.1-x86-mingw32) + gio2 (= 3.1.1) + geocoder (1.4.3) + gherkin (4.1.1) + gherkin3 (3.1.2) + gio2 (3.1.1-x64-mingw32) + glib2 (= 3.1.1) + gobject-introspection (= 3.1.1) + gio2 (3.1.1-x86-mingw32) + glib2 (= 3.1.1) + gobject-introspection (= 3.1.1) + git-version-bump (0.15.1) + glib2 (3.1.1-x64-mingw32) + cairo (>= 1.12.8) + pkg-config + glib2 (3.1.1-x86-mingw32) + cairo (>= 1.12.8) + pkg-config + globalid (0.3.7) + activesupport (>= 4.1.0) + gobject-introspection (3.1.1-x64-mingw32) + glib2 (= 3.1.1) + gobject-introspection (3.1.1-x86-mingw32) + glib2 (= 3.1.1) + guard (2.14.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (~> 1.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-cucumber (2.1.2) + cucumber (~> 2.0) + guard-compat (~> 1.0) + nenv (~> 0.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + haml (4.0.7) + tilt + haml-lint (0.999.999) + haml_lint + haml_lint (0.24.0) + haml (>= 4.0, < 5.1) + rainbow + rake (>= 10, < 13) + rubocop (>= 0.47.0) + sysexits (~> 1.1) + hashdiff (0.3.2) + htmlentities (4.3.4) + http-cookie (1.0.3) + domain_name (~> 0.5) + http_accept_language (2.1.0) + i18n (0.8.1) + image_optimizer (1.7.0) + json (1.8.6) + jwt (1.5.6) + kgio (2.11.0) + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.4.1) + launchy (~> 2.2) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.0.3) + nokogiri (>= 1.5.9) + lumberjack (1.0.11) + mail (2.6.4) + mime-types (>= 1.16, < 4) + meta_request (0.4.0) + callsite (~> 0.0, >= 0.0.11) + rack-contrib (~> 1.1) + railties (>= 3.0.0, < 5.1.0) + metaclass (0.0.4) + method_source (0.8.2) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_magick (4.7.0) + mini_portile2 (2.1.0) + minitest (5.10.1) + mocha (1.2.1) + metaclass (~> 0.0.1) + multi_json (1.12.1) + multi_test (0.1.2) + multi_xml (0.6.0) + multipart-post (2.0.0) + nenv (0.3.0) + net-scp (1.2.1) + net-ssh (>= 2.6.5) + net-ssh (4.1.0) + netrc (0.11.0) + nokogiri (1.6.8.1-x64-mingw32) + mini_portile2 (~> 2.1.0) + nokogiri (1.6.8.1-x86-mingw32) + mini_portile2 (~> 2.1.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + oauth (0.5.1) + oauth2 (1.3.1) + faraday (>= 0.8, < 0.12) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + pango (3.1.1-x64-mingw32) + cairo (>= 1.14.0) + glib2 (= 3.1.1) + pango (3.1.1-x86-mingw32) + cairo (>= 1.14.0) + glib2 (= 3.1.1) + parser (2.4.0.0) + ast (~> 2.2) + pg (0.20.0-x64-mingw32) + pg (0.20.0-x86-mingw32) + pkg-config (1.1.7) + poltergeist (1.14.0) + capybara (~> 2.1) + cliver (~> 0.3.1) + websocket-driver (>= 0.2.0) + powerpack (0.1.1) + premailer (1.10.2) + addressable + css_parser (>= 1.4.10) + htmlentities (>= 4.0.0) + premailer-rails (1.9.5) + actionmailer (>= 3, < 6) + premailer (~> 1.7, >= 1.7.9) + pry (0.10.4) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + public_suffix (2.0.5) + rack (1.6.5) + rack-contrib (1.4.0) + git-version-bump (~> 0.15) + rack (~> 1.4) + rack-mini-profiler (0.10.2) + rack (>= 1.2.0) + rack-protection (1.5.3) + rack + rack-test (0.6.3) + rack (>= 1.0) + rails (4.2.0) + actionmailer (= 4.2.0) + actionpack (= 4.2.0) + actionview (= 4.2.0) + activejob (= 4.2.0) + activemodel (= 4.2.0) + activerecord (= 4.2.0) + activesupport (= 4.2.0) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.0) + sprockets-rails + 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-html-sanitizer (1.0.3) + loofah (~> 2.0) + rails-i18n (4.0.9) + i18n (~> 0.7) + railties (~> 4.0) + rails_12factor (0.0.3) + rails_serve_static_assets + rails_stdout_logging + rails_serve_static_assets (0.0.5) + rails_stdout_logging (0.0.5) + railties (4.2.0) + actionpack (= 4.2.0) + activesupport (= 4.2.0) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rainbow (2.2.1) + raindrops (0.18.0) + rake (11.1.2) + rb-fsevent (0.9.8) + rb-inotify (0.9.8) + ffi (>= 0.5.0) + redcarpet (3.4.0) + redis (3.3.3) + responders (2.3.0) + railties (>= 4.2.0, < 5.1) + rest-client (2.0.1-x64-mingw32) + ffi (~> 1.9) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) + rest-client (2.0.1-x86-mingw32) + ffi (~> 1.9) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-rails (3.5.2) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + rsvg2 (3.1.1-x64-mingw32) + cairo (>= 1.12.8) + gdk_pixbuf2 (= 3.1.1) + pango (>= 3.1.1) + rsvg2 (3.1.1-x86-mingw32) + cairo (>= 1.12.8) + gdk_pixbuf2 (= 3.1.1) + pango (>= 3.1.1) + rubocop (0.48.1) + parser (>= 2.3.3.1, < 3.0) + powerpack (~> 0.1) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 1.0, >= 1.0.1) + ruby-progressbar (1.8.1) + ruby_dep (1.3.1) + rubyzip (1.0.0) + safe_yaml (1.0.4) + sass (3.4.23) + sass-json-vars (0.3.3) + sass (>= 3.1) + sass-rails (5.0.6) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + selenium-webdriver (3.3.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) + websocket (~> 1.0) + shellany (0.0.1) + sidekiq (4.2.10) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + rack-protection (>= 1.5.0) + redis (~> 3.2, >= 3.2.1) + simplecov (0.14.1) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + sitemap_generator (5.3.1) + builder (~> 3.0) + slop (3.6.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.0) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sshkit (1.13.1) + net-scp (>= 1.1.2) + net-ssh (>= 2.8.0) + sysexits (1.2.0) + term-ansicolor (1.5.0) + tins (~> 1.0) + thin (1.7.0) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (>= 1, < 3) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.7) + tins (1.13.2) + tzinfo (1.2.3) + thread_safe (~> 0.1) + tzinfo-data (1.2017.2) + tzinfo (>= 1.0.0) + uglifier (3.1.13) + execjs (>= 0.3.0, < 3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.2-x64-mingw32) + unf_ext (0.0.7.2-x86-mingw32) + unicode-display_width (1.1.3) + unicorn (5.3.0) + kgio (~> 2.6) + raindrops (~> 0.7) + wdm (0.1.1) + webmock (2.3.2) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff + websocket (1.2.4) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + win32console (1.3.2-x86-mingw32) + xpath (2.0.0) + nokogiri (~> 1.3) + +PLATFORMS + x64-mingw32 + x86-mingw32 + +DEPENDENCIES + activerecord-session_store + better_errors + bikecollectives_core! + binding_of_caller + bumbleberry! + capistrano (~> 3.1) + capistrano-faster-assets (~> 1.0) + capistrano-rails (~> 1.1) + capybara-email + carrierwave + carrierwave-imageoptimizer + coveralls + cucumber + cucumber-core + cucumber-rails + daemon-spawn + daemons + database_cleaner + eventmachine! + factory_girl_rails + geocoder + gherkin3 (>= 3.1.0) + guard-cucumber + guard-rspec + haml + haml-lint + launchy + letter_opener + lingua_franca! + marmara! + meta_request + mini_magick + mocha + nokogiri (~> 1.6.8.rc2) + paypal-express! + pg + poltergeist + premailer-rails + rack-mini-profiler + rails (= 4.2.0) + rails_12factor + rake (= 11.1.2) + redcarpet + rspec + rspec-rails + rubocop + ruby_dep (= 1.3.1) + sass + sass-json-vars + sass-rails + selenium-webdriver + sidekiq + simplecov + sitemap_generator + sorcery! + thin + to_spreadsheet! + tzinfo-data + uglifier (>= 1.3.0) + unicorn + wdm (>= 0.1.0) + webmock + win32console + +BUNDLED WITH + 1.14.4 diff --git a/Guardfile b/Guardfile index e6e7c78..e5db626 100644 --- a/Guardfile +++ b/Guardfile @@ -22,3 +22,28 @@ guard :rspec do watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' } end + +cucumber_options = { + # Below are examples overriding defaults + + # cmd: 'bin/cucumber', + # cmd_additional_args: '--profile guard', + + # all_after_pass: false, + # all_on_start: false, + # keep_failed: false, + # feature_sets: ['features/frontend', 'features/experimental'], + + # run_all: { cmd_additional_args: '--profile guard_all' }, + # focus_on: { 'wip' }, # @wip + # notification: false +} + +guard "cucumber", cucumber_options do + watch(%r{^features/.+\.feature$}) + watch(%r{^features/support/.+$}) { "features" } + + watch(%r{^features/step_definitions/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || "features" + end +end diff --git a/README.md b/README.md index 10a69b3..7ce286e 100644 --- a/README.md +++ b/README.md @@ -150,3 +150,8 @@ On hold until our design team determines a director for our identity. ## Testing Practices ## Our focus will be on integration testing using Capybara. While testing the app records all translations that it finds, whether or not they exist, and which pages that they were found on. + +## Attribution ## + +### Icons ### + diff --git a/Rakefile b/Rakefile index b9a026c..ffec68e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,8 @@ # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. +require 'rubygems' +require 'cucumber' +require 'cucumber/rake/task' require File.expand_path('../config/application', __FILE__) @@ -61,3 +64,31 @@ task update_cities_fr: :environment do c.save! end end + +task :i18n do + LinguaFranca.test LinguaFranca::TestModes::RECORD do + Rake::Task[:cucumber].execute + end +end + +task :css do + ENV['CSS_TEST'] = '1' + Rake::Task[:cucumber].execute + ENV['CSS_TEST'] = nil +end + +task :a11y do + ENV['TEST_A11Y'] = '1' + Rake::Task[:cucumber].execute + ENV['TEST_A11Y'] = nil +end + +task "cucumber:debug" do + ENV['TEST_DEBUG'] = '1' + Rake::Task[:cucumber].execute + ENV['TEST_DEBUG'] = nil +end + +Cucumber::Rake::Task.new(:cucumber) do |t| + t.cucumber_opts = "features --format pretty" +end diff --git a/app/assets/images/test-poster.png b/app/assets/images/test-poster.png new file mode 100644 index 0000000..29d20c1 Binary files /dev/null and b/app/assets/images/test-poster.png differ diff --git a/app/assets/javascripts/userfield.js b/app/assets/javascripts/userfield.js index 3ee54d8..593e15a 100644 --- a/app/assets/javascripts/userfield.js +++ b/app/assets/javascripts/userfield.js @@ -21,6 +21,7 @@ var field = fields[i]; var input = field.getElementsByTagName('input')[0]; var name = field.getElementsByClassName('user-name')[0]; + } }, false); })(); diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss index fb851df..d4121c4 100644 --- a/app/assets/stylesheets/_application.scss +++ b/app/assets/stylesheets/_application.scss @@ -1710,17 +1710,17 @@ ul.warnings { a.policy { background-color: $colour-5; - @include _(order, 1); + // @include _(order, 1); } a.about { background-color: $colour-3; - @include _(order, 1); + // @include _(order, 1); } a.conferences { background-color: $colour-2; - @include _(order, 1); + // @include _(order, 1); } form, .register { @@ -1728,7 +1728,8 @@ ul.warnings { } a, form { - width: 33%; + width: 33.333%; + float: left; @include _(flex, 1); } @@ -2948,12 +2949,11 @@ a.logo { .conference-banner { text-align: center; padding: 0; - margin: 0 -1em 2em; - width: auto; + margin: 0; .title { font-size: 5vw; - margin: 1em auto 2em; + margin: 1em auto 0; h1, h2 { margin: 0; @@ -2971,6 +2971,7 @@ a.logo { img { max-width: 100%; + margin-top: 2em; } } @@ -3311,8 +3312,11 @@ body.error-locale-not-available { body { #primary-content { @include _(transition, 'filter 250ms ease-in-out, -webkit-filter 250ms ease-in-out'); - display: -webkit-flex; - flex-direction: column; + + @if capable_of(flexbox, true) { + display: -webkit-flex; + flex-direction: column; + } min-height: 100vh; overflow: hidden; } @@ -4617,6 +4621,7 @@ html[data-ontop] { .nav a { &[class] { width: auto; + float: none; overflow: visible; margin-left: 0.725em; padding: 0.25em 0.5em; diff --git a/app/assets/stylesheets/bumbleberry-settings.json b/app/assets/stylesheets/bumbleberry-settings.json index c0bafee..b8d42ed 100644 --- a/app/assets/stylesheets/bumbleberry-settings.json +++ b/app/assets/stylesheets/bumbleberry-settings.json @@ -1,103 +1,105 @@ { - "stylesheets": ["application", "editor"], - "precompile": { - "test": { - "chrome": ["51"] - }, - "development": { - "and_chr": ["55"], - "chrome": ["55"], - "edge": ["13"], - "firefox": ["50"], - "ie": ["11"], - "ios_saf": ["8", "9"] - } + "stylesheets": ["application", "editor"], + "precompile": { + "test": { + "safari": ["5"], + "chrome": ["55"] }, - "background-color": "#FFFEFE", - "breakpoint-unit": "px", - "unresponsive-width": 1000, - "row-width": 1000, - "total-columns": 12, - "platforms": { - "mobile": { - "range": [0,700] - }, - "desktop": { - "range": [0,0] - } + "development": { + "safari": ["5"], + "and_chr": ["56"], + "chrome": ["56"], + "edge": ["13"], + "firefox": ["50"], + "ie": ["11"], + "ios_saf": ["8", "9"] + } + }, + "background-color": "#FFFEFE", + "breakpoint-unit": "px", + "unresponsive-width": 1000, + "row-width": 1000, + "total-columns": 12, + "platforms": { + "mobile": { + "range": [0,700] + }, + "desktop": { + "range": [0,0] + } + }, + "breakpoints": { + "small": { + "range": [0], + "grid": "y", + "offset": "n", + "reset-order": "n" }, - "breakpoints": { - "small": { - "range": [0], - "grid": "y", - "offset": "n", - "reset-order": "n" - }, - "medium": { - "range": [680], - "grid": "y", - "offset": "n", - "reset-order": "n" - }, - "large": { - "range": [1024], - "grid": "y", - "offset": "n", - "reset-order": "n" - }, - "small-only": { - "range": [0,319], - "grid": "n", - "offset": "n", - "reset-order": "n" - }, - "medium-only": { - "range": [320,1023], - "grid": "n", - "offset": "n", - "reset-order": "n" - } + "medium": { + "range": [680], + "grid": "y", + "offset": "n", + "reset-order": "n" }, - "grid-push": [1, 2], - "grid-pull": [1, 2], - "font-loading-method": "http2", - "fonts": { - "primary": { - "name": "Sanchez Light", - "location": "Sanchez", - "svg_id": "wf", - "ttf_type": "ttf", - "fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"] - }, - "secondary": { - "name": "AlteHaasGroteskBold", - "location": "AlteHaasGroteskBold", - "svg_id": "alte_haas_groteskbold", - "ttf_type": "ttf", - "fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"] - }, - "monospace": { - "name": "NotCourierSans", - "location": "NotCourierSans", - "svg_id": "notcouriersans", - "ttf_type": "ttf", - "fallback": ["Courier New", "monospace"], - "auto_load": "n" - }, - "monospace-bold": { - "name": "NotCourierSans", - "location": "NotCourierSans-Bold", - "svg_id": "notcouriersansbold", - "ttf_type": "ttf", - "fallback": ["Courier New", "monospace"], - "auto_load": "n", - "weight": "bold" - } + "large": { + "range": [1024], + "grid": "y", + "offset": "n", + "reset-order": "n" }, - "sprites": { - "icons": { - "bb-icon-logo": [0, 0, "182px", "149px"], - "bb-icon-logo-text": ["182px", 0, "136px", "149px"] - } + "small-only": { + "range": [0,319], + "grid": "n", + "offset": "n", + "reset-order": "n" + }, + "medium-only": { + "range": [320,1023], + "grid": "n", + "offset": "n", + "reset-order": "n" + } + }, + "grid-push": [1, 2], + "grid-pull": [1, 2], + "font-loading-method": "http2", + "fonts": { + "primary": { + "name": "Sanchez Light", + "location": "Sanchez", + "svg_id": "wf", + "ttf_type": "ttf", + "fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"] + }, + "secondary": { + "name": "AlteHaasGroteskBold", + "location": "AlteHaasGroteskBold", + "svg_id": "alte_haas_groteskbold", + "ttf_type": "ttf", + "fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"] + }, + "monospace": { + "name": "NotCourierSans", + "location": "NotCourierSans", + "svg_id": "notcouriersans", + "ttf_type": "ttf", + "fallback": ["Courier New", "monospace"], + "auto_load": "n" + }, + "monospace-bold": { + "name": "NotCourierSans", + "location": "NotCourierSans-Bold", + "svg_id": "notcouriersansbold", + "ttf_type": "ttf", + "fallback": ["Courier New", "monospace"], + "auto_load": "n", + "weight": "bold" + } + }, + "sprites": { + "icons": { + "bb-icon-logo": [0, 0, "182px", "149px"], + "bb-icon-logo-text": ["182px", 0, "136px", "149px"] } + } } diff --git a/app/assets/stylesheets/user-mailer.scss b/app/assets/stylesheets/user-mailer.scss index af6e781..b312e63 100644 --- a/app/assets/stylesheets/user-mailer.scss +++ b/app/assets/stylesheets/user-mailer.scss @@ -1,268 +1,268 @@ @import "settings"; body { - width: 100% !important; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - margin: 1em; - padding: 0; + width: 100% !important; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + margin: 1em; + padding: 0; } .ExternalClass { - width: 100%; - line-height: 100%; + width: 100%; + line-height: 100%; - p, span, font, td, div { - line-height: 100%; - } + p, span, font, td, div { + line-height: 100%; + } } #backgroundTable { - margin: 0; - padding: 0; - width: 100% !important; - max-width: 100% !important; - line-height: 100% !important; + margin: 0; + padding: 0; + width: 100% !important; + max-width: 100% !important; + line-height: 100% !important; } img { - outline: none; - text-decoration: none; - -ms-interpolation-mode: bicubic; + outline: none; + text-decoration: none; + -ms-interpolation-mode: bicubic; - a & { - border: none; - } + a & { + border: none; + } } .image_fix { - display: block; - max-width: 100%; + display: block; + max-width: 100%; } a { - color: $colour-1; - - #outlook & { - padding: 0; - } - - &:link { color: $colour-1; } - &:visited { color: $colour-1; } - &:hover { color: $colour-5; } - - @media only screen and (max-device-width: 480px) { - &[href^="tel"], &[href^="sms"] { - text-decoration: none; - color: $black; - pointer-events: none; - cursor: default; - } - - .mobile_link &[href^="tel"], .mobile_link &[href^="sms"] { - text-decoration: default; - color: $colour-1 !important; - pointer-events: auto; - cursor: default; - } - } + color: $colour-1; + + #outlook & { + padding: 0; + } + + &:link { color: $colour-1; } + &:visited { color: $colour-1; } + &:hover { color: $colour-5; } + + @media only screen and (max-device-width: 480px) { + &[href^="tel"], &[href^="sms"] { + text-decoration: none; + color: $black; + pointer-events: none; + cursor: default; + } + + .mobile_link &[href^="tel"], .mobile_link &[href^="sms"] { + text-decoration: default; + color: $colour-1 !important; + pointer-events: auto; + cursor: default; + } + } } p { - color: $black !important; - font-size: 1.5em; + color: $black !important; + font-size: 1.5em; } p, blockquote { - margin: 1em; - line-height: 1.3333em; + margin: 1em; + line-height: 1.3333em; } blockquote { - font-size: 1em; + font-size: 1em; } h1 { - font-size: 2.5em; - line-height: 1.25em; - padding: 1em 0; - - &:first-child { - padding-top: 0; - } + font-size: 2.5em; + line-height: 1.25em; + padding: 1em 0; + + &:first-child { + padding-top: 0; + } } h2 { - font-size: 1.8em; - line-height: 1.25em; - padding-bottom: 1em; + font-size: 1.8em; + line-height: 1.25em; + padding-bottom: 1em; } blockquote { - font-style: italic; - margin-bottom: 2em; - color: #666 !important; - border: 0.1em solid #CCC; - padding: 1em; - border-style: none none solid solid; - background-color: #F8F8F8; + font-style: italic; + margin-bottom: 2em; + color: #666 !important; + border: 0.1em solid #CCC; + padding: 1em; + border-style: none none solid solid; + background-color: #F8F8F8; } h1, h2, h3, h4, h5, h6 { - color: $black !important; - - a { - color: $colour-1 !important; - - &:active { - color: $colour-4 !important; - } - - &:visited { - color: $colour-2 !important; - } - } + color: $black !important; + + a { + color: $colour-1 !important; + + &:active { + color: $colour-4 !important; + } + + &:visited { + color: $colour-2 !important; + } + } } table { - border-collapse: collapse; - max-width: 512px; - min-width: 280px; - mso-table-lspace: 0pt; - mso-table-rspace: 0pt; - - td { - border-collapse: collapse; - } - - th { - text-align: left; - } + border-collapse: collapse; + max-width: 512px; + min-width: 280px; + mso-table-lspace: 0pt; + mso-table-rspace: 0pt; + + td { + border-collapse: collapse; + } + + th { + text-align: left; + } } table#bb_full_width, table#ecxbb_full_width { - &, table { - max-width: none; - width: 100%; - } + &, table { + max-width: none; + width: 100%; + } } .error-report { - width: 100%; - max-width: 100%; - border: 0.15em solid #CCC; - background-color: #EEE; - font-size: 1.25em; - margin-bottom: 2em; - - th { - background-color: #CCC; - } - - td, th { - padding: 0.25em 0.5em; - - &:last-child { - border-left: 0.15em solid #CCC; - min-width: 40em; - } - } - - td:last-child { - font-family: monospace; - word-break: break-word; - background-color: #FFF; - font-size: 0.75em; - } + width: 100%; + max-width: 100%; + border: 0.15em solid #CCC; + background-color: #EEE; + font-size: 1.25em; + margin-bottom: 2em; + + th { + background-color: #CCC; + } + + td, th { + padding: 0.25em 0.5em; + + &:last-child { + border-left: 0.15em solid #CCC; + min-width: 40em; + } + } + + td:last-child { + font-family: monospace; + word-break: break-word; + background-color: #FFF; + font-size: 0.75em; + } } code { - color: #C33; - font-size: 0.9em; + color: #C33; + font-size: 0.9em; } pre { - font-size: 1.5em; - padding: 1em; - background-color: #333; - color: antiquewhite; - word-break: break-word; + font-size: 1.5em; + padding: 1em; + background-color: #333; + color: antiquewhite; + word-break: break-word; } .diff, .ecxdiff { - margin: 1em 0 5em 1em; - overflow: auto; - - ul { - list-style: none; - padding: 0; - margin: 0; - position: relative; - } - - li { - width: 40%; - display: inline-block; - padding: 0.5em; - margin: 0; - border-bottom: 1px solid #DDD; - //white-space: nowrap; - - &:nth-child(odd) { - margin-right: -3px; - float: left; - clear: left; - } - - ins { - color: #080;//lighten($colour-3, 33%); - } - - del { - color: #800; - } - } + margin: 1em 0 5em 1em; + overflow: auto; + + ul { + list-style: none; + padding: 0; + margin: 0; + position: relative; + } + + li { + width: 40%; + display: inline-block; + padding: 0.5em; + margin: 0; + border-bottom: 1px solid #DDD; + //white-space: nowrap; + + &:nth-child(odd) { + margin-right: -3px; + float: left; + clear: left; + } + + ins { + color: #080;//lighten($colour-3, 33%); + } + + del { + color: #800; + } + } } // Buttons h3 { - b { - padding: 10px 20px; - line-height: 50px; - - a, a:visited { - color: #FFF !important; - background-color: $colour-5; - text-decoration: none !important; - border-radius: 4px; - padding: 10px 15px; - margin-left: 20px; - border-bottom: 3px solid darken($colour-5, 10%); - -webkit-box-shadow: 0 0.5em 1.5em -0.75em #000; - box-shadow: 0 0.5em 1.5em -0.75em #000; - cursor: pointer !important; - } - - a:hover { - background-color: darken($colour-5, 10%); - } - } + b { + padding: 10px 20px; + line-height: 50px; + + a, a:visited { + color: #FFF !important; + background-color: $colour-5; + text-decoration: none !important; + border-radius: 4px; + padding: 10px 15px; + margin-left: 20px; + border-bottom: 3px solid darken($colour-5, 10%); + -webkit-box-shadow: 0 0.5em 1.5em -0.75em #000; + box-shadow: 0 0.5em 1.5em -0.75em #000; + cursor: pointer !important; + } + + a:hover { + background-color: darken($colour-5, 10%); + } + } } @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { - a[href^="tel"], a[href^="sms"] { - text-decoration: none; - color: $colour-1; - pointer-events: none; - cursor: default; - - .mobile_link & { - text-decoration: default; - color: $colour-1 !important; - pointer-events: auto; - cursor: default; - } - } + a[href^="tel"], a[href^="sms"] { + text-decoration: none; + color: $colour-1; + pointer-events: none; + cursor: default; + + .mobile_link & { + text-decoration: default; + color: $colour-1 !important; + pointer-events: auto; + cursor: default; + } + } } diff --git a/app/controllers/admin_controller.rb b/app/controllers/administration_controller.rb similarity index 94% rename from app/controllers/admin_controller.rb rename to app/controllers/administration_controller.rb index 1c03f0d..4c5d980 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/administration_controller.rb @@ -1,51 +1,51 @@ -require 'geocoder/calculations' - -class AdminController < ApplicationController - def new - return do_404 unless logged_in? && current_user.administrator? - @this_conference = Conference.new - @main_title = @page_title = 'articles.conferences.headings.new' - end - - def edit - return do_404 unless logged_in? && current_user.administrator? - @this_conference = Conference.find_by!(slug: params[:slug]) - @page_title = 'articles.conferences.headings.edit' - @main_title_vars = { vars: { title: @this_conference.title } } - render 'new' - end - - def save - conference = params[:id].present? ? Conference.find_by!(id: params[:id]) : Conference.new - - if params[:button] == 'save' - city = City.search(params[:city]) - conference.city_id = city.id - conference.conferencetype = params[:type] - conference.year = params[:year].to_i - conference.is_public = params[:is_public].present? - conference.is_featured = params[:is_featured].present? - conference.make_slug(true) - conference.save! - elsif params[:button] == 'delete' - conference.destroy - return redirect_to conferences_url - end - - redirect_to conference_url(conference.slug) - end - - rescue_from ActiveRecord::PremissionDenied do |exception| - if logged_in? - redirect_to :register - else - @register_template = :confirm_email - @page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details" - render :register - end - end - - rescue_from ActiveRecord::RecordNotFound do |exception| - do_404 - end -end +require 'geocoder/calculations' + +class AdministrationController < ApplicationController + def new + return do_404 unless logged_in? && current_user.administrator? + @this_conference = Conference.new + @main_title = @page_title = 'articles.conferences.headings.new' + end + + def edit + return do_404 unless logged_in? && current_user.administrator? + @this_conference = Conference.find_by!(slug: params[:slug]) + @page_title = 'articles.conferences.headings.edit' + @main_title_vars = { vars: { title: @this_conference.title } } + render 'new' + end + + def save + conference = params[:id].present? ? Conference.find_by!(id: params[:id]) : Conference.new + + if params[:button] == 'save' + city = City.search(params[:city]) + conference.city_id = city.id + conference.conferencetype = params[:type] + conference.year = params[:year].to_i + conference.is_public = params[:is_public].present? + conference.is_featured = params[:is_featured].present? + conference.make_slug(true) + conference.save! + elsif params[:button] == 'delete' + conference.destroy + return redirect_to conferences_url + end + + redirect_to conference_url(conference.slug) + end + + rescue_from ActiveRecord::PremissionDenied do |exception| + if logged_in? + redirect_to :register + else + @register_template = :confirm_email + @page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details" + render :register + end + end + + rescue_from ActiveRecord::RecordNotFound do |exception| + do_404 + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7f6039b..ae7c2e6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,11 +1,4 @@ -module ActiveRecord - class PremissionDenied < RuntimeError - end -end - -class ApplicationController < LinguaFrancaApplicationController - # Prevent CSRF attacks by raising an exception. - # For APIs, you may want to use :null_session instead. +class ApplicationController < BaseController protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update] before_filter :capture_page_info @@ -16,6 +9,7 @@ class ApplicationController < LinguaFrancaApplicationController @@test_location def capture_page_info + # capture request info in case an error occurs if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact') session[:last_request] request_info = { @@ -27,14 +21,11 @@ class ApplicationController < LinguaFrancaApplicationController 'env' => Hash.new } } - request.env.each do | key, value | + request.env.each do |key, value| request_info['request']['env'][key.to_s] = value.to_s end session['request_info'] = request_info end - # set the translator to the current user if we're logged in - I18n.config.translator = current_user - I18n.config.callback = self # get the current conferences and set them globally status_hierarchy = { @@ -57,11 +48,9 @@ class ApplicationController < LinguaFrancaApplicationController @_inline_scripts ||= [] @_inline_scripts << Rails.application.assets.find_asset('main.js').to_s - ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"} - - if request.post? && params[:action] == 'do_confirm' - halt_redirection! - end + ActionMailer::Base.default_url_options = { + host: "#{request.protocol}#{request.host_with_port}" + } @alt_lang_urls = {} I18n.backend.enabled_locales.each do |locale| @@ -72,17 +61,16 @@ class ApplicationController < LinguaFrancaApplicationController # give each environment a different icon and theme colour so that we can easily see where we are. See https://css-tricks.com/give-development-domain-different-favicon-production @favicon = Rails.env.development? || Rails.env.preview? ? "favicon-#{Rails.env.to_s}.ico" : 'favicon.ico' @theme_colour = Rails.env.preview? ? '#EF57B4' : (Rails.env.development? ? '#D89E59' : '#00ADEF') - - # call the base method to detect the language - super end def home - @workshops = Workshop.where(:conference_id => @conference.id) + if @conference.present? && @conference.id.present? + @workshops = Workshop.where(conference_id: @conference.id) - if @conference.workshop_schedule_published - @event_dlg = true - get_scheule_data(false) + if @conference.workshop_schedule_published + @event_dlg = true + get_scheule_data(false) + end end end @@ -90,14 +78,6 @@ class ApplicationController < LinguaFrancaApplicationController @is_policy_page = true end - def robots - render :text => File.read("config/robots-#{Rails.env.production? ? 'live' : 'dev'}.txt"), :content_type => 'text/plain' - end - - def humans - render :text => File.read("config/humans.txt"), :content_type => 'text/plain' - end - def self.set_host(host) @@test_host = host end @@ -110,35 +90,6 @@ class ApplicationController < LinguaFrancaApplicationController @@test_location end - def do_404 - error_404(status: 404) - end - - def error_404(args = {}) - params[:_original_action] = params[:action] - params[:action] = 'error-404' - @page_title = 'page_titles.404.Page_Not_Found' - @main_title = 'error.404.title' - render 'application/404', args - end - - def do_403(template = nil) - @template = template - @page_title ||= 'page_titles.403.Access_Denied' - @main_title ||= @page_title - params[:_original_action] = params[:action] - params[:action] = 'error-403' - render 'application/permission_denied', status: 403 - end - - def error_500(exception = nil) - @page_title = 'page_titles.500.An_Error_Occurred' - @main_title = 'error.500.title' - params[:_original_action] = params[:action] - params[:action] = 'error-500' - render 'application/500', status: 500 - end - def js_error # send and email if this is production report = "A JavaScript error has occurred on #{params[:location]}" @@ -150,7 +101,7 @@ class ApplicationController < LinguaFrancaApplicationController begin # log the error - logger.info "Javascript exception: #{params[:message]}" + logger.info "A JavaScript error has occurred on #{params[:location]}:#{params[:lineNumber]}: #{params[:message]}" UserMailer.send_mail(:error_report) do [ @@ -163,7 +114,7 @@ class ApplicationController < LinguaFrancaApplicationController current_user, Time.now.strftime("%d/%m/%Y %H:%M") ] - end# if Rails.env.preview? || Rails.env.production? + end if Rails.env.preview? || Rails.env.production? rescue Exception => exception2 logger.info exception2.to_s logger.info exception2.backtrace.join("\n") @@ -171,31 +122,27 @@ class ApplicationController < LinguaFrancaApplicationController render json: {} end - rescue_from ActiveRecord::RecordNotFound do |exception| - do_404 - end - - rescue_from ActiveRecord::PremissionDenied do |exception| - do_403 - end + def confirmation_sent(user) + template = 'login_confirmation_sent' + @page_title ||= 'page_titles.403.Please_Check_Email' - rescue_from AbstractController::ActionNotFound do |exception| - @banner_image = 'grafitti.jpg' - - if current_user - @page_title = nil#'page_titles.Please_Login' - do_403 'not_a_translator' - #return - else - @page_title = 'page_titles.403.Please_Login' - do_403 'translator_login' + if (request.present? && request.referrer.present? && conference = /^\/conferences\/(\w+)\/register\/?$/.match(request.referrer.gsub(/^https?:\/\/.*?\//, '/'))) + @this_conference = Conference.find_by!(slug: conference[1]) + @banner_image = @this_conference.cover_url + template = 'conferences/email_confirm' end + + do_403 template end def locale_not_enabled!(locale = nil) locale_not_available!(locale) end + def locale_not_available + locale_not_available!(params[:locale]) + end + def locale_not_available!(locale = nil) set_default_locale params[:_original_action] = params[:action] @@ -206,11 +153,13 @@ class ApplicationController < LinguaFrancaApplicationController render 'application/locale_not_available', status: 404 end - rescue_from StandardError do |exception| - handle_exception exception + unless Rails.env.test? + rescue_from StandardError do |exception| + handle_exception exception - # show the error page - error_500 exception + # show the error page + error_500 exception + end end def handle_exception(exception) @@ -246,37 +195,6 @@ class ApplicationController < LinguaFrancaApplicationController end end - def generate_confirmation(user, url, expiry = nil) - if user.is_a? String - user = User.find_user(user) - - # if the user doesn't exist, just show them a 403 - do_403 unless user.present? - end - expiry ||= (Time.now + 12.hours) - session[:confirm_uid] = user.id - - unless user.locale.present? - user.locale = I18n.locale - user.save - end - - # send the confirmation email and make sure it get sent as quickly as possible - UserMailer.send_mail :email_confirmation do - EmailConfirmation.create(user_id: user.id, expiry: expiry, url: url) - end - end - - def user_settings - @conferences = Array.new - if logged_in? - Conference.all.each do | conference | - @conferences << conference if conference.host? current_user - end - end - @main_title = @page_title = 'page_titles.user_settings.Your_Account' - end - def contact @main_title = @page_title = 'page_titles.contact.Contact_Us' end @@ -286,8 +204,8 @@ class ApplicationController < LinguaFrancaApplicationController if params[:reason] == 'conference' - @conference.organizations.each do | org | - org.users.each do | user | + @conference.organizations.each do |org| + org.users.each do |user| email_list << user.named_email end end @@ -322,31 +240,8 @@ class ApplicationController < LinguaFrancaApplicationController render 'contact' end - def update_user_settings - return do_403 unless logged_in? - current_user.firstname = params[:name] - current_user.lastname = nil - current_user.languages = (params[:languages] || { I18n.locale.to_s => true }).keys - current_user.is_subscribed = params[:email_subscribe].present? - current_user.save - redirect_to settings_path - end - - def do_confirm(settings = nil) - settings ||= {:template => 'login_confirmation_sent'} + def confirm_user if params[:email] - # see if we've already sent the confirmation email and are just confirming - # the email address - if params[:token] - user = User.find_user(params[:email]) - confirm(user) - return - end - user = User.get(params[:email]) - - # generate the confirmation, send the email and show the 403 - referrer = params[:dest] || (request.present? && request.referer.present? ? request.referer.gsub(/^.*?\/\/.*?\//, '/') : settings_path) - generate_confirmation(params[:email], referrer) template = 'login_confirmation_sent' @page_title ||= 'page_titles.403.Please_Check_Email' @@ -361,75 +256,44 @@ class ApplicationController < LinguaFrancaApplicationController @banner_image ||= 'grafitti.jpg' @page_title ||= 'page_titles.403.Please_Login' - do_403 (template || 'translator_login') + do_403 template else do_404 end end - def confirm(uid = nil) - @confirmation = EmailConfirmation.find_by_token(params[:token]) - - unless @confirmation.present? - @token_not_found = true - return do_404 - end - - confirm_user = nil - if uid.is_a?(User) - confirm_user = uid - uid = confirm_user.id - end - # check to see if we were given a user id to confirm against - # if we were, make sure it was the same one - if (uid ||= (params[:uid] || session[:confirm_uid])) - if uid == @confirmation.user_id - session[:uid] = nil - confirm_user ||= User.find uid - auto_login(confirm_user) - else - @confirmation.delete - end - - redirect_to (@confirmation.url || '/') - return - end - - @banner_image = 'grafitti.jpg' - @page_title = 'page_titles.403.Please_Confirm_Email' - do_403 'login_confirm' + def error_404(args = {}) + params[:_original_action] = params[:action] + params[:action] = 'error-404' + @page_title = 'page_titles.404.Page_Not_Found' + @main_title = 'error.404.title' + super(args) end - def translator_request + def do_403(template = nil) @banner_image = 'grafitti.jpg' - @page_title = 'page_titles.403.Translator_Request_Sent' - do_403 'translator_request_sent' - end - - def user_logout - logout() - redirect_to (params[:url] || '/') - end + + unless current_user + @page_title = 'page_titles.403.Please_Login' + end - def find_user - user = User.find_user(params[:e]) + @template = template + @page_title ||= 'page_titles.403.Access_Denied' + @main_title ||= @page_title + params[:_original_action] = params[:action] + params[:action] = 'error-403' - if user.present? - return render json: { - name: user.name, - email: user.email, - exists: true - } - end - render json: { - name: I18n.t('user.not_found'), - email: nil, - exists: false - } + super(template) end - def login_user(u) - auto_login(u) + def error_500(exception = nil) + @page_title = 'page_titles.500.An_Error_Occurred' + @main_title = 'error.500.title' + params[:_original_action] = params[:action] + params[:action] = 'error-500' + @exception = exception + + super(exception) end def on_translation_change(object, data, locale, translator_id) @@ -541,8 +405,8 @@ class ApplicationController < LinguaFrancaApplicationController @schedule = {} day_1 = conference.start_date.wday - @workshop_blocks.each_with_index do | info, block | - info['days'].each do | block_day | + @workshop_blocks.each_with_index do |info, block| + info['days'].each do |block_day| day_diff = block_day.to_i - day_1 day_diff += 7 if day_diff < 0 day = (conference.start_date + day_diff.days).to_date @@ -555,9 +419,10 @@ class ApplicationController < LinguaFrancaApplicationController end end - @workshops.each do | workshop | + @workshops.each do |workshop| if workshop.block.present? block = @workshop_blocks[workshop.block['block'].to_i] + day_diff = workshop.block['day'].to_i - day_1 day_diff += 7 if day_diff < 0 day = (conference.start_date + day_diff.days).to_date @@ -569,7 +434,7 @@ class ApplicationController < LinguaFrancaApplicationController end end - @meals.each do | time, meal | + @meals.each do |time, meal| day = meal['day'].to_date time = meal['time'].to_f @schedule[day] ||= {} @@ -580,7 +445,7 @@ class ApplicationController < LinguaFrancaApplicationController @schedule[day][:times][time][:item] = meal end - @events.each do | event | + @events.each do |event| if event.present? && event.start_time.present? && event.end_time.present? day = event.start_time.midnight.to_date time = event.start_time.hour.to_f + (event.start_time.min / 60.0) @@ -594,13 +459,13 @@ class ApplicationController < LinguaFrancaApplicationController end @schedule = @schedule.sort.to_h - @schedule.each do | day, data | + @schedule.each do |day, data| @schedule[day][:times] = data[:times].sort.to_h end - @schedule.each do | day, data | + @schedule.each do |day, data| last_event = nil - data[:times].each do | time, time_data | + data[:times].each do |time, time_data| if last_event.present? @schedule[day][:times][last_event][:next_event] = time end @@ -609,8 +474,8 @@ class ApplicationController < LinguaFrancaApplicationController @schedule[day][:num_locations] = (data[:locations] || []).size end - @schedule.deep_dup.each do | day, data | - data[:times].each do | time, time_data | + @schedule.deep_dup.each do |day, data| + data[:times].each do |time, time_data| if time_data[:next_event].present? || time_data[:length] > 0.5 span = 0.5 length = time_data[:next_event].present? ? time_data[:next_event] - time : time_data[:length] @@ -627,7 +492,7 @@ class ApplicationController < LinguaFrancaApplicationController @schedule = @schedule.sort.to_h - @schedule.each do | day, data | + @schedule.each do |day, data| @schedule[day][:times] = data[:times].sort.to_h @schedule[day][:locations] ||= {} @@ -635,19 +500,19 @@ class ApplicationController < LinguaFrancaApplicationController @schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty? if do_analyze - data[:times].each do | time, time_data | + data[:times].each do |time, time_data| if time_data[:type] == :workshop && time_data[:item].present? && time_data[:item][:workshops].present? ids = time_data[:item][:workshops].keys - (0..ids.length).each do | i | + (0..ids.length).each do |i| if time_data[:item][:workshops][ids[i]].present? workshop_i = time_data[:item][:workshops][ids[i]][:workshop] conflicts = {} - (i+1..ids.length).each do | j | + (i+1..ids.length).each do |j| workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil if workshop_i.present? && workshop_j.present? - workshop_i.active_facilitators.each do | facilitator_i | - workshop_j.active_facilitators.each do | facilitator_j | + workshop_i.active_facilitators.each do |facilitator_i| + workshop_j.active_facilitators.each do |facilitator_j| if facilitator_i.id == facilitator_j.id @schedule[day][:times][time][:status] ||= {} @schedule[day][:times][time][:item][:workshops][ids[j]][:status][:errors] << { @@ -669,7 +534,7 @@ class ApplicationController < LinguaFrancaApplicationController needs = JSON.parse(workshop_i.needs || '[]').map &:to_sym amenities = JSON.parse(location.amenities || '[]').map &:to_sym - needs.each do | need | + needs.each do |need| @schedule[day][:times][time][:item][:workshops][ids[i]][:status][:errors] << { name: :need_not_available, need: need, @@ -685,7 +550,7 @@ class ApplicationController < LinguaFrancaApplicationController # collect common interested users interests = [] - (0..ids.length).each do | j | + (0..ids.length).each do |j| workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil if workshop_i.present? && workshop_j.present? && workshop_i.id != workshop_j.id interests = interests | workshop_j.interested.map { | u | u.user_id } @@ -740,4 +605,9 @@ class ApplicationController < LinguaFrancaApplicationController def html_value(value) return value.present? && ActionView::Base.full_sanitizer.sanitize(value).strip.present? ? value : nil end + + # send the confirmation email and make sure it get sent as quickly as possible + def send_confirmation(confirmation) + UserMailer.send_mail(:email_confirmation) { confirmation } + end end diff --git a/app/controllers/conference_administration_controller.rb b/app/controllers/conference_administration_controller.rb index e64d547..2fef5c8 100644 --- a/app/controllers/conference_administration_controller.rb +++ b/app/controllers/conference_administration_controller.rb @@ -62,7 +62,10 @@ class ConferenceAdministrationController < ApplicationController set_flash_messages # redirect to the step unless the method handled redirection itself - unless self.send(method_name) + case self.send(method_name) + when true + administration_step(@admin_step) + when false redirect_to administration_step_path(@this_conference.slug, @admin_step) end end @@ -100,6 +103,9 @@ class ConferenceAdministrationController < ApplicationController end def administrate_broadcast + if @this_conference.start_date.blank? || @this_conference.end_date.blank? + @warning_message = :no_date_warning + end end def administrate_broadcast_sent @@ -120,6 +126,9 @@ class ConferenceAdministrationController < ApplicationController end def administrate_registration_status + if @this_conference.start_date.blank? || @this_conference.end_date.blank? + @warning_message = :no_date_warning + end end def administrate_organizations @@ -142,7 +151,7 @@ class ConferenceAdministrationController < ApplicationController }, data: [], } - @organizations.each do | org | + @organizations.each do |org| if org.present? address = org.locations.first @excel_data[:data] << { @@ -158,18 +167,23 @@ class ConferenceAdministrationController < ApplicationController } end end - return respond_to do | format | + return respond_to do |format| format.xlsx { render xlsx: :stats, filename: "organizations" } end end end def administrate_registrations + if @this_conference.start_date.blank? || @this_conference.end_date.blank? + @warning_message = :no_date_warning + return + end + get_stats(!request.format.xlsx?) if request.format.xlsx? logger.info "Generating stats.xls" - return respond_to do | format | + return respond_to do |format| format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" } end end @@ -180,7 +194,7 @@ class ConferenceAdministrationController < ApplicationController @donation_count = 0 @donations = 0 @food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 } - @registrations.each do | r | + @registrations.each do |r| if view_context.registration_status(r) == :registered @completed_registrations += 1 @@ -200,11 +214,16 @@ class ConferenceAdministrationController < ApplicationController end def administrate_stats + if @this_conference.start_date.blank? || @this_conference.end_date.blank? + @warning_message = :no_date_warning + return + end + get_stats(!request.format.xlsx?) if request.format.xlsx? logger.info "Generating stats.xls" - return respond_to do | format | + return respond_to do |format| format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" } end else @@ -214,7 +233,7 @@ class ConferenceAdministrationController < ApplicationController @donation_count = 0 @donations = 0 @food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 } - @registrations.each do | r | + @registrations.each do |r| if view_context.registration_status(r) == :registered @completed_registrations += 1 @@ -256,7 +275,7 @@ class ConferenceAdministrationController < ApplicationController }, data: [], } - @hosts.each do | id, host | + @hosts.each do |id, host| data = (host.housing_data || {}) host_data = { name: host.user.name, @@ -264,7 +283,7 @@ class ConferenceAdministrationController < ApplicationController email: host.user.email, phone: data['phone'], availability: data['availability'].present? && data['availability'][1].present? ? view_context.date_span(data['availability'][0].to_date, data['availability'][1].to_date) : '', - considerations: ((data['considerations'] || []).map { | consideration | view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '), + considerations: ((data['considerations'] || []).map { |consideration| view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '), empty: '', guests: { columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city], @@ -285,8 +304,8 @@ class ConferenceAdministrationController < ApplicationController } } - @housing_data[id][:guests].each do | space, space_data | - space_data.each do | guest_id, guest_data | + @housing_data[id][:guests].each do |space, space_data| + space_data.each do |guest_id, guest_data| guest = guest_data[:guest] if guest.present? companion = view_context.companion(guest) @@ -307,7 +326,7 @@ class ConferenceAdministrationController < ApplicationController @excel_data[:data] << host_data end - return respond_to do | format | + return respond_to do |format| format.xlsx { render xlsx: :stats, filename: "housing" } end end @@ -439,7 +458,7 @@ class ConferenceAdministrationController < ApplicationController }, data: [] } - User.AVAILABLE_LANGUAGES.each do | l | + User.AVAILABLE_LANGUAGES.each do |l| @excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}" end ConferenceRegistration.all_spaces.each do |s| @@ -449,7 +468,7 @@ class ConferenceAdministrationController < ApplicationController ConferenceRegistration.all_considerations.each do |c| @excel_data[:keys][c] = "articles.conference_registration.host.considerations.#{c.to_s}" end - @registrations.each do | r | + @registrations.each do |r| user = r.user_id ? User.where(id: r.user_id).first : nil if user.present? companion = view_context.companion(r) @@ -509,7 +528,7 @@ class ConferenceAdministrationController < ApplicationController last_day: availability[1].present? ? view_context.date(availability[1].to_date, :span_same_year_date_1) : '' } } - User.AVAILABLE_LANGUAGES.each do | l | + User.AVAILABLE_LANGUAGES.each do |l| can_speak = ((user.languages || []).include? l.to_s) data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '') data[:raw_values]["language_#{l}".to_sym] = can_speak @@ -554,12 +573,12 @@ class ConferenceAdministrationController < ApplicationController first_day: view_context.conference_days_options_list(:before), last_day: view_context.conference_days_options_list(:after) } - User.AVAILABLE_LANGUAGES.each do | l | + User.AVAILABLE_LANGUAGES.each do |l| @column_options["language_#{l}".to_sym] = [ [(view_context._"articles.conference_registration.questions.bike.yes"), true] ] end - ConferenceRegistration.all_considerations.each do | c | + ConferenceRegistration.all_considerations.each do |c| @column_options[c.to_sym] = [ [(view_context._"articles.conference_registration.questions.bike.yes"), true] ] @@ -570,7 +589,7 @@ class ConferenceAdministrationController < ApplicationController def get_housing_data @hosts = {} @guests = {} - ConferenceRegistration.where(:conference_id => @this_conference.id).each do | registration | + ConferenceRegistration.where(:conference_id => @this_conference.id).each do |registration| if registration.can_provide_housing @hosts[registration.id] = registration elsif registration.housing.present? && registration.housing != 'none' @@ -584,11 +603,11 @@ class ConferenceAdministrationController < ApplicationController @housing_data = {} @hosts_affected_by_guests = {} - @hosts.each do | id, host | + @hosts.each do |id, host| @hosts[id].housing_data ||= {} @housing_data[id] = { guests: {}, space: {} } @hosts[id].housing_data['space'] ||= {} - @hosts[id].housing_data['space'].each do | s, size | + @hosts[id].housing_data['space'].each do |s, size| size = (size || 0).to_i @housing_data[id][:guests][s.to_sym] = {} @housing_data[id][:space][s.to_sym] = size @@ -597,7 +616,7 @@ class ConferenceAdministrationController < ApplicationController @guests_housed = 0 - @guests.each do | guest_id, guest | + @guests.each do |guest_id, guest| data = guest.housing_data || {} @hosts_affected_by_guests[guest_id] ||= [] @@ -632,7 +651,7 @@ class ConferenceAdministrationController < ApplicationController end companions = data['companions'] || [] - companions.each do | companion | + companions.each do |companion| user = User.find_user(companion) if user.present? reg = ConferenceRegistration.find_by( @@ -659,10 +678,10 @@ class ConferenceAdministrationController < ApplicationController end end - @hosts.each do | id, host | + @hosts.each do |id, host| host_data = host.housing_data - @hosts[id].housing_data['space'].each do | space, size | + @hosts[id].housing_data['space'].each do |space, size| # make sure the host isn't overbooked space = space.to_sym space_available = (size || 0).to_i @@ -771,7 +790,7 @@ class ConferenceAdministrationController < ApplicationController end def admin_update_description - params[:info].each do | locale, value | + params[:info].each do |locale, value| @this_conference.set_column_for_locale(:info, locale, html_value(value)) end @this_conference.save @@ -792,7 +811,7 @@ class ConferenceAdministrationController < ApplicationController def admin_update_payment_message begin - params[:payment_message].each do | locale, value | + params[:payment_message].each do |locale, value| @this_conference.set_column_for_locale(:payment_message, locale, html_value(value)) end @this_conference.save @@ -864,7 +883,7 @@ class ConferenceAdministrationController < ApplicationController end user_changed = false - params.each do | key, value | + params.each do |key, value| case key.to_sym when :city if value.present? @@ -995,7 +1014,7 @@ class ConferenceAdministrationController < ApplicationController @send_to = params[:send_to] @register_template = :administration if params[:button] == 'send' - view_context.broadcast_to(@send_to).each do | user | + view_context.broadcast_to(@send_to).each do |user| UserMailer.send_mail :broadcast do [ "#{request.protocol}#{request.host_with_port}", @@ -1108,11 +1127,11 @@ class ConferenceAdministrationController < ApplicationController event.end_time = event.start_time + params[:time_span].to_f.hours # save translations - (params[:info] || {}).each do | locale, value | + (params[:info] || {}).each do |locale, value| event.set_column_for_locale(:title, locale, html_value(value), current_user.id) unless value = event._title(locale) end - (params[:title] || {}).each do | locale, value | + (params[:title] || {}).each do |locale, value| event.set_column_for_locale(:info, locale, value, current_user.id) unless value = event._info(locale) end @@ -1126,22 +1145,47 @@ class ConferenceAdministrationController < ApplicationController do_404 return true end - + def admin_update_workshop_times case params[:button] when 'save_block' + empty_param = empty_params(:time, :time_span, :days) + if empty_param.present? + set_error_message "save_block_#{empty_param}_required".to_sym + else + @this_conference.workshop_blocks ||= [] + @this_conference.workshop_blocks[params[:workshop_block].to_i] = { + 'time' => params[:time], + 'length' => params[:time_span], + 'days' => params[:days].keys + } + @this_conference.save + set_success_message :block_saved + end + return false + when 'delete_block' @this_conference.workshop_blocks ||= [] - @this_conference.workshop_blocks[params[:workshop_block].to_i] = { - 'time' => params[:time], - 'length' => params[:time_span], - 'days' => params[:days].keys - } + @this_conference.workshop_blocks.delete_at(params[:workshop_block].to_i) @this_conference.save + set_success_message :block_deleted return false end do_404 - return true + return nil + end + + def admin_update_publish_schedule + case params[:button] + when 'publish' + @this_conference.workshop_schedule_published = !@this_conference.workshop_schedule_published + @this_conference.save + set_success_message "schedule_#{@this_conference.workshop_schedule_published ? '' : 'un'}published".to_sym + return false + end + + do_404 + return false end def admin_update_schedule @@ -1155,7 +1199,6 @@ class ConferenceAdministrationController < ApplicationController @entire_page = false get_scheule_data render partial: 'schedule' - return true when 'get-workshop-list' get_scheule_data(true) @@ -1166,12 +1209,11 @@ class ConferenceAdministrationController < ApplicationController @location = params[:location] @event_location = @location.present? && @location.to_i > 0 ? EventLocation.find(@location.to_i) : nil - @workshops.sort { |a, b| a.title.downcase <=> b.title.downcase }.each do | workshop | + @workshops.sort { |a, b| a.title.downcase <=> b.title.downcase }.each do |workshop| @ordered_workshops[workshop.id] = workshop end render partial: 'select_workshop_table' - return true when 'set-workshop' workshop = Workshop.find_by!(conference_id: @this_conference.id, id: params[:workshop].to_i) workshop.event_location_id = params[:location] @@ -1183,23 +1225,11 @@ class ConferenceAdministrationController < ApplicationController get_scheule_data render partial: 'schedule' - return true - end - - do_404 - return true - end - - def admin_update_schedule - case params[:button] - when 'publish' - @this_conference.workshop_schedule_published = !@this_conference.workshop_schedule_published - @this_conference.save - return false + else + do_404 end - do_404 - return false + return nil end def admin_update_providers @@ -1221,9 +1251,13 @@ class ConferenceAdministrationController < ApplicationController def get_empty(hash, keys) keys = [keys] unless keys.is_a?(Array) - keys.each do | key | + keys.each do |key| return key unless hash[key].present? end return nil end + + def empty_params(*args) + get_empty(params, args) + end end diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 803c77e..1a23fe1 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -2,6 +2,7 @@ require 'geocoder/calculations' require 'rest_client' class ConferencesController < ApplicationController + def list @page_title = 'articles.conferences.headings.Conference_List' @conference_list = { future: [], passed: [] } @@ -17,7 +18,7 @@ class ConferencesController < ApplicationController set_conference do_403 unless @this_conference.is_public || @this_conference.host?(current_user) - @workshops = Workshop.where(:conference_id => @conference.id) + @workshops = Workshop.where(:conference_id => @this_conference.id) if @this_conference.workshop_schedule_published @event_dlg = true @@ -59,7 +60,7 @@ class ConferencesController < ApplicationController steps = nil return do_404 unless registration_steps.present? - @register_template = :administration if params[:admin_step].present? + # @register_template = :administration if params[:admin_step].present? @errors = {} @warnings = [] @@ -72,8 +73,19 @@ class ConferencesController < ApplicationController @register_template = steps[steps.find_index($1.to_sym) - 1] elsif form_step == :paypal_confirm if @registration.present? && @registration.payment_confirmation_token == params[:confirmation_token] - @amount = PayPal!.details(params[:token]).amount.total - @registration.payment_info = {:payer_id => params[:PayerID], :token => params[:token], :amount => @amount}.to_yaml + if Rails.env.test? + @amount = params[:amount].to_f + info = YAML.load(@registration.payment_info) + info[:amount] = @amount + @registration.payment_info = info.to_yaml + else + @amount = PayPal!.details(params[:token]).amount.total + @registration.payment_info = { + payer_id: params[:PayerID], + token: params[:token], + amount: @amount + }.to_yaml + end @amount = (@amount * 100).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2') @@ -86,7 +98,7 @@ class ConferencesController < ApplicationController info = YAML.load(@registration.payment_info) @amount = nil status = nil - if ENV['RAILS_ENV'] == 'test' + if Rails.env.test? status = info[:status] @amount = info[:amount] else @@ -114,7 +126,7 @@ class ConferencesController < ApplicationController case form_step when :confirm_email - return do_confirm + return confirm_email(params[:email], params[:token], register_path(@this_conference.slug)) when :contact_info if params[:name].present? && params[:name].gsub(/[\s\W]/, '').present? current_user.firstname = params[:name].squish @@ -188,18 +200,23 @@ class ConferencesController < ApplicationController amount = params[:amount].to_f if amount > 0 - @registration.payment_confirmation_token = ENV['RAILS_ENV'] == 'test' ? 'token' : Digest::SHA256.hexdigest(rand(Time.now.to_f * 1000000).to_i.to_s) - @registration.save - - host = "#{request.protocol}#{request.host_with_port}" - response = PayPal!.setup( - PayPalRequest(amount), - register_paypal_confirm_url(@this_conference.slug, :paypal_confirm, @registration.payment_confirmation_token), - register_paypal_confirm_url(@this_conference.slug, :paypal_cancel, @registration.payment_confirmation_token), - noshipping: true, - version: 204 - ) - if ENV['RAILS_ENV'] != 'test' + # we can't really test paypal integration in our tests, so we'll fake it instead + if Rails.env.test? + @registration.payment_confirmation_token = 'token' + @registration.payment_info = {amount: amount}.to_yaml + @registration.save! + redirect_to 'https://www.paypal.com' + else + @registration.payment_confirmation_token = Digest::SHA256.hexdigest(rand(Time.now.to_f * 1000000).to_i.to_s) + @registration.save! + pp = PayPal! + response = pp.setup( + PayPalRequest(amount), + register_paypal_confirm_url(@this_conference.slug, :paypal_confirm, @registration.payment_confirmation_token), + register_paypal_confirm_url(@this_conference.slug, :paypal_cancel, @registration.payment_confirmation_token), + noshipping: true, + version: 204 + ) redirect_to response.redirect_uri end return @@ -219,7 +236,7 @@ class ConferencesController < ApplicationController # this step is only completed if a payment has been made if form_step != :payment || (@registration.registration_fees_paid || 0) > 0 @registration.steps_completed ||= [] - @registration.steps_completed << form_step + @registration.steps_completed << form_step.to_s @registration.steps_completed.uniq! end end @@ -334,9 +351,7 @@ class ConferencesController < ApplicationController steps -= [:questions] # if this is a housing provider that is not attending the conference, remove these steps - if @registration.is_attending == 'n' - steps -= [:payment, :workshops] - end + steps -= [:payment, :workshops] if @registration.is_attending == 'n' else steps -= [:hosting] end @@ -344,8 +359,6 @@ class ConferencesController < ApplicationController steps -= [:hosting, :questions] end - steps += [:administration] if conference.host?(current_user) - return steps end @@ -394,11 +407,11 @@ class ConferencesController < ApplicationController def PayPalRequest(amount) Paypal::Payment::Request.new( - :currency_code => 'USD', # if nil, PayPal use USD as default - :description => 'Conference Registration', # item description - :quantity => 1, # item quantity - :amount => amount.to_f, # item value - :custom_fields => { + currency_code: 'USD', # if nil, PayPal use USD as default + description: 'Conference Registration', # item description + quantity: 1, # item quantity + amount: amount.to_f, # item value + custom_fields: { CARTBORDERCOLOR: "00ADEF", LOGOIMG: "https://en.bikebike.org/assets/bblogo-paypal.png" } diff --git a/app/controllers/oauths_controller.rb b/app/controllers/oauths_controller.rb deleted file mode 100644 index decccbb..0000000 --- a/app/controllers/oauths_controller.rb +++ /dev/null @@ -1,101 +0,0 @@ -class OauthsController < ApplicationController - skip_before_filter :require_login - - # sends the user on a trip to the provider, - # and after authorizing there back to the callback url. - def oauth - set_callback - session[:oauth_last_url] = params[:dest] || request.referer - login_at(auth_params[:provider]) - end - - def callback - set_callback - - user_info = (sorcery_fetch_user_hash auth_params[:provider] || {})[:user_info] - - email = user_info['email'] - fb_id = user_info['id'] - - # try to find the user by facebook id - user = User.find_by_fb_id(fb_id) - - # otherwise find the user by email - unless user.present? - # only look if the email address is present - user = User.find_user(email) if email.present? - end - - # create the user if the email is not recognized - if user.nil? - if email.present? - user = User.create(email: email, firstname: user_info['name'], fb_id: fb_id, locale: I18n.locale) - else - session[:oauth_update_user_info] = user_info - return redirect_to oauth_update_path - end - elsif user.fb_id.blank? || user.email.blank? - user.email = email - user.fb_id = fb_id - user.save! - end - - if user.present? && user.email.present? - # log in the user - auto_login(user) - end - - oauth_last_url = (session[:oauth_last_url] || home_path) - session.delete(:oauth_last_url) - redirect_to oauth_last_url - end - - def update - @main_title = @page_title = 'articles.conference_registration.headings.email_confirm' - @errors = { email: flash[:error] } if flash[:error].present? - render 'application/update_user' - end - - def save - unless params[:email].present? - return redirect_to oauth_update_path - end - - user = User.find_user(params[:email]) - - if user.present? - flash[:error] = :exists - return redirect_to oauth_update_path - end - - # create the user - user = User.new(email: params[:email], firstname: session[:oauth_update_user_info]['name'], fb_id: session[:oauth_update_user_info]['id']) - user.save! - - # log in - auto_login(user) - - # clear out the session - oauth_last_url = (session[:oauth_last_url] || home_path) - session.delete(:oauth_last_url) - session.delete(:oauth_update_user_info) - - # go to our final destination - redirect_to oauth_last_url - end - - private - def auth_params - params.permit(:code, :provider) - end - - def set_callback - # force https for prod - protocol = Rails.env.preview? || Rails.env.production? ? 'https://' : request.protocol - - # build the callback url - Sorcery::Controller::Config.send(params[:provider]).callback_url = - "#{protocol}#{request.env['HTTP_HOST']}/oauth/callback?provider=facebook" - end - -end \ No newline at end of file diff --git a/app/controllers/workshops_controller.rb b/app/controllers/workshops_controller.rb index 04b0409..ea7a64b 100644 --- a/app/controllers/workshops_controller.rb +++ b/app/controllers/workshops_controller.rb @@ -1,10 +1,10 @@ - class WorkshopsController < ApplicationController + def workshops set_conference set_conference_registration! - @workshops = Workshop.where(:conference_id => @this_conference.id) - @my_workshops = Workshop.joins(:workshop_facilitators).where(:workshop_facilitators => {:user_id => current_user.id}, :conference_id => @this_conference.id) + @workshops = Workshop.where(conference_id: @this_conference.id) + @my_workshops = @workshops.select { |w| w.active_facilitator?(current_user) } render 'workshops/index' end @@ -58,7 +58,7 @@ class WorkshopsController < ApplicationController @is_translating ||= false if @is_translating - return do_404 if @translation.to_s == @workshop.locale.to_s || !I18n.backend.enabled_locales.include?(@translation.to_s) + return do_404 unless @translation.to_s != @workshop.locale.to_s && LinguaFranca.locale_enabled?(@translation.to_sym) return do_403 unless @workshop.can_translate?(current_user, @translation) @title = @workshop._title(@translation) diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb new file mode 100644 index 0000000..a9b1979 --- /dev/null +++ b/app/helpers/admin_helper.rb @@ -0,0 +1,163 @@ +module AdminHelper + + def administration_steps + { + info: [:administrators, :dates, :description, :poster], + payment: [:payment_message, :suggested_amounts, :paypal], + registration: [:registration_status, :stats, :registrations, :broadcast], + housing: [:providers, :housing], + events: [:locations, :meals, :events], + schedule: [:workshop_times, :schedule, :publish_schedule] + } + end + + def administration_sub_steps + { + location_edit: :locations, + event_edit: :events + } + end + + def get_administration_group(administration_step) + admin_step = administration_step.to_sym + admin_step = administration_sub_steps[admin_step] if administration_sub_steps[admin_step].present? + administration_steps.each do | group, steps | + steps.each do | step | + return group if step == admin_step + end + end + + return nil + end + + def broadcast_to(to, conference = nil) + conference ||= @this_conference || @conference + + users = [] + + case to.to_sym + when :registered + ConferenceRegistration.where(conference_id: conference.id).each do | r | + users << r.user if ((r.steps_completed || []).include? 'questions') && r.user.present? && r.is_attending != 'n' + end + when :pre_registered + ConferenceRegistration.where(conference_id: conference.id).each do | r | + users << r.user if registration_status(r) == :preregistered && r.is_attending != 'n' + end + when :workshop_facilitators + user_hash = {} + Workshop.where(conference_id: conference.id).each do | w | + w.active_facilitators.each do | u | + user_hash[u.id] ||= u if u.present? + end + end + users = user_hash.values + when :unregistered + ConferenceRegistration.where(conference_id: conference.id).each do | r | + users << r.user if registration_status(r) == :unregistered && r.is_attending != 'n' + end + when :housing_providers + ConferenceRegistration.where(conference_id: conference.id, can_provide_housing: true).each do | r | + users << r.user if r.user.present? + end + when :guests + ConferenceRegistration.where(conference_id: conference.id, housing: 'house').each do | r | + users << r.user if r.user.present? && r.is_attending != 'n' + end + when :all + User.all.each do | u | + users << u if u.present? && (u.is_subscribed.nil? || u.is_subscribed) + end + end + + return users + end + + def get_housing_match(host, guest, space) + housing_data = guest.housing_data || [] + + if housing_data['host'].present? + if housing_data['host'] == host.id + return space == housing_data['space'] ? :selected_space : :other_space + end + + return :other_host + end + + if space_matches?(space, guest.housing) && available_dates_match?(host, guest) + return :good_match + end + + return :bad_match + end + + def get_workshop_match(workshop, day, block, location) + if workshop.event_location_id.present? && workshop.present? + if (Date.parse params[:day]).wday == workshop.block['day'] && block == workshop.block['block'].to_i + return :selected_space + end + + if location.present? && location.id == workshop.event_location_id + return :other_space + end + + return :other_host + end + + if location.present? + needs = JSON.parse(workshop.needs || '[]').map &:to_sym + amenities = JSON.parse(location.amenities || '[]').map &:to_sym + + if (needs & amenities).length < needs.length + return :bad_match + end + end + + (((((@schedule[@day] || {})[:times] || {})[@time] || {})[:item] || {})[:workshops] || {}).each do | l, w | + if w[:workshop].id != workshop.id + f_a = w[:workshop].active_facilitators.map { | f | f.id } + f_b = workshop.active_facilitators.map { | f | f.id } + if (f_a & f_b).present? + return :bad_match + end + end + end + + # housing_data = guest.housing_data || [] + + # if housing_data['host'].present? + # if housing_data['host'] == host.id + # return space == housing_data['space'] ? :selected_space : :other_space + # end + + # return :other_host + # end + + # if space_matches?(space, guest.housing) && available_dates_match?(host, guest) + # return :good_match + # end + + # return :bad_match + return :good_match + end + + def space_matches?(host_space, guest_space) + return false unless host_space.present? && guest_space.present? + + if host_space.to_s == 'bed_space' || host_space.to_s == 'floor_space' + return guest_space.to_s == 'house' + end + + return host_space.to_s == 'tent_space' && guest_space.to_s == 'tent' + end + + def available_dates_match?(host, guest) + return false unless host.housing_data['availability'].present? && host.housing_data['availability'][1].present? + if host.housing_data['availability'][0] <= guest.arrival && + host.housing_data['availability'][1] >= guest.departure + return true + end + + return false + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1fbd759..563131d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,521 +1,14 @@ -require 'redcarpet' +require 'lingua_franca/form_helper' module ApplicationHelper + include PageHelper include RegistrationHelper - - @@keyQueue = nil - @@translationsOnThisPage = nil - @@lastTranslation = nil - @@allTranslations = nil - @@no_banner = true - @@banner_attribution_details = nil - @@banner_image = nil - @@has_content = true - @@front_page = false - @@body_class = nil - @@test_location = nil - - def init_vars - @@keyQueue = nil - @@no_banner = true - @@banner_attribution_details = nil - @@banner_image = nil - @@has_content = true - @@front_page = false - @@body_class = nil - end - - def this_is_the_front_page - @@front_page = true - end - - def header_is_fixed - @fixed_header = true - end - - def is_header_fixed? - @fixed_header ||= false - end - - def is_this_the_front_page? - return @@front_page - end - - def header_classes - classes = Array.new - classes << 'fixed' if is_header_fixed? - return classes - end - - def ThereAreTranslationsOnThisPage? - @@translationsOnThisPage - end - - def get_all_translations - @@allTranslations - end - - def title(page_title) - content_for(:title) { page_title.to_s } - end - - def description(page_description) - content_for(:description) { page_description.to_s } - end - - def banner_image(banner_image, name: nil, id: nil, user_id: nil, src: nil) - @@no_banner = false - @@banner_image = banner_image - if (name || id || user_id || src) - @@banner_attribution_details = {:name => name, :id => id, :user_id => user_id, :src => src} - end - content_for(:banner_image) { banner_image.to_s } - end - - def banner_attrs(banner_image) - @@no_banner = false - if banner_image.length > 0 - @@banner_image = banner_image - return {style: 'background-image: url(' + banner_image + ');', class: 'has-image' } - end - {class: 'no-image'} - end - - def has_banner? - !@@no_banner - end - - def has_content? - @@has_content - end - - def has_no_content - @@has_content = false - end - - def banner_title(banner_title) - @@no_banner = false - content_for(:banner) { ('

' + banner_title.to_s + '

').html_safe } - end - - def add_stylesheet(sheet) - @stylesheets ||= [] - @stylesheets << sheet unless @stylesheets.include?(sheet) - end - - def stylesheets - html = '' - Rack::MiniProfiler.step('inject_css') do - html += inject_css! - end - (@stylesheets || []).each do |css| - Rack::MiniProfiler.step("inject_css #{css}") do - html += inject_css! css.to_s - end - end - html += stylesheet_link_tag 'i18n-debug' if request.params['i18nDebug'] - return html.html_safe - end - - def add_inline_script(script) - @_inline_scripts ||= [] - script = Rails.application.assets.find_asset("#{script.to_s}.js").to_s - @_inline_scripts << script unless @_inline_scripts.include?(script) - end - - def inline_scripts - return '' unless @_inline_scripts.present? - "".html_safe - end - - def banner_attribution - if @@banner_image && @@banner_attribution_details - src = @@banner_attribution_details[:src] - attribution = '
' - if src == 'panoramio' - attribution += '© ' + - _('Banner_image_provided_by_panoramio_user') + - ' ' + @@banner_attribution_details[:name] + '' + - '' + _('Photos_provided_by_Panoramio_are_under_the_copyright_of_their_owners') + '' - end - attribution += '
' - attribution.html_safe - end - end - - def dom_ready(&block) - content_for(:dom_ready, &block) - end - - def body_class(c) - @@body_class ||= Array.new - @@body_class << (c.is_a?(Array) ? c.join(' ') : c) - end - - def page_style - classes = Array.new - - classes << 'has-translations' if ThereAreTranslationsOnThisPage? - classes << 'no-content' unless @@has_content - classes << 'has-banner-image' if @@banner_image - classes << @@body_class.join(' ') if @@body_class - classes << 'fixed-banner' if is_header_fixed? - - if params[:controller] - classes << params[:action] - unless params[:controller] == 'application' - classes << params[:controller] - - if params[:action] - classes << "#{params[:controller]}-#{params[:action]}" - end - end - end - return classes - end - - def yield_or_default(section, default = '') - content_for?(section) ? content_for(section) : default - end - - def _translate_me(translation) - @@translationsOnThisPage = true - datakeys = '' - translation['vars'].each { |key, value| datakeys += ' data-var-' + key.to_s + '="' + value.to_s.gsub('"', '"') + '"' } - ('' + (translation['html'] || translation['untranslated']) + '').to_s.html_safe - end - - def _do_translate(key, vars, behavior, behavior_size, locale) - translation = {'key' => key, 'lang' => '0', 'vars' => vars} - v = vars.dup - begin - v[:raise] = true - options = {:raise => true} - if locale - options[:locale] = locale.to_sym - end - translation['untranslated'] = I18n.translate(key, v, options) - translation['lang'] = locale.to_s - translation['is_translated'] = true - - hash = Hash.new - translations = Translation.where(["locale = ? AND key LIKE ?", locale.to_s, key + '%']).take(6).each { |o| hash[o.key] = o.value } - translation['translated'] = hash.to_json.gsub('"', '"') - rescue I18n::MissingTranslationData - default_translation = I18n::MissingTranslationExceptionHandler.note(key, behavior, behavior_size) - translation['untranslated'] = default_translation - end - return translation - end - - def _can_translate?() - false - end - - def off_screen(text, id = nil) - content_tag(:span, text.html_safe, id: id, class: 'screen-reader-text') - end - - def url_for_locale(locale, url = nil) - return url unless locale.present? - - unless url.present? - new_params = params.merge({action: (params[:_original_action] || params[:action])}) - new_params.delete(:_original_action) - - if Rails.env.development? || Rails.env.test? - return url_for(new_params.merge({lang: locale.to_s})) - end - - subdomain = Rails.env.preview? ? "preview-#{locale.to_s}" : locale.to_s - return url_for(new_params.merge(host: "#{subdomain}.bikebike.org")) - end - - return url if Rails.env.development? || Rails.env.test? - return "https://preview-#{locale.to_s}.bikebike.org#{url}" if Rails.env.preview? - "https://#{locale.to_s}.bikebike.org#{url}" - end - - def registration_steps(conference = @conference) - { - pre: [:policy, :contact_info, :workshops], - open: [:policy, :contact_info, :questions, :hosting, :payment, :workshops] - }[@this_conference.registration_status] - end - - def registration_status(registration) - return :unregistered if registration.nil? - return registration.status - end - - def sortable(objects, id = 'id', url: nil, &block) - result = '