Browse Source

Update copy, tests, and administration

development
Godwin 7 years ago
parent
commit
eb4b3c44d6
  1. 39
      app/assets/stylesheets/_application.scss
  2. 61
      app/controllers/conference_administration_controller.rb
  3. 10
      app/controllers/conferences_controller.rb
  4. 30
      app/helpers/widgets_helper.rb
  5. 67
      app/mailers/user_mailer.rb
  6. 8
      app/views/conference_administration/_select_guest_table.html.haml
  7. 11
      app/views/conference_administration/_stats.html.haml
  8. 30
      app/views/conferences/_payment.html.haml
  9. 14
      app/views/conferences/_questions.html.haml
  10. 14
      app/views/registration_steps/_payment_form.html.haml
  11. 18
      app/views/registration_steps/_review.html.haml
  12. 13
      app/views/workshops/_form.html.haml
  13. 2
      app/views/workshops/_show.html.haml
  14. 5
      app/views/workshops/_workshop_previews.html.haml
  15. 4
      app/views/workshops/delete.html.haml
  16. 11
      app/views/workshops/index.html.haml
  17. 2
      app/views/workshops/new.html.haml
  18. 2
      app/views/workshops/show.html.haml
  19. 11
      config/locales/en.yml
  20. 2
      config/routes.rb
  21. 1
      db/schema.rb
  22. 20
      features/registration.feature
  23. 1
      features/step_definitions/interface_steps.rb
  24. 27
      features/support/env.rb
  25. 2
      features/support/helper.rb
  26. 2
      features/support/paths.rb
  27. 6
      features/workshops.feature

39
app/assets/stylesheets/_application.scss

@ -622,6 +622,10 @@ button,
&.center {
text-align: center;
button, .button {
margin-left: 0.5em;
}
}
&.right {
@ -654,6 +658,10 @@ button,
button[value="cancel"], button.red {
background-color: $red;
}
button.back {
background-color: $mid-gray;
}
}
#main {
@ -694,9 +702,23 @@ button,
font-size: 0.9em;
}
.option-space {
margin: 1.5em 0;
}
.setting-option {
p {
display: inline-block;
margin: 0;
}
button {
vertical-align: middle;
}
}
.custom-option {
text-align: right;
border: 0.1rem solid $black;
background-color: $white;
input {
@ -708,13 +730,15 @@ button,
border-right: 0;
text-align: center;
background-color: transparent;
border: 0.05rem solid $black;
border-bottom-style: none;
}
button {
width: 100%;
margin: 0;
border: 0;
border-top: inherit;
// border: 0;
// border-top: inherit;
background-color: lighten($colour-1, 25%);
}
}
@ -3884,16 +3908,19 @@ body.policy .policy-agreement ul {
.custom-option {
margin-top: 1em;
display: table-row;
input {
display: table-cell;
width: 10em;
// width: 10em;
width: 50%;
border-right-style: none;
border-bottom-style: solid;
}
button {
display: table-cell;
width: 50%;
border-top: 0;
border-left: inherit;
}
}
}

61
app/controllers/conference_administration_controller.rb

@ -70,6 +70,17 @@ class ConferenceAdministrationController < ApplicationController
end
end
def previous_stats
set_conference
conference = Conference.find_by_slug(params[:conference_slug])
return do_403 unless conference.is_public
get_stats(false, nil, conference)
logger.info "Generating #{conference.slug}.xls"
return respond_to do |format|
format.xlsx { render xlsx: '../conferences/stats', filename: "stats-#{conference.slug}" }
end
end
rescue_from ActiveRecord::PremissionDenied do |exception|
do_403
end
@ -195,7 +206,7 @@ class ConferenceAdministrationController < ApplicationController
end
end
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "organizations" }
format.xlsx { render xlsx: '../conferences/stats', filename: "organizations" }
end
end
end
@ -211,7 +222,7 @@ class ConferenceAdministrationController < ApplicationController
if request.format.xlsx?
logger.info "Generating stats.xls"
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
format.xlsx { render xlsx: '../conferences/stats', filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end
end
@ -251,7 +262,7 @@ class ConferenceAdministrationController < ApplicationController
if request.format.xlsx?
logger.info "Generating stats.xls"
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
format.xlsx { render xlsx: '../conferences/stats', filename: "stats-#{DateTime.now.strftime('%Y-%m-%d')}" }
end
else
@registration_count = @registrations.size
@ -277,6 +288,11 @@ class ConferenceAdministrationController < ApplicationController
end
end
end
@past_conferences = []
Conference.all.order("start_date DESC").each do |conference|
@past_conferences << conference if conference.is_public && @this_conference.id != conference.id
end
end
end
@ -354,7 +370,7 @@ class ConferenceAdministrationController < ApplicationController
@excel_data[:data] << host_data
end
return respond_to do |format|
format.xlsx { render xlsx: :stats, filename: "housing" }
format.xlsx { render xlsx: '../conferences/stats', filename: "housing" }
end
end
end
@ -406,8 +422,8 @@ class ConferenceAdministrationController < ApplicationController
def administrate_publish_schedule
end
def get_stats(html_format = false, id = nil)
@registrations = ConferenceRegistration.where(:conference_id => @this_conference.id).sort { |a,b| (a.user.present? ? (a.user.firstname || '') : '').downcase <=> (b.user.present? ? (b.user.firstname || '') : '').downcase }
def get_stats(html_format = false, id = nil, conference = @this_conference)
@registrations = ConferenceRegistration.where(conference_id: conference.id).sort { |a,b| (a.user.present? ? (a.user.firstname || '') : '').downcase <=> (b.user.present? ? (b.user.firstname || '') : '').downcase }
@excel_data = {
columns: [
:name,
@ -429,7 +445,6 @@ class ConferenceAdministrationController < ApplicationController
:food,
:companion,
:companion_email,
:allergies,
:other,
:can_provide_housing,
:first_day,
@ -448,7 +463,6 @@ class ConferenceAdministrationController < ApplicationController
arrival: [:date, :day],
departure: [:date, :day],
registration_fees_paid: :money,
allergies: :text,
other: :text,
first_day: [:date, :day],
last_day: [:date, :day],
@ -470,7 +484,6 @@ class ConferenceAdministrationController < ApplicationController
food: 'forms.labels.generic.food',
companion: 'articles.conference_registration.terms.companion',
companion_email: 'articles.conference_registration.terms.companion_email',
allergies: 'forms.labels.generic.allergies',
registration_fees_paid: 'articles.conference_registration.headings.fees_paid',
other: 'forms.labels.generic.other_notes',
can_provide_housing: 'articles.conference_registration.can_provide_housing',
@ -485,6 +498,11 @@ class ConferenceAdministrationController < ApplicationController
},
data: []
}
if conference.id != @this_conference.id
@excel_data[:columns] -= [:name, :email]
end
User.AVAILABLE_LANGUAGES.each do |l|
@excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}"
end
@ -524,10 +542,9 @@ class ConferenceAdministrationController < ApplicationController
bike: r.bike.present? ? (view_context._"articles.conference_registration.questions.bike.#{r.bike}") : '',
food: r.food.present? ? (view_context._"articles.conference_registration.questions.food.#{r.food}") : '',
companion: companion,
companion_email: (housing_data['companions'] || ['']).first,
allergies: r.allergies,
companion_email: (housing_data['companion'] || { 'email' => ''})['email'],
registration_fees_paid: r.registration_fees_paid,
other: r.other,
other: r.allergies.present? ? "#{r.allergies}\n\n#{r.other}" : r.other,
can_provide_housing: r.can_provide_housing ? (view_context._'articles.conference_registration.questions.bike.yes') : '',
first_day: availability[0].present? ? availability[0].strftime("%F %T") : '',
last_day: availability[1].present? ? availability[1].strftime("%F %T") : '',
@ -677,12 +694,16 @@ class ConferenceAdministrationController < ApplicationController
@housing_data[host_id][:guest_data][guest_id][:warnings][:space] = { actual: (view_context._"forms.labels.generic.#{space.to_s}"), expected: (view_context._"articles.conference_registration.questions.housing.#{guest.housing}")}
end
companions = data['companions'] || []
companions.each do |companion|
user = User.find_user(companion)
if user.present?
if data['companion'].present?
companion = if data['companion']['id'].present?
User.find(data['companion']['id'])
else
User.find_user(data['companion']['email'])
end
if companion.present?
reg = ConferenceRegistration.find_by(
user_id: user.id,
user_id: companion.id,
conference_id: @this_conference.id
)
if reg.present? && @guests[reg.id].present?
@ -1010,7 +1031,9 @@ class ConferenceAdministrationController < ApplicationController
registration.send("#{key.to_s}=", value.present? ? Date.parse(value) : nil)
when :companion_email
registration.housing_data ||= {}
registration.housing_data['companions'] = [value]
registration.housing_data['companion'] ||= {}
registration.housing_data['companion']['email'] = value
registration.housing_data['companion']['id'] = User.find_user(value)
when :preferred_language
registration.user.locale = value
user_changed = true
@ -1112,7 +1135,7 @@ class ConferenceAdministrationController < ApplicationController
do_404
end
return true
return nil
end
def admin_update_broadcast

10
app/controllers/conferences_controller.rb

@ -8,7 +8,7 @@ class ConferencesController < ApplicationController
def list
@page_title = 'articles.conferences.headings.Conference_List'
@conference_list = { future: [], passed: [] }
Conference.all.order("start_date DESC").each do | conference |
Conference.all.order("start_date DESC").each do |conference|
if conference.is_public || conference.host?(current_user)
@conference_list[conference.over? ? :passed : :future] << conference
end
@ -337,10 +337,10 @@ class ConferencesController < ApplicationController
if @registration.housing_data.blank?
ConferenceRegistration.where(
conference_id: @this_conference.id, can_provide_housing: [nil, false]
).where.not(housing_data: nil).each do | r |
).where.not(housing_data: nil).each do |r|
@registration.housing_data = {
companions: [ r.user.email ]
} if r.housing_data['companions'].present? && r.housing_data['companions'].include?(current_user.email)
} if r.housing_data['companion'].present? && (r.housing_data['companion']['id'] == current_user.id || r.housing_data['companion']['email'] == current_user.email)
end
@registration.housing_data ||= { }
@ -358,7 +358,7 @@ class ConferencesController < ApplicationController
@workshops = Array.new
# put wach workshop into the correct array
Workshop.where(conference_id: @this_conference.id).each do | workshop |
Workshop.where(conference_id: @this_conference.id).each do |workshop|
if workshop.active_facilitator?(current_user)
@my_workshops << workshop
elsif workshop.requested_collaborator?(current_user)
@ -436,7 +436,7 @@ class ConferencesController < ApplicationController
def registration_complete?(registration = @registration)
completed_steps = registration.steps_completed || []
required_steps(registration.conference).each do | step |
required_steps(registration.conference).each do |step|
return true if step == :workshops
return false unless completed_steps.include?(step.to_s)
end

30
app/helpers/widgets_helper.rb

@ -100,14 +100,14 @@ module WidgetsHelper
id = registration.id
html = ''
@housing_data[id][:guests].each do | area, guests |
@housing_data[id][:guests].each do |area, guests|
guest_rows = ''
guests.each do | guest_id, guest |
guests.each do |guest_id, guest|
status_html = ''
@housing_data[id][:guest_data][guest_id][:errors].each do | error, value |
@housing_data[id][:guest_data][guest_id][:errors].each do |error, value|
if value.is_a?(Array)
value.each do | v |
value.each do |v|
status_html += content_tag(:li, _("errors.messages.housing.space.#{error.to_s}", vars: v))
end
else
@ -115,9 +115,9 @@ module WidgetsHelper
end
end
@housing_data[id][:guest_data][guest_id][:warnings].each do | error, value |
@housing_data[id][:guest_data][guest_id][:warnings].each do |error, value|
if value.is_a?(Array)
value.each do | v |
value.each do |v|
status_html += content_tag(:li, _("warnings.messages.housing.space.#{error.to_s}", v))
end
else
@ -132,7 +132,7 @@ module WidgetsHelper
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 +
(guest[:guest].from +
(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])
@ -151,7 +151,7 @@ module WidgetsHelper
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 |
@housing_data[id][:warnings][:space][area].each do |w|
status_html += content_tag(:li, _("warnings.messages.housing.space.#{w.to_s}"))
end
end
@ -179,18 +179,18 @@ module WidgetsHelper
classes = ['host']
id = registration.id
@housing_data[id][:guests].each do | area, guests |
@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 |
@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 |
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)
@ -258,8 +258,12 @@ module WidgetsHelper
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 registration.housing_data.present? && registration.housing_data['companion'].present?
companion_user = if registration.housing_data['companion']['id'].present?
User.find(registration.housing_data['companion']['id'])
else
User.find_user(registration.housing_data['companion']['email'])
end
if companion_user.present?
cr = ConferenceRegistration.where(user_id: companion_user.id).order(created_at: :desc).limit(1).first

67
app/mailers/user_mailer.rb

@ -11,8 +11,7 @@ class UserMailer < ActionMailer::Base
def email_confirmation(confirmation)
@confirmation = EmailConfirmation.find(confirmation) if confirmation.present?
I18n.locale = @confirmation.user.locale if @confirmation.user.locale.present?
@subject = _'email.subject.confirm_email','Please confirm your email address'
mail to: @confirmation.user.named_email, subject: @subject
mail to: @confirmation.user.named_email, subject: clean_subject(_'email.subject.confirm_email','Please confirm your email address')
end
def registration_confirmation(registration)
@ -20,17 +19,17 @@ class UserMailer < ActionMailer::Base
@conference = @registration.conference
@user = @registration.user
I18n.locale = @user.locale if @user.locale.present?
@subject = @conference.registration_status.to_sym == :pre ?
subject = @conference.registration_status.to_sym == :pre ?
_(
'email.subject.pre_registration_confirmed',
"Thank you for pre-registering for #{@conference.title}",
:vars => {:conference_title => @conference.title}
vars: {conference_title: @conference.title}
) : _(
'email.subject.registration_confirmed',
"Thank you for registering for #{@conference.title}",
:vars => {:conference_title => @conference.title}
vars: {conference_title: @conference.title}
)
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(subject)
end
def broadcast(host, subject, content, user, conference)
@ -39,9 +38,8 @@ class UserMailer < ActionMailer::Base
@banner = nil
@conference = Conference.find(conference) if conference.present?
@user = User.find(user) if user.present?
@subject = "[#{@conference ? @conference.title : 'Bike!Bike!'}] #{subject}"
if @user && @user.named_email
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject("[#{@conference ? @conference.title : 'Bike!Bike!'}] #{subject}")
end
end
@ -55,10 +53,8 @@ class UserMailer < ActionMailer::Base
end
@message = message
@conference = Conference.find(@workshop.conference_id)
@subject = _('email.subject.workshop_facilitator_request',
"Request to facilitate #{@workshop.title} from #{@requester.name}",
:vars => {:workshop_title => @workshop.title, :requester_name => @requester.firstname})
mail to: addresses, reply_to: addresses + [@requester.named_email], subject: @subject
subject = ActionView::Base.full_sanitizer.sanitize(_('email.subject.workshop_facilitator_request', vars: { workshop_title: @workshop.title, requester_name: @requester.firstname }))
mail to: addresses, reply_to: addresses + [@requester.named_email], subject: clean_subject(subject)
end
def workshop_facilitator_request_approved(workshop, user)
@ -66,10 +62,7 @@ class UserMailer < ActionMailer::Base
@conference = Conference.find(@workshop.conference_id)
@user = User.find(user) if user.present?
I18n.locale = @user.locale if @user.locale.present?
@subject = (_'email.subject.workshop_request_approved',
"You have been added as a facilitator of #{@workshop.title}",
:vars => {:workshop_title => @workshop.title})
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(_('email.subject.workshop_request_approved', vars: { workshop_title: @workshop.title }))
end
def workshop_facilitator_request_denied(workshop, user)
@ -77,10 +70,7 @@ class UserMailer < ActionMailer::Base
@conference = @workshop.conference
@user = User.find(user) if user.present?
I18n.locale = @user.locale if @user.present? && @user.locale.present?
@subject = (_'email.subject.workshop_request_denied',
"Your request to facilitate #{@workshop.title} has been denied",
:vars => {:workshop_title => @workshop.title})
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(_'email.subject.workshop_request_denied', vars: { workshop_title: @workshop.title })
end
def workshop_translated(workshop, data, locale, user, translator)
@ -91,13 +81,10 @@ class UserMailer < ActionMailer::Base
@user = User.find(user) if user.present?
I18n.locale = @user.locale if @user.present? && @user.locale.present?
@translator = User.find(translator) if translator.present?
@subject = (_'email.subject.workshop_translated',
"The #{@locale_name} translation for #{@workshop.title} has been modified",
vars: {language: @language_name, workshop_title: @workshop.title})
@wrapper_id = :full_width
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(_'email.subject.workshop_translated', vars: { language: @language_name, workshop_title: @workshop.title })
end
def workshop_original_content_changed(workshop, data, user, translator)
@ -106,9 +93,6 @@ class UserMailer < ActionMailer::Base
@user = User.find(user) if user.present?
I18n.locale = @user.locale if @user.present? && @user.locale.present?
@translator = User.find(translator) if translator.present?
@subject = (_'email.subject.workshop_original_content_changed',
"Original content for #{@workshop.title} has been modified",
vars: {workshop_title: @workshop.title})
@data.each do |field, values|
diff = Diffy::Diff.new(values[:old], values[:new])
@data[field][:diff] = {
@ -119,7 +103,7 @@ class UserMailer < ActionMailer::Base
@wrapper_id = :full_width
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(_'email.subject.workshop_original_content_changed', vars: { workshop_title: @workshop.title })
end
def workshop_comment(workshop, comment, user)
@ -128,17 +112,16 @@ class UserMailer < ActionMailer::Base
@user = User.find(user) if user.present?
I18n.locale = @user.locale if @user.present? && @user.locale.present?
if @comment.reply?
@subject = (_'email.subject.workshop_comment.reply', vars: { user_name: @comment.user.name })
else
@subject = (_'email.subject.workshop_comment.comment', vars: { user_name: @comment.user.name, workshop_title: @workshop.title })
end
subject = if @comment.reply?
(_'email.subject.workshop_comment.reply', vars: { user_name: @comment.user.name })
else
(_'email.subject.workshop_comment.comment', vars: { user_name: @comment.user.name, workshop_title: @workshop.title })
end
mail to: @user.named_email, subject: @subject
mail to: @user.named_email, subject: clean_subject(subject)
end
def error_report(subject, message, report, exception, request, params, user, time = nil)
@subject = subject
@message = message
@report = report
@exception = exception
@ -146,25 +129,23 @@ class UserMailer < ActionMailer::Base
@params = params
@time = time
@user = User.find(user) if user.present?
mail to: 'goodgodwin@hotmail.com', subject: @subject
mail to: 'goodgodwin@hotmail.com', subject: clean_subject(subject)
end
def contact(from, subject, message, email_list)
@message = message
@subject = subject
@from = from.is_a?(Integer) ? User.find(from) : from
mail to: email_list.join(', '), subject: @subject, reply_to: @from.is_a?(User) ? @from.named_email : @from
mail to: email_list.join(', '), subject: clean_subject(subject), reply_to: @from.is_a?(User) ? @from.named_email : @from
end
def contact_details(from, subject, message, request, params)
@message = message
@subject = "Details for: \"#{subject}\""
@from = from.is_a?(Integer) ? User.find(from) : from
@request = request
@params = params
mail to: 'goodgodwin@hotmail.com', subject: @subject
mail to: 'goodgodwin@hotmail.com', subject: clean_subject("Details for: \"#{subject}\"")
end
private
@ -178,4 +159,10 @@ class UserMailer < ActionMailer::Base
end
default_url_options[:host] = @host
end
def clean_subject(subject)
subject = ActionView::Base.full_sanitizer.sanitize(subject) unless Rails.env.test?
@subject = subject
return subject
end
end

8
app/views/conference_administration/_select_guest_table.html.haml

@ -16,23 +16,27 @@
%table.guests.admin-edit
%tr
%th.corner
%th=_'forms.labels.generic.organization'
%th=_'forms.labels.generic.city'
%th=_'forms.labels.generic.housing'
%th=_'articles.admin.housing.headings.arrival_departure'
%th=_'articles.conference_registration.headings.companion'
%th=_'forms.labels.generic.food'
%th=_'forms.labels.generic.allergies'
%th=_'forms.labels.generic.other'
- @guests.each do | id, registration |
%tr.selectable{class: get_housing_match(host, registration, space).to_s.gsub('_', '-'), data: {host: host.id, guest: id, space: space}}
%th=registration.user.name
%td
- if registration.user.organizations.present?
= registration.user.organizations.first.name
- else
%em None
%td=registration.city
%td=registration.housing.present? ? (_"articles.conference_registration.questions.housing.#{registration.housing}") : ''
%td=date_span(registration.arrival.to_date, registration.departure.to_date)
- companion = companion(registration)
%td=companion.present? ? (companion.is_a?(User) ? companion.named_email : (_"articles.conference_registration.terms.registration_status.#{companion}")) : ''
%td=registration.food.present? ? (_"articles.conference_registration.questions.food.#{registration.food}") : ''
%td=registration.allergies
%td
.p=registration.other

11
app/views/conference_administration/_stats.html.haml

@ -16,6 +16,11 @@
= (@completed_registrations || 0) > 0 ? "#{@donation_count} (#{number_to_percentage(@donation_count / @completed_registrations.to_f * 100.0)})" : "0"
= data_set(:h3, 'articles.admin.stats.headings.donation_total') do
= "$#{@donations || 0.00}"
.actions
= link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :stats, :format => :xlsx), class: [:button, :download]
= link_to (_'links.download.Organizations_Excel'), administration_step_path(@this_conference.slug, :organizations, :format => :xlsx), class: [:button, :download, :subdued]
.actions.center
= link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :stats, format: :xlsx), class: [:button, :download]
= link_to (_'links.download.Organizations_Excel'), administration_step_path(@this_conference.slug, :organizations, format: :xlsx), class: [:button, :download, :subdued]
= columns(medium: 12) do
%h3=_'articles.admin.stats.headings.past_stats'
%ul.actions.center
- @past_conferences.each do |conference|
= link_to conference.title, previous_stats_path(@this_conference.slug, conference.slug, format: :xlsx), class: [:button, :download]

30
app/views/conferences/_payment.html.haml

@ -1,30 +0,0 @@
= columns(medium: 12) do
- if @registration.registration_fees_paid.present?
%p
%strong=_'articles.conference_registration.paragraphs.Payment_Made', :p, vars: { fees_paid: (number_to_currency @registration.registration_fees_paid, unit: '$') }
= _'articles.conference_registration.paragraphs.Payment_Add'
= @this_conference.payment_message.html_safe if @this_conference.payment_message.present?
- elsif @this_conference.payment_message.present?
= @this_conference.payment_message.html_safe
- else
%p=@this_conference.payment_message || (_'articles.conference_registration.paragraphs.Payment', :p)
= columns(large: 9, push: 1) do
= show_errors :payment
= form_tag register_path(@this_conference.slug), class: :payment do
= hidden_field_tag :button, :payment
- payment_amounts = @this_conference.payment_amounts.present? ? @this_conference.payment_amounts : Conference.default_payment_amounts
.graded-options{class: "option-count-#{payment_amounts.size}"}
- payment_amounts.each_with_index do | amount, i |
= button :amount_25, name: :amount, value: amount.to_f.to_s, class: "option-#{i + 1}" do
=_! (number_to_currency amount, unit: '$')
= form_tag register_path(@this_conference.slug), class: ['custom-payment', :centered] do
%span.currency=_!'$' # TODO: this needs to be localized
= numberfield :amount, nil, required: true, step: 0.01, min: 0.00, label: false
= button :custom_amount, value: :payment
%p=_'articles.conference_registration.paragraphs.currency','(amounts are in $USD)'
= form_tag register_path(@this_conference.slug), class: :payment do
= hidden_field_tag :button, :payment
.actions.skip
= button :skip, name: :amount, value: '0.0'
= columns(large: 2)

14
app/views/conferences/_questions.html.haml

@ -1,14 +0,0 @@
= columns(medium: 12) do
%p=_'articles.conference_registration.paragraphs.Registration_Info', :p, vars: { city: @this_conference.city_name }
= form_tag register_path(@this_conference.slug), class: [:centered, :clearfix] do
= columns(medium: 12) do
= radiobuttons :housing, ConferenceRegistration.all_housing_options, @registration.housing, 'articles.conference_registration.questions.housing', heading: 'articles.conference_registration.headings.housing', vertical: true, big: true, inline: true
= fieldset :hosting_dates, heading: 'articles.conference_registration.headings.arrival_and_departure', vars: { city: @this_conference.city_name } do
= selectfield :arrival, @registration.arrival || @this_conference.start_date, conference_days_options_list(:before_plus_one)
= selectfield :departure, @registration.departure || @this_conference.start_date, conference_days_options_list(:after_minus_one)
= radiobuttons :bike, ConferenceRegistration.all_bike_options, @registration.bike, 'articles.conference_registration.questions.bike', heading: 'articles.conference_registration.headings.bike', inline: true, big: true
= radiobuttons :food, ConferenceRegistration.all_food_options, @registration.food, 'articles.conference_registration.questions.food', heading: 'articles.conference_registration.headings.food', inline: true, big: true
= emailfield :companion, (@registration.housing_data['companions'] || [nil]).first, heading: 'articles.conference_registration.headings.companion', help: 'articles.conference_registration.paragraphs.companion', big: true
= textfield :allergies, @registration.allergies, heading: 'articles.conference_registration.headings.allergies'
= textarea :other, @registration.other, plain: true, heading: 'articles.conference_registration.headings.other'
= button :register, value: :questions

14
app/views/registration_steps/_payment_form.html.haml

@ -11,14 +11,16 @@
%p.center=_"articles.conference_registration.paragraphs.currency_details", :p, vars: { currency: (_"currencies.#{(@currencies || [@currency]).first}.displayName-count-other") }
= save_registration_step do
.registration-step-options
- if @currencies.present? && @currencies.length > 1
= radiobuttons :currency, (@currencies.map { |c| [(_"currencies.#{c}.displayName-count-other"), c] }), @currency
.options.graded-options{class: "option-count-#{@amounts.size}"}
- @amounts.each_with_index do |option, i|
= button (number_to_currency option, unit: '$'), value: option, name: :value, class: [:unstyled, "option-#{i + 1}"]
= button "#{number_to_currency option, unit: '$'} #{_!@currency}".html_safe, value: option, name: :value, class: [:unstyled, "option-#{i + 1}"]
.option-space
.custom-option
-# if Rails.env.test?
=# text_field_tag :custom_value, nil
-# else
= number_field_tag :custom_value, 50.0, step: 0.05, min: 0.05
= button :custom_amount, name: :custom_amount, value: :custom, class: :unstyled
- if @currencies.present? && @currencies.length > 1
.option-space
.setting-option
%p Change currency to:
- (@currencies - [@currency]).each do |c|
= button (_"currencies.#{c}.displayName-count-other"), name: :currency, value: c, class: :unstyled

18
app/views/registration_steps/_review.html.haml

@ -41,8 +41,22 @@
= row do
= columns(medium: 12) do
%h3=_'articles.workshops.headings.Workshops', :t
%p=_'articles.conference_registration.paragraphs.workshops', :p
- if @this_conference.workshop_info.present?
= richtext @this_conference.workshop_info
- else
%p=_'articles.conference_registration.paragraphs.workshops', :p
.actions.centered
.buttons
= link_to (_'articles.conference_registration.actions.View_Workshops'), workshops_path(@this_conference), class: :button
= link_to (_'actions.workshops.create'), create_workshop_path(@this_conference), class: [:button, :modify]
= link_to (_'actions.workshops.create'), create_workshop_path(@this_conference), class: [:button, :modify]
- if @my_workshops.present?
= row do
= columns(medium: 12) do
%h3=_'articles.workshops.headings.Your_Workshops'
= render 'workshops/workshop_previews', workshops: @my_workshops
= row do
= columns(medium: 12) do
%h3=_'articles.workshops.headings.Workshops_that_you_would_like_to_attend'
%p=_'articles.workshops.paragraphs.Workshops_that_you_would_like_to_attend', :p
- if @interested_workshops.present?
= render 'workshops/workshop_previews', workshops: @interested_workshops

13
app/views/workshops/_form.html.haml

@ -1,13 +0,0 @@
= form_for @workshop, url: conference_workshops_path(@conference, @workshop) do |f|
.columns
= f.text_field :title
= f.text_field :slug
.columns.medium-4
%h2=_'workshop.form.help.title', :t
=_'workshop.form.help', :p
.columns.medium-8
= f.text_area :info
= f.number_field :workshop_stream_id
= f.number_field :workshop_presentation_style
.columns
= f.actions :save

2
app/views/workshops/_show.html.haml

@ -11,7 +11,7 @@
%span.interest-text=interest_text(workshop)
= richtext workshop.info
- if preview.blank? && translations_available_for_editing
.actions
.actions.center
- translations_available_for_editing.each do |locale|
= link_to (_'actions.workshops.Translate', "Translate into #{language_name(locale)}", :vars => {:language => language_name(locale)}), translate_workshop_url(workshop.conference.slug, workshop.id, locale), :class => [:button, :translate]
= columns(medium: 6) do

5
app/views/workshops/_workshop_previews.html.haml

@ -1,8 +1,9 @@
- depth ||= 4
%ul.workshop-list
- workshops.sort_by{ |w| w.title.downcase }.each do |w|
- is_interested = w.interested?(current_user)
%li{class: [is_interested ? :interested : nil]}
%h4.title=_!(w.title)
= content_tag("h#{depth}", w.title, class: :title)
.workshop-interest
- if w.can_show_interest?(current_user)
= form_tag toggle_workshop_interest_path(w.conference.slug, w.id), class: 'js-xhr' do
@ -10,6 +11,6 @@
%span.interest-button=interest_button(w)
- elsif w.interested_count > 0
%span.interest-text=interest_text(w)
.workshop-description=richtext w.info, 4
.workshop-description=richtext w.info, depth
.actions.right
= link_to (_'articles.workshops.info.read_more'), view_workshop_path(w.conference.slug, w.id), class: ['workshop-link', :button, :small]

4
app/views/workshops/delete.html.haml

@ -5,7 +5,7 @@
%h2=_'articles.workshops.headings.Delete_Workshop',"Are you sure you want to delete the workshop: <em>#{@workshop.title}</em>?", vars: {title: "<em>#{@workshop.title}</em>".html_safe}
%p=_'articles.workshops.paragraphs.Delete_Workshop'
= form_tag delete_workshop_path(@this_conference.slug, @workshop.id), class: 'composition' do
.actions
.actions.center
= button :confirm, value: :confirm, class: :delete
= button :cancel, value: :cancel
= button :cancel, value: :cancel, class: :back

11
app/views/workshops/index.html.haml

@ -12,13 +12,8 @@
= row do
= columns(medium: 12) do
%p=_'articles.workshops.paragraphs.Workshops', :p
.actions.center
= link_to (_'actions.workshops.create','New Workshop'), create_workshop_path(@this_conference.slug), class: [:button, :modify] if @this_conference.registration_open
= row do
= columns(medium: 12) do
%h3=_'articles.workshops.headings.Your_Workshops'
= render 'workshops/workshop_previews', workshops: @my_workshops
= link_to (_'actions.workshops.create','New Workshop'), create_workshop_path(@this_conference.slug), class: [:button, :modify] if @conference.registration_open
= row do
= columns(medium: 12) do
%h3=_'articles.conference_registration.headings.All_Workshops'
-#%h3 All Workshops weather you like it or not
= render 'workshops/workshop_previews', workshops: @workshops
= render 'workshops/workshop_previews', workshops: @workshops, depth: 3

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

@ -33,7 +33,7 @@
= columns(medium: 12) do
= textarea :notes, @workshop.notes, warning: 'articles.workshops.paragraphs.notes'
= columns(medium: 12) do
.actions.next-prev
.actions.center
= button :save, value: :save
= button :cancel, value: :cancel, class: :subdued, formnovalidate: true

2
app/views/workshops/show.html.haml

@ -10,6 +10,6 @@
= render 'workshops/show', workshop: @workshop, translations_available_for_editing: @translations_available_for_editing, preview: false
= row do
= columns(medium: 12) do
.actions.next-prev
.actions.center
= (link_to (_'actions.workshops.Edit'), edit_workshop_path(@this_conference.slug, @workshop.id), :class => [:button, :modify]) if @workshop.can_edit?(current_user)
= (link_to (_'actions.workshops.Delete'), delete_workshop_path(@this_conference.slug, @workshop.id), :class => 'button delete') if @workshop.can_delete?(current_user)

11
config/locales/en.yml

@ -1380,6 +1380,7 @@ en:
so far as well as download more detailed data in spreadsheets.
headings:
bikes: Bikes
past_stats: Statistics from Previous Bike!Bike!s
donation_count: Number of donations
donation_total: Total donated
food:
@ -1449,7 +1450,7 @@ en:
instead of a guest form. If you want to consider surrounding cities as
well, enter the distance from %{city} that you wish to be included as
providers. Cities are measured from center to center.
housing: Pair each housing provider with a list of guests.
housing: Pair each housing provider with a list of guests. Try to match guests with hosts and other guests who are good matches and respect their requests, but also keep in mind that we cannot always respect all requests and part of the Bike!Bike! experience is getting to know new people.
locations:
heading: Locations
description: Locations are used to schedule workshops, events, and meals.
@ -1705,7 +1706,7 @@ en:
payment_form: Registration Fee Amount
org_select: Which organization are you a member of?
payment_type: Registration Fee Method
housing_other: Anything else?
housing_other: Other considerations
housing_allergies: Do you have any allergies?
housing_food: What are your eating habits?
housing_bike: Would you like to borrow a bike?
@ -1753,6 +1754,7 @@ en:
Workshops: Workshops
workshops: Workshops
Your_Workshops: Your Workshops
Workshops_that_you_would_like_to_attend: Workshops that you would like to_attend
payment_confirm: Please confirm your payment
Preview: Preview
city: City
@ -1814,7 +1816,7 @@ en:
payment_form: Please select one of the predefined options below or enter a custom amount.
org_select: Please select the organization that you will be representing. This information will be used to help us contact and invite your organization next year and to populate the list of known organizations that will be displayed on bikecollectives.org. If you are involved with multiple oganizations, please select one for now, you will be able to add more organizations at a later date.
payment_type: Registration is by donation but it enables us to pay for spaces, food, equipment, and more. If you can, paying now via PayPal enables us to prepare for the conference without risk of paying out of pocket. Otherwise, pleging to pay on arrival will help us to get a rough idea of what we can and cannot afford.
housing_other: Is there anything else that you would like to let us know?
housing_other: Do you have any special needs or considerations that we should know about for your stay such as allergies, disabilities, or a need for child care? Letting us know in advance will help us determine the best place for you to stay and make any necessary preparations for te conference itself.
housing_allergies: Let us know if you have any allergies that we should be made aware of.
housing_food: Please let us know your eating habits by selecting the option that best describes the type of food that you eat. We will use this to decide the best types of meals to prepare and how much food we will need.
housing_bike: In order for us to get an idea of how many bikes we will need to prepare, please let us know if you would like to borrow a bike from us.
@ -2083,12 +2085,14 @@ en:
notes: Notes
Workshops: Workshops
Your_Workshops: Your Workshops
Workshops_that_you_would_like_to_attend: Workshops that you would like to attend
facilitate: Request to Facilitate ‘%{workshop_title}’
add_facilitator: Add a facilitator
needs_facilitators: Looking for help?
Comments: Comments
Schedule: Schedule
paragraphs:
Workshops_that_you_would_like_to_attend: Add workshops to your schedule by pressing the "+1" button beside a workshop. This will help you keep track of the wokshops that you would like to attend and help organizers to create a better schedule.
Proposed_Workshops: Would you like to facilitate your own workshop? Simply
register and visit the workshops page. If you have already registered you
can access the page by restarting the registration process.
@ -2223,6 +2227,7 @@ en:
send_to: Send To
street_address: Street Address
city: City
organization: Organization
subregion: State / Province
country: Country
postal_code: Postal Code

2
config/routes.rb

@ -18,7 +18,6 @@ BikeBike::Application.routes.draw do
# post 'update' => 'conferences#registration_update', as: :registration_update
get ':step' => 'conferences#register', as: :register_step
# get ':button/:confirmation_token' => 'conferences#register', as: :register_paypal_confirm
end
# Administration
@ -26,6 +25,7 @@ BikeBike::Application.routes.draw do
root 'conference_administration#administration', as: :administrate_conference
get ':step' => 'conference_administration#administration_step', as: :administration_step
get 'stats/:conference_slug' => 'conference_administration#previous_stats', as: :previous_stats
post 'update/:step' => 'conference_administration#admin_update', as: :administration_update
get 'events/edit/:id' => 'conference_administration#edit_event', as: :edit_event
get 'locations/edit/:id' => 'conference_administration#edit_location', as: :edit_location

1
db/schema.rb

@ -110,7 +110,6 @@ ActiveRecord::Schema.define(version: 20170609030149) do
t.boolean "is_participant"
t.boolean "is_volunteer"
t.string "confirmation_token"
t.binary "data_old"
t.string "email"
t.boolean "complete"
t.boolean "completed"

20
features/registration.feature

@ -13,7 +13,7 @@ Feature: Registration
When I enter my email address
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email
@ -80,7 +80,7 @@ Feature: Registration
Then I should see 'Do you plan to attend the group ride?'
When I click on the 'Yes' button
Then I should see 'Anything else?'
Then I should see 'Other considerations'
When I fill in other with 'Thanks!'
And click the 'Next' button
@ -90,7 +90,7 @@ Feature: Registration
Then I should see 'Registration Fee Amount'
When I click on the '$25.00' button
Then I should get a 'Thank you for registering for Bike!Bike! 2025' email
Then I should get a 'Thank you for registering' email
And I should see 'Your registration is complete'
And I should see 'Seattle'
And see 'Bike Works'
@ -134,7 +134,7 @@ Feature: Registration
When I enter my email address
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email
@ -196,7 +196,7 @@ Feature: Registration
And click on 'pay now with PayPal'
And click on the '$25.00' button
And click the 'Confirm' button
Then I should get a 'Thank you for registering for Bike!Bike! 2025' email
Then I should get a 'Thank you for registering' email
And I should see 'Moncton'
And I should see 'Coopérative La Bikery Cooperative'
And I should see 'I don't need a place to stay'
@ -215,7 +215,7 @@ Feature: Registration
When I enter my email address
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email
@ -263,7 +263,7 @@ Feature: Registration
And click on the 'No' button
And click the 'Next' button
And click on the 'Not now' button
Then I should get a 'Thank you for registering for Bike!Bike! 2025' email
Then I should get a 'Thank you for registering' email
And I should see 'Ecum Secum'
And I should see 'Because Reasons'
And I should see 'I am vegetarian'
@ -281,7 +281,7 @@ Feature: Registration
When I enter my email address
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email
@ -379,7 +379,7 @@ Feature: Registration
When I enter my email address as 'me@bikebike.org'
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email
@ -543,7 +543,7 @@ Scenario: Housing providers can enter incorrect data and fix it
When I enter my email address
And press confirm email
Then I should see 'Confirm Email'
Then I should see 'Confirmation Sent'
And I should get a 'confirmation' email
When I click on the 'Confirm' link in the email

1
features/step_definitions/interface_steps.rb

@ -162,5 +162,6 @@ Then /^(?:my |the )([A-Z][a-z]+ )?(workshop|conference|user|conference registrat
object = TestState.send("last_#{type.gsub(' ', '_')}")
attribute = attribute.gsub(' ', '_').downcase
actual_value = locale ? object.get_column_for_locale!(attribute, get_locale(locale)) : object.send(attribute)
actual_value = ActionView::Base.full_sanitizer.sanitize(actual_value)
expect(actual_value).send(negate ? :not_to : :to, (be == value))
end

27
features/support/env.rb

@ -69,12 +69,32 @@ After do
DatabaseCleaner.clean
end
AfterStep do
def step_wait_time(keyword)
# give additional wait time to Given and When steps
if keyword == 'And' || keyword == 'But'
keyword = @_last_keyword
end
@_last_keyword = keyword
case keyword
when 'Given'
return 1
when 'When'
return 3
end
return 0.5
end
AfterStep do |scenario, step|
# capture used selectors to generate css coverage
Marmara.record(page) if Marmara.recording?
Marmara.record(step.source.last.keyword) if Marmara.recording?
# take some extra time between steps if we're recording
sleep(0.5) if LinguaFranca.recording?
keyword = step.source.last.keyword.strip
sleep(step_wait_time(keyword)) if LinguaFranca.recording?
end
Cucumber::Rails::Database.javascript_strategy = :transaction
@ -84,5 +104,4 @@ Geocoder.configure(timeout: 60)
at_exit do
Marmara.stop_recording if Marmara.recording?
# LinguaFranca.capture_translations if LinguaFranca.recording?
end

2
features/support/helper.rb

@ -85,7 +85,7 @@ end
def emails_to(email_address, subject = nil)
ActionMailer::Base.deliveries.select do |mail|
mail.to.include?(email_address) &&
(subject.nil? || mail.subject.downcase.include?(subject.downcase))
(subject.nil? || ActionView::Base.full_sanitizer.sanitize(mail.subject).downcase.include?(subject.downcase))
end
end

2
features/support/paths.rb

@ -22,7 +22,7 @@ module NavigationHelpers
path = :confirm
args << TestState.last_token
when /^google maps$/
path = /^https?:\/\/www\.google\.com\/maps\/place\/.*/
path = /^https?:\/\/www\.google\.com\/maps\/.*/
end
if path.is_a?(Symbol)

6
features/workshops.feature

@ -48,7 +48,7 @@ Feature: Workshops
And should see 'Education'
When I click the 'Workshops' link
Then I should see two workshops
Then I should see one workshop
When I click on the 'Details' link
Then I should see 'Tools'
@ -254,9 +254,7 @@ Feature: Workshops
And I am on the workshops page
Then I should see seven workshops
And I should see two workshops under 'Your Workshops'
And see five workshops under 'All Other Workshops'
Then I should see five workshops
And I should see '3-Speed Hubs and the trouble with Sexism No one is interested in this workshop yet'
And see 'Bike Polo! Mallet making and game 5 people are interested in this workshop'
And see 'The future of Bike! Bike! 10 people are interested in this workshop'

Loading…
Cancel
Save