Browse Source

2017 refactor

development
Godwin 8 years ago
parent
commit
8f852b102b
  1. 4
      .gitignore
  2. 80
      Gemfile
  3. 633
      Gemfile.lock
  4. 25
      Guardfile
  5. 5
      README.md
  6. 31
      Rakefile
  7. BIN
      app/assets/images/test-poster.png
  8. 1
      app/assets/javascripts/userfield.js
  9. 23
      app/assets/stylesheets/_application.scss
  10. 194
      app/assets/stylesheets/bumbleberry-settings.json
  11. 390
      app/assets/stylesheets/user-mailer.scss
  12. 2
      app/controllers/administration_controller.rb
  13. 466
      app/controllers/application_controller.rb
  14. 98
      app/controllers/conference_administration_controller.rb
  15. 71
      app/controllers/conferences_controller.rb
  16. 101
      app/controllers/oauths_controller.rb
  17. 8
      app/controllers/workshops_controller.rb
  18. 163
      app/helpers/admin_helper.rb
  19. 2221
      app/helpers/application_helper.rb
  20. 407
      app/helpers/bike_bike_form_helper.rb
  21. 729
      app/helpers/form_helper.rb
  22. 100
      app/helpers/geocoder_helper.rb
  23. 74
      app/helpers/i18n_helper.rb
  24. 88
      app/helpers/page_helper.rb
  25. 30
      app/helpers/registration_helper.rb
  26. 366
      app/helpers/table_helper.rb
  27. 288
      app/helpers/widgets_helper.rb
  28. 4
      app/mailers/user_mailer.rb
  29. 3
      app/models/authentication.rb
  30. 166
      app/models/city.rb
  31. 21
      app/models/city_cache.rb
  32. 37
      app/models/comment.rb
  33. 160
      app/models/conference.rb
  34. 2
      app/models/conference_admin.rb
  35. 4
      app/models/conference_administrator.rb
  36. 4
      app/models/conference_host_organization.rb
  37. 74
      app/models/conference_registration.rb
  38. 4
      app/models/conference_registration_form_field.rb
  39. 5
      app/models/conference_registration_response.rb
  40. 7
      app/models/conference_type.rb
  41. 40
      app/models/email_confirmation.rb
  42. 20
      app/models/event.rb
  43. 24
      app/models/event_location.rb
  44. 2
      app/models/event_type.rb
  45. 21
      app/models/location.rb
  46. 6
      app/models/locations_organization.rb
  47. 77
      app/models/organization.rb
  48. 2
      app/models/organization_status.rb
  49. 75
      app/models/registration_form_field.rb
  50. 68
      app/models/user.rb
  51. 11
      app/models/user_organization_relationship.rb
  52. 2
      app/models/version.rb
  53. 180
      app/models/workshop.rb
  54. 2
      app/models/workshop_facilitator.rb
  55. 4
      app/models/workshop_interest.rb
  56. 2
      app/models/workshop_presentation_style.rb
  57. 2
      app/models/workshop_requested_resource.rb
  58. 2
      app/models/workshop_resource.rb
  59. 2
      app/models/workshop_stream.rb
  60. 104
      app/uploaders/avatar_uploader.rb
  61. 54
      app/uploaders/cover_uploader.rb
  62. 57
      app/uploaders/logo_uploader.rb
  63. 69
      app/uploaders/poster_uploader.rb
  64. 2
      app/views/admin/new.html.haml
  65. 3
      app/views/application/500.html.haml
  66. 2
      app/views/application/_contact.html.haml
  67. 2
      app/views/application/_login.html.haml
  68. 2
      app/views/application/_login_confirm.html.haml
  69. 6
      app/views/application/_login_confirmation_sent.html.haml
  70. 2
      app/views/application/_not_a_translator.html.haml
  71. 2
      app/views/application/_translator_login.html.haml
  72. 16
      app/views/application/contact.html.haml
  73. 7
      app/views/application/home.html.haml
  74. 16
      app/views/application/permission_denied.html.haml
  75. 2
      app/views/application/update_user.html.haml
  76. 2
      app/views/application/user_settings.html.haml
  77. 10
      app/views/conference_administration/_administrators.html.haml
  78. 17
      app/views/conference_administration/_broadcast.html.haml
  79. 2
      app/views/conference_administration/_dates.html.haml
  80. 2
      app/views/conference_administration/_description.html.haml
  81. 4
      app/views/conference_administration/_events.html.haml
  82. 6
      app/views/conference_administration/_locations.html.haml
  83. 4
      app/views/conference_administration/_meals.html.haml
  84. 2
      app/views/conference_administration/_payment_message.html.haml
  85. 2
      app/views/conference_administration/_paypal.html.haml
  86. 2
      app/views/conference_administration/_poster.html.haml
  87. 2
      app/views/conference_administration/_providers.html.haml
  88. 4
      app/views/conference_administration/_publish_schedule.html.haml
  89. 14
      app/views/conference_administration/_registration_status.html.haml
  90. 38
      app/views/conference_administration/_registrations.html.haml
  91. 40
      app/views/conference_administration/_schedule.html.haml
  92. 2
      app/views/conference_administration/_suggested_amounts.html.haml
  93. 4
      app/views/conference_administration/_workshop_times.html.haml
  94. 6
      app/views/conferences/_administration.html.haml
  95. 27
      app/views/conferences/_conference.html.haml
  96. 20
      app/views/conferences/_confirm_email.html.haml
  97. 4
      app/views/conferences/_contact_info.html.haml
  98. 2
      app/views/conferences/_done.html.haml
  99. 10
      app/views/conferences/_email_confirm.html.haml
  100. 4
      app/views/conferences/_hosting.html.haml

4
.gitignore

@ -47,10 +47,6 @@ rerun.txt
pickle-email-*.html pickle-email-*.html
.project .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 # Ignore Redis' dataset snapshot
dump.rdb dump.rdb

80
Gemfile

@ -5,58 +5,42 @@ gem 'pg'
gem 'rake', '11.1.2' gem 'rake', '11.1.2'
gem 'ruby_dep', '1.3.1' # Lock at 1.3.1 since 1.4 requires ruby 2.5. We should unlock once we upgrade the ruby version on our server gem 'ruby_dep', '1.3.1' # Lock at 1.3.1 since 1.4 requires ruby 2.5. We should unlock once we upgrade the ruby version on our server
# gem 'bcrypt-ruby', '3.0.0', require: 'bcrypt'
# gem 'bcrypt', '3.1.9'
# gem 'bcrypt', require: :ruby
gem 'rack-mini-profiler' gem 'rack-mini-profiler'
gem 'haml' gem 'haml'
gem 'nokogiri', '~> 1.6.8.rc2' gem 'nokogiri'
if Dir.exists?('../lingua_franca')
gem 'lingua_franca', :path => '../lingua_franca'
else
gem 'lingua_franca', :git => 'git://github.com/lingua-franca/lingua_franca.git'
end
gem 'tzinfo-data'
gem 'sass' gem 'sass'
gem 'sass-rails' gem 'sass-rails'
if Dir.exists?('../bumbleberry')
gem 'bumbleberry', :path => "../bumbleberry"
else
gem 'bumbleberry', :git => 'git://github.com/bumbleberry/bumbleberry.git'
end
if Dir.exists?('../paypal-express')
gem 'paypal-express', :path => "../paypal-express"
else
gem 'paypal-express', :git => 'git://github.com/bikebike/paypal-express.git'
end
gem 'uglifier', '>= 1.3.0' gem 'uglifier', '>= 1.3.0'
gem 'sorcery', '>= 0.8.1' # replace this once these changes are merged in sorcery
gem 'oauth2', '~> 0.8.0' gem 'sorcery', git: 'https://github.com/tg90nor/sorcery.git', branch: 'make-facebook-provider-use-json-token-parser'
gem 'carrierwave' gem 'carrierwave'
gem 'carrierwave-imageoptimizer' gem 'carrierwave-imageoptimizer'
gem 'mini_magick' gem 'mini_magick'
gem 'geocoder'
gem 'paper_trail', '~> 3.0.5'
gem 'sitemap_generator'
gem 'activerecord-session_store' gem 'activerecord-session_store'
gem 'sass-json-vars'
gem 'premailer-rails' gem 'premailer-rails'
gem 'redcarpet'
gem 'sidekiq' gem 'sidekiq'
gem 'letter_opener' gem 'letter_opener'
gem 'launchy' gem 'launchy'
gem 'to_spreadsheet', :git => 'git://github.com/glebm/to_spreadsheet.git'
group :test do # Bike Collectives gems, when developing locally execute:
gem 'rspec' # bundle config local.bikecollectives_core ../bikecollectives_core
gem 'rspec-rails' # bundle config local.bumbleberry ../bumbleberry
end # bundle config local.lingua_franca ../lingua_franca
# bundle config local.marmara ../marmara
gem 'bikecollectives_core', git: 'https://github.com/bikebike/bikecollectives_core.git', branch: 'master'
gem 'bumbleberry', git: 'https://github.com/bumbleberry/bumbleberry.git', branch: '2017'
gem 'lingua_franca', git: 'https://github.com/lingua-franca/lingua_franca.git', branch: '2017'
gem 'marmara', git: 'https://github.com/lingua-franca/marmara.git', branch: 'master'
# Bike!Bike! specific stuff
gem 'ianfleeton-paypal-express', require: 'paypal/express'
gem 'geocoder'
gem 'sitemap_generator'
gem 'sass-json-vars'
gem 'redcarpet'
gem 'to_spreadsheet', git: 'https://github.com/glebm/to_spreadsheet.git'
group :development do group :development do
gem 'better_errors' gem 'better_errors'
@ -67,17 +51,23 @@ group :development do
gem 'capistrano-rails', '~> 1.1' gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-faster-assets', '~> 1.0' gem 'capistrano-faster-assets', '~> 1.0'
gem 'eventmachine', :github => 'krzcho/eventmachine', :branch => 'master' gem 'eventmachine', git: 'https://github.com/krzcho/eventmachine', :branch => 'master'
gem 'thin'# , :github => 'krzcho/thin', :branch => 'master' gem 'thin'
gem 'rubocop', require: false
gem 'haml-lint', require: false
end end
group :test do group :test do
gem 'rspec'
gem 'rspec-rails'
gem 'gherkin3', '>= 3.1.0' gem 'gherkin3', '>= 3.1.0'
gem 'cucumber' gem 'cucumber'
gem 'cucumber-core' gem 'cucumber-core'
gem 'cucumber-rails' gem 'cucumber-rails', require: false
gem 'guard-cucumber'
gem 'poltergeist' gem 'poltergeist'
gem 'capybara-email'
gem 'guard-rspec' gem 'guard-rspec'
gem 'factory_girl_rails' gem 'factory_girl_rails'
gem 'coveralls', require: false gem 'coveralls', require: false
@ -90,16 +80,22 @@ end
group :production, :preview do group :production, :preview do
gem 'rails_12factor' gem 'rails_12factor'
gem 'daemon-spawn' end
gem 'daemons'
group :production, :preview do
platforms :ruby do platforms :ruby do
gem 'unicorn' gem 'unicorn', require: false
end end
gem 'daemon-spawn'
gem 'daemons'
end end
platforms 'mswin', 'mingw' do platforms 'mswin', 'mingw' do
gem 'tzinfo-data'
group :test do group :test do
gem 'wdm', '>= 0.1.0' gem 'wdm', '>= 0.1.0'
gem 'win32console', require: false
end end
end end

633
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

25
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' } watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end 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

5
README.md

@ -150,3 +150,8 @@ On hold until our design team determines a director for our identity.
## Testing Practices ## ## 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. 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 ###

31
Rakefile

@ -1,5 +1,8 @@
# Add your own tasks in files placed in lib/tasks ending in .rake, # 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. # 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__) require File.expand_path('../config/application', __FILE__)
@ -61,3 +64,31 @@ task update_cities_fr: :environment do
c.save! c.save!
end end
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

BIN
app/assets/images/test-poster.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

1
app/assets/javascripts/userfield.js

@ -21,6 +21,7 @@
var field = fields[i]; var field = fields[i];
var input = field.getElementsByTagName('input')[0]; var input = field.getElementsByTagName('input')[0];
var name = field.getElementsByClassName('user-name')[0]; var name = field.getElementsByClassName('user-name')[0];
} }
}, false); }, false);
})(); })();

23
app/assets/stylesheets/_application.scss

@ -1710,17 +1710,17 @@ ul.warnings {
a.policy { a.policy {
background-color: $colour-5; background-color: $colour-5;
@include _(order, 1); // @include _(order, 1);
} }
a.about { a.about {
background-color: $colour-3; background-color: $colour-3;
@include _(order, 1); // @include _(order, 1);
} }
a.conferences { a.conferences {
background-color: $colour-2; background-color: $colour-2;
@include _(order, 1); // @include _(order, 1);
} }
form, .register { form, .register {
@ -1728,7 +1728,8 @@ ul.warnings {
} }
a, form { a, form {
width: 33%; width: 33.333%;
float: left;
@include _(flex, 1); @include _(flex, 1);
} }
@ -2948,12 +2949,11 @@ a.logo {
.conference-banner { .conference-banner {
text-align: center; text-align: center;
padding: 0; padding: 0;
margin: 0 -1em 2em; margin: 0;
width: auto;
.title { .title {
font-size: 5vw; font-size: 5vw;
margin: 1em auto 2em; margin: 1em auto 0;
h1, h2 { h1, h2 {
margin: 0; margin: 0;
@ -2971,6 +2971,7 @@ a.logo {
img { img {
max-width: 100%; max-width: 100%;
margin-top: 2em;
} }
} }
@ -3311,8 +3312,11 @@ body.error-locale-not-available {
body { body {
#primary-content { #primary-content {
@include _(transition, 'filter 250ms ease-in-out, -webkit-filter 250ms ease-in-out'); @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; min-height: 100vh;
overflow: hidden; overflow: hidden;
} }
@ -4617,6 +4621,7 @@ html[data-ontop] {
.nav a { .nav a {
&[class] { &[class] {
width: auto; width: auto;
float: none;
overflow: visible; overflow: visible;
margin-left: 0.725em; margin-left: 0.725em;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;

194
app/assets/stylesheets/bumbleberry-settings.json

@ -1,103 +1,105 @@
{ {
"stylesheets": ["application", "editor"], "stylesheets": ["application", "editor", "admin"],
"precompile": { "precompile": {
"test": { "test": {
"chrome": ["51"] "safari": ["5"],
}, "chrome": ["55"]
"development": {
"and_chr": ["56"],
"chrome": ["56"],
"edge": ["13"],
"firefox": ["50"],
"ie": ["11"],
"ios_saf": ["8", "9"]
}
}, },
"background-color": "#FFFEFE", "development": {
"breakpoint-unit": "px", "safari": ["5", "5.1"],
"unresponsive-width": 1000, "and_chr": ["57"],
"row-width": 1000, "chrome": ["57"],
"total-columns": 12, "edge": ["13"],
"platforms": { "firefox": ["50"],
"mobile": { "ie": ["11"],
"range": [0,700] "ios_saf": ["8", "9"]
}, }
"desktop": { },
"range": [0,0] "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": { "medium": {
"small": { "range": [680],
"range": [0], "grid": "y",
"grid": "y", "offset": "n",
"offset": "n", "reset-order": "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"
}
}, },
"grid-push": [1, 2], "large": {
"grid-pull": [1, 2], "range": [1024],
"font-loading-method": "http2", "grid": "y",
"fonts": { "offset": "n",
"primary": { "reset-order": "n"
"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": { "small-only": {
"icons": { "range": [0,319],
"bb-icon-logo": [0, 0, "182px", "149px"], "grid": "n",
"bb-icon-logo-text": ["182px", 0, "136px", "149px"] "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"]
} }
}
} }

390
app/assets/stylesheets/user-mailer.scss

@ -1,268 +1,268 @@
@import "settings"; @import "settings";
body { body {
width: 100% !important; width: 100% !important;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
margin: 1em; margin: 1em;
padding: 0; padding: 0;
} }
.ExternalClass { .ExternalClass {
width: 100%; width: 100%;
line-height: 100%; line-height: 100%;
p, span, font, td, div { p, span, font, td, div {
line-height: 100%; line-height: 100%;
} }
} }
#backgroundTable { #backgroundTable {
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
line-height: 100% !important; line-height: 100% !important;
} }
img { img {
outline: none; outline: none;
text-decoration: none; text-decoration: none;
-ms-interpolation-mode: bicubic; -ms-interpolation-mode: bicubic;
a & { a & {
border: none; border: none;
} }
} }
.image_fix { .image_fix {
display: block; display: block;
max-width: 100%; max-width: 100%;
} }
a { a {
color: $colour-1; color: $colour-1;
#outlook & { #outlook & {
padding: 0; padding: 0;
} }
&:link { color: $colour-1; } &:link { color: $colour-1; }
&:visited { color: $colour-1; } &:visited { color: $colour-1; }
&:hover { color: $colour-5; } &:hover { color: $colour-5; }
@media only screen and (max-device-width: 480px) { @media only screen and (max-device-width: 480px) {
&[href^="tel"], &[href^="sms"] { &[href^="tel"], &[href^="sms"] {
text-decoration: none; text-decoration: none;
color: $black; color: $black;
pointer-events: none; pointer-events: none;
cursor: default; cursor: default;
} }
.mobile_link &[href^="tel"], .mobile_link &[href^="sms"] { .mobile_link &[href^="tel"], .mobile_link &[href^="sms"] {
text-decoration: default; text-decoration: default;
color: $colour-1 !important; color: $colour-1 !important;
pointer-events: auto; pointer-events: auto;
cursor: default; cursor: default;
} }
} }
} }
p { p {
color: $black !important; color: $black !important;
font-size: 1.5em; font-size: 1.5em;
} }
p, blockquote { p, blockquote {
margin: 1em; margin: 1em;
line-height: 1.3333em; line-height: 1.3333em;
} }
blockquote { blockquote {
font-size: 1em; font-size: 1em;
} }
h1 { h1 {
font-size: 2.5em; font-size: 2.5em;
line-height: 1.25em; line-height: 1.25em;
padding: 1em 0; padding: 1em 0;
&:first-child { &:first-child {
padding-top: 0; padding-top: 0;
} }
} }
h2 { h2 {
font-size: 1.8em; font-size: 1.8em;
line-height: 1.25em; line-height: 1.25em;
padding-bottom: 1em; padding-bottom: 1em;
} }
blockquote { blockquote {
font-style: italic; font-style: italic;
margin-bottom: 2em; margin-bottom: 2em;
color: #666 !important; color: #666 !important;
border: 0.1em solid #CCC; border: 0.1em solid #CCC;
padding: 1em; padding: 1em;
border-style: none none solid solid; border-style: none none solid solid;
background-color: #F8F8F8; background-color: #F8F8F8;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
color: $black !important; color: $black !important;
a { a {
color: $colour-1 !important; color: $colour-1 !important;
&:active { &:active {
color: $colour-4 !important; color: $colour-4 !important;
} }
&:visited { &:visited {
color: $colour-2 !important; color: $colour-2 !important;
} }
} }
} }
table { table {
border-collapse: collapse; border-collapse: collapse;
max-width: 512px; max-width: 512px;
min-width: 280px; min-width: 280px;
mso-table-lspace: 0pt; mso-table-lspace: 0pt;
mso-table-rspace: 0pt; mso-table-rspace: 0pt;
td { td {
border-collapse: collapse; border-collapse: collapse;
} }
th { th {
text-align: left; text-align: left;
} }
} }
table#bb_full_width, table#bb_full_width,
table#ecxbb_full_width { table#ecxbb_full_width {
&, table { &, table {
max-width: none; max-width: none;
width: 100%; width: 100%;
} }
} }
.error-report { .error-report {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
border: 0.15em solid #CCC; border: 0.15em solid #CCC;
background-color: #EEE; background-color: #EEE;
font-size: 1.25em; font-size: 1.25em;
margin-bottom: 2em; margin-bottom: 2em;
th { th {
background-color: #CCC; background-color: #CCC;
} }
td, th { td, th {
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
&:last-child { &:last-child {
border-left: 0.15em solid #CCC; border-left: 0.15em solid #CCC;
min-width: 40em; min-width: 40em;
} }
} }
td:last-child { td:last-child {
font-family: monospace; font-family: monospace;
word-break: break-word; word-break: break-word;
background-color: #FFF; background-color: #FFF;
font-size: 0.75em; font-size: 0.75em;
} }
} }
code { code {
color: #C33; color: #C33;
font-size: 0.9em; font-size: 0.9em;
} }
pre { pre {
font-size: 1.5em; font-size: 1.5em;
padding: 1em; padding: 1em;
background-color: #333; background-color: #333;
color: antiquewhite; color: antiquewhite;
word-break: break-word; word-break: break-word;
} }
.diff, .ecxdiff { .diff, .ecxdiff {
margin: 1em 0 5em 1em; margin: 1em 0 5em 1em;
overflow: auto; overflow: auto;
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
position: relative; position: relative;
} }
li { li {
width: 40%; width: 40%;
display: inline-block; display: inline-block;
padding: 0.5em; padding: 0.5em;
margin: 0; margin: 0;
border-bottom: 1px solid #DDD; border-bottom: 1px solid #DDD;
//white-space: nowrap; //white-space: nowrap;
&:nth-child(odd) { &:nth-child(odd) {
margin-right: -3px; margin-right: -3px;
float: left; float: left;
clear: left; clear: left;
} }
ins { ins {
color: #080;//lighten($colour-3, 33%); color: #080;//lighten($colour-3, 33%);
} }
del { del {
color: #800; color: #800;
} }
} }
} }
// Buttons // Buttons
h3 { h3 {
b { b {
padding: 10px 20px; padding: 10px 20px;
line-height: 50px; line-height: 50px;
a, a:visited { a, a:visited {
color: #FFF !important; color: #FFF !important;
background-color: $colour-5; background-color: $colour-5;
text-decoration: none !important; text-decoration: none !important;
border-radius: 4px; border-radius: 4px;
padding: 10px 15px; padding: 10px 15px;
margin-left: 20px; margin-left: 20px;
border-bottom: 3px solid darken($colour-5, 10%); border-bottom: 3px solid darken($colour-5, 10%);
-webkit-box-shadow: 0 0.5em 1.5em -0.75em #000; -webkit-box-shadow: 0 0.5em 1.5em -0.75em #000;
box-shadow: 0 0.5em 1.5em -0.75em #000; box-shadow: 0 0.5em 1.5em -0.75em #000;
cursor: pointer !important; cursor: pointer !important;
} }
a:hover { a:hover {
background-color: darken($colour-5, 10%); background-color: darken($colour-5, 10%);
} }
} }
} }
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
a[href^="tel"], a[href^="sms"] { a[href^="tel"], a[href^="sms"] {
text-decoration: none; text-decoration: none;
color: $colour-1; color: $colour-1;
pointer-events: none; pointer-events: none;
cursor: default; cursor: default;
.mobile_link & { .mobile_link & {
text-decoration: default; text-decoration: default;
color: $colour-1 !important; color: $colour-1 !important;
pointer-events: auto; pointer-events: auto;
cursor: default; cursor: default;
} }
} }
} }

2
app/controllers/admin_controller.rb → app/controllers/administration_controller.rb

@ -1,6 +1,6 @@
require 'geocoder/calculations' require 'geocoder/calculations'
class AdminController < ApplicationController class AdministrationController < ApplicationController
def new def new
return do_404 unless logged_in? && current_user.administrator? return do_404 unless logged_in? && current_user.administrator?
@this_conference = Conference.new @this_conference = Conference.new

466
app/controllers/application_controller.rb

@ -1,21 +1,19 @@
module ActiveRecord class ApplicationController < BaseController
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.
protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update] protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update]
before_filter :capture_page_info before_filter :capture_page_info
helper_method :protect helper_method :protect
@@test_host # @@test_host
@@test_location # @@test_location
def default_url_options
{ host: "#{request.protocol}#{request.host_with_port}", trailing_slash: true }
end
def capture_page_info def capture_page_info
# capture request info in case an error occurs
if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact') if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact')
session[:last_request] session[:last_request]
request_info = { request_info = {
@ -27,14 +25,11 @@ class ApplicationController < LinguaFrancaApplicationController
'env' => Hash.new '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 request_info['request']['env'][key.to_s] = value.to_s
end end
session['request_info'] = request_info session['request_info'] = request_info
end 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 # get the current conferences and set them globally
status_hierarchy = { status_hierarchy = {
@ -50,18 +45,16 @@ class ApplicationController < LinguaFrancaApplicationController
@conference = @conferences.first @conference = @conferences.first
# add some style sheets # add some style sheets
@stylesheets ||= Array.new @stylesheets ||= Set.new
# add the translations stylesheet if translating # add the translations stylesheet if translating
@stylesheets << params[:controller] if params[:controller] == 'translations' @stylesheets << params[:controller] if params[:controller] == 'translations'
@_inline_scripts ||= [] @_inline_scripts ||= Set.new
@_inline_scripts << Rails.application.assets.find_asset('main.js').to_s @_inline_scripts << Rails.application.assets.find_asset('main.js').to_s
ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"} ActionMailer::Base.default_url_options = {
host: "#{request.protocol}#{request.host_with_port}"
if request.post? && params[:action] == 'do_confirm' }
halt_redirection!
end
@alt_lang_urls = {} @alt_lang_urls = {}
I18n.backend.enabled_locales.each do |locale| I18n.backend.enabled_locales.each do |locale|
@ -72,15 +65,10 @@ 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 # 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' @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') @theme_colour = Rails.env.preview? ? '#EF57B4' : (Rails.env.development? ? '#D89E59' : '#00ADEF')
# call the base method to detect the language
super
end end
def home def home
@workshops = [] if @conference.present? && @conference.id.present?
if @conference.present?
@workshops = Workshop.where(conference_id: @conference.id) @workshops = Workshop.where(conference_id: @conference.id)
if @conference.workshop_schedule_published if @conference.workshop_schedule_published
@ -94,54 +82,17 @@ class ApplicationController < LinguaFrancaApplicationController
@is_policy_page = true @is_policy_page = true
end end
def robots # def self.set_host(host)
render :text => File.read("config/robots-#{Rails.env.production? ? 'live' : 'dev'}.txt"), :content_type => 'text/plain' # @@test_host = host
end # end
def humans
render :text => File.read("config/humans.txt"), :content_type => 'text/plain'
end
def self.set_host(host)
@@test_host = host
end
def self.set_location(location)
@@test_location = location
end
def self.get_location()
@@test_location
end
def do_404 # def self.set_location(location)
error_404(status: 404) # @@test_location = location
end # 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) # def self.get_location()
@page_title = 'page_titles.500.An_Error_Occurred' # @@test_location
@main_title = 'error.500.title' # end
params[:_original_action] = params[:action]
params[:action] = 'error-500'
render 'application/500', status: 500
end
def js_error def js_error
# send and email if this is production # send and email if this is production
@ -154,20 +105,30 @@ class ApplicationController < LinguaFrancaApplicationController
begin begin
# log the error # 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 if Rails.env.preview? || Rails.env.production?
[ requestHash = {
"A JavaScript error has occurred", 'remote_ip' => arg.remote_ip,
report, 'uuid' => arg.uuid,
params[:message], 'original_url' => arg.original_url,
nil, 'env' => Hash.new
request, }
params, request.env.each do | key, value |
current_user, requestHash['env'][key.to_s] = value.to_s
Time.now.strftime("%d/%m/%Y %H:%M") end
]
end# if Rails.env.preview? || Rails.env.production? send_mail(:error_report,
"A JavaScript error has occurred",
report,
params[:message],
nil,
requestHash,
params,
current_user,
Time.now.strftime("%d/%m/%Y %H:%M")
)
end
rescue Exception => exception2 rescue Exception => exception2
logger.info exception2.to_s logger.info exception2.to_s
logger.info exception2.backtrace.join("\n") logger.info exception2.backtrace.join("\n")
@ -175,31 +136,27 @@ class ApplicationController < LinguaFrancaApplicationController
render json: {} render json: {}
end end
rescue_from ActiveRecord::RecordNotFound do |exception| def confirmation_sent(user)
do_404 template = 'login_confirmation_sent'
end @page_title ||= 'page_titles.403.Please_Check_Email'
rescue_from ActiveRecord::PremissionDenied do |exception|
do_403
end
rescue_from AbstractController::ActionNotFound do |exception|
@banner_image = 'grafitti.jpg'
if current_user if (request.present? && request.referrer.present? && conference = /^\/conferences\/(\w+)\/register\/?$/.match(request.referrer.gsub(/^https?:\/\/.*?\//, '/')))
@page_title = nil#'page_titles.Please_Login' @this_conference = Conference.find_by!(slug: conference[1])
do_403 'not_a_translator' @banner_image = @this_conference.cover_url
#return template = 'conferences/email_confirm'
else
@page_title = 'page_titles.403.Please_Login'
do_403 'translator_login'
end end
do_403 template
end end
def locale_not_enabled!(locale = nil) def locale_not_enabled!(locale = nil)
locale_not_available!(locale) locale_not_available!(locale)
end end
def locale_not_available
locale_not_available!(params[:locale])
end
def locale_not_available!(locale = nil) def locale_not_available!(locale = nil)
set_default_locale set_default_locale
params[:_original_action] = params[:action] params[:_original_action] = params[:action]
@ -210,11 +167,13 @@ class ApplicationController < LinguaFrancaApplicationController
render 'application/locale_not_available', status: 404 render 'application/locale_not_available', status: 404
end end
rescue_from StandardError do |exception| unless Rails.env.test?
handle_exception exception rescue_from StandardError do |exception|
handle_exception exception
# show the error page # show the error page
error_500 exception error_500 exception
end
end end
def handle_exception(exception) def handle_exception(exception)
@ -223,19 +182,28 @@ class ApplicationController < LinguaFrancaApplicationController
logger.info exception.backtrace.join("\n") logger.info exception.backtrace.join("\n")
# send and email if this is production # send and email if this is production
suppress(Exception) do if Rails.env.preview? || Rails.env.production?
UserMailer.send_mail(:error_report) do suppress(Exception) do
[ requestHash = {
"An error has occurred in #{Rails.env}", 'remote_ip' => arg.remote_ip,
nil, 'uuid' => arg.uuid,
exception.to_s, 'original_url' => arg.original_url,
exception.backtrace.join("\n"), 'env' => Hash.new
request, }
params, request.env.each do | key, value |
current_user, requestHash['env'][key.to_s] = value.to_s
Time.now.strftime("%d/%m/%Y %H:%M") end
] send_mail(:error_report,
end if Rails.env.preview? || Rails.env.production? "An error has occurred in #{Rails.env}",
nil,
exception.to_s,
exception.backtrace.join("\n"),
requestHash,
params,
current_user,
Time.now.strftime("%d/%m/%Y %H:%M")
)
end
end end
# raise the error if we are in development so that we can debug it # raise the error if we are in development so that we can debug it
@ -250,37 +218,6 @@ class ApplicationController < LinguaFrancaApplicationController
end end
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 def contact
@main_title = @page_title = 'page_titles.contact.Contact_Us' @main_title = @page_title = 'page_titles.contact.Contact_Us'
end end
@ -290,32 +227,28 @@ class ApplicationController < LinguaFrancaApplicationController
if params[:reason] == 'conference' if params[:reason] == 'conference'
@conference.organizations.each do | org | @conference.organizations.each do |org|
org.users.each do | user | org.users.each do |user|
email_list << user.named_email # email_list << user.named_email
end end
end end
end end
UserMailer.send_mail(:contact) do send_mail(:contact,
[
current_user || params[:email], current_user || params[:email],
params[:subject], params[:subject],
params[:message], params[:message],
email_list email_list
] )
end
request_info = session['request_info'] || { 'request' => request, 'params' => params } request_info = session['request_info'] || { 'request' => request, 'params' => params }
UserMailer.send_mail(:contact_details) do send_mail(:contact_details,
[
current_user || params[:email], current_user || params[:email],
params[:subject], params[:subject],
params[:message], params[:message],
request_info['request'], request_info['request'],
request_info['params'] request_info['params']
] )
end
redirect_to contact_sent_path redirect_to contact_sent_path
end end
@ -326,31 +259,8 @@ class ApplicationController < LinguaFrancaApplicationController
render 'contact' render 'contact'
end end
def update_user_settings def confirm_user
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'}
if params[:email] 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' template = 'login_confirmation_sent'
@page_title ||= 'page_titles.403.Please_Check_Email' @page_title ||= 'page_titles.403.Please_Check_Email'
@ -365,75 +275,44 @@ class ApplicationController < LinguaFrancaApplicationController
@banner_image ||= 'grafitti.jpg' @banner_image ||= 'grafitti.jpg'
@page_title ||= 'page_titles.403.Please_Login' @page_title ||= 'page_titles.403.Please_Login'
do_403 (template || 'translator_login') do_403 template
else else
do_404 do_404
end end
end end
def confirm(uid = nil) def error_404(args = {})
@confirmation = EmailConfirmation.find_by_token(params[:token]) params[:_original_action] = params[:action]
params[:action] = 'error-404'
unless @confirmation.present? @page_title = 'page_titles.404.Page_Not_Found'
@token_not_found = true @main_title = 'error.404.title'
return do_404 super(args)
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'
end end
def translator_request def do_403(template = nil)
@banner_image = 'grafitti.jpg' @banner_image = 'grafitti.jpg'
@page_title = 'page_titles.403.Translator_Request_Sent'
do_403 'translator_request_sent'
end
def user_logout unless current_user
logout() @page_title = 'page_titles.403.Please_Login'
redirect_to (params[:url] || '/') end
end
def find_user @template = template
user = User.find_user(params[:e]) @page_title ||= 'page_titles.403.Access_Denied'
@main_title ||= @page_title
params[:_original_action] = params[:action]
params[:action] = 'error-403'
if user.present? super(template)
return render json: {
name: user.name,
email: user.email,
exists: true
}
end
render json: {
name: I18n.t('user.not_found'),
email: nil,
exists: false
}
end end
def login_user(u) def error_500(exception = nil)
auto_login(u) @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 end
def on_translation_change(object, data, locale, translator_id) def on_translation_change(object, data, locale, translator_id)
@ -443,8 +322,8 @@ class ApplicationController < LinguaFrancaApplicationController
if object.respond_to?(:get_translators) if object.respond_to?(:get_translators)
object.get_translators(data, locale).each do |id, user| object.get_translators(data, locale).each do |id, user|
if user.id != current_user.id && user.id != translator_id if user.id != current_user.id && user.id != translator_id
UserMailer.send_mail mailer, user.locale do LinguaFranca.with_locale user.locale do
{ :args => [object, data, locale, user, translator] } send_mail(:send, mailer, object.id, data, locale, user.id, translator.id)
end end
end end
end end
@ -457,8 +336,8 @@ class ApplicationController < LinguaFrancaApplicationController
if object.respond_to?(:get_translators) if object.respond_to?(:get_translators)
object.get_translators(data).each do |id, user| object.get_translators(data).each do |id, user|
if user.id != current_user.id if user.id != current_user.id
UserMailer.send_mail mailer, user.locale do LinguaFranca.with_locale user.locale do
{ :args => [object, data, user, current_user] } send_mail(:send, mailer, object.id, data, user.id, current_user.id)
end end
end end
end end
@ -469,23 +348,32 @@ class ApplicationController < LinguaFrancaApplicationController
# log it # log it
logger.info "Missing translation found for: #{key}" logger.info "Missing translation found for: #{key}"
# send and email if this is production # send an email if this is production
begin if Rails.env.preview? || Rails.env.production?
UserMailer.send_mail(:error_report) do begin
[ requestHash = {
"A missing translation found in #{Rails.env}", 'remote_ip' => arg.remote_ip,
"<p>A translation for <code>#{key}</code> in <code>#{locale.to_s}</code> was found. The text that was rendered to the user was:</p><blockquote>#{str || 'nil'}</blockquote>", 'uuid' => arg.uuid,
exception.to_s, 'original_url' => arg.original_url,
nil, 'env' => Hash.new
request, }
params, request.env.each do | key, value |
current_user, requestHash['env'][key.to_s] = value.to_s
Time.now.strftime("%d/%m/%Y %H:%M") end
] send_mail(:error_report,
end if Rails.env.preview? || Rails.env.production? "A missing translation found in #{Rails.env}",
rescue Exception => exception2 "<p>A translation for <code>#{key}</code> in <code>#{locale.to_s}</code> was found. The text that was rendered to the user was:</p><blockquote>#{str || 'nil'}</blockquote>",
logger.info exception2.to_s exception.to_s,
logger.info exception2.backtrace.join("\n") nil,
requestHash,
params,
current_user.id,
Time.now.strftime("%d/%m/%Y %H:%M")
)
rescue Exception => exception2
logger.info exception2.to_s
logger.info exception2.backtrace.join("\n")
end
end end
end end
@ -545,8 +433,8 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule = {} @schedule = {}
day_1 = conference.start_date.wday day_1 = conference.start_date.wday
@workshop_blocks.each_with_index do | info, block | @workshop_blocks.each_with_index do |info, block|
info['days'].each do | block_day | info['days'].each do |block_day|
day_diff = block_day.to_i - day_1 day_diff = block_day.to_i - day_1
day_diff += 7 if day_diff < 0 day_diff += 7 if day_diff < 0
day = (conference.start_date + day_diff.days).to_date day = (conference.start_date + day_diff.days).to_date
@ -559,9 +447,10 @@ class ApplicationController < LinguaFrancaApplicationController
end end
end end
@workshops.each do | workshop | @workshops.each do |workshop|
if workshop.block.present? if workshop.block.present?
block = @workshop_blocks[workshop.block['block'].to_i] block = @workshop_blocks[workshop.block['block'].to_i]
day_diff = workshop.block['day'].to_i - day_1 day_diff = workshop.block['day'].to_i - day_1
day_diff += 7 if day_diff < 0 day_diff += 7 if day_diff < 0
day = (conference.start_date + day_diff.days).to_date day = (conference.start_date + day_diff.days).to_date
@ -573,7 +462,7 @@ class ApplicationController < LinguaFrancaApplicationController
end end
end end
@meals.each do | time, meal | @meals.each do |time, meal|
day = meal['day'].to_date day = meal['day'].to_date
time = meal['time'].to_f time = meal['time'].to_f
@schedule[day] ||= {} @schedule[day] ||= {}
@ -584,7 +473,7 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:times][time][:item] = meal @schedule[day][:times][time][:item] = meal
end end
@events.each do | event | @events.each do |event|
if event.present? && event.start_time.present? && event.end_time.present? if event.present? && event.start_time.present? && event.end_time.present?
day = event.start_time.midnight.to_date day = event.start_time.midnight.to_date
time = event.start_time.hour.to_f + (event.start_time.min / 60.0) time = event.start_time.hour.to_f + (event.start_time.min / 60.0)
@ -598,13 +487,13 @@ class ApplicationController < LinguaFrancaApplicationController
end end
@schedule = @schedule.sort.to_h @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][:times] = data[:times].sort.to_h
end end
@schedule.each do | day, data | @schedule.each do |day, data|
last_event = nil last_event = nil
data[:times].each do | time, time_data | data[:times].each do |time, time_data|
if last_event.present? if last_event.present?
@schedule[day][:times][last_event][:next_event] = time @schedule[day][:times][last_event][:next_event] = time
end end
@ -613,8 +502,8 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:num_locations] = (data[:locations] || []).size @schedule[day][:num_locations] = (data[:locations] || []).size
end end
@schedule.deep_dup.each do | day, data | @schedule.deep_dup.each do |day, data|
data[:times].each do | time, time_data | data[:times].each do |time, time_data|
if time_data[:next_event].present? || time_data[:length] > 0.5 if time_data[:next_event].present? || time_data[:length] > 0.5
span = 0.5 span = 0.5
length = time_data[:next_event].present? ? time_data[:next_event] - time : time_data[:length] length = time_data[:next_event].present? ? time_data[:next_event] - time : time_data[:length]
@ -631,7 +520,7 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule = @schedule.sort.to_h @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][:times] = data[:times].sort.to_h
@schedule[day][:locations] ||= {} @schedule[day][:locations] ||= {}
@ -639,19 +528,19 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty? @schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty?
if do_analyze 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? if time_data[:type] == :workshop && time_data[:item].present? && time_data[:item][:workshops].present?
ids = time_data[:item][:workshops].keys 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? if time_data[:item][:workshops][ids[i]].present?
workshop_i = time_data[:item][:workshops][ids[i]][:workshop] workshop_i = time_data[:item][:workshops][ids[i]][:workshop]
conflicts = {} 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 workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil
if workshop_i.present? && workshop_j.present? if workshop_i.present? && workshop_j.present?
workshop_i.active_facilitators.each do | facilitator_i | workshop_i.active_facilitators.each do |facilitator_i|
workshop_j.active_facilitators.each do | facilitator_j | workshop_j.active_facilitators.each do |facilitator_j|
if facilitator_i.id == facilitator_j.id if facilitator_i.id == facilitator_j.id
@schedule[day][:times][time][:status] ||= {} @schedule[day][:times][time][:status] ||= {}
@schedule[day][:times][time][:item][:workshops][ids[j]][:status][:errors] << { @schedule[day][:times][time][:item][:workshops][ids[j]][:status][:errors] << {
@ -673,7 +562,7 @@ class ApplicationController < LinguaFrancaApplicationController
needs = JSON.parse(workshop_i.needs || '[]').map &:to_sym needs = JSON.parse(workshop_i.needs || '[]').map &:to_sym
amenities = JSON.parse(location.amenities || '[]').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] << { @schedule[day][:times][time][:item][:workshops][ids[i]][:status][:errors] << {
name: :need_not_available, name: :need_not_available,
need: need, need: need,
@ -689,7 +578,7 @@ class ApplicationController < LinguaFrancaApplicationController
# collect common interested users # collect common interested users
interests = [] 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 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 if workshop_i.present? && workshop_j.present? && workshop_i.id != workshop_j.id
interests = interests | workshop_j.interested.map { | u | u.user_id } interests = interests | workshop_j.interested.map { | u | u.user_id }
@ -744,4 +633,17 @@ class ApplicationController < LinguaFrancaApplicationController
def html_value(value) def html_value(value)
return value.present? && ActionView::Base.full_sanitizer.sanitize(value).strip.present? ? value : nil return value.present? && ActionView::Base.full_sanitizer.sanitize(value).strip.present? ? value : nil
end end
# send the confirmation email and make sure it get sent as quickly as possible
def send_confirmation(confirmation)
send_mail(:email_confirmation, confirmation.id)
end
def send_mail(*args)
if Rails.env.preview? || Rails.env.production?
UserMailer.delay(queue: Rails.env.to_s).send(*args)
else
UserMailer.send(*args).deliver_now
end
end
end end

98
app/controllers/conference_administration_controller.rb

@ -151,7 +151,7 @@ class ConferenceAdministrationController < ApplicationController
}, },
data: [], data: [],
} }
@organizations.each do | org | @organizations.each do |org|
if org.present? if org.present?
address = org.locations.first address = org.locations.first
@excel_data[:data] << { @excel_data[:data] << {
@ -167,7 +167,7 @@ class ConferenceAdministrationController < ApplicationController
} }
end end
end end
return respond_to do | format | return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "organizations" } format.xlsx { render xlsx: :stats, filename: "organizations" }
end end
end end
@ -183,7 +183,7 @@ class ConferenceAdministrationController < ApplicationController
if request.format.xlsx? if request.format.xlsx?
logger.info "Generating stats.xls" 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')}" } format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end end
end end
@ -194,7 +194,7 @@ class ConferenceAdministrationController < ApplicationController
@donation_count = 0 @donation_count = 0
@donations = 0 @donations = 0
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 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 if view_context.registration_status(r) == :registered
@completed_registrations += 1 @completed_registrations += 1
@ -223,7 +223,7 @@ class ConferenceAdministrationController < ApplicationController
if request.format.xlsx? if request.format.xlsx?
logger.info "Generating stats.xls" 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')}" } format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end end
else else
@ -233,7 +233,7 @@ class ConferenceAdministrationController < ApplicationController
@donation_count = 0 @donation_count = 0
@donations = 0 @donations = 0
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 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 if view_context.registration_status(r) == :registered
@completed_registrations += 1 @completed_registrations += 1
@ -275,7 +275,7 @@ class ConferenceAdministrationController < ApplicationController
}, },
data: [], data: [],
} }
@hosts.each do | id, host | @hosts.each do |id, host|
data = (host.housing_data || {}) data = (host.housing_data || {})
host_data = { host_data = {
name: host.user.name, name: host.user.name,
@ -283,7 +283,7 @@ class ConferenceAdministrationController < ApplicationController
email: host.user.email, email: host.user.email,
phone: data['phone'], 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) : '', 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: '', empty: '',
guests: { guests: {
columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city], columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city],
@ -304,8 +304,8 @@ class ConferenceAdministrationController < ApplicationController
} }
} }
@housing_data[id][:guests].each do | space, space_data | @housing_data[id][:guests].each do |space, space_data|
space_data.each do | guest_id, guest_data | space_data.each do |guest_id, guest_data|
guest = guest_data[:guest] guest = guest_data[:guest]
if guest.present? if guest.present?
companion = view_context.companion(guest) companion = view_context.companion(guest)
@ -326,7 +326,7 @@ class ConferenceAdministrationController < ApplicationController
@excel_data[:data] << host_data @excel_data[:data] << host_data
end end
return respond_to do | format | return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "housing" } format.xlsx { render xlsx: :stats, filename: "housing" }
end end
end end
@ -458,7 +458,7 @@ class ConferenceAdministrationController < ApplicationController
}, },
data: [] data: []
} }
User.AVAILABLE_LANGUAGES.each do | l | User.AVAILABLE_LANGUAGES.each do |l|
@excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}" @excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}"
end end
ConferenceRegistration.all_spaces.each do |s| ConferenceRegistration.all_spaces.each do |s|
@ -468,7 +468,7 @@ class ConferenceAdministrationController < ApplicationController
ConferenceRegistration.all_considerations.each do |c| ConferenceRegistration.all_considerations.each do |c|
@excel_data[:keys][c] = "articles.conference_registration.host.considerations.#{c.to_s}" @excel_data[:keys][c] = "articles.conference_registration.host.considerations.#{c.to_s}"
end end
@registrations.each do | r | @registrations.each do |r|
user = r.user_id ? User.where(id: r.user_id).first : nil user = r.user_id ? User.where(id: r.user_id).first : nil
if user.present? if user.present?
companion = view_context.companion(r) companion = view_context.companion(r)
@ -528,7 +528,7 @@ class ConferenceAdministrationController < ApplicationController
last_day: availability[1].present? ? view_context.date(availability[1].to_date, :span_same_year_date_1) : '' 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) can_speak = ((user.languages || []).include? l.to_s)
data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '') data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '')
data[:raw_values]["language_#{l}".to_sym] = can_speak data[:raw_values]["language_#{l}".to_sym] = can_speak
@ -573,12 +573,12 @@ class ConferenceAdministrationController < ApplicationController
first_day: view_context.conference_days_options_list(:before), first_day: view_context.conference_days_options_list(:before),
last_day: view_context.conference_days_options_list(:after) 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] = [ @column_options["language_#{l}".to_sym] = [
[(view_context._"articles.conference_registration.questions.bike.yes"), true] [(view_context._"articles.conference_registration.questions.bike.yes"), true]
] ]
end end
ConferenceRegistration.all_considerations.each do | c | ConferenceRegistration.all_considerations.each do |c|
@column_options[c.to_sym] = [ @column_options[c.to_sym] = [
[(view_context._"articles.conference_registration.questions.bike.yes"), true] [(view_context._"articles.conference_registration.questions.bike.yes"), true]
] ]
@ -589,7 +589,7 @@ class ConferenceAdministrationController < ApplicationController
def get_housing_data def get_housing_data
@hosts = {} @hosts = {}
@guests = {} @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 if registration.can_provide_housing
@hosts[registration.id] = registration @hosts[registration.id] = registration
elsif registration.housing.present? && registration.housing != 'none' elsif registration.housing.present? && registration.housing != 'none'
@ -603,11 +603,11 @@ class ConferenceAdministrationController < ApplicationController
@housing_data = {} @housing_data = {}
@hosts_affected_by_guests = {} @hosts_affected_by_guests = {}
@hosts.each do | id, host | @hosts.each do |id, host|
@hosts[id].housing_data ||= {} @hosts[id].housing_data ||= {}
@housing_data[id] = { guests: {}, space: {} } @housing_data[id] = { guests: {}, space: {} }
@hosts[id].housing_data['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 size = (size || 0).to_i
@housing_data[id][:guests][s.to_sym] = {} @housing_data[id][:guests][s.to_sym] = {}
@housing_data[id][:space][s.to_sym] = size @housing_data[id][:space][s.to_sym] = size
@ -616,7 +616,7 @@ class ConferenceAdministrationController < ApplicationController
@guests_housed = 0 @guests_housed = 0
@guests.each do | guest_id, guest | @guests.each do |guest_id, guest|
data = guest.housing_data || {} data = guest.housing_data || {}
@hosts_affected_by_guests[guest_id] ||= [] @hosts_affected_by_guests[guest_id] ||= []
@ -651,7 +651,7 @@ class ConferenceAdministrationController < ApplicationController
end end
companions = data['companions'] || [] companions = data['companions'] || []
companions.each do | companion | companions.each do |companion|
user = User.find_user(companion) user = User.find_user(companion)
if user.present? if user.present?
reg = ConferenceRegistration.find_by( reg = ConferenceRegistration.find_by(
@ -678,10 +678,10 @@ class ConferenceAdministrationController < ApplicationController
end end
end end
@hosts.each do | id, host | @hosts.each do |id, host|
host_data = host.housing_data 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 # make sure the host isn't overbooked
space = space.to_sym space = space.to_sym
space_available = (size || 0).to_i space_available = (size || 0).to_i
@ -755,7 +755,7 @@ class ConferenceAdministrationController < ApplicationController
end end
else else
do_404 do_404
return nil return true
end end
return false return false
@ -790,7 +790,7 @@ class ConferenceAdministrationController < ApplicationController
end end
def admin_update_description 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)) @this_conference.set_column_for_locale(:info, locale, html_value(value))
end end
@this_conference.save @this_conference.save
@ -811,7 +811,7 @@ class ConferenceAdministrationController < ApplicationController
def admin_update_payment_message def admin_update_payment_message
begin 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)) @this_conference.set_column_for_locale(:payment_message, locale, html_value(value))
end end
@this_conference.save @this_conference.save
@ -883,7 +883,7 @@ class ConferenceAdministrationController < ApplicationController
end end
user_changed = false user_changed = false
params.each do | key, value | params.each do |key, value|
case key.to_sym case key.to_sym
when :city when :city
if value.present? if value.present?
@ -964,7 +964,7 @@ class ConferenceAdministrationController < ApplicationController
do_404 do_404
end end
return nil return true
end end
def admin_update_housing def admin_update_housing
@ -1004,7 +1004,7 @@ class ConferenceAdministrationController < ApplicationController
do_404 do_404
end end
return nil return true
end end
def admin_update_broadcast def admin_update_broadcast
@ -1014,36 +1014,32 @@ class ConferenceAdministrationController < ApplicationController
@send_to = params[:send_to] @send_to = params[:send_to]
@register_template = :administration @register_template = :administration
if params[:button] == 'send' 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 send_mail(:broadcast,
[
"#{request.protocol}#{request.host_with_port}", "#{request.protocol}#{request.host_with_port}",
@subject, @subject,
@body, @body,
user, user.id,
@this_conference @this_conference.id
] )
end
end end
redirect_to administration_step_path(@this_conference.slug, :broadcast_sent) redirect_to administration_step_path(@this_conference.slug, :broadcast_sent)
return nil return true
elsif params[:button] == 'preview' elsif params[:button] == 'preview'
@send_to_count = view_context.broadcast_to(@send_to).size @send_to_count = view_context.broadcast_to(@send_to).size
@broadcast_step = :preview @broadcast_step = :preview
elsif params[:button] == 'test' elsif params[:button] == 'test'
@broadcast_step = :test @broadcast_step = :test
UserMailer.send_mail :broadcast do send_mail(:broadcast,
[
"#{request.protocol}#{request.host_with_port}", "#{request.protocol}#{request.host_with_port}",
@subject, @subject,
@body, @body,
current_user, current_user.id,
@this_conference @this_conference.id
] )
end
@send_to_count = view_context.broadcast_to(@send_to).size @send_to_count = view_context.broadcast_to(@send_to).size
end end
return true return false
end end
def admin_update_locations def admin_update_locations
@ -1106,14 +1102,14 @@ class ConferenceAdministrationController < ApplicationController
end end
do_404 do_404
return nil return true
end end
def admin_update_events def admin_update_events
case params[:button] case params[:button]
when 'edit' when 'edit'
redirect_to edit_event_path(@this_conference.slug, params[:id]) redirect_to edit_event_path(@this_conference.slug, params[:id])
return nil return true
when 'save' when 'save'
if params[:id].present? if params[:id].present?
event = Event.find_by!(conference_id: @this_conference.id, id: params[:id]) event = Event.find_by!(conference_id: @this_conference.id, id: params[:id])
@ -1127,11 +1123,11 @@ class ConferenceAdministrationController < ApplicationController
event.end_time = event.start_time + params[:time_span].to_f.hours event.end_time = event.start_time + params[:time_span].to_f.hours
# save translations # 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) event.set_column_for_locale(:title, locale, html_value(value), current_user.id) unless value = event._title(locale)
end 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) event.set_column_for_locale(:info, locale, value, current_user.id) unless value = event._info(locale)
end end
@ -1143,7 +1139,7 @@ class ConferenceAdministrationController < ApplicationController
end end
do_404 do_404
return nil return true
end end
def admin_update_workshop_times def admin_update_workshop_times
@ -1209,7 +1205,7 @@ class ConferenceAdministrationController < ApplicationController
@location = params[:location] @location = params[:location]
@event_location = @location.present? && @location.to_i > 0 ? EventLocation.find(@location.to_i) : nil @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 @ordered_workshops[workshop.id] = workshop
end end
@ -1251,7 +1247,7 @@ class ConferenceAdministrationController < ApplicationController
def get_empty(hash, keys) def get_empty(hash, keys)
keys = [keys] unless keys.is_a?(Array) keys = [keys] unless keys.is_a?(Array)
keys.each do | key | keys.each do |key|
return key unless hash[key].present? return key unless hash[key].present?
end end
return nil return nil

71
app/controllers/conferences_controller.rb

@ -2,6 +2,7 @@ require 'geocoder/calculations'
require 'rest_client' require 'rest_client'
class ConferencesController < ApplicationController class ConferencesController < ApplicationController
def list def list
@page_title = 'articles.conferences.headings.Conference_List' @page_title = 'articles.conferences.headings.Conference_List'
@conference_list = { future: [], passed: [] } @conference_list = { future: [], passed: [] }
@ -17,7 +18,7 @@ class ConferencesController < ApplicationController
set_conference set_conference
do_403 unless @this_conference.is_public || @this_conference.host?(current_user) 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 if @this_conference.workshop_schedule_published
@event_dlg = true @event_dlg = true
@ -59,7 +60,7 @@ class ConferencesController < ApplicationController
steps = nil steps = nil
return do_404 unless registration_steps.present? return do_404 unless registration_steps.present?
@register_template = :administration if params[:admin_step].present? # @register_template = :administration if params[:admin_step].present?
@errors = {} @errors = {}
@warnings = [] @warnings = []
@ -72,8 +73,19 @@ class ConferencesController < ApplicationController
@register_template = steps[steps.find_index($1.to_sym) - 1] @register_template = steps[steps.find_index($1.to_sym) - 1]
elsif form_step == :paypal_confirm elsif form_step == :paypal_confirm
if @registration.present? && @registration.payment_confirmation_token == params[:confirmation_token] if @registration.present? && @registration.payment_confirmation_token == params[:confirmation_token]
@amount = PayPal!.details(params[:token]).amount.total if Rails.env.test?
@registration.payment_info = {:payer_id => params[:PayerID], :token => params[:token], :amount => @amount}.to_yaml @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') @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) info = YAML.load(@registration.payment_info)
@amount = nil @amount = nil
status = nil status = nil
if ENV['RAILS_ENV'] == 'test' if Rails.env.test?
status = info[:status] status = info[:status]
@amount = info[:amount] @amount = info[:amount]
else else
@ -114,7 +126,7 @@ class ConferencesController < ApplicationController
case form_step case form_step
when :confirm_email when :confirm_email
return do_confirm return confirm_email(params[:email], params[:token], register_path(@this_conference.slug))
when :contact_info when :contact_info
if params[:name].present? && params[:name].gsub(/[\s\W]/, '').present? if params[:name].present? && params[:name].gsub(/[\s\W]/, '').present?
current_user.firstname = params[:name].squish current_user.firstname = params[:name].squish
@ -188,18 +200,23 @@ class ConferencesController < ApplicationController
amount = params[:amount].to_f amount = params[:amount].to_f
if amount > 0 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) # we can't really test paypal integration in our tests, so we'll fake it instead
@registration.save if Rails.env.test?
@registration.payment_confirmation_token = 'token'
host = "#{request.protocol}#{request.host_with_port}" @registration.payment_info = {amount: amount}.to_yaml
response = PayPal!.setup( @registration.save!
PayPalRequest(amount), redirect_to 'https://www.paypal.com'
register_paypal_confirm_url(@this_conference.slug, :paypal_confirm, @registration.payment_confirmation_token), else
register_paypal_confirm_url(@this_conference.slug, :paypal_cancel, @registration.payment_confirmation_token), @registration.payment_confirmation_token = Digest::SHA256.hexdigest(rand(Time.now.to_f * 1000000).to_i.to_s)
noshipping: true, @registration.save!
version: 204 pp = PayPal!
) response = pp.setup(
if ENV['RAILS_ENV'] != 'test' 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 redirect_to response.redirect_uri
end end
return return
@ -219,7 +236,7 @@ class ConferencesController < ApplicationController
# this step is only completed if a payment has been made # this step is only completed if a payment has been made
if form_step != :payment || (@registration.registration_fees_paid || 0) > 0 if form_step != :payment || (@registration.registration_fees_paid || 0) > 0
@registration.steps_completed ||= [] @registration.steps_completed ||= []
@registration.steps_completed << form_step @registration.steps_completed << form_step.to_s
@registration.steps_completed.uniq! @registration.steps_completed.uniq!
end end
end end
@ -334,9 +351,7 @@ class ConferencesController < ApplicationController
steps -= [:questions] steps -= [:questions]
# if this is a housing provider that is not attending the conference, remove these steps # if this is a housing provider that is not attending the conference, remove these steps
if @registration.is_attending == 'n' steps -= [:payment, :workshops] if @registration.is_attending == 'n'
steps -= [:payment, :workshops]
end
else else
steps -= [:hosting] steps -= [:hosting]
end end
@ -344,8 +359,6 @@ class ConferencesController < ApplicationController
steps -= [:hosting, :questions] steps -= [:hosting, :questions]
end end
steps += [:administration] if conference.host?(current_user)
return steps return steps
end end
@ -394,11 +407,11 @@ class ConferencesController < ApplicationController
def PayPalRequest(amount) def PayPalRequest(amount)
Paypal::Payment::Request.new( Paypal::Payment::Request.new(
:currency_code => 'USD', # if nil, PayPal use USD as default currency_code: 'USD', # if nil, PayPal use USD as default
:description => 'Conference Registration', # item description description: 'Conference Registration', # item description
:quantity => 1, # item quantity quantity: 1, # item quantity
:amount => amount.to_f, # item value amount: amount.to_f, # item value
:custom_fields => { custom_fields: {
CARTBORDERCOLOR: "00ADEF", CARTBORDERCOLOR: "00ADEF",
LOGOIMG: "https://en.bikebike.org/assets/bblogo-paypal.png" LOGOIMG: "https://en.bikebike.org/assets/bblogo-paypal.png"
} }

101
app/controllers/oauths_controller.rb

@ -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

8
app/controllers/workshops_controller.rb

@ -1,10 +1,10 @@
class WorkshopsController < ApplicationController class WorkshopsController < ApplicationController
def workshops def workshops
set_conference set_conference
set_conference_registration! set_conference_registration!
@workshops = Workshop.where(:conference_id => @this_conference.id) @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) @my_workshops = @workshops.select { |w| w.active_facilitator?(current_user) }
render 'workshops/index' render 'workshops/index'
end end
@ -58,7 +58,7 @@ class WorkshopsController < ApplicationController
@is_translating ||= false @is_translating ||= false
if @is_translating 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) return do_403 unless @workshop.can_translate?(current_user, @translation)
@title = @workshop._title(@translation) @title = @workshop._title(@translation)

163
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

2221
app/helpers/application_helper.rb

File diff suppressed because it is too large

407
app/helpers/bike_bike_form_helper.rb

@ -1,407 +0,0 @@
module BikeBikeFormHelper
include ActionView::Helpers::FormTagHelper
TEMPLATE_DIR = 'layouts/fields'
def check_box_tag(name, value = "1", checked = false, options = {})
render_field(name, options = get_options(name, options), super(name, value, checked, options), value)
end
def color_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def date_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def datetime_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def datetime_local_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def email_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def file_field_tag(name, options = {})
render_field(name, options = get_options(name, options), super(name, options))
end
def hidden_field_tag(name, value = nil, options = {})
super(name, value, options)
end
def month_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def number_field_tag(name, value = nil, options = {})
options[:_no_wrapper] = true
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def password_field_tag(name = "password", value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def phone_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def radio_button_tag(name, value, checked = false, options = {})
render_field(name, options = get_options(name, options), super(name, value, checked, options), value)
end
def range_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def search_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def select_tag(name, option_tags = nil, options = {})
render_field(name, options = get_options(name, options), super(name, option_tags, options))
end
def telephone_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def text_area_tag(name, content = nil, options = {})
render_field(name, options = get_options(name, options), super(name, content, options), content)
end
def text_field_tag(name, value = nil, options = {})
if options[:_no_wrapper]
options.delete(:_no_wrapper)
options[:no_wrapper] = true
end
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def time_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def url_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def week_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def country_select_tag(name, value, options={})
#options[:no_wrapper] = true
render_field(name, options = get_options(name, options), super(name, value, options), value)
end
def subregion_select_tag(name, value, parent_region_or_code, options = {}, html_options = {})
render_field(name, options = get_options(name, options), super(name, value, parent_region_or_code, options), value)
end
#def button_tag
#def field_set_tag
#def form_tag
#def image_submit_tag
#def label_tag
#def submit_tag
#def utf8_enforcer_tag
# FormHelper methods
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
render_field(method, options = get_options(method, options), super(object_name, method, options, checked_value, unchecked_value))
end
def color_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def date_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def datetime_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def datetime_local_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def email_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def file_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options))
end
def hidden_field(object_name, method, options = {})
super(object_name, method, options)
end
def month_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def number_field(object_name, method, options = {})
options[:_no_wrapper] = true
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def password_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def phone_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def radio_button(object_name, method, tag_value, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, tag_value, options), get_value(method, options))
end
def range_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def search_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def telephone_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def text_area(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def text_field(object_name, method, options = {})
if options[:_no_wrapper]
options.delete(:_no_wrapper)
options[:no_wrapper] = true
end
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def time_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def url_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def week_field(object_name, method, options = {})
render_field(method, options = get_options(method, options), super(object_name, method, options), get_value(method, options))
end
def form_for(*args, &block)
@record = args.first
template = 'errors_' + @record.class.name.underscore
template = 'errors_default' unless lookup_context.exists?(template, [TEMPLATE_DIR], true)
( render (TEMPLATE_DIR + '/' + template) ) + super(*args, &block)
end
def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
render_field(method, options = get_options(method, options), super(object, method, collection, value_method, text_method, options, html_options, &block), get_value(method, options))
end
def collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
render_field(method, options = get_options(method, options), super(object, method, collection, value_method, text_method, options, html_options, &block), get_value(method, options))
end
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
render_field(method, options = get_options(method, options), super(object, method, collection, value_method, text_method, options, html_options), get_value(method, options))
end
def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
render_field(method, options = get_options(method, options), super(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options), get_value(method, options))
end
def select(object, method, choices = nil, options = {}, html_options = {}, &block)
render_field(method, options = get_options(method, options), super(object, method, choices, options, html_options, &block), get_value(method, options))
end
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
render_field(method, options = get_options(method, options), super(object, method, priority_zones, options, html_options), get_value(method, options))
end
def country_select(object, method, priorities_or_options = {}, options_or_html_options = {}, html_options = {})
if priorities_or_options.is_a? Array
options = options_or_html_options = get_options(method, priorities_or_options)
else
options = priorities_or_options = get_options(method, priorities_or_options)
end
render_field(method, options, super(object, method, priorities_or_options, options_or_html_options, html_options), get_value(method, options))
end
def subregion_select(object, method, parent_region_or_code, options = {}, html_options = {})
render_field(method, options = get_options(method, options), super(object, method, parent_region_or_code, options, html_options), get_value(method, options))
end
# Custom fields
def image_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), BikeBikeFormHelper.image_field_tag(name, value, options), value)
end
def organization_select_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), BikeBikeFormHelper.organization_select_field_tag(name, value, options), value)
end
def user_select_field_tag(name, value = nil, options = {})
render_field(name, options = get_options(name, options), BikeBikeFormHelper.user_select_field_tag(name, value, options), value)
end
#def grouped_options_for_select
#def option_groups_from_collection_for_select
#def options_for_select
#def options_from_collection_for_select
#def time_zone_options_for_select
def form_actions(actions = [])
BikeBikeFormHelper.form_actions(actions)
end
class << self
def form_actions(actions = [])
render(:actions, {:actions => actions.is_a?(Array) ? actions : [actions]})
end
def image_field_tag(name, value, options, form = nil)
render(:field_image_field, {:name => name, :value => value, :options => options, :form => form})
end
def organization_select_field_tag(name, value, options, form = nil)
render(:field_organization_select_field, {:name => name, :value => value, :options => options, :form => form})
end
def user_select_field_tag(name, value, options, form = nil)
render(:field_user_select_field, {:name => name, :value => value, :options => options, :form => form})
end
def get_options(name, options, type)
if options[:placeholder] === false
options.delete(:placeholder)
elsif (['email_field', 'number_field', 'phone_field', 'search_field', 'telephone_field', 'text_area', 'text_field', 'url_field'].include? type)
options[:placeholder] ||= I18n.translate('form.placeholder.Enter_your_' + name.to_s)
end
return options
end
def render_field(type, name, options, html, value = nil)
options.symbolize_keys!
if (options.has_key?(:no_wrapper) && options[:no_wrapper]) || /country/.match(name.to_s) && /^subregion_select/.match(type.to_s) || options[:type] == 'hidden'
return html
end
params = Hash.new
params[:name] = name.to_sym
params[:options] = options
params[:html] = html
params[:type] = type
params[:value] = value
template = template_exists?(type) ? type : 'default'
params[:label_template] = options[:label] === false ? nil : get_label_template(type, options)
params[:label_position] = options[:label] === false ? :none : label_position(type, options)
render(template, params)
end
def get_label_template(type, options)
if !options[:label] && /select(_field)?$/.match(type.to_s)
return nil
end
template_exists?('label_' + type) ? type : 'default'
end
def label_position(type, options)
# one of: :before, :after, :inside, or :none
case type
when 'image_field'
return :inside
when 'organization_select_field'
return :none
#when 'select_field'
# return :before
end
return :before
end
private
def render (template, params)
view = ActionView::Base.new(ActionController::Base.view_paths, params)
view.extend ApplicationHelper
view.render (TEMPLATE_DIR + '/' + template.to_s)
end
def template_exists? (template)
view = ActionView::Base.new(ActionController::Base.view_paths, {})
view.extend ApplicationHelper
view.lookup_context.exists?(template, [TEMPLATE_DIR], true)
end
end
private
def get_type()
caller[1][/`.*'/][1..-2].gsub(/^(.*?)(_tag)?$/, '\1')
end
def get_value(method, options)
options && options[:object] ? options[:object][method] : nil
end
def get_options(name, options)
options[:_controller] = params[:controller]
BikeBikeFormHelper.get_options(name, options, get_type())
end
def render_field(name, options, html, value = nil)
BikeBikeFormHelper.render_field(get_type(), name, options, html, value)
end
class BikeBikeFormBuilder < ActionView::Helpers::FormBuilder
ActionView::Base.default_form_builder = BikeBikeFormHelper::BikeBikeFormBuilder
def image_field(method, value, options = {})
custom_field(method, value, options, 'image_field')
end
def organization_select_field(method, value, options = {})
custom_field(method, value, options, 'organization_select_field')
end
def user_select_field(method, value, options = {})
custom_field(method, value, options, 'user_select_field')
end
def actions(actions = [])
BikeBikeFormHelper.form_actions(actions)
end
private
def custom_field(method, value, options, type)
if defined? params
options[:_controller] = params[:controller]
end
options[:_record] = object
options = BikeBikeFormHelper.get_options(method, options, type)
html = BikeBikeFormHelper.send(type + '_tag', method, value, options, self)
BikeBikeFormHelper.render_field(type, method, options, html, value)
end
end
end

729
app/helpers/form_helper.rb

@ -0,0 +1,729 @@
module FormHelper
def off_screen(text, id = nil)
content_tag(:span, text.html_safe, id: id, class: 'screen-reader-text')
end
def translate_fields(object, field_options = {}, options = {})
html = ''
nav = ''
# set the selected locale
selected_locale = (options[:locale] || object.locale || I18n.locale).to_sym
I18n.backend.enabled_locales.each do | locale |
# ses if this should b the selected field
class_name = selected_locale == locale.to_sym ? 'selected' : nil
# add the locale to the nav
nav += content_tag(:li,
content_tag(:a, _("languages.#{locale}"), href: 'javascript:void(0)'),
class: class_name, data: { locale: locale }).html_safe
fields = ''
field_options.each do | name, __options |
_options = __options.deep_dup
# add the field
value = object.is_a?(Hash) ? object[locale.to_sym] : object.get_column_for_locale!(name, locale, false)
# use the default value if we need to
if _options[:default].present? && value.blank?
value = _(_options[:default], locale: locale)
end
_options[:index] = locale
_options[:lang] = locale
_options[:parent_options] = { lang: locale }
type = "#{_options[:type].to_s}"
_options.delete(:type)
fields += self.send(type, name, value, _options).html_safe
end
html += content_tag(:li, fields.html_safe, class: class_name, data: { locale: locale }).html_safe
end
if options[:class].nil?
options[:class] = []
elsif options[:class].is_a?(String)
options[:class] = [options[:class]]
end
options[:class] += ['translator', 'multi-field-translator']
(fieldset(nil, options) do
content_tag(:ul, nav.html_safe, class: 'locale-select').html_safe +
content_tag(:ul, html.html_safe, class: 'text-editors').html_safe
end).html_safe
end
def translate_textarea(name, object, property = nil, options = {})
html = ''
nav = ''
# see if options was passed in as property
if options.blank? && property.is_a?(Hash)
options = property
property = nil
end
# set the selected locale
selected_locale = (options[:locale] || object.locale || I18n.locale).to_sym
I18n.backend.enabled_locales.each do | locale |
# ses if this should b the selected field
class_name = selected_locale == locale.to_sym ? 'selected' : nil
# add the locale to the nav
nav += content_tag(:li,
content_tag(:a, _("languages.#{locale}"), href: 'javascript:void(0)'),
class: class_name, data: { locale: locale }).html_safe
# add the field
value = object.is_a?(Hash) ? object[locale.to_sym] : object.get_column_for_locale!(name, locale, false)
# use the default value if we need to
if options[:default].present? && value.blank?
value = _(options[:default], locale: locale)
end
html += content_tag(:li, textarea(name, value, {
label: false,
edit_on: options[:edit_on],
parent_options: {
lang: locale
},
index: locale
}).html_safe, class: class_name, data: { locale: locale }).html_safe
end
if options[:class].nil?
options[:class] = []
elsif options[:class].is_a?(String)
options[:class] = [options[:class]]
end
options[:class] += ['translator']
(fieldset(name, options) do
content_tag(:ul, nav.html_safe, class: 'locale-select').html_safe +
content_tag(:ul, html.html_safe, class: 'text-editors').html_safe
end).html_safe
end
def textarea(name, value = nil, options = {})
id = unique_id(name)
label_id = "#{id}-label"
description_id = nil
html = ''
if options[:heading].present?
label_id = "#{name.to_s}-label" unless options[:label]
html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: label_id)
end
if options[:label] == false
label_id = options[:labelledby]
elsif options[:label].present?
html += label_tag([name, id], nil, id: label_id) do
_(options[:label], :t, vars: options[:vars] || {})
end
else
html += label_tag([name, id], nil, id: label_id)
end
if options[:help].present?
description_id ||= "#{id}-desc"
html += content_tag(:div, _(options[:help], :s, 2), id: description_id, class: 'input-field-help')
end
if options[:warning].present?
description_id ||= "#{id}-desc"
html += content_tag(:div, _(options[:warning], :s, 2), id: description_id, class: 'warning-info')
end
aria = {}
aria[:labelledby] = label_id if label_id.present?
aria[:describedby] = description_id if description_id.present?
css_class = [
options[:short] === true ? :short : nil
].compact
html_name = name.to_s + (options[:index] ? "[#{options[:index]}]" : '')
if options[:plain]
html += (text_area_tag html_name, value,
id: id,
lang: options[:lang],
aria: aria,
class: css_class
)
else
html += content_tag(:div, value.present? ? value.html_safe : '',
id: id,
data: { name: html_name, 'edit-on': options[:edit_on] || :load },
lang: options[:lang],
aria: aria,
tabindex: 0,
class: [:textarea] + css_class
)
add_stylesheet :editor
add_inline_script :pen
add_inline_script :markdown
add_inline_script :editor
end
parent_options = options[:parent_options] || {}
if parent_options[:class].nil?
parent_options[:class] = []
elsif parent_options[:class].is_a?(String)
parent_options[:class] = [parent_options[:class]]
end
parent_options[:class] += ['text-area-field', 'input-field']
html = content_tag(:div, html.html_safe, parent_options).html_safe
html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
return html.html_safe
end
def fieldset(name = nil, options = {}, &block)
html = ''
label = ''
description = ''
description_id = nil
errors = ''
if name.present?
if options[:label] != false
label = content_tag(:legend,
_((
options[:label].is_a?(String) ?
options[:label] :
"forms.labels.generic.#{name}"), :t, vars: options[:vars] || {}))
end
if options[:help].present?
description_id = unique_id("#{name.to_s}-desc")
description = content_tag(:div, _(options[:help], :s, 2), class: 'input-field-help', id: description_id)
end
errors = (show_errors name)
end
html = label + errors + description + content_tag(:div, class: :fieldgroup, &block)
aria = description_id.present? ? { describedby: description_id } : nil
(content_tag(:fieldset, html.html_safe,
aria: aria,
class: ((options[:class] || []) + [
options[:inline] ? :inline : nil,
options[:inline_label] ? 'inline-label' : nil,
errors.present? ? 'has-error' : nil
]).compact
)
).html_safe
end
def selectfield(name, value, select_options, options = {})
unless select_options.first.is_a?(Array)
so = select_options
select_options = []
so.each do | opt |
select_options << [ I18n.t("forms.options.#{name.to_s}.#{opt.to_s}"), opt]
end
end
textfield(name, value, options.merge({type: :select, options: select_options}))
end
def telephonefield(name, value, options = {})
textfield(name, value, options.merge({type: :telephone}))
end
def numberfield(name, value, options = {})
textfield(name, value, options.merge({type: :number}))
end
def searchfield(name, value, options = {})
textfield(name, value, options.merge({type: :search}))
end
def userfield(name, value, options = {})
# eventually this will be a dynamic field to find users, for now we'll just use emails
# add_inline_script :userfield
emailfield(name, value, options)# .merge({
# parent_options: { class: ['user-field'] },
# after: content_tag(:div, '', class: 'user-name')
# }))
end
def emailfield(name, value, options = {})
textfield(name, value, options.merge({type: :email}))
end
def filefield(name, value, options = {})
textfield(name, value, options.merge({type: :file}))
end
def passwordfield(name, value, options = {})
textfield(name, value, options.merge({type: :password}))
end
def textfield(name, value, options = {})
html = ''
id = unique_id(name)
html_name = name.to_s + (options[:index] ? "[#{options[:index]}]" : '')
description_id = nil
if options[:heading].present?
description_id ||= "#{id.to_s}-desc"
html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: description_id)
end
if options[:help].present?
description_id ||= "#{id.to_s}-desc"
html += content_tag(:div, _(options[:help], :s, 2, vars: options[:vars] || {}), class: 'input-field-help', id: description_id)
end
html += show_errors name, value
inside_label = ''
if options[:type] == :file
inside_label = (content_tag(:div, class: 'file-field-selector') do
(options[:preview] ? content_tag(:img, nil, src: value.present? ? value.url : nil).html_safe : '').html_safe +
content_tag(:div, (value.present? ? File.basename(value.url) : (_'forms.labels.generic.no_file_selected')), class: 'file-field-name ' + (value.present? ? 'selected' : 'unselected')).html_safe +
content_tag(:a, (_'forms.actions.generic.select_file'), class: :button)
end)
end
label_text = nil
if options[:label].present?
label_text = _(options[:label], :t, vars: options[:vars] || {})
elsif options[:label] != false
label_text = (_"forms.labels.generic.#{name}")
elsif options[:type] == :select || options[:type] == :file
# add an empty label so that the drop down button will still appear
label_text = ''
end
label_options = {}
# let the label be selected if the input is hidden
label_options[:tabindex] = 0 if options[:type] == :file
unless label_text.nil?
html += label_tag id, (label_text + inside_label).html_safe
end
input_options = {
id: id,
required: options[:required],
lang: options[:lang],
min: options[:min],
max: options[:max],
step: options[:step],
aria: description_id ? { describedby: description_id } : nil
}
case name
when :address
input_options[:autocomplete] = 'address-line1'
when :name
input_options[:autocomplete] = 'name'
when :location
input_options[:autocomplete] = 'address-level2'
when :email
input_options[:autocomplete] = 'email'
when :phone
input_options[:autocomplete] = 'tel'
when :paypal_email_address, :paypal_username, :paypal_password, :paypal_signature
input_options[:autocomplete] = 'off'
end
case options[:type]
when :select
option_list = options_for_select(options[:options], value)
# make sure that we have an empty option if the select is required
if options[:required] && options[:options].first.present? && options[:options].first.last.present?
option_list = ('<option value="">&nbsp;</option>' + option_list).html_safe
end
html += select_tag(html_name, option_list, input_options)
when :file
add_inline_script :filefield
input_options[:tabindex] = '-1'
html += off_screen(file_field_tag html_name, input_options)
else
input_options[:autocomplete] = 'off' if options[:type] == :search
html += send("#{(options[:type] || :text).to_s}_field_tag", html_name, value, input_options)
end
if options[:after].present?
html += options[:after].html_safe
end
html = content_tag(:div, html.html_safe,
class: [
"#{(options[:type] || :text).to_s}-field",
'input-field',
value.present? ? nil : 'empty',
options[:big] ? 'big' : nil,
options[:small] ? 'small' : nil,
options[:stretch] ? 'stretch-item' : nil,
options[:full] ? 'full' : nil,
options[:inline_label] ? 'inline-label' : nil,
(@errors || {})[name].present? ? 'has-error' : nil
].compact + (((options[:parent_options] || {})[:class]) || []))
html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
return html.html_safe
end
def radiobuttons(name, boxes, value, label_key, options = {})
checkboxes(name, boxes, [value], label_key, options.merge({radiobuttons: true}))
end
def checkbox(name, value, label_key, options = {})
checkboxes(name, [true], value, label_key, options)
end
def unique_id(id)
id = id.to_s.gsub('[', '_').gsub(']', '')
@_ids ||= {}
@_ids[id] ||= 0
new_id = id
if @_ids[id] > 0
new_id += "--#{@_ids[id]}"
end
@_ids[id] += 1
return new_id
end
def checkboxes(name, boxes, values, label_key, options = {})
html = ''
boxes.map! { |box| box.is_a?(String) ? box.to_sym : box }
values.map! { |value| value.is_a?(String) ? value.to_sym : value } if values.is_a?(Array)
label_id = nil
description_id = nil
if options[:heading].present?
label_id ||= unique_id("#{name.to_s}-label")
html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: label_id)
end
help = nil
if options[:help].present?
description_id ||= unique_id("#{name.to_s}-desc")
help = content_tag(:div, _(options[:help], :s, 2), class: 'input-field-help', id: description_id)
end
html += help if help.present? && !options[:right_help]
boxes_html = ''
labels = nil
is_single = !values.is_a?(Array)
if boxes.length > 0
if boxes.first.is_a?(Array)
labels = boxes.map(&:first)
boxes = boxes.map(&:last)
end
elsif !boxes.first.is_a?(Integer)
values = values.present? ? values.map(&:to_s) : [] unless is_single
boxes = boxes.map(&:to_s)
end
# convert the required value into a pure boolean
required = !!options[:required]
boxes.each_with_index do |box, i|
checked = (is_single ? values.present? : values.include?(box))
values -= [box] if checked && !is_single
id = nil
if options[:radiobuttons].present?
id = unique_id("#{name.to_s}_#{box}")
boxes_html += radio_button_tag(name, box, checked, id: id, required: required)
else
_name = (is_single ? name : "#{name.to_s}[#{box}]")
id = unique_id(_name)
boxes_html += check_box_tag(_name, 1, checked, data: { toggles: options[:toggles] }.compact, id: id, required: required)
end
# we only need the required attribute on one element
required = false
if labels.present?
label = labels[i]
elsif is_single
label = _(label_key.to_s)
elsif box.is_a?(Integer)
label = I18n.t(label_key.to_s)[box]
else
label = _("#{label_key.to_s}.#{box}")
end
boxes_html += label_tag(id, label)
end
if options[:other].present? && !is_single
id = nil
if options[:radiobuttons].present?
id = unique_id("#{name.to_s}_other")
boxes_html += radio_button_tag(name, :other, values.present?, id: id)
else
_name = "#{name.to_s}[other]"
id = unique_id(_name)
boxes_html += check_box_tag(_name, 1, values.present?, id: id)
end
boxes_html += label_tag id,
content_tag(:div,
text_field_tag("other_#{name.to_s}", values.first, placeholder: (_"#{label_key}.other"), required: values.present?),
class: 'other')
end
html += content_tag(:fieldset, content_tag(:div, boxes_html.html_safe,
class: [
'check-box-field',
'input-field',
options[:vertical] ? 'vertical' : nil,
options[:inline] ? 'inline' : nil,
options[:small] ? 'small' : nil,
options[:big] ? 'big' : nil
].compact).html_safe,
aria: {
labelledby: label_id,
describedby: description_id
},
class: [
options[:centered] ? 'centered' : nil,
options[:right_help] ? 'right-help' : nil
].compact
)
html += help if help.present? && options[:right_help]
return html.html_safe
end
def button(value = nil, options = {}, &block)
if !block_given? && (value.nil? || value.is_a?(Symbol))
return button_tag(I18n.t("forms.actions.generic.#{(value || :button)}"), options)
end
button_tag(value, options, &block)
end
def conference_days_options(conference = nil)
conference ||= @this_conference || @conference
return [] unless conference
dates = []
day = conference.start_date - 7.days
last_day = conference.end_date + 7.days
while day <= last_day
dates << day
day += 1.day
end
return dates
end
def conference_days_options_list(period, conference = nil, format = nil)
conference ||= @this_conference || @conference
return [] unless conference
days = []
conference_days_options(conference).each do |day|
belongs_to_periods = []
belongs_to_periods << :before if day <= conference.start_date
belongs_to_periods << :after if day >= conference.end_date
belongs_to_periods << :before_plus_one if day <= (conference.start_date + 1.day)
belongs_to_periods << :after_minus_one if day >= (conference.end_date - 1.day)
belongs_to_periods << :during if day >= conference.start_date && day <= conference.end_date
days << [date(day.to_date, format || :span_same_year_date_1), day.to_date] if belongs_to_periods.include?(period)
end
return days
end
def registration_status_options_list(conference = nil)
conference ||= @this_conference || @conference
return [] unless conference
options = Array.new
[:closed, :pre, :open].each do | opt |
options << [(_"forms.labels.generic.registration_statuses.#{opt}"), opt]
end
return options
end
def month_select(value = nil, args = {})
options = (1..12).to_a.map { |month| [ (I18n.t "date.#{args[:format] || 'month_names'}")[month], month ] }
selectfield args[:name] || :month, value, options, args
end
def month_day_select(value = nil, args = {})
options = (1..31).to_a.map { |day| [ day, day ] }
selectfield args[:name] || :month_day, value, options, args
end
def day_select(value = nil, args = {})
selectfield :day, value, conference_days_options_list(:during, nil, args[:format]), args
end
def hour_select(value = nil, args = {}, start_time = 8, end_time = 23.5, step = 0.5)
time = start_time
times = []
while time <= end_time
times << [time(DateTime.now.midnight + time.hours), time]
time += step
end
selectfield :time, value, times, args
end
def length_select(value = nil, args = {}, min_length = 0.5, max_length = 6, step = 0.5)
length = min_length
lengths = []
while length <= max_length
lengths << [time_length(length), length]
length += step
end
selectfield :time_span, value, lengths, args
end
def contact_reason_select
reasons = []
[:website, :conference].each do | reason |
reasons << [ _("forms.labels.generic.reasons.#{reason.to_s}"), reason ]
end
[['Something about the website', :website]]
selectfield :reason, nil, reasons, required: true, heading: 'articles.contact.headings.reason', label: false, full: true
end
def block_select(value = nil, args = {})
blocks = {}
@workshop_blocks.each_with_index do | info, block |
info['days'].each do | day |
blocks[(day.to_i * 10) + block] = [ "#{(I18n.t 'date.day_names')[day.to_i]} Block #{block + 1}", "#{day}:#{block}" ]
end
end
selectfield :workshop_block, value, blocks.sort.to_h.values, args
end
def location_select(value = nil, args = {})
locations = []
if @this_conference.event_locations.present?
@this_conference.event_locations.each do | location |
locations << [ location.title, location.id ] unless ((args[:invalid_locations] || []).include? location.id)
end
end
selectfield :event_location, value, locations, args
end
def location_name(id)
begin
location = EventLocation.find(id)
rescue
return ''
end
return '' unless location.present?
return location.title
end
def host_options_list(hosts)
options = [[nil, nil]]
hosts.each do | id, registration |
options << [registration.user.name, id]
end
return options
end
def registration_step_menu
steps = current_registration_steps(@registration)
return '' unless steps.present? && steps.length > 1
pre_registration_steps = ''
post_registration_steps = ''
post_registration = false
steps.each do | step |
text = _"articles.conference_registration.headings.#{step[:name].to_s}"
if step[:name] == :workshops
post_registration = true
end
h = content_tag :li, class: [step[:enabled] ? :enabled : nil, @register_template == step[:name] ? :current : nil, post_registration ? :post : :pre].compact do
if step[:enabled]
content_tag :div, (link_to text, register_step_path(@this_conference.slug, step[:name])).html_safe, class: :step
else
content_tag :div, text, class: :step
end
end
if post_registration
post_registration_steps += h.html_safe
else
pre_registration_steps += h.html_safe
end
end
html = (
row class: 'flow-steps' do
columns do
(content_tag :ul, id: 'registration-steps' do
pre_registration_steps.html_safe +
post_registration_steps.html_safe
end).html_safe
end
end
)
return html.html_safe
end
def broadcast_options(conference = nil)
conference ||= @this_conference || @conference
options = [
:registered,
:pre_registered,
:workshop_facilitators,
:unregistered,
:housing_providers,
:guests,
:all
]
if conference.registration_status != :open
options -= [:registered, :guests]
options -= [:pre_registered] unless conference.registration_status != :pre
end
return options
end
def show_errors(field, value = nil)
return '' unless @errors && @errors[field].present?
error_txt = _"errors.messages.fields.#{field.to_s}.#{@errors[field]}", :s, vars: { value: value }
content_tag(:div, error_txt, class: 'field-error').html_safe
end
private
def _original_content(value, lang)
content_tag(:div, (
content_tag(:h4, _('translate.content.Translation_of')) +
content_tag(:div, value, class: 'value', lang: lang)
).html_safe, class: 'original-text')
end
end

100
app/helpers/geocoder_helper.rb

@ -0,0 +1,100 @@
module GeocoderHelper
def lookup_ip
if request.remote_ip == '127.0.0.1' || request.remote_ip == '::1'
session['remote_ip'] || (session['remote_ip'] = open("http://checkip.dyndns.org").first.gsub(/^.*\s([\d\.]+).*$/s, '\1').gsub(/[^\.\d]/, ''))
else
request.remote_ip
end
end
def get_remote_location
Geocoder.search(session['remote_ip'] || (session['remote_ip'] = open("http://checkip.dyndns.org").first.gsub(/^.*\s([\d\.]+).*$/s, '\1').gsub(/[^\.\d]/, '')), language: 'en').first
end
def lookup_ip_location
begin
if is_test? && ApplicationController::get_location.present?
Geocoder.search(ApplicationController::get_location, language: 'en').first
elsif request.remote_ip == '127.0.0.1' || request.remote_ip == '::1'
get_remote_location
else
request.location || get_remote_location
end
rescue
nil
end
end
def potential_provider(registration)
return false unless registration.present? && registration.city.present? && registration.conference.present?
conditions = registration.conference.provider_conditions ||
Conference.default_provider_conditions
return city_distance_less_than(registration.conference.city, registration.city,
conditions['distance']['number'], conditions['distance']['unit'])
end
def city_distance_less_than(city1, city2, max_distance, unit)
return false if city1.nil? || city2.nil?
return true if city1.id == city2.id
return false if max_distance < 1
return Geocoder::Calculations.distance_between(
[city1.latitude, city1.longitude], [city2.latitude, city2.longitude],
units: unit.to_sym) < max_distance
end
def location(location, locale = I18n.locale)
return nil if location.blank?
city = nil
region = nil
country = nil
if location.is_a?(Location) || location.is_a?(City)
country = location.country
region = location.territory
city = location.city
elsif location.data.present? && location.data['address_components'].present?
component_map = {
'locality' => :city,
'administrative_area_level_1' => :region,
'country' => :country
}
location.data['address_components'].each do | component |
types = component['types']
country = component['short_name'] if types.include? 'country'
region = component['short_name'] if types.include? 'administrative_area_level_1'
city = component['long_name'] if types.include? 'locality'
end
else
country = location.data['country_code']
region = location.data['region_code']
city = location.data['city']
end
# we need cities for our logic, don't let this continue if we don't have one
return nil unless city.present?
hash = Hash.new
region_translation = region.present? && country.present? ? _("geography.subregions.#{country}.#{region}", locale: locale) : ''
country_translation = country.present? ? _("geography.countries.#{country}", locale: locale) : ''
hash[:city] = _!(city) if city.present?
hash[:region] = region_translation if region_translation.present?
hash[:country] = country_translation if country_translation.present?
# return the formatted location or the first value if we only have one value
return hash.length > 1 ? _("geography.formats.#{hash.keys.join('_')}", locale: locale, vars: hash) : hash.values.first
end
def location_link(location)
return '' unless location.present? && location.address.present?
content_tag(:a, (_!location.address), href: "http://www.google.com/maps/place/#{location.latitude},#{location.longitude}")
end
def same_city?(location1, location2)
return false unless location1.present? && location2.present?
location1 = location(location1) unless location1.is_a?(String)
location2 = location(location2) unless location2.is_a?(String)
location1.eql? location2
end
end

74
app/helpers/i18n_helper.rb

@ -0,0 +1,74 @@
module I18nHelper
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 date(date, format = :long)
I18n.l(date.is_a?(String) ? Date.parse(date) : date, :format => format)
end
def time(time, format = :short)
if time.is_a?(String)
time = Date.parse(time)
elsif time.is_a?(Float) || time.is_a?(Integer)
time = DateTime.now.midnight + time.hours
end
I18n.l(time, format: format)
end
def date_span(date1, date2)
key = 'same_month'
if date1.year != date2.year
key = 'different_year'
elsif date1.month != date2.month
key = 'same_year'
end
d1 = I18n.l(date1.to_date, format: "span_#{key}_date_1".to_sym)
d2 = I18n.l(date2.to_date, format: "span_#{key}_date_2".to_sym)
_('date.date_span', vars: {:date_1 => d1, :date_2 => d2})
end
def time_length(length)
hours = length.to_i
minutes = ((length - hours) * 60).to_i
hours = hours > 0 ? (I18n.t 'datetime.distance_in_words.x_hours', count: hours) : nil
minutes = minutes > 0 ? (I18n.t 'datetime.distance_in_words.x_minutes', count: minutes) : nil
return hours.present? ? (minutes.present? ? (I18n.t 'datetime.distance_in_words.x_and_y', x: hours, y: minutes) : hours) : minutes
end
def hour_span(time1, time2)
(time2 - time1) / 3600
end
def hours(time1, time2)
time_length hour_span(time1, time2)
end
def money(amount)
return _!('$0.00') if amount == 0
_!((amount * 100).to_i.to_s.gsub(/^(.*)(\d\d)$/, '$\1.\2'))
end
def percent(p)
return _!('0.00%') if p == 0
_!((p * 10000).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2%'))
end
end

88
app/helpers/page_helper.rb

@ -0,0 +1,88 @@
module PageHelper
@@no_banner = true
@@banner_image = nil
@@has_content = true
@@body_class = nil
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
content_for(:banner_image) { banner_image.to_s }
end
def has_content?
@@has_content
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?
"<script>#{@_inline_scripts.join("\n")}</script>".html_safe
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 << 'no-content' unless @@has_content
classes << 'has-banner-image' if @@banner_image
classes << @@body_class.join(' ') if @@body_class
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
end

30
app/helpers/registration_helper.rb

@ -1,4 +1,16 @@
module RegistrationHelper module RegistrationHelper
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 current_registration_steps(registration = @registration) def current_registration_steps(registration = @registration)
return nil unless registration.present? return nil unless registration.present?
@ -6,7 +18,6 @@ module RegistrationHelper
current_steps = [] current_steps = []
disable_steps = false disable_steps = false
completed_steps = registration.steps_completed || [] completed_steps = registration.steps_completed || []
# registration_complete = registration_complete?(registration)
if potential_provider(registration) if potential_provider(registration)
steps -= [:questions] steps -= [:questions]
@ -14,24 +25,29 @@ module RegistrationHelper
steps -= [:hosting] steps -= [:hosting]
end end
steps.each do | step | steps -= [:payment] unless registration.conference.paypal_email_address.present? && registration.conference.paypal_username.present? && registration.conference.paypal_password.present? && registration.conference.paypal_signature.present?
steps -= [:payment, :workshops] if registration.is_attending == 'n'
steps.each do |step|
# disable the step if we've already found an incomplete step # disable the step if we've already found an incomplete step
enabled = !disable_steps# || registration_complete # enabled = !disable_steps# || registration_complete
# record whether or not we've found an incomplete step # record whether or not we've found an incomplete step
disable_steps ||= !completed_steps.include?(step.to_s) && ![:payment, :workshops].include?(step)
current_steps << { current_steps << {
name: step, name: step,
enabled: enabled enabled: !disable_steps
} }
disable_steps ||= !completed_steps.include?(step.to_s)# && ![:payment, :workshops].include?(step)
end end
return current_steps return current_steps
end end
def current_step(registration = @registration) def current_step(registration = @registration)
completed_steps = registration.steps_completed || [] completed_steps = registration.steps_completed || []
last_step = nil last_step = nil
(current_registration_steps(registration) || []).each do | step | steps = current_registration_steps(registration) || []
steps.each do | step |
# return the last enabled step if this one is disabled # return the last enabled step if this one is disabled
return last_step unless step[:enabled] return last_step unless step[:enabled]
@ -43,6 +59,6 @@ module RegistrationHelper
end end
# if all else fails, return the first step # if all else fails, return the first step
return registration_steps(registration.conference).last return steps.last[:name]
end end
end end

366
app/helpers/table_helper.rb

@ -0,0 +1,366 @@
module TableHelper
def html_edit_table(excel_data, options = {})
attributes = { class: options[:class], id: options[:id] }
attributes[:data] = { 'update-url' => options[:editable] } if options[:editable].present?
if options[:column_names].is_a? Hash
return content_tag(:table, attributes) do
max_columns = 0
column_names = {}
(content_tag(:thead) do
headers = ''
options[:column_names].each do | header_name, columns |
column_names[header_name] ||= []
headers += content_tag(:th, excel_data[:keys][header_name].present? ? _(excel_data[:keys][header_name]) : '', colspan: 2)
row_count = columns.size
columns.each do | column |
column_names[header_name] << column
if (options[:row_spans] || {})[column].present?
row_count += (options[:row_spans][column] - 1)
for i in 1...options[:row_spans][column]
column_names[header_name] << false
end
end
end
max_columns = row_count if row_count > max_columns
end
content_tag(:tr, headers.html_safe)
end) + (content_tag(:tbody) do
rows = ''
for i in 0...max_columns
columns_html = ''
column_names.each do | header_name, columns |
column = columns[i]
if column.present?
attributes = { class: [excel_data[:column_types][column]], data: { 'column-id' => column } }
if (options[:row_spans] || {})[column].present?
attributes[:rowspan] = options[:row_spans][column]
end
columns_html += content_tag(:th, excel_data[:keys][column].present? ? _(excel_data[:keys][column]) : '', rowspan: attributes[:rowspan]) +
edit_column(nil, column, nil, attributes, excel_data, options)
elsif column != false
columns_html += content_tag(:td, ' ', colspan: 2, class: :empty)
end
end
rows += content_tag(:tr, columns_html.html_safe, { class: 'always-edit', data: { key: '' } })
end
rows.html_safe
end)
end
else
return content_tag(:table, attributes) do
(content_tag(:tbody) do
rows = ''
excel_data[:columns].each do |column|
if (excel_data[:column_types] || {})[column] != :table && ((options[:column_names] || []).include? column)
rows += content_tag(:tr, { class: 'always-edit', data: { key: '' } }) do
attributes = { class: [excel_data[:column_types][column]], data: { 'column-id' => column } }
columns = content_tag(:th, excel_data[:keys][column].present? ? _(excel_data[:keys][column]) : '') +
edit_column(nil, column, nil, attributes, excel_data, options)
end
end
end
rows.html_safe
end)
end
end
end
def html_table(excel_data, options = {})
options[:html] = true
attributes = { class: options[:class], id: options[:id] }
attributes[:data] = { 'update-url' => options[:editable] } if options[:editable].present?
content_tag(:table, attributes) do
(content_tag(:thead) do
content_tag(:tr, excel_header_columns(excel_data))
end) +
content_tag(:tbody, excel_rows(excel_data, {}, options))
end
end
def excel_table(excel_data)
format_xls 'table' do
workbook use_autowidth: true
format bg_color: '333333'
format 'td', font_name: 'Calibri', fg_color: '333333'
format 'th', font_name: 'Calibri', b: true, bg_color: '333333', fg_color: 'ffffff'
format 'th.sub-table', font_name: 'Calibri', b: true, bg_color: 'DDDDDD', fg_color: '333333'
format 'td.datetime', num_fmt: 22, font_name: 'Courier New', sz: 10, fg_color: '333333'
format 'td.date.day', num_fmt: 14, font_name: 'Courier New', sz: 10, fg_color: '333333'
format 'td.money', num_fmt: 2, font_name: 'Courier New', sz: 10, fg_color: '333333'
format 'td.number', font_name: 'Courier New', sz: 10, fg_color: '333333'
format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true
end
content_tag(:table) do
(content_tag(:thead) do
content_tag(:tr, excel_header_columns(excel_data))
end) +
content_tag(:tbody, excel_rows(excel_data))
end
end
def excel_header_columns(data, padding = {}, class_name = nil)
columns = ''
data[:columns].each do |column|
unless data[:column_types].present? && data[:column_types][column] == :table
columns += content_tag(:th, data[:keys][column].present? ? _(data[:keys][column]) : '', class: class_name)
end
end
pad_columns(columns, padding, :th)
end
def excel_empty_row(data, padding = {})
columns = ''
data[:columns].each do |column|
unless data[:column_types].present? && data[:column_types][column] == :table
columns += content_tag(:td)
end
end
content_tag(:tr, pad_columns(columns, padding))
end
def pad_columns(columns, padding, column_type = :td)
left = ''
for i in 1..(padding['left'] || 0)
left += content_tag(:td)
end
right = ''
for i in 1..(padding['right'] || 0)
right += content_tag(:td)
end
(left + columns + right).html_safe
end
def excel_columns(row, data, padding = {}, options = {})
columns = ''
data[:columns].each do |column|
value = row[column].present? ? (_!row[column].to_s) : ''
class_name = nil
is_sub_table = false
if data[:column_types].present? && data[:column_types][column].present?
if data[:column_types][column] == :table
is_sub_table = true
else
class_name = data[:column_types][column]
end
end
unless is_sub_table
attributes = { class: [class_name] }
if options[:html] && row[:html_values].present? && row[:html_values][column].present?
value = row[:html_values][column]
end
if options[:editable]
attributes[:data] = { 'column-id' => column }
end
if (options[:column_names] || []).include? column
attributes[:tabindex] = 0
end
columns += content_tag(:td, value, attributes)
end
end
pad_columns(columns, padding)
end
def editor_columns(row, data, padding = {}, options = {})
columns = ''
data[:columns].each do |column|
value = row[column].present? ? (_!row[column].to_s) : ''
class_name = nil
is_sub_table = false
if data[:column_types].present? && data[:column_types][column].present?
if data[:column_types][column] == :table
is_sub_table = true
else
class_name = data[:column_types][column]
end
end
unless is_sub_table
attributes = { class: [class_name] }
if options[:editable]
attributes[:data] = { 'column-id' => column }
end
if (options[:column_names] || []).include? column
columns += edit_column(row, column, value, attributes, data, options)
else
columns += content_tag(:td, value, attributes)
end
end
end
pad_columns(columns, padding)
end
def edit_column(row, column, value, attributes, data, options)
attributes[:class] << 'has-editor'
raw_value = row.present? ? (row[:raw_values][column] || value) : nil
if row.present? && options[:html] && row[:html_values].present? && row[:html_values][column].present?
value = row[:html_values][column]
end
editor_attributes = { class: 'cell-editor', data: { value: raw_value.to_s } }
# create the control but add the original value to set the width and height
editor_value = content_tag(:div, value, class: 'value')
if (options[:column_options] || {})[column].present?
value = (editor_value.html_safe + select_tag(column, options_for_select([['', '']] + options[:column_options][column], raw_value), editor_attributes)).html_safe
elsif data[:column_types][column] == :text
editor_attributes[:name] = column
value = (editor_value.html_safe + content_tag(:textarea, raw_value, editor_attributes)).html_safe
else
editor_attributes[:name] = column
editor_attributes[:value] = raw_value
editor_attributes[:required] = :required if (options[:required_columns] || []).include? column
type = data[:column_types][column] || :unknown
editor_attributes[:type] = { money: :number, number: :number, email: :email }[type] || :text
value = (editor_value.html_safe + content_tag(:input, nil, editor_attributes)).html_safe
end
return content_tag(:td, value, attributes)
end
def excel_sub_tables(row, data, padding = {}, options = {})
rows = ''
# shift the table right
new_padding = {
'left' => (padding['right'] || 0) + 1,
'right' => (padding['right'] || 0) - 1
}
data[:columns].each do |column|
if data[:column_types].present? && data[:column_types][column] == :table
rows += content_tag(:tr, excel_header_columns(row[column], new_padding, 'sub-table'))
rows += excel_rows(row[column], new_padding)
rows += excel_empty_row(row[column], new_padding)
end
end
rows.html_safe
end
def excel_rows(data, padding = {}, options = {})
rows = ''
data[:data].each do |row|
attributes = {}
if options[:primary_key].present?
attributes[:data] = { key: row[options[:primary_key]] }
end
attributes[:class] = []
if options[:editable]
attributes[:class] << :editable
end
rows += content_tag(:tr, excel_columns(row, data, padding, options), attributes) +
excel_sub_tables(row, data, padding)
rows += content_tag(:tr, editor_columns(row, data, padding, options), class: :editor) if options[:editable]
end
rows.html_safe
end
def registrations_edit_table_options
{
id: 'create-table',
class: ['registrations', 'admin-edit', 'always-editing'],
primary_key: :id,
column_names: {
contact_info: [
:name,
:email,
:is_subscribed,
:city,
:preferred_language
] + User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym },
questions: [
:registration_fees_paid,
:is_attending,
:arrival,
:departure,
:housing,
:bike,
:food,
:companion_email,
:allergies,
:other
],
hosting: [
:can_provide_housing,
:address,
:phone,
:first_day,
:last_day
] + ConferenceRegistration.all_spaces +
ConferenceRegistration.all_considerations + [
:notes
]
},
row_spans: {
allergies: 3,
other: 2
},
required_columns: [:name, :email],
editable: administration_update_path(@this_conference.slug, @admin_step),
column_options: @column_options
}
end
def registrations_table_options
{
id: 'search-table',
class: ['registrations', 'admin-edit'],
primary_key: :id,
column_names: [
:registration_fees_paid,
:is_attending,
:is_subscribed,
:city,
:preferred_language,
:arrival,
:departure,
:housing,
:bike,
:food,
:companion_email,
:allergies,
:other,
:can_provide_housing,
:address,
:phone,
:first_day,
:last_day,
:notes
] +
User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } +
ConferenceRegistration.all_spaces +
ConferenceRegistration.all_considerations,
editable: administration_update_path(@this_conference.slug, @admin_step),
column_options: @column_options
}
end
end

288
app/helpers/widgets_helper.rb

@ -0,0 +1,288 @@
require 'redcarpet'
module WidgetsHelper
def m(*args)
_(*args) { |t|
markdown(t)
}
end
def markdown(object, attribute = nil)
return '' unless object
content = attribute ? object.send(attribute.to_s) : object
@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML.new({
filter_html: true,
hard_wrap: true,
space_after_headers: true,
fenced_code_blocks: true,
link_attributes: { target: "_blank" }
}), {
autolink: true,
disable_indented_code_blocks: true,
superscript: true
})
@markdown.render(content).html_safe
end
def paragraph(object, attribute = nil)
return '' unless object
content = attribute ? object.send(attribute.to_s) : object
result = ''
if content =~ /<(p|span|h\d|div)[^>]*>/
result = content.gsub(/\s*(style|class|id|width|height|font)=\".*?\"/, '')
.gsub(/&nbsp;/, ' ')
.gsub(/<(\/)?\s*h\d\s*>/, '<\1h3>')
.gsub(/<p>(.*?)<br\s\/?>\s*(<br\s\/?>)+/, '<p>\1</p><p>')
.gsub(/<span[^>]*>\s*(.*?)\s*<\/span>/, '\1')
.gsub(/<p>\s*<\/p>/, '')
.gsub(/<(\/)?div>/, '<\1p>')
if !(result =~ /<p[^>]*>/)
result = '<p>' + result + '</p>'
end
else
result = markdown(object, attribute)
end
result.html_safe
end
def nav_link(link, title = nil, class_name = nil)
if title.nil? && link.is_a?(Symbol)
title = link
link = send("#{link.to_s}_path")
end
if class_name.nil? && title.is_a?(Symbol)
class_name = title
end
title = _"page_titles.#{title.to_s.titlecase.gsub(/\s/, '_')}"
classes = []
classes << class_name if class_name.present?
classes << "strlen-#{strip_tags(title).length}"
classes << 'current' if request.fullpath.start_with?(link.gsub(/^(.*?)\/$/, '\1'))
link_to "<span class=\"title\">#{title}</span>".html_safe, link, :class => classes
end
def data_set(header_type, header_key, attributes = {}, &block)
raw_data_set(header_type, _(header_key), attributes, &block)
end
def raw_data_set(header_type, header, attributes = {}, &block)
attributes[:class] = attributes[:class].split(' ') if attributes[:class].is_a?(String)
attributes[:class] = [attributes[:class].to_s] if attributes[:class].is_a?(Symbol)
attributes[:class] ||= []
attributes[:class] << 'data-set'
content_tag(:div, attributes) do
content_tag(header_type, header, class: 'data-set-key') +
content_tag(:div, class: 'data-set-value', &block)
end
end
def admin_update_form(options = {}, &block)
form_tag(administration_update_path(@this_conference.slug, @admin_step), options, &block)
end
def interest_button(workshop)
interested = workshop.interested?(current_user) ? :remove_interest : :show_interest
id = "#{interested.to_s.gsub('_', '-')}-#{workshop.id}"
return (off_screen (_"forms.actions.aria.#{interested.to_s}"), id) +
(button interested, :value => :toggle_interest, :class => (workshop.interested?(current_user) ? :delete : :add), aria: { labelledby: id })
end
def interest_text(workshop)
if workshop.interested?(current_user)
return _'articles.workshops.info.you_are_interested_count', :vars => {:count => (workshop.interested_count - 1)}
end
return _'articles.workshops.info.interested_count', :vars => {:count => workshop.interested_count}
end
def host_guests_table(registration)
id = registration.id
html = ''
@housing_data[id][:guests].each do | area, guests |
guest_rows = ''
guests.each do | guest_id, guest |
status_html = ''
@housing_data[id][:guest_data][guest_id][:errors].each do | error, value |
if value.is_a?(Array)
value.each do | v |
status_html += content_tag(:li, _("errors.messages.housing.space.#{error.to_s}", vars: v))
end
else
status_html += content_tag(:li, _("errors.messages.housing.space.#{error.to_s}", vars: value))
end
end
@housing_data[id][:guest_data][guest_id][:warnings].each do | error, value |
if value.is_a?(Array)
value.each do | v |
status_html += content_tag(:li, _("warnings.messages.housing.space.#{error.to_s}", v))
end
else
status_html += content_tag(:li, _("warnings.messages.housing.space.#{error.to_s}", vars: value))
end
end
if status_html.present?
status_html = content_tag(:ul, status_html.html_safe)
end
guest_rows += content_tag :tr, id: "hosted-guest-#{guest_id}" do
(content_tag :td, guest[:guest].user.name) +
(content_tag :td do
(guest[:guest].city +
(content_tag :a, (_'actions.workshops.Remove'), href: '#', class: 'remove-guest', data: { guest: guest_id })).html_safe
end) +
(content_tag :td, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy])
end
end
space_size = (@housing_data[id][:space][area] || 0)
# add empty rows to represent empty guest spots
for i in guests.size...space_size
guest_rows += content_tag :tr, class: 'empty-space' do
(content_tag :td, '&nbsp'.html_safe, colspan: 2) +
(content_tag :td)
end
end
status_html = ''
if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present?
@housing_data[id][:warnings][:space][area].each do | w |
status_html += content_tag(:li, _("warnings.messages.housing.space.#{w.to_s}"))
end
end
if status_html.present?
status_html = content_tag(:ul, status_html.html_safe)
end
html += content_tag :tr do
(content_tag :th, (_"forms.labels.generic.#{area}"), colspan: 2) +
(content_tag :th, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy])
end
html += guest_rows
html += content_tag :tr, class: 'place-guest' do
content_tag :td, class: guests.size >= space_size ? 'full' : nil, colspan: 3 do
content_tag :a, (_'forms.actions.generic.place_guest'), class: 'select-guest', href: '#', data: { host: id, space: area }
end
end
end
content_tag :table, html.html_safe, class: 'host-table'
end
def host_guests_widget(registration)
html = ''
classes = ['host']
id = registration.id
@housing_data[id][:guests].each do | area, guests |
max_space = @housing_data[id][:space][area] || 0
area_name = (_"forms.labels.generic.#{area}")
status_html = ''
if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present?
@housing_data[id][:warnings][:space][area].each do | w |
status_html += content_tag(:div, _("warnings.housing.space.#{w.to_s}"), class: 'warning')
end
end
space_html = content_tag(:h5, area_name + _!(" (#{guests.size.to_s}/#{max_space.to_s})") + status_html.html_safe)
guest_items = ''
guests.each do | guest_id, guest |
guest_items += content_tag(:li, guest[:guest].user.name, id: "hosted-guest-#{guest_id}")
end
space_html += content_tag(:ul, guest_items.html_safe)
space_html += button :place_guest, type: :button, value: "#{area}:#{id}", class: [:small, 'place-guest', 'on-top-only', guests.size >= max_space ? (guests.size > max_space ? :overbooked : :booked) : nil, max_space > 0 ? nil : :unwanted]
html += content_tag(:div, space_html, class: [:space, area, max_space > 0 || guests.size > 0 ? nil : 'on-top-only'])
end
classes << 'status-warning' if @housing_data[id][:warnings].present?
classes << 'status-error' if @housing_data[id][:errors].present?
return { html: html.html_safe, class: classes.join(' ') }
end
def signin_link
@login_dlg ||= true
link_to (_'forms.actions.generic.login'), settings_path, data: { 'sign-in': true }
end
def link_with_confirmation(link_text, confirmation_text, path, args = {})
@confirmation_dlg ||= true
args[:data] ||= {}
args[:data][:confirmation] = true
link_to path, args do
(link_text.to_s + content_tag(:template, confirmation_text, class: 'message')).html_safe
end
end
def link_info_dlg(link_text, info_text, info_title, args = {})
@info_dlg ||= true
args[:data] ||= {}
args[:data]['info-title'] = info_title
args[:data]['info-text'] = true
content_tag(:a, args) do
(link_text.to_s + content_tag(:template, info_text, class: 'message')).html_safe
end
end
def button_with_confirmation(button_name, confirmation_text = nil, args = {})
if confirmation_text.is_a? Hash
args = confirmation_text
confirmation_text = nil
end
confirmation_text ||= (_"forms.confirmations.#{button_name.to_s}", :p)
@confirmation_dlg ||= true
args[:data] ||= {}
args[:data][:confirmation] = true
button button_name, args do
((_"forms.actions.generic.#{button_name.to_s}") + content_tag(:template, confirmation_text, class: 'message')).html_safe
end
end
def richtext(text, reduce_headings = 2)
return '' unless text.present?
return _!(text).
gsub(/<(\/?)h4>/, '<\1h' + (reduce_headings + 4).to_s + '>').
gsub(/<(\/?)h3>/, '<\1h' + (reduce_headings + 3).to_s + '>').
gsub(/<(\/?)h2>/, '<\1h' + (reduce_headings + 2).to_s + '>').
gsub(/<(\/?)h1>/, '<\1h' + (reduce_headings + 1).to_s + '>').
html_safe
end
def truncate(text)
strip_tags(text.gsub('>', '> ')).gsub(/^(.{40,60})\s.*$/m, '\1&hellip;').html_safe
end
def companion(registration)
if registration.housing_data.present? && registration.housing_data['companions'].present? && registration.housing_data['companions'].first.present?
companion_user = User.find_user(registration.housing_data['companions'].first)
if companion_user.present?
cr = ConferenceRegistration.where(user_id: companion_user.id).order(created_at: :desc).limit(1).first
if cr.present? && ((cr.steps_completed || []).include? 'questions')
return companion_user
end
end
return :unregistered
end
return nil
end
def comment(comment)
add_inline_script :time
add_js_translation('datetime.distance_in_words')
content_tag(:div, class: 'comment-body') do
content_tag(:h4, _!(comment.user.name), class: 'comment-title') +
content_tag(:time, time(comment.created_at, :default), datetime: comment.created_at.to_s) +
content_tag(:div, class: 'comment-text') do
_!(markdown comment.comment)
end
end
end
end

4
app/mailers/user_mailer.rb

@ -1,12 +1,12 @@
require 'diffy' require 'diffy'
class UserMailer < ActionMailer::Base class UserMailer < ActionMailer::Base
add_template_helper(ApplicationHelper)
include LinguaFrancaHelper include LinguaFrancaHelper
add_template_helper(ApplicationHelper)
before_filter :set_host before_filter :set_host
default from: "Bike!Bike! <noreply@bikebike.org>" default from: "Bike!Bike! <godwin@bikebike.org>"
def email_confirmation(confirmation) def email_confirmation(confirmation)
@confirmation = EmailConfirmation.find(confirmation) if confirmation.present? @confirmation = EmailConfirmation.find(confirmation) if confirmation.present?

3
app/models/authentication.rb

@ -1,3 +0,0 @@
class Authentication < ActiveRecord::Base
belongs_to :user
end

166
app/models/city.rb

@ -1,166 +0,0 @@
require 'geocoder'
require 'geocoder/railtie'
require 'geocoder/calculations'
Geocoder::Railtie.insert
class City < ActiveRecord::Base
geocoded_by :address
translates :city
reverse_geocoded_by :latitude, :longitude, :address => :full_address
after_validation :geocode, if: ->(obj){ obj.country_changed? or obj.territory_changed? or obj.city_changed? or obj.latitude.blank? or obj.longitude.blank? }
def address
([city!, territory, country] - [nil, '']).join(', ')
end
def get_translation(locale)
location = Geocoder.search(address, language: locale.to_s).first
# if the service lets us down, return nil
return nil unless location.present?
searched_component = false
location.data['address_components'].each do | component |
# city is usually labeled a 'locality' but sometimes this is missing and only 'colloquial_area' is present
if component['types'].first == 'locality'
return component['short_name']
end
if component['types'] == location.data['types']
searched_component = component['short_name']
end
end
# return the type we searched for but it's still possible that it will be false
searched_component
end
# this method will get called automatically if a translation is asked for but not found
def translate_city(locale)
translation = get_translation(locale)
# if we found it, set it
if translation.present?
set_column_for_locale(:city, locale, translation)
save!
end
return translation
end
def to_s
([
city,
territory.present? && country.present? ? I18n.t("geography.subregions.#{country}.#{territory}") : '',
country.present? ? I18n.t("geography.countries.#{country}") : ''
] - ['', nil]).join(', ')
end
def self.search(str)
cache = CityCache.search(str)
# return the city if this search is in our cache
return cache.city if cache.present?
# look up the city in the geocoder
location = Geocoder.search(str, language: 'en').first
# return nil to indicate that the service is down
return nil unless location.present?
# see if the city is already present in our database
city = City.find_by_place_id(location.data['place_id'])
# if we didn't find a match by place id, collect the city, territory, and country from the result
unless city.present?
# google names things differently than we do, we'll look for these items
component_alises = {
'locality' => :city,
'administrative_area_level_1' => :territory,
'country' => :country
}
# and populate this map to eventually create the city if we need to
city_data = {
locale: :en,
latitude: location.data['geometry']['location']['lat'],
longitude: location.data['geometry']['location']['lng'],
place_id: location.data['place_id']
}
# these things are definitely not cities, make sure we don't think they're one
not_a_city = [
'administrative_area_level_1',
'country',
'street_address',
'street_number',
'postal_code',
'postal_code_prefix',
'route',
'intersection',
'premise',
'subpremise',
'natural_feature',
'airport',
'park',
'point_of_interest',
'bus_station',
'train_station',
'transit_station',
'room',
'post_box',
'parking',
'establishment',
'floor'
]
searched_component = nil
location.data['address_components'].each do | component |
property = component_alises[component['types'].first]
city_data[property] = component['short_name'] if property.present?
# ideally we will find the component that is labeled a locality but
# if that fails we will select what was searched for, hopefully they searched for a city
# and not an address or country
# some places are not labeled 'locality', search for 'Halifax NS' for example and you will
# get 'administrative_area_level_2' since Halifax is a municipality
if component['types'] == location.data['types'] && !not_a_city.include?(component['types'].first)
searched_component = component['short_name']
end
end
# fall back to the searched component
city_data[:city] ||= searched_component
# we need to have the city and country at least
return false unless city_data[:city].present? && city_data[:country].present?
# one last attempt to make sure we don't already have a record of this city
city = City.where(city: city_data[:city], territory: city_data[:territory], country: city_data[:country]).first
# only if we still can't find the city, then save it as a new one
unless city.present?
city = City.new(city_data)
# if we found exactly what we were looking for, keep these location details
# otherwise we may have searched for 'The Bronx' and set the sity the 'New York' but these details will be about The Bronx
# so if we try to show New York on a map it will always point to The Bronx, not very fair to those from Staten Island
unless city_data[:city] == searched_component
new_location = Geocoder.search(str, language: 'en').first
city.latitude = new_location.data['geometry']['location']['lat']
city.longitude = new_location.data['geometry']['location']['lng']
city.place_id = new_location.data['place_id']
end
# and create the new city
city.save!
end
end
# save this to our cache
CityCache.cache(str, city.id)
# and return it
return city
end
end

21
app/models/city_cache.rb

@ -1,21 +0,0 @@
class CityCache < ActiveRecord::Base
self.table_name = :city_cache
belongs_to :city
# look for a term to see if its already been searched for
def self.search(str)
CityCache.find_by_search(normalize_string(str))
end
# cache this search term
def self.cache(str, city_id)
CityCache.create(city_id: city_id, search: normalize_string(str))
end
private
def self.normalize_string(str)
# remove accents, unnecessary whitespace, punctuation, and lowcase tje string
I18n.transliterate(str).gsub(/[^\w\s]/, '').gsub(/\s\s+/, ' ').strip.downcase
end
end

37
app/models/comment.rb

@ -1,37 +0,0 @@
class Comment < ActiveRecord::Base
belongs_to :user
def comment_object
model_type.classify.constantize.find(model_id)
end
def set_model(model)
model_type = model.class.name.tableize
model_id = model.id
end
def self.for(model)
where(model_type: model.class.name.tableize, model_id: model.id).order(created_at: :asc)
end
def self.create_for(model, user, comment)
create(
model_type: model.class.name.tableize,
model_id: model.id,
user_id: user.id,
comment: comment
)
end
def add_comment(user, comment)
Comment.create_for(self, user, comment)
end
def comments
Comment.for(self)
end
def reply?
model_type == 'comments'
end
end

160
app/models/conference.rb

@ -1,160 +0,0 @@
class Conference < ActiveRecord::Base
translates :info, :title, :payment_message
mount_uploader :cover, CoverUploader
mount_uploader :poster, PosterUploader
belongs_to :conference_type
belongs_to :city
has_many :conference_host_organizations, dependent: :destroy
has_many :organizations, through: :conference_host_organizations
has_many :conference_administrators, dependent: :destroy
has_many :administrators, through: :conference_administrators, source: :user
has_many :event_locations
has_many :workshops
accepts_nested_attributes_for :conference_host_organizations, reject_if: proc {|u| u[:organization_id].blank?}, allow_destroy: true
before_create :make_slug, :make_title
def to_param
slug
end
def host_organization?(org)
return false unless org.present?
org_id = org.is_a?(Organization) ? org.id : org
organizations.each do |o|
return true if o.id = org_id
end
return false
end
def host?(user)
if user.present?
return true if user.administrator?
conference_administrators.each do |u|
return true if user.id == u.id
end
organizations.each do |o|
return true if o.host?(user)
end
end
return false
end
def url(action = :show)
path(action)
end
def path(action = :show)
action = action.to_sym
'/conferences/' + conference_type.slug + '/' + slug + (action == :show ? '' : '/' + action.to_s)
end
def location
return nil unless organizations.present?
organizations.first.location
end
def registered?(user)
registration = ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id)
return registration ? registration.is_attending : false
end
def registration_exists?(user)
ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id).present?
end
def registration_open
registration_status == :open
end
def can_register?
registration_status == :open || registration_status == :pre
end
def registration_status
s = read_attribute(:registration_status)
s.present? ? s.to_sym : nil
end
def registration_status=(new_registration_status)
write_attribute :registration_status, new_registration_status.to_s
end
def make_slug(reset = false)
if reset
self.slug = nil
end
self.slug ||= Conference.generate_slug(
conferencetype || :annual,
conference_year,
city_name.gsub(/\s/, '')
)
end
def make_title(reset = false)
if reset
self.title = nil
end
self.title ||= Conference.generate_title(
conferencetype || :annual,
conference_year,
city_name.gsub(/\s/, '')
)
end
def city_name
return city.city if city.present?
return location.present? ? location.city : nil
end
def conference_year
self.year || (end_date.present? ? end_date.year : nil)
end
def over?
return false unless end_date.present?
return end_date < DateTime.now
end
def self.default_payment_amounts
[25, 50, 100]
end
def self.conference_types
{
annual: { slug: '%{city}%{year}', title: 'Bike!Bike! %{year}'},
n: { slug: 'North%{year}', title: 'Bike!Bike! North %{year}'},
s: { slug: 'South%{year}', title: 'Bike!Bike! South %{year}'},
e: { slug: 'East%{year}', title: 'Bike!Bike! East %{year}'},
w: { slug: 'West%{year}', title: 'Bike!Bike! West %{year}'},
ne: { slug: 'Northeast%{year}', title: 'Bike!Bike! Northeast %{year}'},
nw: { slug: 'Northwest%{year}', title: 'Bike!Bike! Northwest %{year}'},
se: { slug: 'Southeast%{year}', title: 'Bike!Bike! Southeast %{year}'},
sw: { slug: 'Southwest%{year}', title: 'Bike!Bike! Southwest %{year}'}
}
end
def self.generate_slug(type, year, city)
Conference.conference_types[(type || :annual).to_sym][:slug].gsub('%{city}', city).gsub('%{year}', year.to_s)
end
def self.generate_title(type, year, city)
Conference.conference_types[(type || :annual).to_sym][:title].gsub('%{city}', city).gsub('%{year}', year.to_s)
end
def self.default_provider_conditions
{ 'distance' => { 'number' => 0, 'unit' => 'mi' }}
end
end

2
app/models/conference_admin.rb

@ -1,2 +0,0 @@
class ConferenceAdmin < ActiveRecord::Base
end

4
app/models/conference_administrator.rb

@ -1,4 +0,0 @@
class ConferenceAdministrator < ActiveRecord::Base
belongs_to :user
belongs_to :conference
end

4
app/models/conference_host_organization.rb

@ -1,4 +0,0 @@
class ConferenceHostOrganization < ActiveRecord::Base
belongs_to :conference
belongs_to :organization
end

74
app/models/conference_registration.rb

@ -1,74 +0,0 @@
class ConferenceRegistration < ActiveRecord::Base
belongs_to :conference
belongs_to :user
has_many :conference_registration_responses
AttendingOptions = [:yes, :no]
def languages
user.languages
end
def self.all_housing_options
[:none, :tent, :house]
end
def self.all_spaces
[:bed_space, :floor_space, :tent_space]
end
def self.all_bike_options
[:yes, :no]
end
def self.all_food_options
[:meat, :vegetarian, :vegan]
end
def self.all_considerations
[:vegan, :smoking, :pets, :quiet]
end
def city
city_id.present? ? City.find(city_id) : nil
end
def status(was = false)
# our user hasn't registered if their user doesn't exist or they haven't entered a city
return :unregistered if user.nil? || check(:city, was).blank?
# registration completes once a guest has entered a housing preference or
# a housing provider has opted in or out of providing housing
return :preregistered unless
check(:housing, was).present? || !check(:can_provide_housing, was).nil?
# they must be registered
return :registered
end
around_update :check_status
def check_status
yield
old_status = status(true)
new_status = status
if old_status.present? && old_status != new_status
if (conference.registration_status == :pre && new_status == :preregistered) ||
(conference.registration_status == :open && new_status == :registered)
UserMailer.send_mail :registration_confirmation do
{
:args => self
}
end
end
end
end
private
def check(field, was)
send("#{field}#{was ? '_was' : ''}")
end
end

4
app/models/conference_registration_form_field.rb

@ -1,4 +0,0 @@
class ConferenceRegistrationFormField < ActiveRecord::Base
belongs_to :conference
belongs_to :registration_form_field
end

5
app/models/conference_registration_response.rb

@ -1,5 +0,0 @@
class ConferenceRegistrationResponse < ActiveRecord::Base
belongs_to :conference_registration
belongs_to :user
#belongs_to :conference, :through => :conference_registration
end

7
app/models/conference_type.rb

@ -1,7 +0,0 @@
class ConferenceType < ActiveRecord::Base
#belongs_to :conference
def to_param
slug
end
end

40
app/models/email_confirmation.rb

@ -1,40 +0,0 @@
class EmailConfirmation < ActiveRecord::Base
belongs_to :user
before_create :prepare
def prepare
# clean up any expired records
EmailConfirmation.delete_all(['expiry < ?', Time.now])
# fill in defaults
self.expiry ||= Time.now + 1.day
while self.token.nil? do
# create a token based on the user id and current time
self.token = generate_token
# conflicts should be extremely rare, but let's just be sure
if EmailConfirmation.exists?(:token => self.token)
self.token = nil # keep the loop going
# because we generate the token based on the time, just make sure
# some time has passed
sleep 0.1
end
end
end
def valid_for_user?(user)
user.id == user_id && !expired?
end
def expired?
expiry >= Time.now
end
protected
def generate_token
Digest::SHA256.hexdigest(user_id.to_s + (Time.now.to_f * 1000000).to_i.to_s)
end
end

20
app/models/event.rb

@ -1,20 +0,0 @@
class Event < ActiveRecord::Base
translates :info, :title
belongs_to :conference
belongs_to :event_location
def conference_day
return nil unless start_time.present? && end_time.present?
start_day = conference.start_date.change(hour: 0, minute: 0, second: 0)
w_start_day = start_time.change(hour: 0, minute: 0, second: 0)
return (((w_start_day - start_day) / 86400) + 1).to_i
end
def duration
return nil unless start_time.present? && end_time.present?
((end_time - start_time) / 60).to_i
end
end

24
app/models/event_location.rb

@ -1,24 +0,0 @@
require 'geocoder'
require 'geocoder/railtie'
Geocoder::Railtie.insert
class EventLocation < ActiveRecord::Base
belongs_to :conference
geocoded_by :full_address
reverse_geocoded_by :latitude, :longitude, :address => :full_address
after_validation :geocode, if: ->(obj){ obj.address_changed? }
def full_address
[address, conference.city.city, conference.city.territory, conference.city.country].join(', ')
end
def self.all_spaces
Workshop.all_spaces + [:event_space]
end
def self.all_amenities
Workshop.all_needs
end
end

2
app/models/event_type.rb

@ -1,2 +0,0 @@
class EventType < ActiveRecord::Base
end

21
app/models/location.rb

@ -1,21 +0,0 @@
class Location < ActiveRecord::Base
#attr_accessible :title, :country, :territory, :city, :street, :postal_code, :latitude, :longitude
has_many :locations_organization
has_many :organizations, :through => :locations_organization
geocoded_by :full_address
reverse_geocoded_by :latitude, :longitude, :address => :full_address
after_validation :geocode, if: ->(obj){ obj.country_changed? or obj.territory_changed? or obj.city_changed? or obj.street_changed? or obj.postal_code_changed? or obj.latitude.blank? or obj.longitude.blank? }
def full_address
addr = title
addr = (addr ? ', ' : '') + (street || '')
addr = (addr ? ', ' : '') + (city || '')
addr = (addr ? ', ' : '') + (territory || '')
addr = (addr ? ' ' : '') + (country || '')
addr = (addr ? ' ' : '') + (postal_code || '')
addr
end
end

6
app/models/locations_organization.rb

@ -1,6 +0,0 @@
class LocationsOrganization < ActiveRecord::Base
belongs_to :location
belongs_to :organization
self.primary_key = :location_id
end

77
app/models/organization.rb

@ -1,77 +0,0 @@
class Organization < ActiveRecord::Base
mount_uploader :logo, LogoUploader
mount_uploader :avatar, AvatarUploader
mount_uploader :cover, CoverUploader
has_many :locations_organization
has_many :locations, through: :locations_organization
has_many :user_organization_relationships, dependent: :destroy
has_many :users, through: :user_organization_relationships
accepts_nested_attributes_for :locations, :reject_if => proc {|l| l[id].blank?}
accepts_nested_attributes_for :user_organization_relationships, :reject_if => proc {|u| u[:user_id].blank?}, :allow_destroy => true
before_create :make_slug
def location
locations.first
end
def longitude
location.longitude
end
def latitude
location.latitude
end
def to_param
slug
end
def host?(user)
return false unless user.present?
return true if user.administrator?
users.each do |u|
return true if u.id == user.id
end
return false
end
def generate_slug(name, location = nil)
s = name.gsub(/[^a-z1-9]+/i, '-').chomp('-').gsub(/\-([A-Z])/, '\1')
if Organization.find_by(:slug => s).present? && !location.nil?
if location.city.present?
s += '-' + location.city
end
if Organization.find_by(:slug => s).present? && location.territory.present?
s += '-' + location.territory
end
if Organization.find_by(:slug => s).present?
s += '-' + location.country
end
end
attempt = 1
ss = s
while Organization.find_by(:slug => s)
attempt += 1
s = ss + '-' + attempt.to_s
end
s
end
def self.find_by_city(city)
Organization.joins(:locations).where(locations: {
city_id: city.is_a?(City) ? city.id : city
})
end
private
def make_slug
if !self.slug
self.slug = generate_slug(self.name, self.locations && self.locations[0])
end
end
end

2
app/models/organization_status.rb

@ -1,2 +0,0 @@
class OrganizationStatus < ActiveRecord::Base
end

75
app/models/registration_form_field.rb

@ -1,75 +0,0 @@
class RegistrationFormField < ActiveRecord::Base
Types = {
:single => [:title, :required, :input_type, :help],
:multiple => [:title, :required, :selection_type, :options, :other, :help]
}
Fields = {
:title => {:control => 'text_field'},
:input_type => {:control => 'select', :options => [[:text_field, :text_area, :number_field, :date_field, :time_field, :phone_field, :checkbox]], :option => true},
:selection_type => {:control => 'select', :options => [[:check_box, :radio_button, :select]], :option => true},
:options => {:control => 'text_area', :option => true},
:help => {:control => 'text_area'},
:other => {:control => 'check_box', :option => true},
:required => {:control => 'check_box'}
}
def self.TypesForField(field)
types = []
Types.each do |k, t|
if t.include?(field)
types << k
end
end
types
end
def input_type
get_from_options 'input_type'
end
def selection_type
get_from_options 'selection_type'
end
def other
get_from_options 'other'
end
def self.GetOptions(type, values)
o = {}
Fields.each do |k, f|
if f[:option] && Types[type.to_sym].include?(k)
o[k] = values[k]
end
end
o
end
def self.GetNonOptionKeys(type, values)
o = []
Fields.each do |k, f|
if !f[:option] && Types[type.to_sym].include?(k)
o << k
end
end
o
end
def repeats?()
field_type.to_s == 'multiple' && selection_type.to_s != 'select'
end
def is_array?()
field_type.to_s == 'multiple' && selection_type.to_s != 'radio_button'
end
private
def get_from_options(key)
if options
_options = ActiveSupport::JSON.decode(options)
return _options[key]
end
nil
end
end

68
app/models/user.rb

@ -1,68 +0,0 @@
class User < ActiveRecord::Base
authenticates_with_sorcery! do |config|
config.authentications_class = Authentication
end
validates :email, uniqueness: true
mount_uploader :avatar, AvatarUploader
has_many :user_organization_relationships
has_many :organizations, through: :user_organization_relationships
has_many :conferences, through: :conference_administrators
has_many :authentications, :dependent => :destroy
accepts_nested_attributes_for :authentications
before_update do |user|
user.locale ||= I18n.locale
user.email.downcase!
end
before_save do |user|
user.locale ||= I18n.locale
user.email.downcase!
end
def can_translate?(to_locale = nil, from_locale = nil)
is_translator unless to_locale.present?
from_locale = I18n.locale unless from_locale.present?
return languages.present? &&
to_locale.to_s != from_locale.to_s &&
languages.include?(to_locale.to_s) &&
languages.include?(from_locale.to_s)
end
def name
firstname || username || email
end
def named_email
name = firstname || username
return email unless name
return "#{name} <#{email}>"
end
def administrator?
role == 'administrator'
end
def self.AVAILABLE_LANGUAGES
[:en, :es, :fr, :ar]
end
def self.get(email)
user = find_user(email)
unless user
user = create(email: email, locale: I18n.locale)
end
return user
end
def self.find_user(email)
User.where('lower(email) = ?', email.downcase).first
end
end

11
app/models/user_organization_relationship.rb

@ -1,11 +0,0 @@
class UserOrganizationRelationship < ActiveRecord::Base
belongs_to :user
belongs_to :organization
Administrator = 'administrator'
Member = 'member'
DefaultRelationship = Member
AllRelationships = [Administrator, Member]
end

2
app/models/version.rb

@ -1,2 +0,0 @@
class Version < ActiveRecord::Base
end

180
app/models/workshop.rb

@ -1,180 +0,0 @@
class Workshop < ActiveRecord::Base
translates :info, :title
belongs_to :conference
belongs_to :event_location
has_many :workshop_facilitators, :dependent => :destroy
has_many :users, :through => :workshop_facilitators
accepts_nested_attributes_for :workshop_facilitators, :reject_if => proc {|u| u[:user_id].blank?}, :allow_destroy => true
before_create :make_slug
def to_param
slug
end
def role(user)
return nil unless user
workshop_facilitators.each do |u|
if u.user_id == user.id
return conference.registration_exists?(user) ? u.role.to_sym : :unregistered
end
end
return nil
end
def facilitator?(user)
!!role(user)
end
def active_facilitators
users = []
workshop_facilitators.each do |u|
users << User.find(u.user_id) unless u.role.to_sym == :requested || u.user_id.nil?
end
return users
end
def active_facilitator?(user)
facilitator?(user) && !requested_collaborator?(user)
end
def public_facilitator?(user)
return false if !active_facilitator?(user)
return true if creator?(user)
conference.registered?(user)
end
def creator?(user)
role(user) == :creator
end
def collaborator?(user)
role(user) == :collaborator
end
def requested_collaborator?(user)
role(user) == :requested
end
def can_edit?(user)
creator?(user) || collaborator?(user) || conference.host?(user)
end
def can_remove?(owner, facilitator)
# creators cannot be removed
return false if creator?(facilitator)
# creator can remove anyone, facilitators can remove themselves
return creator?(owner) || owner.id == facilitator.id
end
def can_delete?(user)
creator?(user) || conference.host?(user)
end
def can_show_interest?(user)
user.present? && !active_facilitator?(user)
end
def interested?(user)
user.present? && !active_facilitator?(user) && WorkshopInterest.find_by(workshop_id: id, user_id: user.id)
end
def interested_count
interested.size
end
def interested
return [] unless id
return @interested if @interested.present?
collaborators = []
workshop_facilitators.each do |f|
collaborators << f.user_id unless f.role.to_sym == :requested || f.user_id.nil?
end
return 10 unless collaborators.present?
@interested = WorkshopInterest.where("workshop_id=#{id} AND user_id NOT IN (#{collaborators.join ','})") || []
end
def can_translate?(user, lang)
return false unless user.present?
user.can_translate?(lang, locale) || (can_edit?(user) && lang.to_s != locale.to_s)
end
def conference_day
return nil unless start_time.present? && end_time.present?
start_day = conference.start_date.change(hour: 0, minute: 0, second: 0)
w_start_day = start_time.change(hour: 0, minute: 0, second: 0)
return (((w_start_day - start_day) / 86400) + 1).to_i
end
def duration
return nil unless start_time.present? && end_time.present?
((end_time - start_time) / 60).to_i
end
def self.all_themes
[:race_gender, :mechanics, :funding, :organization, :community]
end
def self.all_spaces
[:meeting_room, :workshop, :outdoor_meeting]
end
def self.all_needs
[:sound, :projector, :tools]
end
def get_translators(data, loc = nil)
notify_list = {}
active_facilitators.each do |facilitator|
notify_list[facilitator.id] = facilitator
end
data.each do | column, value |
(
loc.present? ?
get_translators_for_column_and_locale(column, loc) :
get_translators_for_column(column)
).each do |id|
notify_list[id] = User.find(id)
end
end
return notify_list
end
def comments
Comment.for(self)
end
def add_comment(user, comment)
Comment.create_for(self, user, comment)
end
private
def make_slug
if !self.slug
s = self.title.gsub(/[^a-z1-9]+/i, '-').chomp('-').gsub(/\-([A-Z])/, '\1')
if Organization.find_by(:slug => s) && self.locations && self.locations[0]
s += '-' + self.locations[0].city
if Organization.find_by(:slug => s) && locations[0].territory
s += '-' + self.locations[0].territory
end
if Organization.find_by(:slug => s)
s += '-' + self.locations[0].country
end
end
attempt = 1
ss = s
while Organization.find_by(:slug => s)
attempt += 1
s = ss + '-' + attempt
end
self.slug = s
end
end
end

2
app/models/workshop_facilitator.rb

@ -1,2 +0,0 @@
class WorkshopFacilitator < ActiveRecord::Base
end

4
app/models/workshop_interest.rb

@ -1,4 +0,0 @@
class WorkshopInterest < ActiveRecord::Base
belongs_to :workshop
has_one :user
end

2
app/models/workshop_presentation_style.rb

@ -1,2 +0,0 @@
class WorkshopPresentationStyle < ActiveRecord::Base
end

2
app/models/workshop_requested_resource.rb

@ -1,2 +0,0 @@
class WorkshopRequestedResource < ActiveRecord::Base
end

2
app/models/workshop_resource.rb

@ -1,2 +0,0 @@
class WorkshopResource < ActiveRecord::Base
end

2
app/models/workshop_stream.rb

@ -1,2 +0,0 @@
class WorkshopStream < ActiveRecord::Base
end

104
app/uploaders/avatar_uploader.rb

@ -1,104 +0,0 @@
# encoding: utf-8
require 'carrierwave/processing/mini_magick'
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::ImageOptimizer
include CarrierWave::MiniMagick
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
process :optimize
@@sizes = {:thumb => [120, 120], :icon => [48, 48], :preview => [360, 120], :normal => [512, 512]}
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
#"/images/fallback/" + [version_name, "default.png"].compact.join('_')
# "http://placehold.it/" + (@@sizes[version_name] || [300, 300]).join('x')
#end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
#def scale(width, height)
#end
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_fill => @@sizes[:thumb]
end
version :icon do
process :resize_to_fill => @@sizes[:icon]
end
version :preview do
process :resize_to_fit => @@sizes[:preview]
end
version :normal do
process :resize_to_fit => @@sizes[:normal]
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
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
def image
@image ||= MiniMagick::Image.open(file.path)
end
def is_landscape?
image['width'] > (image['height'] * 1.25)
end
#def recreate_versions!(*versions)
# if !current_path.nil?
# current_path = "'" + (current_path || '') + "'"
# end
# super(*versions)
#end
# def manipulate!
# cache_stored_file! if !cached?
# image = ::MiniMagick::Image.open(current_path)
#
# begin
# image.format(@format.to_s.downcase) if @format
# image = yield(image)
# image.write(current_path)
# image.run_command("identify", '"' + current_path + '"')
# ensure
# image.destroy!
# end
# rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
# default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
# message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
# raise CarrierWave::ProcessingError, message
# end
end

54
app/uploaders/cover_uploader.rb

@ -1,54 +0,0 @@
# encoding: utf-8
require 'carrierwave/processing/mini_magick'
class CoverUploader < CarrierWave::Uploader::Base
include CarrierWave::ImageOptimizer
include CarrierWave::MiniMagick
storage :file
process :optimize
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :preview do
process :resize_to_fit => [480, 240]
end
version :full do
process :resize_to_fit => [1200, 800]
end
def image
@image ||= MiniMagick::Image.open(file.path)
end
def is_landscape?
image['width'] > image['height']
end
def manipulate!
cache_stored_file! if !cached?
image = ::MiniMagick::Image.open(current_path)
begin
image.format(@format.to_s.downcase) if @format
image = yield(image)
image.write(current_path)
begin
image.run_command("identify", current_path)
rescue
image.run_command("identify", '"' + current_path + '"')
end
ensure
image.destroy!
end
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
raise CarrierWave::ProcessingError, message
end
end

57
app/uploaders/logo_uploader.rb

@ -1,57 +0,0 @@
# encoding: utf-8
class LogoUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::ImageOptimizer
include CarrierWave::MiniMagick
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
process :optimize
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process :scale => [50, 50]
# 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
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end

69
app/uploaders/poster_uploader.rb

@ -1,69 +0,0 @@
# encoding: utf-8
require 'carrierwave/processing/mini_magick'
class PosterUploader < CarrierWave::Uploader::Base
include CarrierWave::ImageOptimizer
include CarrierWave::MiniMagick
storage :file
process :optimize
@@sizes = {
:thumb => [120, 120],
:icon => [48, 48],
:preview => [512, 512],
:full => [1024, 1024]
}
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_fill => @@sizes[:thumb]
end
version :icon do
process :resize_to_fill => @@sizes[:icon]
end
version :preview do
process :resize_to_fit => @@sizes[:preview]
end
version :full do
process :resize_to_fit => @@sizes[:full]
end
def image
@image ||= MiniMagick::Image.open(file.path)
end
def is_landscape?
image['width'] > image['height']
end
def manipulate!
cache_stored_file! if !cached?
image = ::MiniMagick::Image.open(current_path)
begin
image.format(@format.to_s.downcase) if @format
image = yield(image)
image.write(current_path)
begin
image.run_command("identify", current_path)
rescue
image.run_command("identify", '"' + current_path + '"')
end
ensure
image.destroy!
end
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
raise CarrierWave::ProcessingError, message
end
end

2
app/views/admin/new.html.haml

@ -19,6 +19,6 @@
= checkbox :is_featured, @this_conference.id.present? && @this_conference.is_featured != false, 'forms.labels.generic.is_featured' = checkbox :is_featured, @this_conference.id.present? && @this_conference.is_featured != false, 'forms.labels.generic.is_featured'
= columns(medium: 12) do = columns(medium: 12) do
.actions.next-prev .actions.next-prev
= button_tag :save, value: :save = button :save, value: :save
- if @this_conference.id.present? - if @this_conference.id.present?
= button_with_confirmation :delete, value: :delete, class: 'delete' = button_with_confirmation :delete, value: :delete, class: 'delete'

3
app/views/application/500.html.haml

@ -1,6 +1,5 @@
= render :partial => 'application/header', :locals => {:image_file => 'parts.jpg'} = render partial: 'application/header', locals: {image_file: 'parts.jpg'}
= row do = row do
= columns(medium: 12) do = columns(medium: 12) do
%p= _'error.500.description', :p %p= _'error.500.description', :p
= render 'contact', cancel_btn: false, contact_reason: :website = render 'contact', cancel_btn: false, contact_reason: :website

2
app/views/application/_contact.html.haml

@ -9,6 +9,6 @@
= textfield :subject, nil, required: true, big: true = textfield :subject, nil, required: true, big: true
= textarea :message, nil, required: true, plain: true = textarea :message, nil, required: true, plain: true
.actions .actions
= button_tag :send, value: :send = button :send, value: :send
- if cancel_btn - if cancel_btn
%button.close.subdued=_'forms.actions.generic.cancel' %button.close.subdued=_'forms.actions.generic.cancel'

2
app/views/application/_login.html.haml

@ -2,5 +2,5 @@
= form_tag do_confirm_path, class: 'flex-form' do = form_tag do_confirm_path, class: 'flex-form' do
= hidden_field_tag :dest, settings_path if dest.present? = hidden_field_tag :dest, settings_path if dest.present?
= emailfield :email, nil, big: true = emailfield :email, nil, big: true
= button_tag :continue, :value => :confirm_email = button :continue, value: :confirm_email
= link_to (_'forms.actions.generic.facebook_sign_in','Facebook Sign In'), auth_at_provider_path(provider: :facebook, dest: dest), class: [:button, :facebook] = link_to (_'forms.actions.generic.facebook_sign_in','Facebook Sign In'), auth_at_provider_path(provider: :facebook, dest: dest), class: [:button, :facebook]

2
app/views/application/_login_confirm.html.haml

@ -4,4 +4,4 @@
= form_tag :do_confirm, :authenticity_token => false, class: 'flex-form' do = form_tag :do_confirm, :authenticity_token => false, class: 'flex-form' do
= emailfield :email, nil, required: true, big: true = emailfield :email, nil, required: true, big: true
= hidden_field_tag :token, @confirmation.token = hidden_field_tag :token, @confirmation.token
= button_tag :login = button :login

6
app/views/application/_login_confirmation_sent.html.haml

@ -1,4 +1,4 @@
= row do = row do
= columns(medium: 12) do = columns(medium: 12) do
%h2=_'articles.permission_denied.headings.confirmation_sent' %h2=_'articles.permission_denied.headings.confirmation_sent'
%p=_'articles.conference_registration.paragraphs.email_confirm', :p %p=_'articles.conference_registration.paragraphs.email_confirm', :p

2
app/views/application/_not_a_translator.html.haml

@ -6,4 +6,4 @@
= columns(medium: 6) do = columns(medium: 6) do
= form_tag :translator_request do = form_tag :translator_request do
= text_area_tag :comment, nil, placeholder: true, required: true = text_area_tag :comment, nil, placeholder: true, required: true
= button_tag :translator_request = button :translator_request

2
app/views/application/_translator_login.html.haml

@ -8,4 +8,4 @@
.email-field.input-field .email-field.input-field
= email_field_tag :email, nil, required: true = email_field_tag :email, nil, required: true
= label_tag :email = label_tag :email
= button_tag :login = button :login

16
app/views/application/contact.html.haml

@ -1,10 +1,10 @@
= render :partial => 'application/header', :locals => {:image_file => @banner_image || 'grafitti.jpg'} = render :partial => 'application/header', :locals => {:image_file => @banner_image || 'grafitti.jpg'}
%article %article
= row do = row do
= columns do = columns do
- if @sent - if @sent
%h2=_'articles.contact.headings.sent', :t %h2=_'articles.contact.headings.sent', :t
%p=_'articles.contact.paragraphs.sent', :p %p=_'articles.contact.paragraphs.sent', :p
- else - else
%h2=_'articles.contact.headings.contact' %h2=_'articles.contact.headings.contact'
= render 'contact', cancel_btn: false = render 'contact', cancel_btn: false

7
app/views/application/home.html.haml

@ -1,5 +1,6 @@
- content_for :og_image do - content_for :og_image do
= (@conference.present? ? @conference.poster.full.url : nil) || image_path('default_poster.jpg') - if @conference.present?
- if @conferences.present? = @conference.poster.full.url || image_path('default_poster.jpg')
- if @conferences
- @conferences.each do | conference | - @conferences.each do | conference |
= render 'conferences/conference', conference: conference, links: [ :read_more, :register ] = render 'conferences/conference', conference: conference, links: [ :read_more, :register ], sections: @conference.front_page_details

16
app/views/application/permission_denied.html.haml

@ -1,10 +1,10 @@
= render :partial => 'application/header', :locals => {:image_file => @banner_image || '403.jpg'} = render :partial => 'application/header', :locals => {:image_file => @banner_image || '403.jpg'}
%article %article
- if @template.present? - if @template.present?
=render @template =render @template
- else - else
= row do = row do
= columns do = columns do
%h2=_'error.403.title','Sorry, you currently don\'t have access to this page' %h2=_'error.403.title','Sorry, you currently don\'t have access to this page'
%p=_'error.403.description', :p %p=_'error.403.description', :p
= render 'contact', cancel_btn: false, contact_reason: :website = render 'contact', cancel_btn: false, contact_reason: :website

2
app/views/application/update_user.html.haml

@ -6,4 +6,4 @@
%p=_'articles.conference_registration.paragraphs.provide_email', :p %p=_'articles.conference_registration.paragraphs.provide_email', :p
= form_tag oauth_save_path, class: 'flex-form' do = form_tag oauth_save_path, class: 'flex-form' do
= emailfield :email, nil, required: true, big: true = emailfield :email, nil, required: true, big: true
= button_tag :save, value: :save = button :save, value: :save

2
app/views/application/user_settings.html.haml

@ -19,7 +19,7 @@
= radiobuttons :preferred_language, I18n.backend.enabled_locales, current_user.locale || I18n.locale, 'languages', heading: 'articles.conference_registration.headings.preferred_language' = radiobuttons :preferred_language, I18n.backend.enabled_locales, current_user.locale || I18n.locale, 'languages', heading: 'articles.conference_registration.headings.preferred_language'
= checkbox :email_subscribe, current_user.is_subscribed != false, 'articles.user_settings.email_subscribe', heading: 'articles.user_settings.headings.email_subscribe', help: 'articles.user_settings.paragraphs.email_subscribe', inline: true, right_help: true = checkbox :email_subscribe, current_user.is_subscribed != false, 'articles.user_settings.email_subscribe', heading: 'articles.user_settings.headings.email_subscribe', help: 'articles.user_settings.paragraphs.email_subscribe', inline: true, right_help: true
.actions .actions
= button_tag :save, value: :save = button :save, value: :save
- else - else
%h2=_'forms.actions.generic.login' %h2=_'forms.actions.generic.login'
= render 'login' = render 'login'

10
app/views/conference_administration/_administrators.html.haml

@ -4,7 +4,7 @@
= admin_update_form do = admin_update_form do
= checkboxes :organizations, (@organizations.map { |org| [org.name, org.id] }), @this_conference.organizations.map(&:id), 'test.test', vertical: true, big: true = checkboxes :organizations, (@organizations.map { |org| [org.name, org.id] }), @this_conference.organizations.map(&:id), 'test.test', vertical: true, big: true
.actions.right.small .actions.right.small
= button_tag :save, value: :set_organizations = button :save, value: :set_organizations
- @this_conference.organizations.each do | organization | - @this_conference.organizations.each do | organization |
%h4=organization.name %h4=organization.name
- if organization.users.present? - if organization.users.present?
@ -16,11 +16,11 @@
= admin_update_form class: [:inline, :right] do = admin_update_form class: [:inline, :right] do
= hidden_field_tag :user_id, user.id = hidden_field_tag :user_id, user.id
= hidden_field_tag :org_id, organization.id = hidden_field_tag :org_id, organization.id
= button_tag :remove_member, value: :remove_org_member, class: [:small, :delete] = button :remove_member, value: :remove_org_member, class: [:small, :delete]
= admin_update_form class: 'mini-flex-form' do = admin_update_form class: 'mini-flex-form' do
= hidden_field_tag :org_id, organization.id = hidden_field_tag :org_id, organization.id
= emailfield :email, nil, required: true = emailfield :email, nil, required: true
= button_tag :add_member, value: :add_org_member, class: :small = button :add_member, value: :add_org_member, class: :small
%h3=_'articles.admin.info.headings.External_Administrators' %h3=_'articles.admin.info.headings.External_Administrators'
%p=_'articles.admin.info.descriptions.External_Administrators' %p=_'articles.admin.info.descriptions.External_Administrators'
@ -32,10 +32,10 @@
- unless user.id == current_user.id && !current_user.administrator? - unless user.id == current_user.id && !current_user.administrator?
= admin_update_form class: [:inline, :right] do = admin_update_form class: [:inline, :right] do
= hidden_field_tag :user_id, user.id = hidden_field_tag :user_id, user.id
= button_tag :remove_member, value: :remove_administrator, class: [:small, :delete] = button :remove_member, value: :remove_administrator, class: [:small, :delete]
= admin_update_form class: 'mini-flex-form' do = admin_update_form class: 'mini-flex-form' do
= userfield :email, nil, required: true = userfield :email, nil, required: true
-#= emailfield :email, nil, required: true -#= emailfield :email, nil, required: true
= button_tag :add_member, value: :add_administrator, class: :small = button :add_member, value: :add_administrator, class: :small
= columns(large: 2) do = columns(large: 2) do
&nbsp; &nbsp;

17
app/views/conference_administration/_broadcast.html.haml

@ -20,8 +20,25 @@
= button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }), value: :send, class: :delete if @broadcast_step == :test = button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }), value: :send, class: :delete if @broadcast_step == :test
= button_tag :edit, value: :edit = button_tag :edit, value: :edit
- else - else
<<<<<<< HEAD
= selectfield :send_to, nil, broadcast_options, full: true = selectfield :send_to, nil, broadcast_options, full: true
= textfield :subject, @subject, required: true, big: true = textfield :subject, @subject, required: true, big: true
= textarea :body, @body, lang: @this_conference.locale, edit_on: :focus = textarea :body, @body, lang: @this_conference.locale, edit_on: :focus
.actions.right .actions.right
= button_tag :preview, value: :preview = button_tag :preview, value: :preview
=======
.warning-info.make-room= _'articles.conference_registration.paragraphs.admin.broadcast.preview', vars: { send_to_count: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }
.test-preview
%h3=@subject
= richtext @body, 4
.actions.right
= button :test, value: :test, class: :secondary if @broadcast_step == :preview
= button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }), value: :send, class: :delete if @broadcast_step == :test
= button :edit, value: :edit
- else
= selectfield :send_to, nil, broadcast_options, full: true
= textfield :subject, @subject, required: true, big: true
= textarea :body, @body, lang: @this_conference.locale, edit_on: :focus
.actions.right
= button :preview, value: :preview
>>>>>>> d1db46f... 2017 refactor

2
app/views/conference_administration/_dates.html.haml

@ -14,4 +14,4 @@
= row do = row do
= columns(medium: 6, push: { medium: 1 }) do = columns(medium: 6, push: { medium: 1 }) do
.actions .actions
= button_tag :save, value: :save = button :save, value: :save

2
app/views/conference_administration/_description.html.haml

@ -2,4 +2,4 @@
= admin_update_form do = admin_update_form do
= translate_textarea :info, @this_conference, label: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', edit_on: :focus = translate_textarea :info, @this_conference, label: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', edit_on: :focus
.actions.right .actions.right
= button_tag :save, value: :save = button :save, value: :save

4
app/views/conference_administration/_events.html.haml

@ -37,5 +37,5 @@
= length_select @length, small: true = length_select @length, small: true
= translate_fields @event, { title: { type: :textfield, big: true, label: 'forms.labels.generic.title' }, info: { type: :textarea, label: 'forms.labels.generic.info', edit_on: :focus } } = translate_fields @event, { title: { type: :textfield, big: true, label: 'forms.labels.generic.title' }, info: { type: :textarea, label: 'forms.labels.generic.info', edit_on: :focus } }
.actions.next-prev .actions.next-prev
= button_tag :save, value: :save = button :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true if @event.id.present? = button :cancel, value: :cancel, class: :subdued, formnovalidate: true if @event.id.present?

6
app/views/conference_administration/_locations.html.haml

@ -36,7 +36,7 @@
= columns(medium: 12) do = columns(medium: 12) do
.actions.next-prev .actions.next-prev
- if @location.present? - if @location.present?
= button_tag :save, value: :save = button :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true = button :cancel, value: :cancel, class: :subdued, formnovalidate: true
- else - else
= button_tag :create, value: :create = button :create, value: :create

4
app/views/conference_administration/_meals.html.haml

@ -20,7 +20,7 @@
%td.form %td.form
= admin_update_form do = admin_update_form do
= hidden_field_tag :meal, time = hidden_field_tag :meal, time
= button_tag :delete, value: :delete, class: [:small, :delete] = button :delete, value: :delete, class: [:small, :delete]
= admin_update_form do = admin_update_form do
%h3=_'articles.admin.locations.headings.add_meal', :t %h3=_'articles.admin.locations.headings.add_meal', :t
.flex-inputs .flex-inputs
@ -30,6 +30,6 @@
= textfield :title, nil, required: true, big: true, help: 'articles.admin.locations.paragraphs.meal_title' = textfield :title, nil, required: true, big: true, help: 'articles.admin.locations.paragraphs.meal_title'
= textfield :info, nil, help: 'articles.admin.locations.paragraphs.meal_info' = textfield :info, nil, help: 'articles.admin.locations.paragraphs.meal_info'
.actions.next-prev .actions.next-prev
= button_tag :add_meal, value: :add_meal = button :add_meal, value: :add_meal
- else - else
.warning-info=_'articles.admin.meals.no_locations_warning' .warning-info=_'articles.admin.meals.no_locations_warning'

2
app/views/conference_administration/_payment_message.html.haml

@ -3,4 +3,4 @@
= translate_textarea :payment_message, @this_conference, default: 'articles.conference_registration.paragraphs.Payment', help: 'articles.conference_registration.paragraphs.admin.payment.message', edit_on: :focus, short: true = translate_textarea :payment_message, @this_conference, default: 'articles.conference_registration.paragraphs.Payment', help: 'articles.conference_registration.paragraphs.admin.payment.message', edit_on: :focus, short: true
.actions.right .actions.right
= button_tag :save, value: :save = button :save, value: :save

2
app/views/conference_administration/_paypal.html.haml

@ -5,4 +5,4 @@
= passwordfield :paypal_password, @this_conference.paypal_password = passwordfield :paypal_password, @this_conference.paypal_password
= textfield :paypal_signature, @this_conference.paypal_signature = textfield :paypal_signature, @this_conference.paypal_signature
.actions.right .actions.right
= button_tag :save, value: :save = button :save, value: :save

2
app/views/conference_administration/_poster.html.haml

@ -2,4 +2,4 @@
= form_tag administration_update_path(@this_conference.slug, :poster), multipart: true do = form_tag administration_update_path(@this_conference.slug, :poster), multipart: true do
= filefield :poster, @this_conference.poster, required: true, label: false, preview: true = filefield :poster, @this_conference.poster, required: true, label: false, preview: true
.actions.left .actions.left
= button_tag :upload, value: :upload, id: 'upload-file' = button :upload, value: :upload, id: 'upload-file'

2
app/views/conference_administration/_providers.html.haml

@ -7,4 +7,4 @@
= selectfield :distance_unit, @conditions['distance']['unit'], [:km, :mi], label: false, inline: true = selectfield :distance_unit, @conditions['distance']['unit'], [:km, :mi], label: false, inline: true
= columns(medium: 12) do = columns(medium: 12) do
.actions.right .actions.right
= button_tag :save, value: :save_distance = button :save, value: :save_distance

4
app/views/conference_administration/_publish_schedule.html.haml

@ -2,7 +2,7 @@
= form_tag administration_update_path(@this_conference.slug, @admin_step) do = form_tag administration_update_path(@this_conference.slug, @admin_step) do
- if @this_conference.workshop_schedule_published - if @this_conference.workshop_schedule_published
%p=_'articles.conference_registration.paragraphs.admin.schedule.published', :p %p=_'articles.conference_registration.paragraphs.admin.schedule.published', :p
.actions= button_tag :un_publish, value: :publish, class: :delete .actions= button :un_publish, value: :publish, class: :delete
- else - else
%p=_'articles.conference_registration.paragraphs.admin.schedule.un_published', :p %p=_'articles.conference_registration.paragraphs.admin.schedule.un_published', :p
.actions= button_tag :publish, value: :publish .actions= button :publish, value: :publish

14
app/views/conference_administration/_registration_status.html.haml

@ -1,9 +1,5 @@
- if @warning_message = columns(medium: 12) do
= columns(medium: 12) do = form_tag administration_update_path(@this_conference.slug, @admin_step) do
.warning-info=_"articles.admin.registrations.#{@warning_message}" = selectfield :registration_status, @this_conference.registration_status || 'closed', registration_status_options_list, inline_label: true
- else .actions.left
= columns(medium: 12) do = button :save, value: :save
= form_tag administration_update_path(@this_conference.slug, @admin_step) do
= selectfield :registration_status, @this_conference.registration_status || 'closed', registration_status_options_list, inline_label: true
.actions.left
= button_tag :save, value: :save

38
app/views/conference_administration/_registrations.html.haml

@ -1,21 +1,17 @@
- if @warning_message - add_inline_script :registrations
= columns(medium: 12) do = columns(medium: 12) do
.warning-info=_"articles.admin.registrations.#{@warning_message}" .goes-fullscreen#registrations-table
- else .flex-column
- add_inline_script :registrations = searchfield :search, nil, big: true, stretch: true
= columns(medium: 12) do %a.button{data: { expands: 'registrations-table' }}='expand'
.goes-fullscreen#registrations-table %a.button.delete{data: { contracts: 'registrations-table' }}='close'
.flex-column %a.button.modify{data: { 'opens-modal': 'new-registration' }}='+'
= searchfield :search, nil, big: true, stretch: true .table-scroller
%a.button{data: { expands: 'registrations-table' }}='expand' = html_table @excel_data, registrations_table_options
%a.button.delete{data: { contracts: 'registrations-table' }}='close' = admin_update_form id: 'new-registration', class: 'modal-edit' do
%a.button.modify{data: { 'opens-modal': 'new-registration' }}='+' .modal-edit-overlay{data: { 'closes-modal': 'new-registration' }}
.table-scroller .modal-edit-content
= html_table @excel_data, registrations_table_options = html_edit_table @excel_data, registrations_edit_table_options
= admin_update_form id: 'new-registration', class: 'modal-edit' do .actions.right
.modal-edit-overlay{data: { 'closes-modal': 'new-registration' }} %a.button.subdued{data: { 'closes-modal': 'new-registration' }}='Cancel'
.modal-edit-content = button :save, value: :save, class: :modify
= html_edit_table @excel_data, registrations_edit_table_options
.actions.right
%a.button.subdued{data: { 'closes-modal': 'new-registration' }}='Cancel'
= button_tag :save, value: :save, class: :modify

40
app/views/conference_administration/_schedule.html.haml

@ -6,22 +6,22 @@
- else - else
- add_inline_script :schedule if @entire_page - add_inline_script :schedule if @entire_page
#schedule-preview #schedule-preview
- @schedule.each do | day, data | - @schedule.each do |day, data|
%h4=date(day, :weekday) %h4=date(day, :weekday).html_safe
%table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]} %table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]}
- if data[:locations].present? && data[:locations].values.first != :add - if data[:locations].present? && data[:locations].values.first != :add
%thead %thead
%tr %tr
%th.corner %th.corner
- data[:locations].each do | id, location | - data[:locations].each do |id, location|
%th=location.is_a?(Symbol) ? '' : location.title %th=location.is_a?(Symbol) ? '' : _!(location.title)
%tbody %tbody
- data[:times].each do | time, time_data | - data[:times].each do |time, time_data|
%tr %tr
- rowspan = (time_data[:length] * 2).to_i - rowspan = (time_data[:length] * 2).to_i
%th=time(time) %th=time(time).html_safe
- if time_data[:type] == :workshop - if time_data[:type] == :workshop
- data[:locations].each do | id, location | - data[:locations].each do |id, location|
- if time_data[:item][:workshops][id].present? - if time_data[:item][:workshops][id].present?
- workshop = time_data[:item][:workshops][id][:workshop] - workshop = time_data[:item][:workshops][id][:workshop]
- status = time_data[:item][:workshops][id][:status] - status = time_data[:item][:workshops][id][:status]
@ -31,11 +31,11 @@
- if workshop.present? && workshop.event_location.present? - if workshop.present? && workshop.event_location.present?
= link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do = link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do
.details .details
.title=workshop.title .title=_!workshop.title
%template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }} %template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }}
%h1.title=workshop.title %h1.title=_!workshop.title
%p.address %p.address
= workshop.event_location.title + _!(': ') = _!("#{workshop.event_location.title}:")
= location_link workshop.event_location = location_link workshop.event_location
.workshop-description= richtext workshop.info, 1 .workshop-description= richtext workshop.info, 1
- if @can_edit - if @can_edit
@ -46,10 +46,10 @@
%span.value="#{status[:conflict_score]} / #{workshop.interested.size}" %span.value="#{status[:conflict_score]} / #{workshop.interested.size}"
- if status[:errors].present? - if status[:errors].present?
.errors .errors
- status[:errors].each do | error | - status[:errors].each do |error|
.error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars] .error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars]
= hidden_field_tag :id, workshop.id = hidden_field_tag :id, workshop.id
= button_tag :deschedule, value: :deschedule_workshop, class: [:delete, :small] = button :deschedule, value: :deschedule_workshop, class: [:delete, :small]
- elsif @can_edit - elsif @can_edit
.title="Block #{time_data[:item][:block] + 1}" .title="Block #{time_data[:item][:block] + 1}"
- elsif time_data[:type] != :nil - elsif time_data[:type] != :nil
@ -60,23 +60,23 @@
- if location.present? - if location.present?
%a.event-detail-link %a.event-detail-link
.details .details
.title= time_data[:item]['title'] .title=_!(time_data[:item]['title'])
.location= location.title .location=_!location.title
%template.event-details %template.event-details
%h1.title=time_data[:item]['title'] %h1.title=_!(time_data[:item]['title'])
%p.address %p.address
= location.title + _!(': ') = _!("#{location.title}:")
= location_link location = location_link location
- when :event - when :event
- if time_data[:item].event_location.present? - if time_data[:item].event_location.present?
%a.event-detail-link %a.event-detail-link
.details .details
.title= time_data[:item][:title] .title=_!(time_data[:item][:title]) if time_data[:item][:title]
.location= time_data[:item].event_location.title .location=_!(time_data[:item].event_location.title)
%template.event-details %template.event-details
%h1.title=time_data[:item][:title] %h1.title=_!(time_data[:item][:title]) if time_data[:item][:title]
%p.address %p.address
= time_data[:item].event_location.title + _!(': ') = _!("#{time_data[:item].event_location.title}:")
= location_link time_data[:item].event_location = location_link time_data[:item].event_location
= richtext time_data[:item][:info], 1 = richtext time_data[:item][:info], 1
- if @entire_page - if @entire_page

2
app/views/conference_administration/_suggested_amounts.html.haml

@ -5,4 +5,4 @@
- for i in 1..5 do - for i in 1..5 do
= numberfield "payment_amounts[#{i - 1}]", payment_amounts[i - 1], step: 0.01, min: 0.00, label: false = numberfield "payment_amounts[#{i - 1}]", payment_amounts[i - 1], step: 0.01, min: 0.00, label: false
.actions.right .actions.right
= button_tag :save, value: :save = button :save, value: :save

4
app/views/conference_administration/_workshop_times.html.haml

@ -15,5 +15,5 @@
.table-td=checkboxes :days, @block_days, info['days'].map(&:to_i), 'date.day_names', vertical: true, small: true .table-td=checkboxes :days, @block_days, info['days'].map(&:to_i), 'date.day_names', vertical: true, small: true
.table-td.form .table-td.form
= hidden_field_tag :workshop_block, block = hidden_field_tag :workshop_block, block
= button_tag :delete_block, value: :delete_block, class: [:small, :delete] if block == @workshop_blocks.length - 2 = button :delete_block, value: :delete_block, class: [:small, :delete] if block == @workshop_blocks.length - 2
= button_tag (is_new ? :add_block : :update_block), value: :save_block, class: [:small, :add] = button (is_new ? :add_block : :update_block), value: :save_block, class: [:small, :add]

6
app/views/conferences/_administration.html.haml

@ -1,6 +0,0 @@
= columns(medium: 3, large: 2) do
= admin_menu
= columns(medium: 9, large: 10) do
%h3.subtitle=_("menu.submenu.admin.#{@admin_step.titlecase.gsub(/\s/, '_')}")
%p=(_"articles.admin.#{@admin_step.gsub(/\s/, '_')}.description", :p) unless @hide_description === true
%div{id: "admin-#{@admin_step}"}= render "conferences/admin/#{@admin_step}"

27
app/views/conferences/_conference.html.haml

@ -1,18 +1,17 @@
- links ||= [ :register ] - links ||= [ :register ]
- sections ||= [ :info ] - sections ||= [ :info ]
= row(tag: :header) do
= columns(class: 'conference-banner') do
.title
%h1=_!conference.title
.details
%h2.primary=location(conference.city || conference.location) if conference.city_name.present?
- if conference.start_date.present? && conference.end_date.present?
.secondary
= date_span(conference.start_date.to_date, conference.end_date.to_date)
- if conference.poster.present?
%img{src: conference.poster.full.url, role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: conference.title })}
%article %article
= row(tag: :header) do
= columns(class: 'conference-banner') do
.title
%h1=_!conference.title
.details
%h2.primary=location(conference.city || conference.location) if conference.city_name.present?
- if conference.start_date.present? && conference.end_date.present?
.secondary
= date_span(conference.start_date.to_date, conference.end_date.to_date)
- if conference.poster.present?
%img{src: conference.poster.full.url || image_path('default_poster.jpg'), role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: conference.title })}
= row(class: 'conference-details') do = row(class: 'conference-details') do
= columns(medium: 10, push: {medium: 1}) do = columns(medium: 10, push: {medium: 1}) do
%h2=_!conference.title if conference.poster.present? %h2=_!conference.title if conference.poster.present?
@ -25,9 +24,9 @@
- else - else
%h3=_'articles.workshops.headings.Proposed_Workshops' %h3=_'articles.workshops.headings.Proposed_Workshops'
%p=_'articles.workshops.paragraphs.Proposed_Workshops' %p=_'articles.workshops.paragraphs.Proposed_Workshops'
= render 'workshops/workshop_previews', :workshops => (conference.workshops.sort { |a, b| a.title.downcase <=> b.title.downcase }) = render 'workshops/workshop_previews', workshops: (conference.workshops.sort { |a, b| a.title.downcase <=> b.title.downcase })
.links .links
= (link_to (_'forms.actions.generic.register'), register_path(conference.slug), class: [:button, :register]) if links.include?(:register) && conference.registration_status == :open = (link_to (_'forms.actions.generic.register'), register_path(conference.slug), class: [:button, :register]) if links.include?(:register) && conference.can_register?
= (link_to (_'articles.workshops.info.read_more'), conference_path(conference.slug), class: :button) if links.include?(:read_more) = (link_to (_'articles.workshops.info.read_more'), conference_path(conference.slug), class: :button) if links.include?(:read_more)
= (link_to (_'forms.actions.generic.administrate'), administrate_conference_path(conference.slug), class: [:button]) if links.include?(:administrate) = (link_to (_'forms.actions.generic.administrate'), administrate_conference_path(conference.slug), class: [:button]) if links.include?(:administrate)
= (link_to (_'forms.actions.generic.edit'), edit_conference_path(conference.slug), class: [:button, :subdued]) if links.include?(:edit) = (link_to (_'forms.actions.generic.edit'), edit_conference_path(conference.slug), class: [:button, :subdued]) if links.include?(:edit)

20
app/views/conferences/_confirm_email.html.haml

@ -1,13 +1,13 @@
= columns(medium: 12) do = columns(medium: 12) do
%p=_"articles.conference_registration.paragraphs.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details" %p=_"articles.conference_registration.paragraphs.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
%h3=_'articles.conference_registration.headings.Verify_Account' %h3=_'articles.conference_registration.headings.Verify_Account'
%p=_'articles.conference_registration.paragraphs.Verify_Account' %p=_'articles.conference_registration.paragraphs.Verify_Account'
= form_tag register_path(@this_conference.slug), class: 'flex-form' do = form_tag register_path(@this_conference.slug), class: 'flex-form' do
.email-field.input-field.big .email-field.input-field.big
= email_field_tag :email, nil, required: true = email_field_tag :email, nil, required: true
= label_tag :email = label_tag :email
= button_tag :continue, :value => :confirm_email = button :continue, value: :confirm_email
= columns(medium: 12, class: 'flex-column') do = columns(medium: 12, class: 'flex-column') do
%p.stretch-item=_'articles.conference_registration.paragraphs.facebook_sign_in' %p.stretch-item=_'articles.conference_registration.paragraphs.facebook_sign_in'
= link_to (_'forms.actions.generic.facebook_sign_in','Facebook Sign In'), auth_at_provider_path(:provider => :facebook), class: [:button, :facebook] = link_to (_'forms.actions.generic.facebook_sign_in','Facebook Sign In'), auth_at_provider_path(:provider => :facebook), class: [:button, :facebook]

4
app/views/conferences/_contact_info.html.haml

@ -5,5 +5,5 @@
= textfield :location, (params[:location] || location(@registration.city ||lookup_ip_location)), required: true, heading: 'articles.conference_registration.headings.location' = textfield :location, (params[:location] || location(@registration.city ||lookup_ip_location)), required: true, heading: 'articles.conference_registration.headings.location'
= checkboxes :languages, User.AVAILABLE_LANGUAGES, (current_user.languages || [I18n.locale]).map(&:to_sym), 'languages', heading: 'articles.conference_registration.headings.languages' = checkboxes :languages, User.AVAILABLE_LANGUAGES, (current_user.languages || [I18n.locale]).map(&:to_sym), 'languages', heading: 'articles.conference_registration.headings.languages'
.actions.next-prev .actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :contact_info = button (params[:step] == :save ? :save : :next), value: :contact_info
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true = button :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true

2
app/views/conferences/_done.html.haml

@ -48,4 +48,4 @@
- if @conference.registration_open - if @conference.registration_open
= form_tag register_path(@this_conference.slug) do = form_tag register_path(@this_conference.slug) do
.actions .actions
= button_tag :edit_registration, :value => :register = button :edit_registration, :value => :register

10
app/views/conferences/_email_confirm.html.haml

@ -1,6 +1,6 @@
%article %article
= row do = row do
= columns(medium: 12) do = columns(medium: 12) do
%h2=_'articles.conference_registration.headings.email_confirm','Please confirm your email address' %h2=_'articles.conference_registration.headings.email_confirm','Please confirm your email address'
= columns(medium: 12) do = columns(medium: 12) do
%p=_'articles.conference_registration.paragraphs.email_confirm', :p %p=_'articles.conference_registration.paragraphs.email_confirm', :p

4
app/views/conferences/_hosting.html.haml

@ -16,5 +16,5 @@
= checkboxes :considerations, ConferenceRegistration.all_considerations, @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true = checkboxes :considerations, ConferenceRegistration.all_considerations, @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true
= textarea :notes, @hosting_data['notes'], help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus = textarea :notes, @hosting_data['notes'], help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus
.actions.next-prev .actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :hosting = button (params[:step] == :save ? :save : :next), value: :hosting
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true = button :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save