diff --git a/app/assets/images/admin/check_in.svg b/app/assets/images/admin/check_in.svg
new file mode 100644
index 0000000..392c447
--- /dev/null
+++ b/app/assets/images/admin/check_in.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/assets/stylesheets/_admin.scss b/app/assets/stylesheets/_admin.scss
index b9980e0..3c441dc 100644
--- a/app/assets/stylesheets/_admin.scss
+++ b/app/assets/stylesheets/_admin.scss
@@ -812,6 +812,20 @@ nav.sub-menu {
}
}
+@mixin hover-info {
+ display: none;
+ position: absolute;
+ right: 100%;
+ top: 0;
+ background-color: $white;
+ border: 0.1em solid #CCC;
+ padding: 0.25em 0.75em;
+ margin: 0;
+ list-style-type: square;
+ @include default-box-shadow(top, 2);
+ z-index: 10;
+}
+
@include keyframes(unhappy) {
from {
@include _(transform, rotate(15deg));
@@ -872,6 +886,66 @@ nav.sub-menu {
vertical-align: top;
}
+ > th {
+ min-width: 15em;
+ }
+
+ .host-notes {
+ @include font-family(primary);
+ font-size: 0.85em;
+ border: 0.1em solid $light-gray;
+ background-color: $white;
+ padding: 0.5em;
+ margin: 1em 0;
+
+ > p:first-child {
+ margin-top: 0;
+ }
+
+ > p:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .guest-notes {
+ position: relative;
+ float: left;
+ margin-top: -0.2em;
+ margin-right: 0.25em;
+ cursor: pointer;
+
+ @include after {
+ content: '\1F4C4';
+ width: 2em;
+ height: 2em;
+ }
+
+ .notes {
+ @include hover-info;
+ top: auto;
+ bottom: 100%;
+ right: auto;
+ min-width: 25em;
+
+ p {
+ font-size: 1.125em;
+
+ &:first-child {
+ margin-top: 0;
+ }
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ &:hover {
+ .notes {
+ display: block;
+ }
+ }
+ }
+
.address {
margin-top: 1em;
text-align: right;
@@ -937,17 +1011,7 @@ nav.sub-menu {
}
ul {
- display: none;
- position: absolute;
- right: 100%;
- top: 0;
- background-color: $white;
- border: 0.1em solid #CCC;
- padding: 0.25em 0.75em;
- margin: 0;
- list-style-type: square;
- @include default-box-shadow(top, 2);
- z-index: 10;
+ @include hover-info;
}
li {
@@ -1719,6 +1783,113 @@ html[data-ontop] {
}
}
+.search-message {
+ display: none;
+ border: 0.05em solid $gray;
+ text-align: center;
+ padding: 1em;
+ margin: 1em;
+ border-radius: 0.2em;
+ box-shadow: 0 0 1em -0.5em;
+}
+
+#search-results {
+ display: none;
+ width: 100%;
+ margin-left: 0;
+
+ a {
+ color: inherit;
+
+ @include after {
+ display: none;
+ }
+ }
+
+ .name {
+ font-size: 1.5em;
+ min-width: 10em;
+ }
+
+ .registration {
+ &:hover, &:focus {
+ background-color: lighten($colour-1, 33%);
+ cursor: pointer;
+
+ th {
+ background-color: lighten($colour-1, 25%);
+ }
+ }
+ }
+}
+
+#search-form {
+ #no-search {
+ display: block;
+ }
+
+ #new-user {
+ display: none;
+ }
+
+ &[data-status="no-results"] {
+ #no-search, #search-results, #new-user {
+ display: none;
+ }
+
+ #no-results {
+ display: block;
+ }
+ }
+
+ &[data-status="success"] {
+ #no-search, #no-results, #new-user {
+ display: none;
+ }
+
+ #search-results {
+ display: block;
+ }
+ }
+
+ &[data-status="new-user"] {
+ #no-search, #no-results, #search-results {
+ display: none;
+ }
+
+ #new-user {
+ display: block;
+ }
+ }
+}
+
+#check-in {
+ .currency {
+ font-size: 1.5em;
+ margin-top: 0.5em;
+ margin-right: 0.5em;
+
+ ~ .select-field {
+ margin-top: 0.25em;
+ margin-right: 0.5em;
+ }
+ }
+
+ .input-field {
+ margin-bottom: 0;
+ }
+}
+
+.back-to-start {
+ @include before {
+ content: '◀';
+ font-size: 0.65em;
+ margin-right: 0.333em;
+ display: inline-block;
+ vertical-align: bottom;
+ }
+}
+
@include breakpoint(medium) {
nav.sub-nav {
float: right;
diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss
index a958a9a..3ab5328 100644
--- a/app/assets/stylesheets/_application.scss
+++ b/app/assets/stylesheets/_application.scss
@@ -384,6 +384,10 @@ table, .table {
}
}
+.no-wrap {
+ white-space: nowrap;
+}
+
body.modal-open {
overflow: hidden;
}
@@ -2432,8 +2436,8 @@ a.logo {
}
.register-link {
- font-size: 1.25em;
- margin: 0.5em;
+ font-size: 0.75em;
+ margin: 0.5em 0 0;
}
}
@@ -3632,8 +3636,6 @@ body.policy .policy-agreement ul {
}
.conference-banner {
- @include _-(display, flex);
- @include _(flex-wrap, wrap);
margin: 0 auto;
width: 100%;
diff --git a/app/controllers/conference_administration_controller.rb b/app/controllers/conference_administration_controller.rb
index 1354ef8..ac0d8a3 100644
--- a/app/controllers/conference_administration_controller.rb
+++ b/app/controllers/conference_administration_controller.rb
@@ -84,6 +84,30 @@ class ConferenceAdministrationController < ApplicationController
end
end
+ def check_in
+ set_conference
+ return do_403 unless @this_conference.host? current_user
+
+ @page_title_vars = { title: @this_conference.title }
+ @admin_step = :check_in
+ @admin_group = view_context.get_administration_group(@admin_step)
+
+ if params[:id] =~ /^\S+@\S+\.\S{2,}$/
+ @user = User.new(email: params[:id])
+ elsif params[:id] =~ /^\d+$/
+ @user = User.find(params[:id].to_i)
+ else
+ return do_404
+ end
+
+ @registration = @this_conference.registration_for(@user) || ConferenceRegistration.new(conference: @this_conference)
+ @registration.data ||= {}
+
+ @user_name = @user.firstname || 'this person'
+ @user_name_proper = @user.firstname || 'This person'
+ @user_name_for_title = @user.firstname || "#{@user.email}"
+ end
+
rescue_from ActiveRecord::PremissionDenied do |exception|
do_403
end
@@ -199,7 +223,7 @@ class ConferenceAdministrationController < ApplicationController
name: org.name,
street_address: address.present? ? address.street : nil,
city: address.present? ? address.city : nil,
- subregion: address.present? ? I18n.t("geography.subregions.#{address.country}.#{address.territory}") : nil,
+ subregion: address.present? ? I18n.t("geography.subregions.#{address.country}.#{address.territory}", resolve: false) : nil,
country: address.present? ? I18n.t("geography.countries.#{address.country}") : nil,
postal_code: address.present? ? address.postal_code : nil,
email: org.email_address,
@@ -299,6 +323,46 @@ class ConferenceAdministrationController < ApplicationController
end
end
+ def administrate_check_in
+ sort_weight = {
+ checked_in: 5,
+ registered: 4,
+ incomplete: 3,
+ cancelled: 2,
+ unregistered: 1
+ }
+
+ @registration_data = []
+ User.all.each do |user|
+ if user.email.present?
+ new_data = {
+ user_id: user.id,
+ email: user.email,
+ name: user.firstname
+ }
+
+ organization = user.organizations.first
+ new_data[:organization] = organization.present? ? organization.name : ''
+
+ registration = @this_conference.registration_for(user)
+ if registration.present? && registration.city_id.present?
+ new_data[:location] = registration.city.to_s
+ status = registration.status
+ else
+ new_data[:location] = user.last_location.to_s
+ status = :unregistered
+ end
+
+ new_data[:status] = I18n.t("articles.conference_registration.terms.registration_status.#{status}")
+ new_data[:sort_weight] = sort_weight[status]
+
+ @registration_data << new_data
+ end
+ end
+
+ @registration_data.sort! { |a, b| b[:sort_weight] <=> a[:sort_weight] }
+ end
+
def administrate_stats
if @this_conference.start_date.blank? || @this_conference.end_date.blank?
@warning_message = :no_date_warning
@@ -476,6 +540,7 @@ class ConferenceAdministrationController < ApplicationController
@excel_data = {
columns: [
:name,
+ :pronoun,
:email,
:date,
:status,
@@ -524,6 +589,7 @@ class ConferenceAdministrationController < ApplicationController
},
keys: {
name: 'forms.labels.generic.name',
+ pronoun: 'forms.labels.generic.pronoun',
email: 'forms.labels.generic.email',
status: 'forms.labels.generic.registration_status',
is_attending: 'articles.conference_registration.terms.is_attending',
@@ -590,6 +656,7 @@ class ConferenceAdministrationController < ApplicationController
data = {
id: r.id,
name: user.firstname || '',
+ pronoun: user.pronoun || '',
email: user.email || '',
status: I18n.t("articles.conference_registration.terms.registration_status.#{view_context.registration_status(r)}"),
is_attending: I18n.t("articles.conference_registration.questions.bike.#{r.is_attending == 'n' ? 'no' : 'yes'}"),
@@ -1101,6 +1168,9 @@ class ConferenceAdministrationController < ApplicationController
# delete deprecated values
registration.allergies = nil
registration.other = nil
+ when :org_non_member_interest
+ registration.data ||= {}
+ registration.data['non_member_interest'] = value
when :registration_fees_paid
registration.data ||= {}
registration.data['payment_amount'] = value.to_f
@@ -1116,8 +1186,8 @@ class ConferenceAdministrationController < ApplicationController
registration.housing_data['companion'] ||= {}
registration.housing_data['companion']['email'] = value
registration.housing_data['companion']['id'] = User.find_user(value).id
- when :preferred_language
- registration.user.locale = value
+ when :preferred_language, :pronoun
+ registration.user.send("#{key}=", value)
user_changed = true
when :is_subscribed
registration.user.is_subscribed = (value != "false")
@@ -1180,6 +1250,67 @@ class ConferenceAdministrationController < ApplicationController
return nil
end
+ def admin_update_check_in
+ unless params[:button] == 'cancel'
+ user_id = params[:user_id]
+
+ if params[:user_id].present?
+ user_id = user_id.to_i
+ else
+ user_id = User.get(params[:email]).id
+ end
+
+ registration = ConferenceRegistration.where(
+ user_id: user_id,
+ conference_id: @this_conference.id
+ ).limit(1).first ||
+ ConferenceRegistration.new(
+ conference_id: @this_conference.id,
+ user_id: user_id
+ )
+
+ registration.data ||= {}
+ registration.data['checked_in'] ||= DateTime.now
+
+ if params[:payment]
+ amount = params[:payment].to_f
+ if amount > 0
+ registration.registration_fees_paid ||= 0
+ registration.registration_fees_paid += amount
+ registration.data['payment_amount'] = amount
+ registration.data['payment_currency'] ||= params[:currency]
+ end
+ end
+
+ user = nil
+ if params[:name].present?
+ user ||= registration.user
+ user.firstname ||= params[:name]
+ end
+
+ if params[:pronoun].present?
+ user ||= registration.user
+ user.pronoun ||= params[:pronoun]
+ end
+
+ if params[:location].present?
+ unless registration.city_id.present?
+ city = City.search(params[:location])
+ registration.city_id = city.id if city.present?
+ end
+ end
+
+ user.save if user.present?
+
+ registration.bike = params[:bike]
+ registration.data['programme'] = params[:programme]
+
+ registration.save
+ end
+
+ return false
+ end
+
def admin_update_housing
# modify the guest data
if params[:button] == 'get-guest-list'
diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb
index efe822d..ff88956 100644
--- a/app/controllers/conferences_controller.rb
+++ b/app/controllers/conferences_controller.rb
@@ -104,297 +104,6 @@ class ConferencesController < ApplicationController
end
end
- def old_register
- set_conference
-
- @register_template = nil
-
- if logged_in?
- set_or_create_conference_registration
-
- @name = current_user.firstname
- # we should phase out last names
- @name += " #{current_user.lastname}" if current_user.lastname
-
- @name ||= current_user.username
-
- @is_host = @this_conference.host? current_user
- else
- @register_template = :confirm_email
- end
-
- steps = nil
- return do_404 unless registration_steps.present?
-
- # @register_template = :administration if params[:admin_step].present?
-
- @errors = {}
- @warnings = []
- form_step = params[:button] ? params[:button].to_sym : nil
-
- # process any data that was passed to us
- if form_step
- if form_step.to_s =~ /^prev_(.+)$/
- steps = registration_steps
- @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]
- 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')
-
- @registration.save!
- end
-
- @page_title = 'articles.conference_registration.headings.Payment'
- @register_template = :paypal_confirm
- elsif form_step == :paypal_confirmed
- info = YAML.load(@registration.payment_info)
- @amount = nil
- status = nil
- if Rails.env.test?
- status = info[:status]
- @amount = info[:amount]
- else
- paypal = PayPal!.checkout!(info[:token], info[:payer_id], PayPalRequest(info[:amount]))
- status = paypal.payment_info.first.payment_status
- @amount = paypal.payment_info.first.amount.total
- end
- if status == 'Completed'
- @registration.registration_fees_paid ||= 0
- @registration.registration_fees_paid += @amount
-
- # don't complete the step unless fees have been paid
- if @registration.registration_fees_paid > 0
- @registration.steps_completed << :payment
- @registration.steps_completed.uniq!
- end
-
- @registration.save!
- else
- @errors[:payment] = :incomplete
- @register_template = :payment
- end
- @page_title = 'articles.conference_registration.headings.Payment'
- else
-
- case form_step
- when :confirm_email
- 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
- current_user.lastname = nil
- else
- @errors[:name] = :empty
- end
-
- if params[:location].present? && params[:location].gsub(/[\s\W]/, '').present?
- city = City.search(params[:location])
-
- if city.present?
- @registration.city_id = city.id
- if params[:location].gsub(/[\s,]/, '').downcase != view_context.location(city).gsub(/[\s,]/, '').downcase
- @warnings << view_context._('warnings.messages.location_corrected', vars: {original: params[:location], corrected: view_context.location(city)})
- end
- else
- @errors[:location] = :unknown
- end
- else
- @errors[:location] = :empty
- end
-
- if params[:languages].present?
- current_user.languages = params[:languages].keys
- else
- @errors[:languages] = :empty
- end
-
- current_user.save! unless @errors.present?
- when :hosting
- @registration.can_provide_housing = params[:can_provide_housing].present?
- if params[:not_attending]
- @registration.is_attending = 'n'
-
- if current_user.is_subscribed.nil?
- current_user.is_subscribed = false
- current_user.save!
- end
- else
- @registration.is_attending = 'y'
- end
-
- @registration.housing_data = {
- address: params[:address],
- phone: params[:phone],
- space: {
- bed_space: params[:bed_space],
- floor_space: params[:floor_space],
- tent_space: params[:tent_space],
- },
- considerations: (params[:considerations] || {}).keys,
- availability: [ params[:first_day], params[:last_day] ],
- notes: params[:notes]
- }
- when :questions
- # create the companion's user account and send a registration link unless they have already registered
- generate_confirmation(User.create(email: params[:companion]), register_path(@this_conference.slug)) if params[:companion].present? && User.find_user(params[:companion]).nil?
-
- @registration.housing = params[:housing]
- @registration.arrival = params[:arrival]
- @registration.departure = params[:departure]
- @registration.housing_data = {
- companions: [ params[:companion] ]
- }
- @registration.bike = params[:bike]
- @registration.food = params[:food]
- @registration.allergies = params[:allergies]
- @registration.other = params[:other]
- when :payment
- amount = params[:amount].to_f
-
- if amount > 0
- # 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
- end
- end
-
- if @errors.present?
- @register_template = form_step
- else
- unless @registration.nil?
- steps = registration_steps
- step_index = steps.find_index(form_step)
- @register_template = steps[step_index + 1] if step_index.present?
-
- # have we reached a new level?
- unless @registration.steps_completed.include? form_step.to_s
- # 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.to_s
- @registration.steps_completed.uniq!
- end
- end
-
- @registration.save!
- end
- end
- end
- end
-
- steps ||= registration_steps
-
- # make sure we're on a valid step
- @register_template ||= (params[:step] || view_context.current_step).to_sym
-
- if logged_in? && @register_template != :paypal_confirm
- # if we're logged in
- if !steps.include?(@register_template)
- # and we are not viewing a valid step
- return redirect_to register_path(@this_conference.slug)
- elsif @register_template != view_context.current_step && !registration_complete? && !@registration.steps_completed.include?(@register_template.to_s)
- # or the step hasn't been reached, registration is not yet complete, and we're not viewing the latest incomplete step
- return redirect_to register_path(@this_conference.slug)
- end
- # then we'll redirect to the current registration step
- end
-
- # prepare the form
- case @register_template
- when :questions
- # see if someone else has asked to be your companion
- 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|
- @registration.housing_data = {
- companions: [ r.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 ||= { }
- end
- @page_title = 'articles.conference_registration.headings.Registration_Info'
- when :payment
- @page_title = 'articles.conference_registration.headings.Payment'
- when :workshops
- @page_title = 'articles.conference_registration.headings.Workshops'
-
- # initialize our arrays
- @my_workshops = Array.new
- @requested_workshops = Array.new
- @workshops_in_need = Array.new
- @workshops = Array.new
-
- # put wach workshop into the correct array
- 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)
- @requested_workshops << workshop
- elsif workshop.needs_facilitators
- @workshops_in_need << workshop
- else
- @workshops << workshop
- end
- end
-
- # sort the arrays by name
- @my_workshops.sort! { |a, b| a.title.downcase <=> b.title.downcase }
- @requested_workshops.sort! { |a, b| a.title.downcase <=> b.title.downcase }
- @workshops_in_need.sort! { |a, b| a.title.downcase <=> b.title.downcase }
- @workshops.sort! { |a, b| a.title.downcase <=> b.title.downcase }
- when :contact_info
- @page_title = 'articles.conference_registration.headings.Contact_Info'
- when :hosting
- @page_title = 'articles.conference_registration.headings.Hosting'
- @hosting_data = @registration.housing_data || {}
- @hosting_data['space'] ||= Hash.new
- @hosting_data['availability'] ||= Array.new
- @hosting_data['considerations'] ||= Array.new
- when :policy
- @page_title = 'articles.conference_registration.headings.Policy_Agreement'
- when :confirm_email
- @page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
- @main_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Register"
- @main_title_vars = { vars: { title: @this_conference.title } }
- end
-
- end
-
- # helper_method :registration_steps
- # helper_method :current_registration_steps
helper_method :registration_complete?
def registration_steps(conference = nil)
diff --git a/app/controllers/workshops_controller.rb b/app/controllers/workshops_controller.rb
index 49792ba..fd60519 100644
--- a/app/controllers/workshops_controller.rb
+++ b/app/controllers/workshops_controller.rb
@@ -2,7 +2,7 @@ class WorkshopsController < ApplicationController
def workshops
set_conference
- set_conference_registration!
+ set_conference_registration
@workshops = Workshop.where(conference_id: @this_conference.id)
@my_workshops = @workshops.select { |w| w.active_facilitator?(current_user) }
render 'workshops/index'
@@ -10,7 +10,7 @@ class WorkshopsController < ApplicationController
def view_workshop
set_conference
- set_conference_registration!
+ set_conference_registration
@workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless @workshop
diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb
index 2cb13b2..848354c 100644
--- a/app/helpers/admin_helper.rb
+++ b/app/helpers/admin_helper.rb
@@ -28,7 +28,8 @@ module AdminHelper
:registration_status,
:stats,
:registrations,
- :broadcast
+ :broadcast,
+ :check_in
],
housing: [
:providers,
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 91627c0..a488b9e 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -228,7 +228,11 @@ module FormHelper
so = select_options
select_options = []
so.each do |opt|
- select_options << [ I18n.t("forms.options.#{name.to_s}.#{opt.to_s}"), opt]
+ if opt.is_a?(Array)
+ select_options << opt
+ else
+ select_options << [ I18n.t("forms.options.#{name.to_s}.#{opt.to_s}"), opt]
+ end
end
end
textfield(name, value, options.merge({type: :select, options: select_options}))
@@ -470,11 +474,11 @@ module FormHelper
if labels.present?
label = labels[i]
elsif is_single
- label = _(label_key.to_s)
+ label = options[:translate] == false ? label_key.to_s : _(label_key.to_s)
elsif box.is_a?(Integer)
label = I18n.t(label_key.to_s)[box]
else
- label = _("#{label_key.to_s}.#{box}")
+ label = options[:translate] == false ? box : _("#{label_key.to_s}.#{box}")
end
boxes_html += label_tag(id, label)
diff --git a/app/helpers/table_helper.rb b/app/helpers/table_helper.rb
index c355465..2238a6a 100644
--- a/app/helpers/table_helper.rb
+++ b/app/helpers/table_helper.rb
@@ -367,6 +367,7 @@ module TableHelper
class: ['registrations', 'admin-edit'],
primary_key: :id,
column_names: [
+ :pronoun,
:registration_fees_paid,
:payment_currency,
:payment_method,
@@ -377,6 +378,7 @@ module TableHelper
:arrival,
:departure,
:group_ride,
+ :org_non_member_interest,
:housing,
:bike,
:food,
diff --git a/app/helpers/widgets_helper.rb b/app/helpers/widgets_helper.rb
index a9f4b23..73ad5a2 100644
--- a/app/helpers/widgets_helper.rb
+++ b/app/helpers/widgets_helper.rb
@@ -133,8 +133,17 @@ module WidgetsHelper
status_html = content_tag(:ul, status_html.html_safe)
end
+ name_html = guest[:guest].user.name
+
+ other = (guest[:guest].housing_data || {})['other']
+ other.strip! if other.present?
+
+ if other.present?
+ name_html += content_tag :div, (content_tag :div, paragraph(other), class: 'notes').html_safe, class: 'guest-notes'
+ end
+
guest_rows += content_tag :tr, id: "hosted-guest-#{guest_id}" do
- (content_tag :td, guest[:guest].user.name) +
+ (content_tag :td, name_html.html_safe) +
(content_tag :td do
(guest[:guest].from +
(content_tag :a, (_'actions.workshops.Remove'), href: '#', class: 'remove-guest', data: { guest: guest_id })).html_safe
diff --git a/app/views/conference_administration/_check_in.html.haml b/app/views/conference_administration/_check_in.html.haml
new file mode 100644
index 0000000..581af9f
--- /dev/null
+++ b/app/views/conference_administration/_check_in.html.haml
@@ -0,0 +1,174 @@
+%script#registration-data{type: :json}=@registration_data.to_json.to_s.html_safe
+= columns(medium: 12) do
+ = admin_update_form id: 'search-form' do
+ = searchfield :search, nil, big: true
+ %table#search-results
+ %thead
+ %tr
+ %th.corner
+ %th Email
+ %th Location
+ %th Organization
+ %th Status
+ %tbody
+
+ %p#no-search.search-message Search for a user by name, email, location, or organization
+ %p#no-results.search-message No matching user was found, enter an email address to regster a new user
+ #new-user.actions.center=link_to 'Register %{email}', check_in_path(@this_conference.slug, 'new_user').gsub('new_user', '%{url_email}'), class: :button
+ %template#search-result
+ %tr.registration{tabindex: 0}
+ %th.name= link_to '%{name}', check_in_path(@this_conference.slug, 'user_id').gsub('user_id', '%{user_id}')
+ %td %{email}
+ %td %{location}
+ %td %{organization}
+ %td.no-wrap %{status}
+:javascript
+ var searchTable = null,
+ searchField = null,
+ lastSearch = null,
+ registrationData = null,
+ newUserMessage = null,
+ newUserMessageTemplate = null,
+ searchResultTemplate = null,
+ searchForm = null,
+ searchFields = ['email', 'name', 'location', 'oranization'];
+
+ function getRegistrationData() {
+ return JSON.parse(document.getElementById('registration-data').innerHTML);
+ }
+
+ function getSearchTable() {
+ return document.getElementById('search-results').getElementsByTagName('tbody')[0];
+ }
+
+ function getSearchResultTemplate() {
+ return document.getElementById('search-result').innerHTML;
+ }
+
+ function matchScore(data, terms) {
+ var score = 0;
+ for (var i = 0; i < terms.length; i++) {
+ var keys = Object.keys(data), termPos = -1;
+ for (var j = 0; j < keys.length; j++) {
+ var dataItem = data[keys[j]];
+ if (typeof(dataItem) === "string" && dataItem.length > 0) {
+ dataItem = dataItem.toLocaleLowerCase();
+ var index = dataItem.indexOf(' ' + terms[i]);
+ if (index < 0) {
+ index = dataItem.indexOf(terms[i]);
+ } else {
+ index = 0;
+ }
+ if (index >= 0 && (termPos < 0 || index < termPos)) {
+ termPos = index;
+ }
+ }
+ }
+ if (termPos >= 0) {
+ score += (termPos > 0 ? 10 : 20);
+ } else {
+ return 0;
+ }
+ }
+ return score + data['sort_weight'];
+ }
+
+ function searchResultHTML(data) {
+ if (searchResultTemplate === null) {
+ searchResultTemplate = getSearchResultTemplate();
+ }
+
+ var keys = Object.keys(data), html = searchResultTemplate;
+ for (var i = 0; i < keys.length; i++) {
+ var value = data[keys[i]];
+ if (value === null) {
+ value = '';
+ }
+ html = html.replace(new RegExp('%\\{' + keys[i] + '\\}', 'ig'), value);
+ }
+
+ return html;
+ }
+
+ function filterSearchResults() {
+ if (searchTable === null) {
+ searchTable = getSearchTable();
+ }
+ if (searchField === null) {
+ searchField = document.getElementById('search');
+ }
+ if (searchForm === null) {
+ searchForm = document.getElementById('search-form');
+ }
+
+ var searchTerm = searchField.value.toLocaleLowerCase().trim();
+
+ if (searchTerm != lastSearch) {
+ searchForm.classList.add('requesting');
+
+ var range = document.createRange();
+ range.selectNodeContents(searchTable);
+ range.deleteContents();
+
+ lastSearch = searchTerm;
+ var status = null;
+
+ if (searchTerm.length > 0) {
+ var terms = searchTerm.split(/\s+/);
+ if (registrationData === null) {
+ registrationData = getRegistrationData();
+ }
+
+ var matches = [];
+ for (var i = 0; i < registrationData.length; i++) {
+ var score = matchScore(registrationData[i], terms);
+ if (score > 0) {
+ matches.push({ score: score, data: registrationData[i] });
+ }
+ }
+
+ if (matches.length > 0) {
+ matches.sort(function(a, b) { return b.score - a.score; });
+
+ var html = '';
+ for (var i = 0; i < matches.length; i++) {
+ html += searchResultHTML(matches[i].data);
+ }
+ searchTable.innerHTML = html;
+
+ status = 'success';
+ } else if (searchTerm.match(/^\S+@\S+\.\S{2,}$/)) {
+ status = 'new-user';
+ if (newUserMessage === null) {
+ newUserMessage = document.getElementById('new-user');
+ newUserMessageTemplate = newUserMessage.innerHTML;
+ }
+ newUserMessage.innerHTML = newUserMessageTemplate.replace(/%\{email\}/g, searchTerm).replace(/%\{url_email\}/g, encodeURIComponent(searchTerm));
+ } else {
+ status = 'no-results';
+ }
+ } else {
+ status = 'no-search';
+ }
+
+ searchForm.setAttribute('data-status', status);
+ searchForm.classList.remove('requesting');
+ }
+ }
+
+ document.addEventListener('click', function(event) {
+ if (searchTable === null) {
+ searchTable = getSearchTable();
+ }
+ var target = event.target;
+ if (searchTable.contains(target)) {
+ while (target.tagName !== 'TR') {
+ target = target.parentElement;
+ }
+ var link = target.getElementsByTagName('a')[0];
+ window.location.href = link.href;
+ }
+ });
+ document.addEventListener('keyup', filterSearchResults);
+
+ filterSearchResults();
diff --git a/app/views/conference_administration/_hosts_table.html.haml b/app/views/conference_administration/_hosts_table.html.haml
index d20f1a5..21ed137 100644
--- a/app/views/conference_administration/_hosts_table.html.haml
+++ b/app/views/conference_administration/_hosts_table.html.haml
@@ -16,5 +16,7 @@
%th
.name=registration.user.name
.address=registration.housing_data['address']
+ - if registration.housing_data['notes'].present?
+ .host-notes=paragraph(registration.housing_data['notes'])
%td.inner-table{colspan: 2}=host_guests_table(registration)
- first_row = false
diff --git a/app/views/conference_administration/_housing.html.haml b/app/views/conference_administration/_housing.html.haml
index f5564b8..ba6a7e8 100644
--- a/app/views/conference_administration/_housing.html.haml
+++ b/app/views/conference_administration/_housing.html.haml
@@ -7,4 +7,4 @@
%h3 Select a Guest
#table
.actions.center
- = link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, @admin_step, :format => :xlsx), class: [:button, :download]
+ = link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, @admin_step, format: :xlsx), class: [:button, :download]
diff --git a/app/views/conference_administration/administration_step.html.haml b/app/views/conference_administration/administration_step.html.haml
index 7b6396a..211975c 100644
--- a/app/views/conference_administration/administration_step.html.haml
+++ b/app/views/conference_administration/administration_step.html.haml
@@ -13,8 +13,8 @@
= columns(medium: 12) do
%nav.sub-nav
%ul
- %li=link_to (_'articles.admin.headings.back'), administrate_conference_path(@this_conference.slug)
- - administration_steps[@admin_group].each do | step |
+ %li=link_to (_'articles.admin.headings.back'), administrate_conference_path(@this_conference.slug), class: 'back-to-start'
+ - administration_steps[@admin_group].each do |step|
%li
- title = (_"articles.admin.#{@admin_group}.headings.#{step}", :t)
- if step == @admin_step.to_sym
diff --git a/app/views/conference_administration/check_in.html.haml b/app/views/conference_administration/check_in.html.haml
new file mode 100644
index 0000000..5390f5b
--- /dev/null
+++ b/app/views/conference_administration/check_in.html.haml
@@ -0,0 +1,94 @@
+- body_class 'banner-bottom' unless @this_conference.poster.present?
+- add_stylesheet :admin
+- content_for :banner do
+ = render partial: 'application/header', locals: { page_group: :administration, page_key: 'Administration', image_file: @this_conference.poster_url || 'admin.jpg'}
+
+%article{id: "admin-#{@admin_step}"}
+ = row do
+ = columns(medium: 12) do
+ - if admin_help_pages[@admin_step.to_sym]
+ = link_help_dlg("admin_#{admin_help_pages[@admin_step.to_sym]}", class: ['button', 'help-link'])
+ %h2.floating=_("articles.admin.#{@admin_group}.headings.check_in_user", vars: { name: @user_name_for_title }).html_safe
+ = row do
+ = columns(medium: 12) do
+ %nav.sub-nav
+ %ul
+ %li=link_to (_'articles.admin.headings.back'), administrate_conference_path(@this_conference.slug), class: 'back-to-start'
+ - administration_steps[@admin_group].each do |step|
+ %li
+ - title = (_"articles.admin.#{@admin_group}.headings.#{step}", :t)
+ - if step == @admin_step.to_sym
+ = title
+ - else
+ = link_to title, administration_step_path(@this_conference.slug, step.to_s)
+ = row do
+ = admin_update_form do
+ = columns(medium: 12) do
+ %p="Please verify with #{@user_name} that the following is correct. If you need to change check in information later, you can check the person in again to overwrite these values."
+ - if @user.id.present?
+ = hidden_field_tag :user_id, @user.id
+ - else
+ = hidden_field_tag :email, @user.email
+ = columns(medium: 12) do
+ %table#check-in{aria: { role: :presentation }}
+ - unless @user.firstname.present?
+ %tr
+ %td
+ %p="What is their name?"
+ %td= textfield :name, nil, big: true, label: false, required: true
+ - if @user.pronoun.nil?
+ %tr
+ %td
+ %p="Does #{@user_name} have a preferred pronoun? If so, enter it here"
+ %td= textfield :pronoun, nil, label: false
+ - unless @registration.city.present?
+ %tr
+ %td
+ %p="What city is #{@user_name} based? (Please be specific)"
+ %td= textfield :location, @user.last_location, label: false
+ %tr
+ %td
+ %p="Did you give #{@user_name} a programme and any other informational materials?"
+ %td= selectfield :programme, 'yes', [["I gave #{@user_name} a programme", 'yes'], ["I DID NOT give #{@user_name} a programme", 'no']], stretch: true, label: false
+ %tr
+ %td
+ - if @registration.bike.to_s == 'yes'
+ %p="#{@user_name_proper} said they do need a bike".html_safe
+ - elsif @registration.bike.to_s == 'no'
+ %p="#{@user_name_proper} said they do not need a bike".html_safe
+ - else
+ %p="Does #{@user_name} need a bike?".html_safe
+ %td= selectfield :bike, @registration.bike.to_s, [["#{@user_name_proper} is taking a bike", 'yes'], ["#{@user_name_proper} is NOT taking a bike", 'no']], stretch: true, label: false
+ %tr
+ %td
+ %p
+ - amount = @registration.registration_fees_paid || 0
+ - currency = @registration.conference.default_currency
+ - can_change_currency = true
+ - if amount > 0
+ - currency = @registration.data['payment_currency'] if @registration.data['payment_currency'].present?
+ ="#{@user_name_proper} has already paid #{number_to_currency amount, unit: '$'} #{currency}, if they decide to make another donation you can add the amount here".html_safe
+ - amount = 0
+ - can_change_currency = false
+ - else
+ - amount = @registration.data['payment_amount'] || 0
+ - if amount > 0
+ ="#{@user_name_proper} has pledged to pay #{number_to_currency amount, unit: '$'} #{@registration.data['payment_currency']}, please confirm and take their payment now".html_safe
+ - elsif @registration.data['payment_method'].present?
+ ="#{@user_name_proper} has not pledged to pay for registration. If they would like to pay for registration now, enter their donation amount here".html_safe
+ - else
+ ="Please collect registration fees from #{@user_name} if they are willing to donate and enter the amount here".html_safe
+ %td
+ .flex-column
+ .currency $
+ = numberfield :payment, amount || 0.0, required: true, step: 0.01, min: 0.0, inline: true, label: false, stretch: true
+ - if can_change_currency
+ = selectfield :currency, currency, [:CAD, :USD], inline: true, label: false, inline: true, label: false
+ - else
+ .currency
+ = currency
+ = hidden_field_tag :currency, currency
+ = columns(medium: 12) do
+ .actions.center
+ = button :check_in
+ = button :cancel, value: :cancel
diff --git a/app/views/conferences/_banner_image.svg.erb b/app/views/conferences/_banner_image.svg.erb
deleted file mode 100644
index 89a5852..0000000
--- a/app/views/conferences/_banner_image.svg.erb
+++ /dev/null
@@ -1,20 +0,0 @@
-
diff --git a/app/views/conferences/_conference.html.haml b/app/views/conferences/_conference.html.haml
index 12a762b..ad60f64 100644
--- a/app/views/conferences/_conference.html.haml
+++ b/app/views/conferences/_conference.html.haml
@@ -10,8 +10,9 @@
- if conference.start_date.present? && conference.end_date.present?
.secondary
= date_span(conference.start_date.to_date, conference.end_date.to_date)
- .register-link
- = (link_to (_'forms.actions.generic.register'), register_path(conference.slug), class: [:button, :register]) if links.include?(:register) && conference.can_register?
+ - if conference.poster.present? && links.include?(:register) && conference.can_register?
+ .register-link
+ = (link_to _(is_registered ? 'actions.conference.edit_registration' : 'forms.actions.generic.register'), register_path(conference.slug), class: [:button, :register])
- if conference.poster.present?
%figure
%img{src: conference.poster.full.url, role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: conference.title })}
@@ -20,26 +21,21 @@
= columns(medium: 10, push: {medium: 1}) do
%h2=_!conference.title if conference.poster.present?
= richtext conference.info
- - conference.extended_details.each do |section|
- - if sections.include?(section) && conference.copy_data[section][:show]
- %h3=(_ conference.copy_data[section][:heading], vars: conference.copy_data[section][:vars]) unless conference.copy_data[section][:heading] == false
- = richtext conference.copy_data[section][:value], (conference.copy_data[section][:heading] == false ? 2 : 3)
-
+
.links
= (link_to (_(is_registered ? 'actions.conference.edit_registration' : '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)
- - if conference.registration_status == :open && sections.include?(:workshops)
+ - conference.extended_details.each do |section|
+ - if sections.include?(section) && conference.copy_data[section][:show]
+ %h3{id: section}=(_ conference.copy_data[section][:heading], vars: conference.copy_data[section][:vars]) unless conference.copy_data[section][:heading] == false
+ = richtext conference.copy_data[section][:value], (conference.copy_data[section][:heading] == false ? 2 : 3)
+ - if section == :workshop_info
+ .actions.center= link_to (_'articles.conference_registration.actions.View_Workshops'), workshops_path(conference), class: :button
+ - if conference.registration_status == :open && sections.include?(:schedule)
- if conference.workshop_schedule_published
- add_inline_script :home_schedule
%h3=_'articles.workshops.headings.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 })
- .actions.center
- = link_to (_'actions.workshops.create'), create_workshop_path(conference.slug), class: [:button, :modify]
-
diff --git a/app/views/workshops/_show.html.haml b/app/views/workshops/_show.html.haml
index 381275d..ca2d29e 100644
--- a/app/views/workshops/_show.html.haml
+++ b/app/views/workshops/_show.html.haml
@@ -14,39 +14,40 @@
.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
- %h3=_'articles.workshops.headings.facilitators'
- .facilitators
- - workshop.workshop_facilitators.each do |f|
- - u = User.find(f.user_id)
- - is_this_user = (f.user_id == current_user.id)
- - if logged_in? && (workshop.public_facilitator?(u) || is_this_user || is_facilitator)
- .facilitator
- .name=_!u.name
- .role
- =_"roles.workshops.facilitator.#{workshop.role(u).to_s}"
- - if is_facilitator && preview.blank?
- .details
- .email=_!u.email
- - if f.role.to_sym == :requested
- =(link_to (_'actions.workshops.Approve'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'approve'), :class => [:button, :modify])
- =(link_to (_'actions.workshops.Deny'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'deny'), :class => [:button, :delete])
- - elsif workshop.can_remove?(current_user, u)
- =(link_with_confirmation (_'actions.workshops.Make_Owner'), (_'modals.workshops.facilitators.confirm_transfer_ownership', vars: { user_name: u.name}),approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'switch_ownership'), :class => [:button, :modify]) unless f.role.to_sym == :creator || !workshop.creator?(current_user)
- =(link_with_confirmation (_"actions.workshops.#{is_this_user ? 'Leave' : 'Remove'}"), (_"modals.workshops.facilitators.confirm_remove#{is_this_user ? '_self' : ''}", vars: { user_name: u.name}), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete])
- - if is_this_user && workshop.requested_collaborator?(current_user)
- .details
- =(link_with_confirmation (_'actions.workshops.Cancel_Request'), (_'modals.workshops.facilitators.confirm_cancel_request'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete])
- - unless preview.present?
- =(link_to (_'actions.workshops.Facilitate'), facilitate_workshop_path(workshop.conference.slug, workshop.id), :class => [:button, workshop.needs_facilitators ? :accented : :subdued]) unless workshop.facilitator?(current_user)
- - if is_facilitator
- %h4=_'articles.workshops.headings.add_facilitator','Add a facilitator'
- = form_tag workshop_add_facilitator_path(workshop.conference.slug, workshop.id), :class => 'add-facilitator mini-flex-form' do
- .email-field.input-field
- = email_field_tag :email, nil, required: true
- = label_tag :email
- = off_screen (_'forms.actions.aria.add'), 'add-new-desc'
- = button :add, aria: { labelledby: 'add-new-desc' }
+ - if logged_in?
+ = columns(medium: 6) do
+ %h3=_'articles.workshops.headings.facilitators'
+ .facilitators
+ - workshop.workshop_facilitators.each do |f|
+ - u = User.find(f.user_id)
+ - is_this_user = (f.user_id == current_user.id)
+ - if logged_in? && (workshop.public_facilitator?(u) || is_this_user || is_facilitator)
+ .facilitator
+ .name=_!u.name
+ .role
+ =_"roles.workshops.facilitator.#{workshop.role(u).to_s}"
+ - if is_facilitator && preview.blank?
+ .details
+ .email=_!u.email
+ - if f.role.to_sym == :requested
+ =(link_to (_'actions.workshops.Approve'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'approve'), :class => [:button, :modify])
+ =(link_to (_'actions.workshops.Deny'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'deny'), :class => [:button, :delete])
+ - elsif workshop.can_remove?(current_user, u)
+ =(link_with_confirmation (_'actions.workshops.Make_Owner'), (_'modals.workshops.facilitators.confirm_transfer_ownership', vars: { user_name: u.name}),approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'switch_ownership'), :class => [:button, :modify]) unless f.role.to_sym == :creator || !workshop.creator?(current_user)
+ =(link_with_confirmation (_"actions.workshops.#{is_this_user ? 'Leave' : 'Remove'}"), (_"modals.workshops.facilitators.confirm_remove#{is_this_user ? '_self' : ''}", vars: { user_name: u.name}), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete])
+ - if is_this_user && workshop.requested_collaborator?(current_user)
+ .details
+ =(link_with_confirmation (_'actions.workshops.Cancel_Request'), (_'modals.workshops.facilitators.confirm_cancel_request'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete])
+ - unless preview.present?
+ =(link_to (_'actions.workshops.Facilitate'), facilitate_workshop_path(workshop.conference.slug, workshop.id), :class => [:button, workshop.needs_facilitators ? :accented : :subdued]) unless workshop.facilitator?(current_user)
+ - if is_facilitator
+ %h4=_'articles.workshops.headings.add_facilitator','Add a facilitator'
+ = form_tag workshop_add_facilitator_path(workshop.conference.slug, workshop.id), :class => 'add-facilitator mini-flex-form' do
+ .email-field.input-field
+ = email_field_tag :email, nil, required: true
+ = label_tag :email
+ = off_screen (_'forms.actions.aria.add'), 'add-new-desc'
+ = button :add, aria: { labelledby: 'add-new-desc' }
- languages = JSON.parse(workshop.languages || '[]')
- if languages.present?
= columns(medium: 6) do
@@ -66,24 +67,25 @@
= columns(medium: 12, class: 'workshop-notes') do
%h3=_'articles.workshops.headings.notes','Notes'
= richtext workshop.notes, 3
- = columns(medium: 12, id: :comments) do
- %h3=_'articles.workshops.headings.Comments'
- %ul.comments
- - workshop.comments.each do |comment|
- %li.comment{id: "comment-#{comment.id}"}
- = comment(comment)
- - sub_comments = comment.comments
- - if sub_comments.present?
- %ul.sub-comments.comments
- - sub_comments.each do |sub_comment|
- %li.sub-comment.comment{id: "comment-#{sub_comment.id}"}
- = comment(sub_comment)
- = form_tag workshop_comment_path(workshop.conference.slug, workshop.id) do
- = hidden_field_tag :comment_id, comment.id
- = textarea :reply, nil, plain: true, required: true, label: false, labelledby: "replyto-#{comment.id}"
- .actions.right
- = button :reply, value: :reply, data: {opens: "#comment-#{comment.id} form", focus: :textarea}, class: :small, id: "replyto-#{comment.id}"
- = form_tag workshop_comment_path(workshop.conference.slug, workshop.id) do
- = textarea :comment, nil, plain: true, required: true, label: false, labelledby: :add_comment
- .actions.right
- = button :add_comment, value: :add_comment, id: :add_comment
+ - if logged_in?
+ = columns(medium: 12, id: :comments) do
+ %h3=_'articles.workshops.headings.Comments'
+ %ul.comments
+ - workshop.comments.each do |comment|
+ %li.comment{id: "comment-#{comment.id}"}
+ = comment(comment)
+ - sub_comments = comment.comments
+ - if sub_comments.present?
+ %ul.sub-comments.comments
+ - sub_comments.each do |sub_comment|
+ %li.sub-comment.comment{id: "comment-#{sub_comment.id}"}
+ = comment(sub_comment)
+ = form_tag workshop_comment_path(workshop.conference.slug, workshop.id) do
+ = hidden_field_tag :comment_id, comment.id
+ = textarea :reply, nil, plain: true, required: true, label: false, labelledby: "replyto-#{comment.id}"
+ .actions.right
+ = button :reply, value: :reply, data: {opens: "#comment-#{comment.id} form", focus: :textarea}, class: :small, id: "replyto-#{comment.id}"
+ = form_tag workshop_comment_path(workshop.conference.slug, workshop.id) do
+ = textarea :comment, nil, plain: true, required: true, label: false, labelledby: :add_comment
+ .actions.right
+ = button :add_comment, value: :add_comment, id: :add_comment
diff --git a/config/initializers/sorcery.rb b/config/initializers/sorcery.rb
index c32d74e..28852d2 100644
--- a/config/initializers/sorcery.rb
+++ b/config/initializers/sorcery.rb
@@ -231,7 +231,7 @@ Rails.application.config.sorcery.configure do |config|
# How long in seconds the session length will be
# Default: `604800`
#
- user.remember_me_for = 2592000
+ user.remember_me_for = 31556926
# -- user_activation --
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 1b866f1..4c01d5b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1569,6 +1569,8 @@ en:
registrations: Modify Registrations
broadcast: Contact Users
broadcast_sent: Message Sent
+ check_in: Check In
+ check_in_user: Check in %{name}
description: Open or close registration, view registration statistics, modify
information submitted by registratnts and contact users.
descriptions:
@@ -1579,6 +1581,7 @@ en:
process.
broadcast: Send emails to targeted subsets of users.
broadcast_sent: Your message has been sent.
+ check_in: Check in attendees to the conference
broadcast:
heading: Broadcast
description: The broadcast tool is used to contact users through email. You
@@ -2124,8 +2127,10 @@ en:
registration_status:
unregistered: Unregistered
preregistered: Preregistered
+ incomplete: Incomplete
registered: Registered
cancelled: Cancelled
+ checked_in: Checked in
companion: Companion
companion_email: Companion Email
Preferred_Languages: Language
@@ -2364,6 +2369,7 @@ en:
no_file_selected: No file selected
actions:
generic:
+ check_in: Complete check in
reopen_registration: Re-open my registration
cancel_registration: Cancel my registration
organization_none: None of the above
diff --git a/config/routes.rb b/config/routes.rb
index 1095a73..71da3d6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -29,6 +29,7 @@ BikeBike::Application.routes.draw do
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
+ get 'check_in/:id' => 'conference_administration#check_in', as: :check_in, constraints: { id: /.+/ }
end
# Workshops
diff --git a/features/schedule.feature b/features/schedule.feature
index f6a4020..72d1ef9 100644
--- a/features/schedule.feature
+++ b/features/schedule.feature
@@ -32,18 +32,9 @@ Feature: Conference Schedule
| Bike Sharing! | Recycled bike art |
| Classes, Workshops, Space | Software developers exchange |
- And the workshop schedule is not published
+ And the workshop schedule is published
And I am on the conference page
- Then I should see 'Bike!Bike! 2025'
- And see 'Proposed Workshops'
- And see 'Bike Sharing!'
- But I should not see 'Schedule'
- And not see 'Tuesday'
- And I should see 16 workshops under 'Proposed Workshops'
-
- When the workshop schedule is published
- And I refresh the page
Then I should see 'Schedule'
And see 'Tuesday'
And see 'Wednesday'