Browse Source

2017 refactor

development
Godwin 7 years ago
parent
commit
d1db46ffaf
  1. 4
      .gitignore
  2. 133
      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. 398
      app/assets/stylesheets/user-mailer.scss
  12. 102
      app/controllers/administration_controller.rb
  13. 302
      app/controllers/application_controller.rb
  14. 146
      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. 2219
      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. 25
      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. 3
      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. 6
      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. 2
      app/views/conference_administration/_registration_status.html.haml
  90. 2
      app/views/conference_administration/_registrations.html.haml
  91. 167
      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. 29
      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
.project
# Ignore Gemfile.lock so that we always get the most up to date gems
# We'll be testing in 'preview' to avoid clashes
Gemfile.lock
# Ignore Redis' dataset snapshot
dump.rdb

133
Gemfile

@ -10,93 +10,106 @@ gem 'rack-mini-profiler'
gem 'haml'
gem 'nokogiri', '~> 1.6.8.rc2'
gem 'tzinfo-data'
gem 'sass'
gem 'sass-rails'
gem 'uglifier', '>= 1.3.0'
# replace this once these changes are merged in sorcery
gem 'sorcery', git: 'https://github.com/tg90nor/sorcery.git', branch: 'make-facebook-provider-use-json-token-parser'
gem 'carrierwave'
gem 'carrierwave-imageoptimizer'
gem 'mini_magick'
gem 'activerecord-session_store'
gem 'premailer-rails'
gem 'sidekiq'
gem 'letter_opener'
gem 'launchy'
if Dir.exists?('../lingua_franca')
gem 'lingua_franca', :path => '../lingua_franca'
gem 'lingua_franca', path: '../lingua_franca'
else
gem 'lingua_franca', :git => 'git://github.com/lingua-franca/lingua_franca.git'
gem 'lingua_franca', git: 'https://github.com/lingua-franca/lingua_franca.git', :branch => '2017'
end
gem 'tzinfo-data'
gem 'sass'
gem 'sass-rails'
if Dir.exists?('../marmara')
gem 'marmara', path: '../marmara'
else
gem 'marmara', git: 'https://github.com/lingua-franca/marmara.git'
end
if Dir.exists?('../bumbleberry')
gem 'bumbleberry', :path => "../bumbleberry"
if Dir.exists?('../bikecollectives_core')
gem 'bikecollectives_core', path: '../bikecollectives_core'
else
gem 'bumbleberry', :git => 'git://github.com/bumbleberry/bumbleberry.git'
gem 'bikecollectives_core', git: 'https://github.com/bikebike/bikecollectives_core.git'
end
if Dir.exists?('../paypal-express')
gem 'paypal-express', :path => "../paypal-express"
if Dir.exists?('../bumbleberry')
gem 'bumbleberry', path: '../bumbleberry'
else
gem 'paypal-express', :git => 'git://github.com/bikebike/paypal-express.git'
gem 'bumbleberry', git: 'https://github.com/bumbleberry/bumbleberry.git'
end
gem 'uglifier', '>= 1.3.0'
gem 'sorcery', '>= 0.8.1'
gem 'oauth2', '~> 0.8.0'
gem 'carrierwave'
gem 'carrierwave-imageoptimizer'
gem 'mini_magick'
# gem 'paper_trail', '~> 3.0.5'
# Bike!Bike! specific stuff
gem 'paypal-express', git: 'https://github.com/ianfleeton/paypal-express'
gem 'geocoder'
gem 'paper_trail', '~> 3.0.5'
gem 'sitemap_generator'
gem 'activerecord-session_store'
gem 'sass-json-vars'
gem 'premailer-rails'
gem 'redcarpet'
gem 'sidekiq'
gem 'letter_opener'
gem 'launchy'
gem 'to_spreadsheet', :git => 'git://github.com/glebm/to_spreadsheet.git'
group :test do
gem 'rspec'
gem 'rspec-rails'
end
gem 'to_spreadsheet', git: 'https://github.com/glebm/to_spreadsheet.git'
group :development do
gem 'better_errors'
gem 'binding_of_caller'
gem 'meta_request'
gem 'capistrano', '~> 3.1'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-faster-assets', '~> 1.0'
gem 'eventmachine', :github => 'krzcho/eventmachine', :branch => 'master'
gem 'thin'# , :github => 'krzcho/thin', :branch => 'master'
gem 'better_errors'
gem 'binding_of_caller'
gem 'meta_request'
gem 'capistrano', '~> 3.1'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-faster-assets', '~> 1.0'
gem 'eventmachine', git: 'https://github.com/krzcho/eventmachine', :branch => 'master'
gem 'thin'# , :github => 'krzcho/thin', :branch => 'master'
gem 'rubocop', require: false
gem 'haml-lint', require: false
end
group :test do
gem 'gherkin3', '>= 3.1.0'
gem 'cucumber'
gem 'cucumber-core'
gem 'cucumber-rails'
gem 'poltergeist'
gem 'guard-rspec'
gem 'factory_girl_rails'
gem 'coveralls', require: false
gem 'selenium-webdriver'
gem 'simplecov', require: false
gem 'webmock', require: false
gem 'database_cleaner'
gem 'mocha'
gem 'rspec'
gem 'rspec-rails'
gem 'gherkin3', '>= 3.1.0'
gem 'cucumber'
gem 'cucumber-core'
gem 'cucumber-rails', require: false
gem 'guard-cucumber'
gem 'poltergeist'
gem 'capybara-email'
# gem 'capybara-webkit'
gem 'guard-rspec'
gem 'factory_girl_rails'
gem 'coveralls', require: false
gem 'selenium-webdriver'
gem 'simplecov', require: false
gem 'webmock', require: false
gem 'database_cleaner'
gem 'mocha'
end
group :staging, :production, :preview do
gem 'rails_12factor'
gem 'rails_12factor'
end
group :production, :preview do
gem 'unicorn'
gem 'daemon-spawn'
gem 'daemons'
gem 'unicorn', require: false
gem 'daemon-spawn'
gem 'daemons'
end
platforms 'mswin', 'mingw' do
group :test do
gem 'wdm', '>= 0.1.0'
end
group :test do
gem 'wdm', '>= 0.1.0'
gem 'win32console', require: false
end
end

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' }
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 ##
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,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require 'rubygems'
require 'cucumber'
require 'cucumber/rake/task'
require File.expand_path('../config/application', __FILE__)
@ -61,3 +64,31 @@ task update_cities_fr: :environment do
c.save!
end
end
task :i18n do
LinguaFranca.test LinguaFranca::TestModes::RECORD do
Rake::Task[:cucumber].execute
end
end
task :css do
ENV['CSS_TEST'] = '1'
Rake::Task[:cucumber].execute
ENV['CSS_TEST'] = nil
end
task :a11y do
ENV['TEST_A11Y'] = '1'
Rake::Task[:cucumber].execute
ENV['TEST_A11Y'] = nil
end
task "cucumber:debug" do
ENV['TEST_DEBUG'] = '1'
Rake::Task[:cucumber].execute
ENV['TEST_DEBUG'] = nil
end
Cucumber::Rake::Task.new(:cucumber) do |t|
t.cucumber_opts = "features --format pretty"
end

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 input = field.getElementsByTagName('input')[0];
var name = field.getElementsByClassName('user-name')[0];
}
}, false);
})();

23
app/assets/stylesheets/_application.scss

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

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

@ -1,103 +1,105 @@
{
"stylesheets": ["application", "editor"],
"precompile": {
"test": {
"chrome": ["51"]
},
"development": {
"and_chr": ["55"],
"chrome": ["55"],
"edge": ["13"],
"firefox": ["50"],
"ie": ["11"],
"ios_saf": ["8", "9"]
}
"stylesheets": ["application", "editor"],
"precompile": {
"test": {
"safari": ["5"],
"chrome": ["55"]
},
"background-color": "#FFFEFE",
"breakpoint-unit": "px",
"unresponsive-width": 1000,
"row-width": 1000,
"total-columns": 12,
"platforms": {
"mobile": {
"range": [0,700]
},
"desktop": {
"range": [0,0]
}
"development": {
"safari": ["5"],
"and_chr": ["56"],
"chrome": ["56"],
"edge": ["13"],
"firefox": ["50"],
"ie": ["11"],
"ios_saf": ["8", "9"]
}
},
"background-color": "#FFFEFE",
"breakpoint-unit": "px",
"unresponsive-width": 1000,
"row-width": 1000,
"total-columns": 12,
"platforms": {
"mobile": {
"range": [0,700]
},
"desktop": {
"range": [0,0]
}
},
"breakpoints": {
"small": {
"range": [0],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"breakpoints": {
"small": {
"range": [0],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"medium": {
"range": [680],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"large": {
"range": [1024],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"small-only": {
"range": [0,319],
"grid": "n",
"offset": "n",
"reset-order": "n"
},
"medium-only": {
"range": [320,1023],
"grid": "n",
"offset": "n",
"reset-order": "n"
}
"medium": {
"range": [680],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"grid-push": [1, 2],
"grid-pull": [1, 2],
"font-loading-method": "http2",
"fonts": {
"primary": {
"name": "Sanchez Light",
"location": "Sanchez",
"svg_id": "wf",
"ttf_type": "ttf",
"fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"]
},
"secondary": {
"name": "AlteHaasGroteskBold",
"location": "AlteHaasGroteskBold",
"svg_id": "alte_haas_groteskbold",
"ttf_type": "ttf",
"fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"]
},
"monospace": {
"name": "NotCourierSans",
"location": "NotCourierSans",
"svg_id": "notcouriersans",
"ttf_type": "ttf",
"fallback": ["Courier New", "monospace"],
"auto_load": "n"
},
"monospace-bold": {
"name": "NotCourierSans",
"location": "NotCourierSans-Bold",
"svg_id": "notcouriersansbold",
"ttf_type": "ttf",
"fallback": ["Courier New", "monospace"],
"auto_load": "n",
"weight": "bold"
}
"large": {
"range": [1024],
"grid": "y",
"offset": "n",
"reset-order": "n"
},
"sprites": {
"icons": {
"bb-icon-logo": [0, 0, "182px", "149px"],
"bb-icon-logo-text": ["182px", 0, "136px", "149px"]
}
"small-only": {
"range": [0,319],
"grid": "n",
"offset": "n",
"reset-order": "n"
},
"medium-only": {
"range": [320,1023],
"grid": "n",
"offset": "n",
"reset-order": "n"
}
},
"grid-push": [1, 2],
"grid-pull": [1, 2],
"font-loading-method": "http2",
"fonts": {
"primary": {
"name": "Sanchez Light",
"location": "Sanchez",
"svg_id": "wf",
"ttf_type": "ttf",
"fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"]
},
"secondary": {
"name": "AlteHaasGroteskBold",
"location": "AlteHaasGroteskBold",
"svg_id": "alte_haas_groteskbold",
"ttf_type": "ttf",
"fallback": ["Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", "sans-serif"]
},
"monospace": {
"name": "NotCourierSans",
"location": "NotCourierSans",
"svg_id": "notcouriersans",
"ttf_type": "ttf",
"fallback": ["Courier New", "monospace"],
"auto_load": "n"
},
"monospace-bold": {
"name": "NotCourierSans",
"location": "NotCourierSans-Bold",
"svg_id": "notcouriersansbold",
"ttf_type": "ttf",
"fallback": ["Courier New", "monospace"],
"auto_load": "n",
"weight": "bold"
}
},
"sprites": {
"icons": {
"bb-icon-logo": [0, 0, "182px", "149px"],
"bb-icon-logo-text": ["182px", 0, "136px", "149px"]
}
}
}

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

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

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

@ -1,51 +1,51 @@
require 'geocoder/calculations'
class AdminController < ApplicationController
def new
return do_404 unless logged_in? && current_user.administrator?
@this_conference = Conference.new
@main_title = @page_title = 'articles.conferences.headings.new'
end
def edit
return do_404 unless logged_in? && current_user.administrator?
@this_conference = Conference.find_by!(slug: params[:slug])
@page_title = 'articles.conferences.headings.edit'
@main_title_vars = { vars: { title: @this_conference.title } }
render 'new'
end
def save
conference = params[:id].present? ? Conference.find_by!(id: params[:id]) : Conference.new
if params[:button] == 'save'
city = City.search(params[:city])
conference.city_id = city.id
conference.conferencetype = params[:type]
conference.year = params[:year].to_i
conference.is_public = params[:is_public].present?
conference.is_featured = params[:is_featured].present?
conference.make_slug(true)
conference.save!
elsif params[:button] == 'delete'
conference.destroy
return redirect_to conferences_url
end
redirect_to conference_url(conference.slug)
end
rescue_from ActiveRecord::PremissionDenied do |exception|
if logged_in?
redirect_to :register
else
@register_template = :confirm_email
@page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
render :register
end
end
rescue_from ActiveRecord::RecordNotFound do |exception|
do_404
end
end
require 'geocoder/calculations'
class AdministrationController < ApplicationController
def new
return do_404 unless logged_in? && current_user.administrator?
@this_conference = Conference.new
@main_title = @page_title = 'articles.conferences.headings.new'
end
def edit
return do_404 unless logged_in? && current_user.administrator?
@this_conference = Conference.find_by!(slug: params[:slug])
@page_title = 'articles.conferences.headings.edit'
@main_title_vars = { vars: { title: @this_conference.title } }
render 'new'
end
def save
conference = params[:id].present? ? Conference.find_by!(id: params[:id]) : Conference.new
if params[:button] == 'save'
city = City.search(params[:city])
conference.city_id = city.id
conference.conferencetype = params[:type]
conference.year = params[:year].to_i
conference.is_public = params[:is_public].present?
conference.is_featured = params[:is_featured].present?
conference.make_slug(true)
conference.save!
elsif params[:button] == 'delete'
conference.destroy
return redirect_to conferences_url
end
redirect_to conference_url(conference.slug)
end
rescue_from ActiveRecord::PremissionDenied do |exception|
if logged_in?
redirect_to :register
else
@register_template = :confirm_email
@page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
render :register
end
end
rescue_from ActiveRecord::RecordNotFound do |exception|
do_404
end
end

302
app/controllers/application_controller.rb

@ -1,11 +1,4 @@
module ActiveRecord
class PremissionDenied < RuntimeError
end
end
class ApplicationController < LinguaFrancaApplicationController
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
class ApplicationController < BaseController
protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update]
before_filter :capture_page_info
@ -16,6 +9,7 @@ class ApplicationController < LinguaFrancaApplicationController
@@test_location
def capture_page_info
# capture request info in case an error occurs
if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact')
session[:last_request]
request_info = {
@ -27,14 +21,11 @@ class ApplicationController < LinguaFrancaApplicationController
'env' => Hash.new
}
}
request.env.each do | key, value |
request.env.each do |key, value|
request_info['request']['env'][key.to_s] = value.to_s
end
session['request_info'] = request_info
end
# set the translator to the current user if we're logged in
I18n.config.translator = current_user
I18n.config.callback = self
# get the current conferences and set them globally
status_hierarchy = {
@ -57,11 +48,9 @@ class ApplicationController < LinguaFrancaApplicationController
@_inline_scripts ||= []
@_inline_scripts << Rails.application.assets.find_asset('main.js').to_s
ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"}
if request.post? && params[:action] == 'do_confirm'
halt_redirection!
end
ActionMailer::Base.default_url_options = {
host: "#{request.protocol}#{request.host_with_port}"
}
@alt_lang_urls = {}
I18n.backend.enabled_locales.each do |locale|
@ -72,17 +61,16 @@ class ApplicationController < LinguaFrancaApplicationController
# give each environment a different icon and theme colour so that we can easily see where we are. See https://css-tricks.com/give-development-domain-different-favicon-production
@favicon = Rails.env.development? || Rails.env.preview? ? "favicon-#{Rails.env.to_s}.ico" : 'favicon.ico'
@theme_colour = Rails.env.preview? ? '#EF57B4' : (Rails.env.development? ? '#D89E59' : '#00ADEF')
# call the base method to detect the language
super
end
def home
@workshops = Workshop.where(:conference_id => @conference.id)
if @conference.present? && @conference.id.present?
@workshops = Workshop.where(conference_id: @conference.id)
if @conference.workshop_schedule_published
@event_dlg = true
get_scheule_data(false)
if @conference.workshop_schedule_published
@event_dlg = true
get_scheule_data(false)
end
end
end
@ -90,14 +78,6 @@ class ApplicationController < LinguaFrancaApplicationController
@is_policy_page = true
end
def robots
render :text => File.read("config/robots-#{Rails.env.production? ? 'live' : 'dev'}.txt"), :content_type => 'text/plain'
end
def humans
render :text => File.read("config/humans.txt"), :content_type => 'text/plain'
end
def self.set_host(host)
@@test_host = host
end
@ -110,35 +90,6 @@ class ApplicationController < LinguaFrancaApplicationController
@@test_location
end
def do_404
error_404(status: 404)
end
def error_404(args = {})
params[:_original_action] = params[:action]
params[:action] = 'error-404'
@page_title = 'page_titles.404.Page_Not_Found'
@main_title = 'error.404.title'
render 'application/404', args
end
def do_403(template = nil)
@template = template
@page_title ||= 'page_titles.403.Access_Denied'
@main_title ||= @page_title
params[:_original_action] = params[:action]
params[:action] = 'error-403'
render 'application/permission_denied', status: 403
end
def error_500(exception = nil)
@page_title = 'page_titles.500.An_Error_Occurred'
@main_title = 'error.500.title'
params[:_original_action] = params[:action]
params[:action] = 'error-500'
render 'application/500', status: 500
end
def js_error
# send and email if this is production
report = "A JavaScript error has occurred on <code>#{params[:location]}</code>"
@ -150,7 +101,7 @@ class ApplicationController < LinguaFrancaApplicationController
begin
# log the error
logger.info "Javascript exception: #{params[:message]}"
logger.info "A JavaScript error has occurred on #{params[:location]}:#{params[:lineNumber]}: #{params[:message]}"
UserMailer.send_mail(:error_report) do
[
@ -163,7 +114,7 @@ class ApplicationController < LinguaFrancaApplicationController
current_user,
Time.now.strftime("%d/%m/%Y %H:%M")
]
end# if Rails.env.preview? || Rails.env.production?
end if Rails.env.preview? || Rails.env.production?
rescue Exception => exception2
logger.info exception2.to_s
logger.info exception2.backtrace.join("\n")
@ -171,31 +122,27 @@ class ApplicationController < LinguaFrancaApplicationController
render json: {}
end
rescue_from ActiveRecord::RecordNotFound do |exception|
do_404
end
rescue_from ActiveRecord::PremissionDenied do |exception|
do_403
end
def confirmation_sent(user)
template = 'login_confirmation_sent'
@page_title ||= 'page_titles.403.Please_Check_Email'
rescue_from AbstractController::ActionNotFound do |exception|
@banner_image = 'grafitti.jpg'
if current_user
@page_title = nil#'page_titles.Please_Login'
do_403 'not_a_translator'
#return
else
@page_title = 'page_titles.403.Please_Login'
do_403 'translator_login'
if (request.present? && request.referrer.present? && conference = /^\/conferences\/(\w+)\/register\/?$/.match(request.referrer.gsub(/^https?:\/\/.*?\//, '/')))
@this_conference = Conference.find_by!(slug: conference[1])
@banner_image = @this_conference.cover_url
template = 'conferences/email_confirm'
end
do_403 template
end
def locale_not_enabled!(locale = nil)
locale_not_available!(locale)
end
def locale_not_available
locale_not_available!(params[:locale])
end
def locale_not_available!(locale = nil)
set_default_locale
params[:_original_action] = params[:action]
@ -206,11 +153,13 @@ class ApplicationController < LinguaFrancaApplicationController
render 'application/locale_not_available', status: 404
end
rescue_from StandardError do |exception|
handle_exception exception
unless Rails.env.test?
rescue_from StandardError do |exception|
handle_exception exception
# show the error page
error_500 exception
# show the error page
error_500 exception
end
end
def handle_exception(exception)
@ -246,37 +195,6 @@ class ApplicationController < LinguaFrancaApplicationController
end
end
def generate_confirmation(user, url, expiry = nil)
if user.is_a? String
user = User.find_user(user)
# if the user doesn't exist, just show them a 403
do_403 unless user.present?
end
expiry ||= (Time.now + 12.hours)
session[:confirm_uid] = user.id
unless user.locale.present?
user.locale = I18n.locale
user.save
end
# send the confirmation email and make sure it get sent as quickly as possible
UserMailer.send_mail :email_confirmation do
EmailConfirmation.create(user_id: user.id, expiry: expiry, url: url)
end
end
def user_settings
@conferences = Array.new
if logged_in?
Conference.all.each do | conference |
@conferences << conference if conference.host? current_user
end
end
@main_title = @page_title = 'page_titles.user_settings.Your_Account'
end
def contact
@main_title = @page_title = 'page_titles.contact.Contact_Us'
end
@ -286,8 +204,8 @@ class ApplicationController < LinguaFrancaApplicationController
if params[:reason] == 'conference'
@conference.organizations.each do | org |
org.users.each do | user |
@conference.organizations.each do |org|
org.users.each do |user|
email_list << user.named_email
end
end
@ -322,31 +240,8 @@ class ApplicationController < LinguaFrancaApplicationController
render 'contact'
end
def update_user_settings
return do_403 unless logged_in?
current_user.firstname = params[:name]
current_user.lastname = nil
current_user.languages = (params[:languages] || { I18n.locale.to_s => true }).keys
current_user.is_subscribed = params[:email_subscribe].present?
current_user.save
redirect_to settings_path
end
def do_confirm(settings = nil)
settings ||= {:template => 'login_confirmation_sent'}
def confirm_user
if params[:email]
# see if we've already sent the confirmation email and are just confirming
# the email address
if params[:token]
user = User.find_user(params[:email])
confirm(user)
return
end
user = User.get(params[:email])
# generate the confirmation, send the email and show the 403
referrer = params[:dest] || (request.present? && request.referer.present? ? request.referer.gsub(/^.*?\/\/.*?\//, '/') : settings_path)
generate_confirmation(params[:email], referrer)
template = 'login_confirmation_sent'
@page_title ||= 'page_titles.403.Please_Check_Email'
@ -361,75 +256,44 @@ class ApplicationController < LinguaFrancaApplicationController
@banner_image ||= 'grafitti.jpg'
@page_title ||= 'page_titles.403.Please_Login'
do_403 (template || 'translator_login')
do_403 template
else
do_404
end
end
def confirm(uid = nil)
@confirmation = EmailConfirmation.find_by_token(params[:token])
unless @confirmation.present?
@token_not_found = true
return do_404
end
confirm_user = nil
if uid.is_a?(User)
confirm_user = uid
uid = confirm_user.id
end
# check to see if we were given a user id to confirm against
# if we were, make sure it was the same one
if (uid ||= (params[:uid] || session[:confirm_uid]))
if uid == @confirmation.user_id
session[:uid] = nil
confirm_user ||= User.find uid
auto_login(confirm_user)
else
@confirmation.delete
end
redirect_to (@confirmation.url || '/')
return
end
@banner_image = 'grafitti.jpg'
@page_title = 'page_titles.403.Please_Confirm_Email'
do_403 'login_confirm'
def error_404(args = {})
params[:_original_action] = params[:action]
params[:action] = 'error-404'
@page_title = 'page_titles.404.Page_Not_Found'
@main_title = 'error.404.title'
super(args)
end
def translator_request
def do_403(template = nil)
@banner_image = 'grafitti.jpg'
@page_title = 'page_titles.403.Translator_Request_Sent'
do_403 'translator_request_sent'
end
def user_logout
logout()
redirect_to (params[:url] || '/')
end
unless current_user
@page_title = 'page_titles.403.Please_Login'
end
def find_user
user = User.find_user(params[:e])
@template = template
@page_title ||= 'page_titles.403.Access_Denied'
@main_title ||= @page_title
params[:_original_action] = params[:action]
params[:action] = 'error-403'
if user.present?
return render json: {
name: user.name,
email: user.email,
exists: true
}
end
render json: {
name: I18n.t('user.not_found'),
email: nil,
exists: false
}
super(template)
end
def login_user(u)
auto_login(u)
def error_500(exception = nil)
@page_title = 'page_titles.500.An_Error_Occurred'
@main_title = 'error.500.title'
params[:_original_action] = params[:action]
params[:action] = 'error-500'
@exception = exception
super(exception)
end
def on_translation_change(object, data, locale, translator_id)
@ -541,8 +405,8 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule = {}
day_1 = conference.start_date.wday
@workshop_blocks.each_with_index do | info, block |
info['days'].each do | block_day |
@workshop_blocks.each_with_index do |info, block|
info['days'].each do |block_day|
day_diff = block_day.to_i - day_1
day_diff += 7 if day_diff < 0
day = (conference.start_date + day_diff.days).to_date
@ -555,9 +419,10 @@ class ApplicationController < LinguaFrancaApplicationController
end
end
@workshops.each do | workshop |
@workshops.each do |workshop|
if workshop.block.present?
block = @workshop_blocks[workshop.block['block'].to_i]
day_diff = workshop.block['day'].to_i - day_1
day_diff += 7 if day_diff < 0
day = (conference.start_date + day_diff.days).to_date
@ -569,7 +434,7 @@ class ApplicationController < LinguaFrancaApplicationController
end
end
@meals.each do | time, meal |
@meals.each do |time, meal|
day = meal['day'].to_date
time = meal['time'].to_f
@schedule[day] ||= {}
@ -580,7 +445,7 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:times][time][:item] = meal
end
@events.each do | event |
@events.each do |event|
if event.present? && event.start_time.present? && event.end_time.present?
day = event.start_time.midnight.to_date
time = event.start_time.hour.to_f + (event.start_time.min / 60.0)
@ -594,13 +459,13 @@ class ApplicationController < LinguaFrancaApplicationController
end
@schedule = @schedule.sort.to_h
@schedule.each do | day, data |
@schedule.each do |day, data|
@schedule[day][:times] = data[:times].sort.to_h
end
@schedule.each do | day, data |
@schedule.each do |day, data|
last_event = nil
data[:times].each do | time, time_data |
data[:times].each do |time, time_data|
if last_event.present?
@schedule[day][:times][last_event][:next_event] = time
end
@ -609,8 +474,8 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:num_locations] = (data[:locations] || []).size
end
@schedule.deep_dup.each do | day, data |
data[:times].each do | time, time_data |
@schedule.deep_dup.each do |day, data|
data[:times].each do |time, time_data|
if time_data[:next_event].present? || time_data[:length] > 0.5
span = 0.5
length = time_data[:next_event].present? ? time_data[:next_event] - time : time_data[:length]
@ -627,7 +492,7 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule = @schedule.sort.to_h
@schedule.each do | day, data |
@schedule.each do |day, data|
@schedule[day][:times] = data[:times].sort.to_h
@schedule[day][:locations] ||= {}
@ -635,19 +500,19 @@ class ApplicationController < LinguaFrancaApplicationController
@schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty?
if do_analyze
data[:times].each do | time, time_data |
data[:times].each do |time, time_data|
if time_data[:type] == :workshop && time_data[:item].present? && time_data[:item][:workshops].present?
ids = time_data[:item][:workshops].keys
(0..ids.length).each do | i |
(0..ids.length).each do |i|
if time_data[:item][:workshops][ids[i]].present?
workshop_i = time_data[:item][:workshops][ids[i]][:workshop]
conflicts = {}
(i+1..ids.length).each do | j |
(i+1..ids.length).each do |j|
workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil
if workshop_i.present? && workshop_j.present?
workshop_i.active_facilitators.each do | facilitator_i |
workshop_j.active_facilitators.each do | facilitator_j |
workshop_i.active_facilitators.each do |facilitator_i|
workshop_j.active_facilitators.each do |facilitator_j|
if facilitator_i.id == facilitator_j.id
@schedule[day][:times][time][:status] ||= {}
@schedule[day][:times][time][:item][:workshops][ids[j]][:status][:errors] << {
@ -669,7 +534,7 @@ class ApplicationController < LinguaFrancaApplicationController
needs = JSON.parse(workshop_i.needs || '[]').map &:to_sym
amenities = JSON.parse(location.amenities || '[]').map &:to_sym
needs.each do | need |
needs.each do |need|
@schedule[day][:times][time][:item][:workshops][ids[i]][:status][:errors] << {
name: :need_not_available,
need: need,
@ -685,7 +550,7 @@ class ApplicationController < LinguaFrancaApplicationController
# collect common interested users
interests = []
(0..ids.length).each do | j |
(0..ids.length).each do |j|
workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil
if workshop_i.present? && workshop_j.present? && workshop_i.id != workshop_j.id
interests = interests | workshop_j.interested.map { | u | u.user_id }
@ -740,4 +605,9 @@ class ApplicationController < LinguaFrancaApplicationController
def html_value(value)
return value.present? && ActionView::Base.full_sanitizer.sanitize(value).strip.present? ? value : nil
end
# send the confirmation email and make sure it get sent as quickly as possible
def send_confirmation(confirmation)
UserMailer.send_mail(:email_confirmation) { confirmation }
end
end

146
app/controllers/conference_administration_controller.rb

@ -62,7 +62,10 @@ class ConferenceAdministrationController < ApplicationController
set_flash_messages
# redirect to the step unless the method handled redirection itself
unless self.send(method_name)
case self.send(method_name)
when true
administration_step(@admin_step)
when false
redirect_to administration_step_path(@this_conference.slug, @admin_step)
end
end
@ -100,6 +103,9 @@ class ConferenceAdministrationController < ApplicationController
end
def administrate_broadcast
if @this_conference.start_date.blank? || @this_conference.end_date.blank?
@warning_message = :no_date_warning
end
end
def administrate_broadcast_sent
@ -120,6 +126,9 @@ class ConferenceAdministrationController < ApplicationController
end
def administrate_registration_status
if @this_conference.start_date.blank? || @this_conference.end_date.blank?
@warning_message = :no_date_warning
end
end
def administrate_organizations
@ -142,7 +151,7 @@ class ConferenceAdministrationController < ApplicationController
},
data: [],
}
@organizations.each do | org |
@organizations.each do |org|
if org.present?
address = org.locations.first
@excel_data[:data] << {
@ -158,18 +167,23 @@ class ConferenceAdministrationController < ApplicationController
}
end
end
return respond_to do | format |
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "organizations" }
end
end
end
def administrate_registrations
if @this_conference.start_date.blank? || @this_conference.end_date.blank?
@warning_message = :no_date_warning
return
end
get_stats(!request.format.xlsx?)
if request.format.xlsx?
logger.info "Generating stats.xls"
return respond_to do | format |
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end
end
@ -180,7 +194,7 @@ class ConferenceAdministrationController < ApplicationController
@donation_count = 0
@donations = 0
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 }
@registrations.each do | r |
@registrations.each do |r|
if view_context.registration_status(r) == :registered
@completed_registrations += 1
@ -200,11 +214,16 @@ class ConferenceAdministrationController < ApplicationController
end
def administrate_stats
if @this_conference.start_date.blank? || @this_conference.end_date.blank?
@warning_message = :no_date_warning
return
end
get_stats(!request.format.xlsx?)
if request.format.xlsx?
logger.info "Generating stats.xls"
return respond_to do | format |
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end
else
@ -214,7 +233,7 @@ class ConferenceAdministrationController < ApplicationController
@donation_count = 0
@donations = 0
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 }
@registrations.each do | r |
@registrations.each do |r|
if view_context.registration_status(r) == :registered
@completed_registrations += 1
@ -256,7 +275,7 @@ class ConferenceAdministrationController < ApplicationController
},
data: [],
}
@hosts.each do | id, host |
@hosts.each do |id, host|
data = (host.housing_data || {})
host_data = {
name: host.user.name,
@ -264,7 +283,7 @@ class ConferenceAdministrationController < ApplicationController
email: host.user.email,
phone: data['phone'],
availability: data['availability'].present? && data['availability'][1].present? ? view_context.date_span(data['availability'][0].to_date, data['availability'][1].to_date) : '',
considerations: ((data['considerations'] || []).map { | consideration | view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '),
considerations: ((data['considerations'] || []).map { |consideration| view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '),
empty: '',
guests: {
columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city],
@ -285,8 +304,8 @@ class ConferenceAdministrationController < ApplicationController
}
}
@housing_data[id][:guests].each do | space, space_data |
space_data.each do | guest_id, guest_data |
@housing_data[id][:guests].each do |space, space_data|
space_data.each do |guest_id, guest_data|
guest = guest_data[:guest]
if guest.present?
companion = view_context.companion(guest)
@ -307,7 +326,7 @@ class ConferenceAdministrationController < ApplicationController
@excel_data[:data] << host_data
end
return respond_to do | format |
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "housing" }
end
end
@ -439,7 +458,7 @@ class ConferenceAdministrationController < ApplicationController
},
data: []
}
User.AVAILABLE_LANGUAGES.each do | l |
User.AVAILABLE_LANGUAGES.each do |l|
@excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}"
end
ConferenceRegistration.all_spaces.each do |s|
@ -449,7 +468,7 @@ class ConferenceAdministrationController < ApplicationController
ConferenceRegistration.all_considerations.each do |c|
@excel_data[:keys][c] = "articles.conference_registration.host.considerations.#{c.to_s}"
end
@registrations.each do | r |
@registrations.each do |r|
user = r.user_id ? User.where(id: r.user_id).first : nil
if user.present?
companion = view_context.companion(r)
@ -509,7 +528,7 @@ class ConferenceAdministrationController < ApplicationController
last_day: availability[1].present? ? view_context.date(availability[1].to_date, :span_same_year_date_1) : ''
}
}
User.AVAILABLE_LANGUAGES.each do | l |
User.AVAILABLE_LANGUAGES.each do |l|
can_speak = ((user.languages || []).include? l.to_s)
data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '')
data[:raw_values]["language_#{l}".to_sym] = can_speak
@ -554,12 +573,12 @@ class ConferenceAdministrationController < ApplicationController
first_day: view_context.conference_days_options_list(:before),
last_day: view_context.conference_days_options_list(:after)
}
User.AVAILABLE_LANGUAGES.each do | l |
User.AVAILABLE_LANGUAGES.each do |l|
@column_options["language_#{l}".to_sym] = [
[(view_context._"articles.conference_registration.questions.bike.yes"), true]
]
end
ConferenceRegistration.all_considerations.each do | c |
ConferenceRegistration.all_considerations.each do |c|
@column_options[c.to_sym] = [
[(view_context._"articles.conference_registration.questions.bike.yes"), true]
]
@ -570,7 +589,7 @@ class ConferenceAdministrationController < ApplicationController
def get_housing_data
@hosts = {}
@guests = {}
ConferenceRegistration.where(:conference_id => @this_conference.id).each do | registration |
ConferenceRegistration.where(:conference_id => @this_conference.id).each do |registration|
if registration.can_provide_housing
@hosts[registration.id] = registration
elsif registration.housing.present? && registration.housing != 'none'
@ -584,11 +603,11 @@ class ConferenceAdministrationController < ApplicationController
@housing_data = {}
@hosts_affected_by_guests = {}
@hosts.each do | id, host |
@hosts.each do |id, host|
@hosts[id].housing_data ||= {}
@housing_data[id] = { guests: {}, space: {} }
@hosts[id].housing_data['space'] ||= {}
@hosts[id].housing_data['space'].each do | s, size |
@hosts[id].housing_data['space'].each do |s, size|
size = (size || 0).to_i
@housing_data[id][:guests][s.to_sym] = {}
@housing_data[id][:space][s.to_sym] = size
@ -597,7 +616,7 @@ class ConferenceAdministrationController < ApplicationController
@guests_housed = 0
@guests.each do | guest_id, guest |
@guests.each do |guest_id, guest|
data = guest.housing_data || {}
@hosts_affected_by_guests[guest_id] ||= []
@ -632,7 +651,7 @@ class ConferenceAdministrationController < ApplicationController
end
companions = data['companions'] || []
companions.each do | companion |
companions.each do |companion|
user = User.find_user(companion)
if user.present?
reg = ConferenceRegistration.find_by(
@ -659,10 +678,10 @@ class ConferenceAdministrationController < ApplicationController
end
end
@hosts.each do | id, host |
@hosts.each do |id, host|
host_data = host.housing_data
@hosts[id].housing_data['space'].each do | space, size |
@hosts[id].housing_data['space'].each do |space, size|
# make sure the host isn't overbooked
space = space.to_sym
space_available = (size || 0).to_i
@ -771,7 +790,7 @@ class ConferenceAdministrationController < ApplicationController
end
def admin_update_description
params[:info].each do | locale, value |
params[:info].each do |locale, value|
@this_conference.set_column_for_locale(:info, locale, html_value(value))
end
@this_conference.save
@ -792,7 +811,7 @@ class ConferenceAdministrationController < ApplicationController
def admin_update_payment_message
begin
params[:payment_message].each do | locale, value |
params[:payment_message].each do |locale, value|
@this_conference.set_column_for_locale(:payment_message, locale, html_value(value))
end
@this_conference.save
@ -864,7 +883,7 @@ class ConferenceAdministrationController < ApplicationController
end
user_changed = false
params.each do | key, value |
params.each do |key, value|
case key.to_sym
when :city
if value.present?
@ -995,7 +1014,7 @@ class ConferenceAdministrationController < ApplicationController
@send_to = params[:send_to]
@register_template = :administration
if params[:button] == 'send'
view_context.broadcast_to(@send_to).each do | user |
view_context.broadcast_to(@send_to).each do |user|
UserMailer.send_mail :broadcast do
[
"#{request.protocol}#{request.host_with_port}",
@ -1108,11 +1127,11 @@ class ConferenceAdministrationController < ApplicationController
event.end_time = event.start_time + params[:time_span].to_f.hours
# save translations
(params[:info] || {}).each do | locale, value |
(params[:info] || {}).each do |locale, value|
event.set_column_for_locale(:title, locale, html_value(value), current_user.id) unless value = event._title(locale)
end
(params[:title] || {}).each do | locale, value |
(params[:title] || {}).each do |locale, value|
event.set_column_for_locale(:info, locale, value, current_user.id) unless value = event._info(locale)
end
@ -1126,22 +1145,47 @@ class ConferenceAdministrationController < ApplicationController
do_404
return true
end
def admin_update_workshop_times
case params[:button]
when 'save_block'
empty_param = empty_params(:time, :time_span, :days)
if empty_param.present?
set_error_message "save_block_#{empty_param}_required".to_sym
else
@this_conference.workshop_blocks ||= []
@this_conference.workshop_blocks[params[:workshop_block].to_i] = {
'time' => params[:time],
'length' => params[:time_span],
'days' => params[:days].keys
}
@this_conference.save
set_success_message :block_saved
end
return false
when 'delete_block'
@this_conference.workshop_blocks ||= []
@this_conference.workshop_blocks[params[:workshop_block].to_i] = {
'time' => params[:time],
'length' => params[:time_span],
'days' => params[:days].keys
}
@this_conference.workshop_blocks.delete_at(params[:workshop_block].to_i)
@this_conference.save
set_success_message :block_deleted
return false
end
do_404
return true
return nil
end
def admin_update_publish_schedule
case params[:button]
when 'publish'
@this_conference.workshop_schedule_published = !@this_conference.workshop_schedule_published
@this_conference.save
set_success_message "schedule_#{@this_conference.workshop_schedule_published ? '' : 'un'}published".to_sym
return false
end
do_404
return false
end
def admin_update_schedule
@ -1155,7 +1199,6 @@ class ConferenceAdministrationController < ApplicationController
@entire_page = false
get_scheule_data
render partial: 'schedule'
return true
when 'get-workshop-list'
get_scheule_data(true)
@ -1166,12 +1209,11 @@ class ConferenceAdministrationController < ApplicationController
@location = params[:location]
@event_location = @location.present? && @location.to_i > 0 ? EventLocation.find(@location.to_i) : nil
@workshops.sort { |a, b| a.title.downcase <=> b.title.downcase }.each do | workshop |
@workshops.sort { |a, b| a.title.downcase <=> b.title.downcase }.each do |workshop|
@ordered_workshops[workshop.id] = workshop
end
render partial: 'select_workshop_table'
return true
when 'set-workshop'
workshop = Workshop.find_by!(conference_id: @this_conference.id, id: params[:workshop].to_i)
workshop.event_location_id = params[:location]
@ -1183,23 +1225,11 @@ class ConferenceAdministrationController < ApplicationController
get_scheule_data
render partial: 'schedule'
return true
end
do_404
return true
end
def admin_update_schedule
case params[:button]
when 'publish'
@this_conference.workshop_schedule_published = !@this_conference.workshop_schedule_published
@this_conference.save
return false
else
do_404
end
do_404
return false
return nil
end
def admin_update_providers
@ -1221,9 +1251,13 @@ class ConferenceAdministrationController < ApplicationController
def get_empty(hash, keys)
keys = [keys] unless keys.is_a?(Array)
keys.each do | key |
keys.each do |key|
return key unless hash[key].present?
end
return nil
end
def empty_params(*args)
get_empty(params, args)
end
end

71
app/controllers/conferences_controller.rb

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

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
def workshops
set_conference
set_conference_registration!
@workshops = Workshop.where(:conference_id => @this_conference.id)
@my_workshops = Workshop.joins(:workshop_facilitators).where(:workshop_facilitators => {:user_id => current_user.id}, :conference_id => @this_conference.id)
@workshops = Workshop.where(conference_id: @this_conference.id)
@my_workshops = @workshops.select { |w| w.active_facilitator?(current_user) }
render 'workshops/index'
end
@ -58,7 +58,7 @@ class WorkshopsController < ApplicationController
@is_translating ||= false
if @is_translating
return do_404 if @translation.to_s == @workshop.locale.to_s || !I18n.backend.enabled_locales.include?(@translation.to_s)
return do_404 unless @translation.to_s != @workshop.locale.to_s && LinguaFranca.locale_enabled?(@translation.to_sym)
return do_403 unless @workshop.can_translate?(current_user, @translation)
@title = @workshop._title(@translation)

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

2219
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
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)
return nil unless registration.present?
@ -6,32 +18,36 @@ module RegistrationHelper
current_steps = []
disable_steps = false
completed_steps = registration.steps_completed || []
# registration_complete = registration_complete?(registration)
if potential_provider(registration)
steps -= [:questions]
else
steps -= [:hosting]
end
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 |
steps.each do |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
disable_steps ||= !completed_steps.include?(step.to_s) && ![:payment, :workshops].include?(step)
current_steps << {
name: step,
enabled: enabled
enabled: !disable_steps
}
disable_steps ||= !completed_steps.include?(step.to_s)# && ![:payment, :workshops].include?(step)
end
return current_steps
end
def current_step(registration = @registration)
completed_steps = registration.steps_completed || []
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 last_step unless step[:enabled]
@ -43,6 +59,6 @@ module RegistrationHelper
end
# if all else fails, return the first step
return registration_steps(registration.conference).last
return steps.last[:name]
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'
class UserMailer < ActionMailer::Base
add_template_helper(ApplicationHelper)
include LinguaFrancaHelper
add_template_helper(ApplicationHelper)
before_filter :set_host
default from: "Bike!Bike! <noreply@bikebike.org>"
default from: "Bike!Bike! <godwin@bikebike.org>"
def email_confirmation(confirmation)
@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

25
app/models/event_location.rb

@ -1,25 +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
l = conference.location
[address, l.city, l.territory, l.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'
= columns(medium: 12) do
.actions.next-prev
= button_tag :save, value: :save
= button :save, value: :save
- if @this_conference.id.present?
= 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
= columns(medium: 12) do
%p= _'error.500.description', :p
= 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
= textarea :message, nil, required: true, plain: true
.actions
= button_tag :send, value: :send
= button :send, value: :send
- if cancel_btn
%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
= hidden_field_tag :dest, settings_path if dest.present?
= 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]

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

@ -4,4 +4,4 @@
= form_tag :do_confirm, :authenticity_token => false, class: 'flex-form' do
= emailfield :email, nil, required: true, big: true
= 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
= columns(medium: 12) do
%h2=_'articles.permission_denied.headings.confirmation_sent'
%p=_'articles.conference_registration.paragraphs.email_confirm', :p
= columns(medium: 12) do
%h2=_'articles.permission_denied.headings.confirmation_sent'
%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
= form_tag :translator_request do
= 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_tag :email, nil, required: true
= 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'}
%article
= row do
= columns do
- if @sent
%h2=_'articles.contact.headings.sent', :t
%p=_'articles.contact.paragraphs.sent', :p
- else
%h2=_'articles.contact.headings.contact'
= render 'contact', cancel_btn: false
= row do
= columns do
- if @sent
%h2=_'articles.contact.headings.sent', :t
%p=_'articles.contact.paragraphs.sent', :p
- else
%h2=_'articles.contact.headings.contact'
= render 'contact', cancel_btn: false

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

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

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

@ -1,10 +1,10 @@
= render :partial => 'application/header', :locals => {:image_file => @banner_image || '403.jpg'}
%article
- if @template.present?
=render @template
- else
= row do
= columns do
%h2=_'error.403.title','Sorry, you currently don\'t have access to this page'
%p=_'error.403.description', :p
= render 'contact', cancel_btn: false, contact_reason: :website
- if @template.present?
=render @template
- else
= row do
= columns do
%h2=_'error.403.title','Sorry, you currently don\'t have access to this page'
%p=_'error.403.description', :p
= 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
= form_tag oauth_save_path, class: 'flex-form' do
= 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'
= 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
= button_tag :save, value: :save
= button :save, value: :save
- else
%h2=_'forms.actions.generic.login'
= render 'login'

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

@ -4,7 +4,7 @@
= admin_update_form do
= checkboxes :organizations, (@organizations.map { |org| [org.name, org.id] }), @this_conference.organizations.map(&:id), 'test.test', vertical: true, big: true
.actions.right.small
= button_tag :save, value: :set_organizations
= button :save, value: :set_organizations
- @this_conference.organizations.each do | organization |
%h4=organization.name
- if organization.users.present?
@ -16,11 +16,11 @@
= admin_update_form class: [:inline, :right] do
= hidden_field_tag :user_id, user.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
= hidden_field_tag :org_id, organization.id
= 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'
%p=_'articles.admin.info.descriptions.External_Administrators'
@ -32,10 +32,10 @@
- unless user.id == current_user.id && !current_user.administrator?
= admin_update_form class: [:inline, :right] do
= 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
= userfield :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
&nbsp;

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

@ -12,12 +12,12 @@
%h3=@subject
= richtext @body, 4
.actions.right
= button_tag :test, value: :test, class: :secondary if @broadcast_step == :preview
= 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_tag :edit, value: :edit
= 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_tag :preview, value: :preview
= button :preview, value: :preview

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

@ -14,4 +14,4 @@
= row do
= columns(medium: 6, push: { medium: 1 }) do
.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
= 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
= 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
= 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
= button_tag :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true if @event.id.present?
= button :save, value: :save
= 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
.actions.next-prev
- if @location.present?
= button_tag :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true
= button :save, value: :save
= button :cancel, value: :cancel, class: :subdued, formnovalidate: true
- else
= button_tag :create, value: :create
= button :create, value: :create

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

@ -20,7 +20,7 @@
%td.form
= admin_update_form do
= hidden_field_tag :meal, time
= button_tag :delete, value: :delete, class: [:small, :delete]
= button :delete, value: :delete, class: [:small, :delete]
= admin_update_form do
%h3=_'articles.admin.locations.headings.add_meal', :t
.flex-inputs
@ -30,6 +30,6 @@
= textfield :title, nil, required: true, big: true, help: 'articles.admin.locations.paragraphs.meal_title'
= textfield :info, nil, help: 'articles.admin.locations.paragraphs.meal_info'
.actions.next-prev
= button_tag :add_meal, value: :add_meal
= button :add_meal, value: :add_meal
- else
.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
.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
= textfield :paypal_signature, @this_conference.paypal_signature
.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
= filefield :poster, @this_conference.poster, required: true, label: false, preview: true
.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
= columns(medium: 12) do
.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
- if @this_conference.workshop_schedule_published
%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
%p=_'articles.conference_registration.paragraphs.admin.schedule.un_published', :p
.actions= button_tag :publish, value: :publish
.actions= button :publish, value: :publish

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

@ -2,4 +2,4 @@
= 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
= button :save, value: :save

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

@ -14,4 +14,4 @@
= 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
= button :save, value: :save, class: :modify

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

@ -1,85 +1,86 @@
= columns(medium: 12) do
- conference = @this_conference || @conference
- if conference.event_locations.blank? && @entire_page
.warning-info=_'articles.admin.schedule.no_locations_warning'
- else
- add_inline_script :schedule if @entire_page
#schedule-preview
- @schedule.each do | day, data |
%h4=date(day, :weekday)
%table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]}
- if data[:locations].present? && data[:locations].values.first != :add
%thead
%tr
%th.corner
- data[:locations].each do | id, location |
%th=location.is_a?(Symbol) ? '' : location.title
%tbody
- data[:times].each do | time, time_data |
%tr
- rowspan = (time_data[:length] * 2).to_i
%th=time(time)
- if time_data[:type] == :workshop
- data[:locations].each do | id, location |
- if time_data[:item][:workshops][id].present?
- workshop = time_data[:item][:workshops][id][:workshop]
- status = time_data[:item][:workshops][id][:status]
- else
- workshop = status = nil
%td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }}
- if workshop.present? && workshop.event_location.present?
= link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do
.details
.title=workshop.title
%template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }}
%h1.title=workshop.title
%p.address
= workshop.event_location.title + _!(': ')
= location_link workshop.event_location
.workshop-description= richtext workshop.info, 1
- if @can_edit
= form_tag administration_update_path(conference.slug, @admin_step), class: 'deschedule-workshop' do
.status
.conflict-score
%span.title Conflicts:
%span.value="#{status[:conflict_score]} / #{workshop.interested.size}"
- if status[:errors].present?
.errors
- status[:errors].each do | error |
.error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars]
= hidden_field_tag :id, workshop.id
= button_tag :deschedule, value: :deschedule_workshop, class: [:delete, :small]
- elsif @can_edit
.title="Block #{time_data[:item][:block] + 1}"
- elsif time_data[:type] != :nil
%td{class: time_data[:type], rowspan: rowspan, colspan: data[:locations].present? ? data[:locations].size : 1}
- case time_data[:type]
- when :meal
- location = EventLocation.where(id: time_data[:item]['location'].to_i).first
- if location.present?
%a.event-detail-link
= row do
= columns(medium: 12) do
- conference = @this_conference || @conference
- if conference.event_locations.blank? && @entire_page
.warning-info=_'articles.admin.schedule.no_locations_warning'
- else
- add_inline_script :schedule if @entire_page
#schedule-preview
- @schedule.each do |day, data|
%h4=date(day, :weekday)
%table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]}
- if data[:locations].present? && data[:locations].values.first != :add
%thead
%tr
%th.corner
- data[:locations].each do |id, location|
%th=location.is_a?(Symbol) ? '' : _!(location.title)
%tbody
- data[:times].each do |time, time_data|
%tr
- rowspan = (time_data[:length] * 2).to_i
%th=time(time)
- if time_data[:type] == :workshop
- data[:locations].each do |id, location|
- if time_data[:item][:workshops][id].present?
- workshop = time_data[:item][:workshops][id][:workshop]
- status = time_data[:item][:workshops][id][:status]
- else
- workshop = status = nil
%td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }}
- if workshop.present? && workshop.event_location.present?
= link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do
.details
.title= time_data[:item]['title']
.location= location.title
%template.event-details
%h1.title=time_data[:item]['title']
.title=_!workshop.title
%template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }}
%h1.title=_!workshop.title
%p.address
= location.title + _!(': ')
= location_link location
- when :event
- if time_data[:item].event_location.present?
%a.event-detail-link
.details
.title= time_data[:item][:title]
.location= time_data[:item].event_location.title
%template.event-details
%h1.title=time_data[:item][:title]
%p.address
= time_data[:item].event_location.title + _!(': ')
= location_link time_data[:item].event_location
= richtext time_data[:item][:info], 1
- if @entire_page
#workshop-selector
= form_tag administration_update_path(@this_conference.slug, @admin_step), class: 'workshop-dlg', id: 'workshop-table-form' do
%h3 Select a Workshop
#table
= _!("#{workshop.event_location.title}:")
= location_link workshop.event_location
.workshop-description= richtext workshop.info, 1
- if @can_edit
= form_tag administration_update_path(conference.slug, @admin_step), class: 'deschedule-workshop' do
.status
.conflict-score
%span.title Conflicts:
%span.value="#{status[:conflict_score]} / #{workshop.interested.size}"
- if status[:errors].present?
.errors
- status[:errors].each do |error|
.error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars]
= hidden_field_tag :id, workshop.id
= button :deschedule, value: :deschedule_workshop, class: [:delete, :small]
- elsif @can_edit
.title="Block #{time_data[:item][:block] + 1}"
- elsif time_data[:type] != :nil
%td{class: time_data[:type], rowspan: rowspan, colspan: data[:locations].present? ? data[:locations].size : 1}
- case time_data[:type]
- when :meal
- location = EventLocation.where(id: time_data[:item]['location'].to_i).first
- if location.present?
%a.event-detail-link
.details
.title=_!(time_data[:item]['title'])
.location=_!location.title
%template.event-details
%h1.title=_!(time_data[:item]['title'])
%p.address
= _!("#{location.title}:")
= location_link location
- when :event
- if time_data[:item].event_location.present?
%a.event-detail-link
.details
.title=_!(time_data[:item][:title]) if time_data[:item][:title]
.location=_!(time_data[:item].event_location.title)
%template.event-details
%h1.title=_!(time_data[:item][:title]) if time_data[:item][:title]
%p.address
= _!("#{time_data[:item].event_location.title}:")
= location_link time_data[:item].event_location
= richtext time_data[:item][:info], 1
- if @entire_page
#workshop-selector
= form_tag administration_update_path(@this_conference.slug, @admin_step), class: 'workshop-dlg', id: 'workshop-table-form' do
%h3 Select a Workshop
#table

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

@ -5,4 +5,4 @@
- for i in 1..5 do
= numberfield "payment_amounts[#{i - 1}]", payment_amounts[i - 1], step: 0.01, min: 0.00, label: false
.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.form
= hidden_field_tag :workshop_block, block
= button_tag :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 :delete_block, value: :delete_block, class: [:small, :delete] if block == @workshop_blocks.length - 2
= 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}"

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

@ -1,18 +1,17 @@
- links ||= [ :register ]
- 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
= 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
= columns(medium: 10, push: {medium: 1}) do
%h2=_!conference.title if conference.poster.present?
@ -21,13 +20,13 @@
- if conference.workshop_schedule_published
- add_inline_script :home_schedule
%h3=_'articles.workshops.headings.Schedule'
= render 'conferences/admin/schedule'
= render 'conference_administration/schedule'
- else
%h3=_'articles.workshops.headings.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
= (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 (_'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)

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

@ -1,13 +1,13 @@
= columns(medium: 12) do
%p=_"articles.conference_registration.paragraphs.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
%h3=_'articles.conference_registration.headings.Verify_Account'
%p=_'articles.conference_registration.paragraphs.Verify_Account'
%p=_"articles.conference_registration.paragraphs.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
%h3=_'articles.conference_registration.headings.Verify_Account'
%p=_'articles.conference_registration.paragraphs.Verify_Account'
= form_tag register_path(@this_conference.slug), class: 'flex-form' do
.email-field.input-field.big
= email_field_tag :email, nil, required: true
= label_tag :email
= button_tag :continue, :value => :confirm_email
= form_tag register_path(@this_conference.slug), class: 'flex-form' do
.email-field.input-field.big
= email_field_tag :email, nil, required: true
= label_tag :email
= button :continue, value: :confirm_email
= columns(medium: 12, class: 'flex-column') do
%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]
%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]

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'
= checkboxes :languages, User.AVAILABLE_LANGUAGES, (current_user.languages || [I18n.locale]).map(&:to_sym), 'languages', heading: 'articles.conference_registration.headings.languages'
.actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :contact_info
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true
= button (params[:step] == :save ? :save : :next), value: :contact_info
= 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
= form_tag register_path(@this_conference.slug) do
.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
= row do
= columns(medium: 12) do
%h2=_'articles.conference_registration.headings.email_confirm','Please confirm your email address'
= columns(medium: 12) do
%p=_'articles.conference_registration.paragraphs.email_confirm', :p
= row do
= columns(medium: 12) do
%h2=_'articles.conference_registration.headings.email_confirm','Please confirm your email address'
= columns(medium: 12) do
%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
= textarea :notes, @hosting_data['notes'], help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus
.actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :hosting
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true
= button (params[:step] == :save ? :save : :next), value: :hosting
= 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