From 4ee45f013b9347da8115f4bab5f8578ac03ea7f6 Mon Sep 17 00:00:00 2001 From: Godwin Date: Mon, 29 Aug 2016 22:03:12 -0700 Subject: [PATCH] Updates to schedule maker --- app/assets/javascripts/housing.js | 3 +- app/assets/javascripts/registrations.js | 1 - app/assets/javascripts/schedule.js | 139 +- app/assets/stylesheets/_application.scss | 50 +- app/controllers/application_controller.rb | 643 ------ app/controllers/conferences_controller.rb | 1841 ----------------- app/helpers/application_helper.rb | 2 +- .../conferences/admin/_schedule.html.haml | 125 +- 8 files changed, 189 insertions(+), 2615 deletions(-) delete mode 100644 app/controllers/application_controller.rb delete mode 100644 app/controllers/conferences_controller.rb diff --git a/app/assets/javascripts/housing.js b/app/assets/javascripts/housing.js index 87c644b..e420498 100644 --- a/app/assets/javascripts/housing.js +++ b/app/assets/javascripts/housing.js @@ -1,6 +1,7 @@ (function() { function closeGuestSelector() { document.getElementById('guest-selector').classList.remove('open'); + document.body.classList.remove('modal-open'); } function _post(form, params, f) { var request = new XMLHttpRequest(); @@ -16,7 +17,6 @@ params['authenticity_token'] = form.querySelector('[name="authenticity_token"]').value; var data = []; for (var key in params) { - //data.push(key + '=' + encodeURI(params[key])); data.push(key + '=' + params[key]); } request.send(data.join('&')); @@ -29,6 +29,7 @@ document.getElementById('guest-selector').classList.add('open'); var table = document.getElementById('table'); table.classList.add('loading'); + document.body.classList.add('modal-open'); _post( document.getElementById('housing-table-form'), { diff --git a/app/assets/javascripts/registrations.js b/app/assets/javascripts/registrations.js index a37c302..f22d9e1 100644 --- a/app/assets/javascripts/registrations.js +++ b/app/assets/javascripts/registrations.js @@ -129,7 +129,6 @@ document.observe("focusin", function (event) { editTableCell(event.target); }); } else { document.addEventListener("focus", function (event) { editTableCell(event.target); }, true); - // document.addEventListener("focus", function (event) { editTableCell(event.target); }, true); } searchControl.addEventListener('keyup', filterTable); diff --git a/app/assets/javascripts/schedule.js b/app/assets/javascripts/schedule.js index 16b6ceb..2bf8b88 100644 --- a/app/assets/javascripts/schedule.js +++ b/app/assets/javascripts/schedule.js @@ -1,39 +1,114 @@ (function() { - function initSchedule() { - forEachElement('table.schedule td.workshop.empty', function(block) { - block.addEventListener('click', function(event) { - console.log('clicked'); - }); - }); + function closeWorkshopSelector() { + document.getElementById('workshop-selector').classList.remove('open'); + document.body.classList.remove('modal-open'); + } + document.getElementById('workshop-selector').addEventListener('click', function(event) { + if (event.target.id == 'workshop-selector') { + closeWorkshopSelector(); + } + }); + function _post(form, params, f) { + var request = new XMLHttpRequest(); + request.onreadystatechange = function() { + if (request.readyState == 4) { + if (request.status == 200) { + f(request.responseText); + } + } + } + request.open('POST', form.getAttribute('action'), true); + request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); + params['authenticity_token'] = form.querySelector('[name="authenticity_token"]').value; + var data = []; + for (var key in params) { + data.push(key + '=' + params[key]); + } + request.send(data.join('&')); + } + function selectorMatches(el, selector) { + var p = Element.prototype; + var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) { + return [].indexOf.call(document.querySelectorAll(s), this) !== -1; + }; + return f.call(el, selector); + } + function updateSchedule(html) { + var schedule = document.getElementById('schedule-preview'); + var s = document.createElement('div'); + s.innerHTML = html; + schedule.innerHTML = s.children[0].innerHTML; + schedule.classList.remove('requesting'); } - initSchedule(); - - /*var body = document.querySelector('body'); - var primaryContent = document.getElementById('primary-content'); - var eventDlg = document.getElementById('event-dlg'); - - forEachElement('.event-detail-link', function(link) { - var eventDetails = link.parentElement.querySelector('.event-details'); - var moreDetails = eventDlg.querySelector('.more-details'); - link.addEventListener('click', function(event) { + document.body.addEventListener('submit', function (event) { + if (event.target.classList.contains('deschedule-workshop')) { event.preventDefault(); - eventDlg.querySelector('.event-details').innerHTML = eventDetails.innerHTML; - var href = eventDetails.getAttribute('data-href'); - if (href) { - moreDetails.setAttribute('href', href); - moreDetails.classList.remove('hidden'); - } else { - moreDetails.classList.add('hidden'); + var schedule = document.getElementById('schedule-preview'); + var form = event.target; + schedule.classList.add('requesting'); + _post( + form, + { + id: form.querySelector('[name="id"]').value, + button: 'deschedule_workshop' + }, + updateSchedule + ); + } + }); + document.body.addEventListener('click', function (event) { + //console.log(event.target); + + if (selectorMatches(event.target, 'td.workshop.open, td.workshop.open *')) { + //event.stopPropagation(); + var button = event.target; + while (button && button.tagName && button.tagName !== 'TD') { + button = button.parentElement; } - window.openOverlay(eventDlg, primaryContent, body); - var closeDlg = function(event) { - event.preventDefault(); - window.closeOverlay(eventDlg, primaryContent, body); - }; - eventDlg.querySelector('.close-btn').onclick = closeDlg; - document.getElementById('overlay').onclick = closeDlg; - }); - });*/ + document.getElementById('workshop-selector').classList.add('open'); + var table = document.getElementById('table'); + table.classList.add('loading'); + document.body.classList.add('modal-open'); + + var block = button.getAttribute('data-block'); + var day = button.getAttribute('data-day'); + var location = button.getAttribute('data-location'); + + _post( + document.getElementById('workshop-table-form'), + { + block: block, + day: day, + location: location, + button: 'get-workshop-list' + }, + function (response) { + var table = document.getElementById('table'); + table.innerHTML = response; + table.classList.remove('loading'); + forEachElement('tr.selectable', function(row) { + row.addEventListener('click', function(event) { + var schedule = document.getElementById('schedule-preview'); + schedule.classList.add('requesting'); + closeWorkshopSelector(); + var form = document.getElementById('workshop-table-form'); + _post( + form, + { + workshop: row.getAttribute('data-workshop'), + block: block, + day: day, + location: form.querySelector('#event_location').value, + button: 'set-workshop' + }, + updateSchedule + ); + }); + }, table); + } + ); + } + }, true); })(); diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss index 363365b..dee5f6e 100644 --- a/app/assets/stylesheets/_application.scss +++ b/app/assets/stylesheets/_application.scss @@ -1761,7 +1761,7 @@ ul.warnings li, } } -#admin-housing { +#admin-housing, #admin-schedule { .guests-housed { margin-bottom: 1em; text-align: right; @@ -1873,7 +1873,19 @@ ul.warnings li, } } - #guest-selector { + #workshop-selector { + td, th { + white-space: nowrap; + } + + td .text { + max-width: 50em; + overflow: hidden; + text-overflow: ellipsis; + } + } + + #guest-selector, #workshop-selector { display: none; position: fixed; top: 0; @@ -1888,7 +1900,7 @@ ul.warnings li, display: block; } - .guest-dlg { + .guest-dlg, .workshop-dlg { position: absolute; top: 0; right: 0; @@ -1931,7 +1943,7 @@ ul.warnings li, } table { - min-width: 100em; + margin: 0 0 2em; } h4 { @@ -2035,6 +2047,10 @@ ul.warnings li, } #admin-housing { + #table table { + min-width: 100em; + } + #hosts { background-color: $white; @@ -2208,9 +2224,8 @@ table.schedule { &.locations-6 td.workshop.filled { width: 16.66667%; } - td { - position: relative; + //position: relative; text-align: center; &.empty { @@ -2249,21 +2264,20 @@ table.schedule { } .event-detail-link { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; + display: inline-block; + display: inline-flex; + position: relative; + height: 100%; + width: 100%; color: inherit; + align-items: center; @include after { display: none; } - &:hover { - outline: 0.33rem solid #02CA9E; - outline-offset: 0.25rem; - z-index: 1; + .details { + flex: 1; } } @@ -2329,6 +2343,12 @@ table.schedule { } } +body.home table.schedule td .event-detail-link:hover { + outline: 0.33rem solid #02CA9E; + outline-offset: 0.25rem; + z-index: 1; +} + .event-dlg { @include _-(flex, 0); position: relative; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb deleted file mode 100644 index e11fd09..0000000 --- a/app/controllers/application_controller.rb +++ /dev/null @@ -1,643 +0,0 @@ -module ActiveRecord - class PremissionDenied < RuntimeError - end -end - -class ApplicationController < LinguaFrancaApplicationController - include ScheduleHelper - - # Prevent CSRF attacks by raising an exception. - # For APIs, you may want to use :null_session instead. - protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update] - - before_filter :capture_page_info - - @@test_host - @@test_location - - def capture_page_info - if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact') - session[:last_request] - request_info = { - 'params' => params, - 'request' => { - 'remote_ip' => request.remote_ip, - 'uuid' => request.uuid, - 'original_url' => request.original_url, - 'env' => Hash.new - } - } - request.env.each do | key, value | - request_info['request']['env'][key.to_s] = value.to_s - end - session['request_info'] = request_info - end - # set the translator to the current user if we're logged in - I18n.config.translator = current_user - I18n.config.callback = self - - # get the current confernece and set it globally - @conference = Conference.order("start_date DESC").first - - # add some style sheets - @stylesheets ||= Array.new - # add the translations stylesheet if translating - @stylesheets << params[:controller] if params[:controller] == 'translations' - - @_inline_scripts ||= [] - @_inline_scripts << Rails.application.assets.find_asset('main.js').to_s - - ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"} - - if request.post? && params[:action] == 'do_confirm' - halt_redirection! - end - - @alt_lang_urls = {} - I18n.backend.enabled_locales.each do |locale| - locale = locale.to_s - @alt_lang_urls[locale] = view_context.url_for_locale(locale) # don't show the current locale - end - - # give each environment a different icon and theme colour so that we can easily see where we are. See https://css-tricks.com/give-development-domain-different-favicon-production - @favicon = Rails.env.development? || Rails.env.preview? ? "favicon-#{Rails.env.to_s}.ico" : 'favicon.ico' - @theme_colour = Rails.env.preview? ? '#EF57B4' : (Rails.env.development? ? '#D89E59' : '#00ADEF') - - # call the base method to detect the language - super - end - - def home - @workshops = Workshop.where(:conference_id => @conference.id) - - if @conference.workshop_schedule_published - @event_dlg = true - view_context.add_inline_script :schedule - get_scheule_data#(false) - # @events = Event.where(:conference_id => @conference.id) - # schedule = get_schedule_data - # @schedule = schedule[:schedule] - # @locations = Hash.new - # EventLocation.where(:conference_id => @conference.id).each do |l| - # @locations[l.id.to_s] = l - # end - # @day_parts = @conference.day_parts ? JSON.parse(@conference.day_parts) : {:morning => 0, :afternoon => 13, :evening => 18} - end - end - - def policy - @is_policy_page = true - end - - def robots - render :text => File.read("config/robots-#{Rails.env.production? ? 'live' : 'dev'}.txt"), :content_type => 'text/plain' - end - - def humans - render :text => File.read("config/humans.txt"), :content_type => 'text/plain' - end - - def self.set_host(host) - @@test_host = host - end - - def self.set_location(location) - @@test_location = location - end - - def self.get_location() - @@test_location - end - - def do_404 - error_404(status: 404) - end - - def error_404(args = {}) - params[:_original_action] = params[:action] - params[:action] = 'error-404' - @page_title = 'page_titles.404.Page_Not_Found' - @main_title = 'error.404.title' - render 'application/404', args - end - - def do_403(template = nil) - @template = template - @page_title ||= 'page_titles.403.Access_Denied' - @main_title ||= @page_title - params[:_original_action] = params[:action] - params[:action] = 'error-403' - render 'application/permission_denied', status: 403 - end - - def error_500(exception = nil) - @page_title = 'page_titles.500.An_Error_Occurred' - @main_title = 'error.500.title' - params[:_original_action] = params[:action] - params[:action] = 'error-500' - render 'application/500', status: 500 - end - - def js_error - # send and email if this is production - report = "A JavaScript error has occurred on #{params[:location]}" - if params[:location] == params[:url] - report += " on line #{params[:lineNumber]}" - else - report += " in #{params[:url]}:#{params[:lineNumber]}" - end - - begin - # log the error - logger.info exception.to_s - logger.info exception.backtrace.join("\n") - - UserMailer.send_mail(:error_report) do - [ - "A JavaScript error has occurred", - report, - params[:message], - nil, - request, - params, - current_user, - Time.now.strftime("%d/%m/%Y %H:%M") - ] - end if Rails.env.preview? || Rails.env.production? - rescue exception2 - logger.info exception2.to_s - logger.info exception2.backtrace.join("\n") - end - render json: {} - end - - rescue_from ActiveRecord::RecordNotFound do |exception| - do_404 - end - - rescue_from ActiveRecord::PremissionDenied do |exception| - do_403 - end - - rescue_from AbstractController::ActionNotFound do |exception| - @banner_image = 'grafitti.jpg' - - if current_user - @page_title = nil#'page_titles.Please_Login' - do_403 'not_a_translator' - #return - else - @page_title = 'page_titles.403.Please_Login' - do_403 'translator_login' - end - end - - def locale_not_enabled!(locale = nil) - locale_not_available!(locale) - end - - def locale_not_available!(locale = nil) - set_default_locale - params[:_original_action] = params[:action] - params[:action] = 'error-locale-not-available' - @page_title = 'page_titles.404.Locale_Not_Available' - @main_title_vars = { vars: { language: view_context.language_name(locale) } } - @main_title = 'error.locale_not_available.title' - render 'application/locale_not_available', status: 404 - end - - rescue_from StandardError do |exception| - # log the error - logger.info exception.to_s - logger.info exception.backtrace.join("\n") - - # send and email if this is production - suppress(Exception) do - UserMailer.send_mail(:error_report) do - [ - "An error has occurred in #{Rails.env}", - nil, - exception.to_s, - exception.backtrace.join("\n"), - request, - params, - current_user, - Time.now.strftime("%d/%m/%Y %H:%M") - ] - end if Rails.env.preview? || Rails.env.production? - end - - # raise the error if we are in development so that we can debug it - raise exception if Rails.env.development? - - # show the error page - error_500 exception - end - - def generate_confirmation(user, url, expiry = nil) - if user.is_a? String - user = User.find_by_email(user) - - # if the user doesn't exist, just show them a 403 - do_403 unless user.present? - end - expiry ||= (Time.now + 12.hours) - session[:confirm_uid] = user.id - - unless user.locale.present? - user.locale = I18n.locale - user.save - end - - # send the confirmation email and make sure it get sent as quickly as possible - UserMailer.send_mail :email_confirmation do - EmailConfirmation.create(user_id: user.id, expiry: expiry, url: url) - end - end - - def user_settings - @conferences = Array.new - if logged_in? - Conference.all.each do | conference | - @conferences << conference if conference.host? current_user - end - end - @main_title = @page_title = 'page_titles.user_settings.Your_Account' - end - - def contact - @main_title = @page_title = 'page_titles.contact.Contact_Us' - end - - def contact_send - email_list = ['Godwin '] - - if params[:reason] == 'conference' - - @conference.organizations.each do | org | - org.users.each do | user | - email_list << user.named_email - end - end - end - - UserMailer.send_mail(:contact) do - [ - current_user || params[:email], - params[:subject], - params[:message], - email_list - ] - end - - request_info = session['request_info'] || { 'request' => request, 'params' => params } - UserMailer.send_mail(:contact_details) do - [ - current_user || params[:email], - params[:subject], - params[:message], - request_info['request'], - request_info['params'] - ] - end - - redirect_to contact_sent_path - end - - def contact_sent - @main_title = @page_title = 'page_titles.contact.Contact_Us' - @sent = true - render 'contact' - end - - def update_user_settings - return do_403 unless logged_in? - current_user.firstname = params[:name] - current_user.lastname = nil - current_user.languages = params[:languages].keys - current_user.is_subscribed = params[:email_subscribe].present? - current_user.save - redirect_to settings_path - end - - def do_confirm(settings = nil) - settings ||= {:template => 'login_confirmation_sent'} - if params[:email] - # see if we've already sent the confirmation email and are just confirming - # the email address - if params[:token] - user = User.find_by_email(params[:email]) - confirm(user) - return - end - user = User.find_by_email(params[:email]) - - unless user.present? - user = User.create(:email => params[:email], locale: I18n.locale) - end - - # generate the confirmation, send the email and show the 403 - referrer = params[:dest] || (request.present? && request.referer.present? ? request.referer.gsub(/^.*?\/\/.*?\//, '/') : settings_path) - generate_confirmation(params[:email], referrer) - template = 'login_confirmation_sent' - @page_title ||= 'page_titles.403.Please_Check_Email' - - if (request.present? && request.referrer.present? && conference = /^\/conferences\/(\w+)\/register\/?$/.match(request.referrer.gsub(/^https?:\/\/.*?\//, '/'))) - @this_conference = Conference.find_by!(slug: conference[1]) - @banner_image = @this_conference.cover_url - template = 'conferences/email_confirm' - end - end - - if request.post? - @banner_image ||= 'grafitti.jpg' - @page_title ||= 'page_titles.403.Please_Login' - - do_403 (template || 'translator_login') - else - do_404 - end - end - - def confirm(uid = nil) - @confirmation = EmailConfirmation.find_by_token(params[:token]) - - unless @confirmation.present? - @token_not_found = true - return do_404 - end - - confirm_user = nil - if uid.is_a?(User) - confirm_user = uid - uid = confirm_user.id - end - # check to see if we were given a user id to confirm against - # if we were, make sure it was the same one - if (uid ||= (params[:uid] || session[:confirm_uid])) - if uid == @confirmation.user_id - session[:uid] = nil - confirm_user ||= User.find uid - auto_login(confirm_user) - else - @confirmation.delete - end - - redirect_to (@confirmation.url || '/') - return - end - - @banner_image = 'grafitti.jpg' - @page_title = 'page_titles.403.Please_Confirm_Email' - do_403 'login_confirm' - end - - def translator_request - @banner_image = 'grafitti.jpg' - @page_title = 'page_titles.403.Translator_Request_Sent' - do_403 'translator_request_sent' - end - - def user_logout - logout() - redirect_to (params[:url] || '/') - end - - def login_user(u) - auto_login(u) - end - - def on_translation_change(object, data, locale, translator_id) - translator = User.find(translator_id) - mailer = "#{object.class.table_name.singularize}_translated" - - if object.respond_to?(:get_translators) - object.get_translators(data, locale).each do |id, user| - if user.id != current_user.id && user.id != translator_id - UserMailer.send_mail mailer, user.locale do - { :args => [object, data, locale, user, translator] } - end - end - end - end - end - - def on_translatable_content_change(object, data) - mailer = "#{object.class.table_name.singularize}_original_content_changed" - - if object.respond_to?(:get_translators) - object.get_translators(data).each do |id, user| - if user.id != current_user.id - UserMailer.send_mail mailer, user.locale do - { :args => [object, data, user, current_user] } - end - end - end - end - end - - def i18n_exception(str, exception, locale, key) - # log it - logger.info "Missing translation found for: #{key}" - - # send and email if this is production - begin - UserMailer.send_mail(:error_report) do - [ - "A missing translation found in #{Rails.env}", - "

A translation for #{key} in #{locale.to_s} was found. The text that was rendered to the user was:

#{str || 'nil'}
", - exception.to_s, - nil, - request, - params, - current_user, - Time.now.strftime("%d/%m/%Y %H:%M") - ] - end if Rails.env.preview? || Rails.env.production? - rescue exception2 - logger.info exception2.to_s - logger.info exception2.backtrace.join("\n") - end - end - - - def get_block_data - conference = @this_conference || @conference - @workshop_blocks = conference.workshop_blocks || [] - @block_days = [] - day = conference.start_date - while day <= conference.end_date - @block_days << day.wday - day += 1.day - end - end - - def get_scheule_data(do_analyze = true) - conference = @this_conference || @conference - @meals = Hash[(conference.meals || {}).map{ |k, v| [k.to_i, v] }].sort.to_h - @events = Event.where(:conference_id => conference.id).order(start_time: :asc) - @workshops = Workshop.where(:conference_id => conference.id).order(start_time: :asc) - @locations = {} - - get_block_data - - @schedule = {} - day_1 = conference.start_date.wday - - @workshop_blocks.each_with_index do | info, block | - info['days'].each do | block_day | - day_diff = block_day.to_i - day_1 - day_diff += 7 if day_diff < 0 - day = (conference.start_date + day_diff.days).to_date - time = info['time'].to_f - @schedule[day] ||= { times: {}, locations: {} } - @schedule[day][:times][time] ||= {} - @schedule[day][:times][time][:type] = :workshop - @schedule[day][:times][time][:length] = info['length'].to_f - @schedule[day][:times][time][:item] = { block: block, workshops: {} } - end - end - - @workshops.each do | workshop | - if workshop.block.present? - block = @workshop_blocks[workshop.block['block'].to_i] - day_diff = workshop.block['day'].to_i - day_1 - day_diff += 7 if day_diff < 0 - day = (conference.start_date + day_diff.days).to_date - - if @schedule[day].present? && @schedule[day][:times].present? && @schedule[day][:times][block['time'].to_f].present? - @schedule[day][:times][block['time'].to_f][:item][:workshops][workshop.event_location_id] = { workshop: workshop, status: { errors: [], warnings: [], conflict_score: nil } } - @schedule[day][:locations][workshop.event_location_id] ||= workshop.event_location if workshop.event_location.present? - end - end - end - - @meals.each do | time, meal | - day = meal['day'].to_date - time = meal['time'].to_f - @schedule[day] ||= {} - @schedule[day][:times] ||= {} - @schedule[day][:times][time] ||= {} - @schedule[day][:times][time][:type] = :meal - @schedule[day][:times][time][:length] = (meal['length'] || 1.0).to_f - @schedule[day][:times][time][:item] = meal - end - - @events.each do | event | - day = event.start_time.midnight.to_date - time = event.start_time.hour.to_f + (event.start_time.min / 60.0) - @schedule[day] ||= {} - @schedule[day][:times] ||= {} - @schedule[day][:times][time] ||= {} - @schedule[day][:times][time][:type] = :event - @schedule[day][:times][time][:length] = (event.end_time - event.start_time) / 3600.0 - @schedule[day][:times][time][:item] = event - end - - @schedule = @schedule.sort.to_h - @schedule.each do | day, data | - @schedule[day][:times] = data[:times].sort.to_h - end - - @schedule.each do | day, data | - last_event = nil - data[:times].each do | time, time_data | - if last_event.present? - @schedule[day][:times][last_event][:next_event] = time - end - last_event = time - end - @schedule[day][:num_locations] = (data[:locations] || []).size - end - - @schedule.deep_dup.each do | day, data | - data[:times].each do | time, time_data | - if time_data[:next_event].present? || time_data[:length] > 0.5 - span = 0.5 - length = time_data[:next_event].present? ? time_data[:next_event] - time : time_data[:length] - while span < length - @schedule[day][:times][time + span] ||= { - type: (span >= time_data[:length] ? :empty : :nil), - length: 0.5 - } - span += 0.5 - end - end - end - end - - @schedule = @schedule.sort.to_h - - return unless do_analyze - - @schedule.each do | day, data | - @schedule[day][:times] = data[:times].sort.to_h - @schedule[day][:locations][0] = :add if (@schedule[day][:locations] || []).size > 0 - - data[:times].each do | time, time_data | - if time_data[:type] == :workshop && time_data[:item].present? && time_data[:item][:workshops].present? - ids = time_data[:item][:workshops].keys - (0..ids.length).each do | i | - if time_data[:item][:workshops][ids[i]].present? - workshop_i = time_data[:item][:workshops][ids[i]][:workshop] - conflicts = {} - - (i+1..ids.length).each do | j | - workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil - if workshop_i.present? && workshop_j.present? - workshop_i.active_facilitators.each do | facilitator_i | - workshop_j.active_facilitators.each do | facilitator_j | - if facilitator_i.id == facilitator_j.id - @schedule[day][:times][time][:status] ||= {} - @schedule[day][:times][time][:item][:workshops][ids[j]][:status][:errors] << { - name: :common_facilitator, - facilitator: facilitator_i, - workshop: workshop_i, - i18nVars: { - facilitator_name: facilitator_i.name, - workshop_title: workshop_i.title - } - } - end - end - end - end - end - - (0..ids.length).each do | j | - workshop_j = time_data[:item][:workshops][ids[j]].present? ? time_data[:item][:workshops][ids[j]][:workshop] : nil - if workshop_i.present? && workshop_j.present? && workshop_i.id != workshop_j.id - workshop_i.interested.each do | interested_i | - workshop_j.interested.each do | interested_j | - conflicts[interested_i.id] ||= true - end - end - end - end - - location = workshop_i.event_location || EventLocation.new - needs = JSON.parse(workshop_i.needs || '[]').map &:to_sym - amenities = JSON.parse(location.amenities || '[]').map &:to_sym - - needs.each do | need | - @schedule[day][:times][time][:item][:workshops][ids[i]][:status][:errors] << { - name: :need_not_available, - need: need, - location: location, - workshop: workshop_i, - i18nVars: { - need: need.to_s, - location: location.title, - workshop_title: workshop_i.title - } - } unless amenities.include? need - end - - @schedule[day][:times][time][:item][:workshops][ids[i]][:status][:conflict_score] = workshop_i.interested.present? ? (conflicts.length / workshop_i.interested.size) : 0 - end - end - end - end - end - end -end diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb deleted file mode 100644 index 18a012a..0000000 --- a/app/controllers/conferences_controller.rb +++ /dev/null @@ -1,1841 +0,0 @@ -require 'geocoder/calculations' -require 'rest_client' - -class ConferencesController < ApplicationController - include ScheduleHelper - - before_action :set_conference, only: [:show, :edit, :update, :destroy, :registrations] - before_filter :authenticate, only: [:registrations] - - def authenticate - auth = get_secure_info(:registrations_access) - authenticate_or_request_with_http_basic('Administration') do |username, password| - username == auth[:username] && password == auth[:password] - end - end - - def 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] - @amount = PayPal!.details(params[:token]).amount.total - @registration.payment_info = {:payer_id => params[:PayerID], :token => params[:token], :amount => @amount}.to_yaml - - @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 ENV['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 = :incomplete - @register_template = :payment - end - @page_title = 'articles.conference_registration.headings.Payment' - else - - case form_step - when :confirm_email - return do_confirm - 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? && (l = Geocoder.search(params[:location], language: 'en')).present? - corrected = view_context.location(l.first, @this_conference.locale) - - if corrected.present? - @registration.city = corrected - if params[:location].gsub(/[\s,]/, '').downcase != @registration.city.gsub(/[\s,]/, '').downcase - @warnings << view_context._('warnings.messages.location_corrected', vars: {original: params[:location], corrected: corrected}) - 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_by_email(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 - @registration.payment_confirmation_token = ENV['RAILS_ENV'] == 'test' ? 'token' : Digest::SHA256.hexdigest(rand(Time.now.to_f * 1000000).to_i.to_s) - @registration.save - - host = "#{request.protocol}#{request.host_with_port}" - response = PayPal!.setup( - PayPalRequest(amount), - register_paypal_confirm_url(@this_conference.slug, :paypal_confirm, @registration.payment_confirmation_token), - register_paypal_confirm_url(@this_conference.slug, :paypal_cancel, @registration.payment_confirmation_token), - noshipping: true, - version: 204 - ) - if ENV['RAILS_ENV'] != 'test' - 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 - @registration.steps_completed.uniq! - end - - # workshops is the last step - if @register_template == :workshops - UserMailer.send_mail :registration_confirmation do - { - :args => @registration - } - end - end - end - - @registration.save! - end - end - end - end - - steps ||= registration_steps - - # make sure we're on a valid step - @register_template ||= (params[:step] || 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 != 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['companions'].present? && r.housing_data['companions'].include?(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' - - # initalize 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 :administration - @warnings << flash[:error] if flash[:error].present? - @admin_step = params[:admin_step] || view_context.admin_steps.first.to_s - return do_404 unless view_context.valid_admin_steps.include?(@admin_step.to_sym) - @page_title = 'articles.conference_registration.headings.Administration' - - case @admin_step.to_sym - when :organizations - @organizations = Organization.all - - if request.format.xlsx? - logger.info "Generating organizations.xls" - @excel_data = { - columns: [:name, :street_address, :city, :subregion, :country, :postal_code, :email, :phone, :status], - keys: { - name: 'forms.labels.generic.name', - street_address: 'forms.labels.generic.street_address', - city: 'forms.labels.generic.city', - subregion: 'forms.labels.generic.subregion', - country: 'forms.labels.generic.country', - postal_code: 'forms.labels.generic.postal_code', - email: 'forms.labels.generic.email', - phone: 'forms.labels.generic.phone', - status: 'forms.labels.generic.status' - }, - data: [], - } - @organizations.each do | org | - if org.present? - address = org.locations.first - @excel_data[:data] << { - 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, - country: address.present? ? I18n.t("geography.countries.#{address.country}") : nil, - postal_code: address.present? ? address.postal_code : nil, - email: org.email_address, - phone: org.phone, - status: org.status - } - end - end - return respond_to do | format | - format.xlsx { render xlsx: :stats, filename: "organizations" } - end - end - when :stats - get_stats(!request.format.xlsx?) - - 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')}" } - end - else - @registration_count = @registrations.size - @completed_registrations = 0 - @bikes = 0 - @donation_count = 0 - @donations = 0 - @food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 } - @registrations.each do | r | - if r.steps_completed.include? 'questions' - @completed_registrations += 1 - - @bikes += 1 if r.bike == 'yes' - - if r.food.present? - @food[r.food.to_sym] += 1 - @food[:all] += 1 - end - - if r.registration_fees_paid.present? && r.registration_fees_paid > 0 - @donation_count += 1 - @donations += r.registration_fees_paid - end - end - end - end - when :housing - # do a full analysis - analyze_housing - - if request.format.xlsx? - logger.info "Generating housing.xls" - @excel_data = { - columns: [:name, :phone, :street_address, :email, :availability, :considerations, :empty, :empty, :empty, :guests], - keys: { - name: 'forms.labels.generic.name', - street_address: 'forms.labels.generic.street_address', - email: 'forms.labels.generic.email', - phone: 'forms.labels.generic.phone', - availability: 'articles.conference_registration.headings.host.availability', - considerations: 'articles.conference_registration.headings.host.considerations' - }, - column_types: { - name: :bold, - guests: :table - }, - data: [], - } - @hosts.each do | id, host | - data = (host.housing_data || {}) - host_data = { - name: host.user.name, - street_address: data['address'], - email: host.user.email, - phone: data['phone'], - availability: data['availability'].present? && data['availability'][1].present? ? view_context.date_span(data['availability'][0].to_date, data['availability'][1].to_date) : '', - considerations: (data['considerations'].map { | consideration | view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '), - empty: '', - guests: { - columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city], - keys: { - name: 'forms.labels.generic.name', - area: 'articles.workshops.headings.space', - email: 'forms.labels.generic.email', - arrival_departure: 'articles.admin.housing.headings.arrival_departure', - companion: 'forms.labels.generic.companion', - city: 'forms.labels.generic.city', - food: 'forms.labels.generic.food', - allergies: 'forms.labels.generic.allergies' - }, - column_types: { - name: :bold - }, - data: [] - } - } - - @housing_data[id][:guests].each do | space, space_data | - space_data.each do | guest_id, guest_data | - guest = guest_data[:guest] - if guest.present? - companion = view_context.companion(guest) - - host_data[:guests][:data] << { - name: guest.user.name, - area: (view_context._"forms.labels.generic.#{space}"), - email: guest.user.email, - arrival_departure: guest.arrival.present? && guest.departure.present? ? view_context.date_span(guest.arrival.to_date, guest.departure.to_date) : '', - companion: companion.present? ? (companion.is_a?(User) ? companion.name : (view_context._"articles.conference_registration.terms.registration_status.#{companion}")) : '', - city: guest.city, - food: (view_context._"articles.conference_registration.questions.food.#{guest.food}"), - allergies: guest.allergies - } - end - end - end - - @excel_data[:data] << host_data - end - return respond_to do | format | - format.xlsx { render xlsx: :stats, filename: "housing" } - end - end - when :locations - @locations = EventLocation.where(:conference_id => @this_conference.id) - when :events - @event = Event.new(locale: I18n.locale) - @events = Event.where(:conference_id => @this_conference.id) - @day = nil - @time = nil - @length = 1.5 - when :meals - @meals = Hash[(@this_conference.meals || {}).map{ |k, v| [k.to_i, v] }].sort.to_h - when :workshop_times - get_block_data - @workshop_blocks << { - 'time' => nil, - 'length' => 1.0, - 'days' => [] - } - when :schedule - @can_edit = true - @entire_page = true - get_scheule_data - end - when :confirm_email - @page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details" - end - - 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 } - @excel_data = { - columns: [ - :name, - :email, - :status, - :is_attending, - :is_subscribed, - :registration_fees_paid, - :date, - :city, - :preferred_language - ] + - User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } + - [ - :arrival, - :departure, - :housing, - :bike, - :food, - :companion, - :companion_email, - :allergies, - :other, - :can_provide_housing, - :first_day, - :last_day, - :address, - :phone - ] + ConferenceRegistration.all_spaces + - ConferenceRegistration.all_considerations + [ - :notes - ], - column_types: { - name: :bold, - date: :datetime, - email: :email, - companion_email: :email, - arrival: [:date, :day], - departure: [:date, :day], - registration_fees_paid: :money, - allergies: :text, - other: :text, - first_day: [:date, :day], - last_day: [:date, :day], - notes: :text - }, - keys: { - name: 'forms.labels.generic.name', - email: 'forms.labels.generic.email', - status: 'forms.labels.generic.registration_status', - is_attending: 'articles.conference_registration.terms.is_attending', - is_subscribed: 'articles.user_settings.headings.email_subscribe', - city: 'forms.labels.generic.event_location', - date: 'articles.conference_registration.terms.Date', - preferred_language: 'articles.conference_registration.terms.Preferred_Languages', - arrival: 'forms.labels.generic.arrival', - departure: 'forms.labels.generic.departure', - housing: 'forms.labels.generic.housing', - bike: 'forms.labels.generic.bike', - 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', - first_day: 'forms.labels.generic.first_day', - last_day: 'forms.labels.generic.last_day', - notes: 'forms.labels.generic.notes', - phone: 'forms.labels.generic.phone', - address: 'forms.labels.generic.address', - contact_info: 'articles.conference_registration.headings.contact_info', - questions: 'articles.conference_registration.headings.questions', - hosting: 'articles.conference_registration.headings.hosting' - }, - data: [] - } - User.AVAILABLE_LANGUAGES.each do | l | - @excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}" - end - ConferenceRegistration.all_spaces.each do |s| - @excel_data[:column_types][s] = :number - @excel_data[:keys][s] = "forms.labels.generic.#{s.to_s}" - end - ConferenceRegistration.all_considerations.each do |c| - @excel_data[:keys][c] = "articles.conference_registration.host.considerations.#{c.to_s}" - end - @registrations.each do | r | - user = r.user_id ? User.where(id: r.user_id).first : nil - if user.present? - companion = view_context.companion(r) - companion = companion.is_a?(User) ? companion.name : (view_context._"articles.conference_registration.terms.registration_status.#{companion}") if companion.present? - steps = r.steps_completed || [] - - if id.nil? || id == r.id - housing_data = r.housing_data || {} - availability = housing_data['availability'] || [] - availability[0] = Date.parse(availability[0]) if availability[0].present? - availability[1] = Date.parse(availability[1]) if availability[1].present? - - data = { - id: r.id, - name: user.firstname || '', - email: user.email || '', - status: (view_context._"articles.conference_registration.terms.registration_status.#{(steps.include? 'questions') ? 'registered' : ((steps.include? 'contact_info') ? 'preregistered' : 'unregistered')}"), - is_attending: (view_context._"articles.conference_registration.questions.bike.#{r.is_attending == 'n' ? 'no' : 'yes'}"), - is_subscribed: user.is_subscribed == false ? (view_context._'articles.conference_registration.questions.bike.no') : '', - date: r.created_at ? r.created_at.strftime("%F %T") : '', - city: r.city || '', - preferred_language: user.locale.present? ? (view_context.language_name user.locale) : '', - arrival: r.arrival ? r.arrival.strftime("%F %T") : '', - departure: r.departure ? r.departure.strftime("%F %T") : '', - housing: r.housing.present? ? (view_context._"articles.conference_registration.questions.housing.#{r.housing}") : '', - 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, - registration_fees_paid: r.registration_fees_paid, - 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") : '', - notes: housing_data['notes'], - address: housing_data['address'], - phone: housing_data['phone'], - raw_values: { - housing: r.housing, - bike: r.bike, - food: r.food, - arrival: r.arrival.present? ? r.arrival.to_date : nil, - departure: r.departure.present? ? r.departure.to_date : nil, - preferred_language: user.locale, - is_attending: r.is_attending != 'n', - is_subscribed: user.is_subscribed, - can_provide_housing: r.can_provide_housing, - first_day: availability[0].present? ? availability[0].to_date : nil, - last_day: availability[1].present? ? availability[1].to_date : nil - }, - html_values: { - date: r.created_at.present? ? r.created_at.strftime("%F %T") : '', - arrival: r.arrival.present? ? view_context.date(r.arrival.to_date, :span_same_year_date_1) : '', - departure: r.departure.present? ? view_context.date(r.departure.to_date, :span_same_year_date_1) : '', - first_day: availability[0].present? ? view_context.date(availability[0].to_date, :span_same_year_date_1) : '', - last_day: availability[1].present? ? view_context.date(availability[1].to_date, :span_same_year_date_1) : '' - } - } - User.AVAILABLE_LANGUAGES.each do | l | - can_speak = ((user.languages || []).include? l.to_s) - data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '') - data[:raw_values]["language_#{l}".to_sym] = can_speak - end - ConferenceRegistration.all_spaces.each do |s| - space = (housing_data['space'] || {})[s.to_s] - data[s] = space.present? ? space.to_i : nil - end - ConferenceRegistration.all_considerations.each do |c| - consideration = (housing_data['considerations'] || []).include?(c.to_s) - data[c] = (consideration ? (view_context._'articles.conference_registration.questions.bike.yes') : '') - data[:raw_values][c] = consideration - end - @excel_data[:data] << data - end - end - end - - if html_format - yes_no = [ - [(view_context._"articles.conference_registration.questions.bike.yes"), true], - [(view_context._"articles.conference_registration.questions.bike.no"), false] - ] - @column_options = { - housing: ConferenceRegistration.all_housing_options.map { |h| [ - (view_context._"articles.conference_registration.questions.housing.#{h}"), - h] }, - bike: ConferenceRegistration.all_bike_options.map { |b| [ - (view_context._"articles.conference_registration.questions.bike.#{b}"), - b] }, - food: ConferenceRegistration.all_food_options.map { |f| [ - (view_context._"articles.conference_registration.questions.food.#{f}"), - f] }, - arrival: view_context.conference_days_options_list(:before_plus_one), - departure: view_context.conference_days_options_list(:after_minus_one), - preferred_language: I18n.backend.enabled_locales.map { |l| [ - (view_context.language_name l), l - ] }, - is_attending: [yes_no.first], - is_subscribed: [yes_no.last], - can_provide_housing: yes_no, - first_day: view_context.conference_days_options_list(:before), - last_day: view_context.conference_days_options_list(:after) - } - User.AVAILABLE_LANGUAGES.each do | l | - @column_options["language_#{l}".to_sym] = [ - [(view_context._"articles.conference_registration.questions.bike.yes"), true] - ] - end - ConferenceRegistration.all_considerations.each do | c | - @column_options[c.to_sym] = [ - [(view_context._"articles.conference_registration.questions.bike.yes"), true] - ] - end - end - end - - def get_housing_data - @hosts = {} - @guests = {} - ConferenceRegistration.where(:conference_id => @this_conference.id).each do | registration | - if registration.can_provide_housing - @hosts[registration.id] = registration - elsif registration.housing.present? && registration.housing != 'none' - @guests[registration.id] = registration - end - end - end - - def analyze_housing - get_housing_data unless @hosts.present? && @guests.present? - - @housing_data = {} - @hosts_affected_by_guests = {} - @hosts.each do | id, host | - @hosts[id].housing_data ||= {} - @housing_data[id] = { guests: {}, space: {} } - @hosts[id].housing_data['space'] ||= {} - @hosts[id].housing_data['space'].each do | s, size | - size = (size || 0).to_i - @housing_data[id][:guests][s.to_sym] = {} - @housing_data[id][:space][s.to_sym] = size - end - end - - @guests_housed = 0 - - @guests.each do | guest_id, guest | - data = guest.housing_data || {} - @hosts_affected_by_guests[guest_id] ||= [] - - if data['host'] - @guests_housed += 1 - host_id = (data['host'].present? ? data['host'].to_i : nil) - host = host_id.present? ? @hosts[host_id] : nil - - # make sure the host was found and that they are still accepting guests - if host.present? && host.can_provide_housing - @hosts_affected_by_guests[guest_id] << host_id - - space = (data['space'] || :bed).to_sym - - @housing_data[host_id] ||= {} - host_data = host.housing_data - unless @housing_data[host_id][:guests][space].present? - @housing_data[host_id][:guests][space] ||= {} - @housing_data[host_id][:space][space] ||= 0 - end - - @housing_data[host_id][:guests][space][guest_id] = { guest: guest } - - @housing_data[host_id][:guest_data] ||= {} - @housing_data[host_id][:guest_data][guest_id] = { warnings: {}, errors: {} } - - @housing_data[host_id][:guest_data][guest_id][:warnings][:dates] = {} unless view_context.available_dates_match?(host, guest) - - if (guest.housing == 'house' && space == :tent) || - (guest.housing == 'tent' && (space == :bed_space || space == :floor_space)) - @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_by_email(companion) - if user.present? - reg = ConferenceRegistration.find_by( - :user_id => user.id, - :conference_id => @this_conference.id - ) - if reg.present? && @guests[reg.id].present? - housing_data = reg.housing_data || {} - companion_host = housing_data['host'].present? ? housing_data['host'].to_i : nil - @hosts_affected_by_guests[guest_id] << companion_host - if companion_host != host_id && reg.housing.present? && reg.housing != 'none' - # set this as an error if the guest has selected only one other to stay with, but if they have requested to stay with more, make this only a warning - @housing_data[host_id][:guest_data][guest_id][:warnings][:companions] = { name: "#{reg.user.name}".html_safe, id: reg.id } - end - end - end - end - else - # make sure the housing data is empty if the host wasn't found, just in case something happened to the host - @guests[guest_id].housing_data ||= {} - @guests[guest_id].housing_data['host'] = nil - @guests[guest_id].housing_data['space'] = nil - end - end - end - - @hosts.each do | id, host | - host_data = host.housing_data - - @hosts[id].housing_data['space'].each do | space, size | - # make sure the host isn't overbooked - space = space.to_sym - space_available = (size || 0).to_i - @housing_data[id][:warnings] ||= {} - @housing_data[id][:warnings][:space] ||= {} - @housing_data[id][:warnings][:space][space] ||= [] - - if @housing_data[id][:guests][space].size > space_available - @housing_data[id][:warnings][:space][space] << :overbooked - end - end - end - - return @hosts_affected_by_guests - end - - def admin_update - set_conference - # set_conference_registration - return do_403 unless @this_conference.host? current_user - - # set the page title in case we render instead of redirecting - @page_title = 'articles.conference_registration.headings.Administration' - @register_template = :administration - @admin_step = params[:admin_step] - - case params[:admin_step] - when 'stats' - if params[:button] == 'save' || params[:button] == 'update' - if params[:button] == 'save' - return do_404 unless params[:email].present? && params[:name].present? - - user = User.find_by_email(params[:email]) || User.create(email: params[:email]) - user.firstname = params[:name] - user.save! - registration = ConferenceRegistration.new( - conference: @this_conference, - user_id: user.id, - steps_completed: [] - ) - else - registration = ConferenceRegistration.where( - id: params[:key].to_i, - conference_id: @this_conference.id - ).limit(1).first - end - - user_changed = false - params.each do | key, value | - case key.to_sym - when :city - registration.city = value.present? ? view_context.location(Geocoder.search(value, language: @this_conference.locale).first, @this_conference.locale) : nil - when :housing, :bike, :food, :allergies, :other - registration.send("#{key.to_s}=", value) - when :registration_fees_paid - registration.registration_fees_paid = value.to_i - when :can_provide_housing - registration.send("#{key.to_s}=", value.present?) - when :arrival, :departure - registration.send("#{key.to_s}=", value.present? ? Date.parse(value) : nil) - when :companion_email - registration.housing_data ||= {} - registration.housing_data['companions'] = [value] - when :preferred_language - registration.user.locale = value - user_changed = true - when :is_subscribed - registration.user.is_subscribed = (value != "false") - user_changed = true - when :is_attending - registration.is_attending = value.present? ? 'y' : 'n' - when :address, :phone, :first_day, :last_day, :notes - registration.housing_data ||= {} - registration.housing_data[key.to_s] = value - else - if key.start_with?('language_') - l = key.split('_').last - if User.AVAILABLE_LANGUAGES.include? l.to_sym - registration.user.languages ||= [] - if value.present? - registration.user.languages |= [l] - else - registration.user.languages -= [l] - end - user_changed = true - end - elsif ConferenceRegistration.all_considerations.include? key.to_sym - registration.housing_data ||= {} - registration.housing_data['considerations'] ||= {} - if value.present? - registration.housing_data['considerations'] |= [key] - else - registration.housing_data['considerations'] -= [key] - end - elsif ConferenceRegistration.all_spaces.include? key.to_sym - registration.housing_data ||= {} - registration.housing_data['space'] ||= {} - registration.housing_data['space'][key.to_s] = value - end - end - end - registration.user.save! if user_changed - registration.save! - - if params[:button] == 'save' - return redirect_to register_step_path(@this_conference.slug, :administration) - end - - get_stats(true, params[:key].to_i) - options = view_context.registrations_table_options - options[:html] = true - return render html: view_context.excel_rows(@excel_data, {}, options) - end - when 'edit' - case params[:button] - when 'save' - @this_conference.registration_status = params[:registration_status] - @this_conference.info = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:info]) unless @this_conference.info! == params[:info] - - params[:info_translations].each do | locale, value | - @this_conference.set_column_for_locale(:info, locale, value, current_user.id) unless value == @this_conference._info(locale) - end - @this_conference.save - return redirect_to administration_step_path(@this_conference.slug, :edit) - when 'add_member' - org = nil - @this_conference.organizations.each do | organization | - org = organization if organization.id == params[:org_id].to_i - end - org.users << (User.get params[:email]) - org.save - return redirect_to administration_step_path(@this_conference.slug, :edit) - end - when 'payment' - case params[:button] - when 'save' - @this_conference.payment_message = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:payment_message]) unless @this_conference.payment_message! == params[:payment_message] - - params[:payment_message_translations].each do | locale, value | - @this_conference.set_column_for_locale(:payment_message, locale, value, current_user.id) unless value == @this_conference._payment_message(locale) - end - - @this_conference.payment_amounts = ((params[:payment_amounts] || {}).values.map &:to_i) - [0] - - @this_conference.paypal_email_address = params[:paypal_email_address] - @this_conference.paypal_username = params[:paypal_username] - @this_conference.paypal_password = params[:paypal_password] - @this_conference.paypal_signature = params[:paypal_signature] - @this_conference.save - return redirect_to administration_step_path(@this_conference.slug, :payment) - end - when 'housing' - # modify the guest data - - if params[:button] == 'get-guest-list' - # get_housing_data - analyze_housing - return render partial: 'conferences/admin/select_guest_table', locals: { host: @hosts[params['host'].to_i], space: params['space'] } - elsif params[:button] == 'set-guest' - guest = ConferenceRegistration.where( - id: params[:guest].to_i, - conference_id: @this_conference.id - ).limit(1).first - - guest.housing_data ||= {} - guest.housing_data['space'] = params[:space] - guest.housing_data['host'] = params[:host].to_i - guest.save! - - analyze_housing - - return render partial: 'conferences/admin/hosts_table' - elsif params[:button] == 'remove-guest' - guest = ConferenceRegistration.where( - id: params[:guest].to_i, - conference_id: @this_conference.id - ).limit(1).first - - guest.housing_data ||= {} - guest.housing_data.delete('space') - guest.housing_data.delete('host') - guest.save! - - analyze_housing - - return render partial: 'conferences/admin/hosts_table' - end - when 'broadcast' - @hide_description = true - @subject = params[:subject] - @body = params[:body] - @send_to = params[:send_to] - @register_template = :administration - if params[:button] == 'send' - view_context.broadcast_to(@send_to).each do | user | - UserMailer.send_mail :broadcast do - [ - "#{request.protocol}#{request.host_with_port}", - @subject, - @body, - user, - @this_conference - ] - end - end - return redirect_to administration_step_path(@this_conference.slug, :broadcast_sent) - elsif params[:button] == 'preview' - @send_to_count = view_context.broadcast_to(@send_to).size - @broadcast_step = :preview - elsif params[:button] == 'test' - @broadcast_step = :test - UserMailer.send_mail :broadcast do - [ - "#{request.protocol}#{request.host_with_port}", - @subject, - @body, - current_user, - @this_conference - ] - end - @send_to_count = view_context.broadcast_to(@send_to).size - end - return render 'conferences/register' - when 'locations' - case params[:button] - when 'edit' - @location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id - return render 'conferences/register' - when 'save' - location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id - empty_param = get_empty(params, [:title, :address, :space]) - if empty_param.present? - flash[:error] = (view_context._"errors.messages.fields.#{empty_param.to_s}.empty") - else - location.title = params[:title] - location.address = params[:address] - location.amenities = (params[:needs] || {}).keys.to_json - location.space = params[:space] - location.save! - end - return redirect_to administration_step_path(@this_conference.slug, :locations) - when 'cancel' - return redirect_to administration_step_path(@this_conference.slug, :locations) - when 'delete' - location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id - location.destroy - return redirect_to administration_step_path(@this_conference.slug, :locations) - when 'create' - empty_param = get_empty(params, [:title, :address, :space]) - if empty_param.present? - flash[:error] = (view_context._"errors.messages.fields.#{empty_param.to_s}.empty") - else - EventLocation.create( - conference_id: @this_conference.id, - title: params[:title], - address: params[:address], - amenities: (params[:needs] || {}).keys.to_json, - space: params[:space] - ) - end - return redirect_to administration_step_path(@this_conference.slug, :locations) - end - when 'meals' - case params[:button] - when 'add_meal' - @this_conference.meals ||= {} - @this_conference.meals[(Date.parse(params[:day]) + params[:time].to_f.hours).to_time.to_i] = { - title: params[:title], - info: params[:info], - location: params[:event_location], - day: params[:day], - time: params[:time] - } - @this_conference.save! - return redirect_to administration_step_path(@this_conference.slug, :meals) - when 'delete' - @this_conference.meals ||= {} - @this_conference.meals.delete params[:meal] - @this_conference.save! - return redirect_to administration_step_path(@this_conference.slug, :meals) - end - when 'events' - case params[:button] - when 'edit' - @event = Event.find_by!(conference_id: @this_conference.id, id: params[:id]) - @day = @event.start_time.midnight - @time = view_context.hour_span(@day, @event.start_time) - @length = view_context.hour_span(@event.start_time, @event.end_time) - return render 'conferences/register' - when 'save' - if params[:id].present? - event = Event.find_by!(conference_id: @this_conference.id, id: params[:id]) - else - event = Event.new(conference_id: @this_conference.id, locale: I18n.locale) - end - - # save title and info - event.title = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:title]) unless event.title! == params[:title] - event.info = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:info]) unless event.info! == params[:info] - - # save schedule data - event.event_location_id = params[:event_location] - event.start_time = Date.parse(params[:day]) + params[:time].to_f.hours - event.end_time = event.start_time + params[:time_span].to_f.hours - - # save translations - (params[:info_translations] || {}).each do | locale, value | - event.set_column_for_locale(:title, locale, value, current_user.id) unless value = event._title(locale) - event.set_column_for_locale(:info, locale, value, current_user.id) unless value = event._info(locale) - end - - event.save - - return redirect_to administration_step_path(@this_conference.slug, :events) - when 'cancel' - return redirect_to administration_step_path(@this_conference.slug, :events) - end - when 'workshop_times' - case params[:button] - when 'save_block' - @this_conference.workshop_blocks ||= [] - @this_conference.workshop_blocks[params[:workshop_block].to_i] = { - 'time' => params[:time], - 'length' => params[:time_span], - 'days' => params[:days].keys - } - @this_conference.save - return redirect_to administration_step_path(@this_conference.slug, :workshop_times) - end - when 'schedule' - success = false - - case params[:button] - when 'schedule_workshop' - workshop = Workshop.find_by!(conference_id: @this_conference.id, id: params[:id]) - booked = false - workshop.event_location_id = params[:event_location] - block_data = params[:workshop_block].split(':') - workshop.block = { - day: block_data[0].to_i, - block: block_data[1].to_i - } - - # make sure this spot isn't already taken - Workshop.where(:conference_id => @this_conference.id).each do | w | - if request.xhr? - if w.block.present? && - w.id != workshop.id && - w.block['day'] == workshop.block['day'] && - w.block['block'] == workshop.block['block'] && - w.event_location_id == workshop.event_location_id - return render json: [ { - selector: '.already-booked', - className: 'already-booked is-true' - } ] - end - else - return redirect_to administration_step_path(@this_conference.slug, :schedule) - end - end - - workshop.save! - success = true - when 'deschedule_workshop' - workshop = Workshop.find_by!(conference_id: @this_conference.id, id: params[:id]) - workshop.event_location_id = nil - workshop.block = nil - workshop.save! - success = true - when 'publish' - @this_conference.workshop_schedule_published = !@this_conference.workshop_schedule_published - @this_conference.save - return redirect_to administration_step_path(@this_conference.slug, :schedule) - end - - if success - if request.xhr? - @can_edit = true - @entire_page = false - get_scheule_data - schedule = render_to_string partial: 'conferences/admin/schedule' - return render json: [ { - globalSelector: '#schedule-preview', - html: schedule - }, { - globalSelector: "#workshop-#{workshop.id}", - className: workshop.block.present? ? 'booked' : 'not-booked' - }, { - globalSelector: "#workshop-#{workshop.id} .already-booked", - className: 'already-booked' - } ] - else - return redirect_to administration_step_path(@this_conference.slug, :schedule) - end - end - end - do_404 - end - - def workshops - set_conference - set_conference_registration! - @workshops = Workshop.where(:conference_id => @this_conference.id) - @my_workshops = Workshop.joins(:workshop_facilitators).where(:workshop_facilitators => {:user_id => current_user.id}, :conference_id => @this_conference.id) - render 'workshops/index' - end - - def view_workshop - set_conference - set_conference_registration! - @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless @workshop - - @translations_available_for_editing = [] - I18n.backend.enabled_locales.each do |locale| - @translations_available_for_editing << locale if @workshop.can_translate?(current_user, locale) - end - @page_title = 'page_titles.conferences.View_Workshop' - @register_template = :workshops - - render 'workshops/show' - end - - def create_workshop - set_conference - set_conference_registration! - @workshop = Workshop.new - @languages = [I18n.locale.to_sym] - @needs = [] - @page_title = 'page_titles.conferences.Create_Workshop' - @register_template = :workshops - render 'workshops/new' - end - - def translate_workshop - @is_translating = true - @translation = params[:locale] - @page_title = 'page_titles.conferences.Translate_Workshop' - @page_title_vars = { language: view_context.language_name(@translation) } - @register_template = :workshops - - edit_workshop - end - - def edit_workshop - set_conference - set_conference_registration! - @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - - return do_404 unless @workshop.present? - - @page_title ||= 'page_titles.conferences.Edit_Workshop' - - @can_edit = @workshop.can_edit?(current_user) - - @is_translating ||= false - if @is_translating - return do_404 if @translation.to_s == @workshop.locale.to_s || !I18n.backend.enabled_locales.include?(@translation.to_s) - return do_403 unless @workshop.can_translate?(current_user, @translation) - - @title = @workshop._title(@translation) - @info = @workshop._info(@translation) - else - return do_403 unless @can_edit - - @title = @workshop.title - @info = @workshop.info - end - - @needs = JSON.parse(@workshop.needs || '[]').map &:to_sym - @languages = JSON.parse(@workshop.languages || '[]').map &:to_sym - @space = @workshop.space.to_sym if @workshop.space - @theme = @workshop.theme.to_sym if @workshop.theme - @notes = @workshop.notes - @register_template = :workshops - - render 'workshops/new' - end - - def delete_workshop - set_conference - set_conference_registration! - @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - - return do_404 unless @workshop.present? - return do_403 unless @workshop.can_delete?(current_user) - - if request.post? - if params[:button] == 'confirm' - if @workshop - @workshop.workshop_facilitators.destroy_all - @workshop.destroy - end - - return redirect_to register_step_path(@this_conference.slug, 'workshops') - end - return redirect_to view_workshop_url(@this_conference.slug, @workshop.id) - end - @register_template = :workshops - - render 'workshops/delete' - end - - def save_workshop - set_conference - set_conference_registration! - - if params[:button].to_sym != :save - if params[:workshop_id].present? - return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id]) - end - return redirect_to register_step_path(@this_conference.slug, 'workshops') - end - - if params[:workshop_id].present? - workshop = Workshop.find(params[:workshop_id]) - return do_404 unless workshop.present? - can_edit = workshop.can_edit?(current_user) - else - workshop = Workshop.new(:conference_id => @this_conference.id) - workshop.workshop_facilitators = [WorkshopFacilitator.new(:user_id => current_user.id, :role => :creator)] - can_edit = true - end - - title = params[:title] - info = params[:info].gsub(/^\s*(.*?)\s*$/, '\1') - - if params[:translation].present? && workshop.can_translate?(current_user, params[:translation]) - old_title = workshop._title(params[:translation]) - old_info = workshop._info(params[:translation]) - - do_save = false - - unless title == old_title - workshop.set_column_for_locale(:title, params[:translation], title, current_user.id) - do_save = true - end - unless info == old_info - workshop.set_column_for_locale(:info, params[:translation], info, current_user.id) - do_save = true - end - - # only save if the text has changed, if we want to make sure only to update the translator id if necessary - workshop.save_translations if do_save - elsif can_edit - workshop.title = title - workshop.info = info - workshop.languages = (params[:languages] || {}).keys.to_json - workshop.needs = (params[:needs] || {}).keys.to_json - workshop.theme = params[:theme] == 'other' ? params[:other_theme] : params[:theme] - workshop.space = params[:space] - workshop.notes = params[:notes] - workshop.needs_facilitators = params[:needs_facilitators].present? - workshop.save - - # Rouge nil facilitators have been know to be created, just destroy them here now - WorkshopFacilitator.where(:user_id => nil).destroy_all - else - return do_403 - end - - redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - - def toggle_workshop_interest - set_conference - set_conference_registration! - workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless workshop - - # save the current state - interested = workshop.interested? current_user - # remove all associated fields - WorkshopInterest.delete_all(:workshop_id => workshop.id, :user_id => current_user.id) - - # creat the new interest row if we weren't interested before - WorkshopInterest.create(:workshop_id => workshop.id, :user_id => current_user.id) unless interested - - if request.xhr? - render json: [ - { - selector: '.interest-button', - html: view_context.interest_button(workshop) - }, - { - selector: '.interest-text', - html: view_context.interest_text(workshop) - } - ] - else - # go back to the workshop - redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - end - - def facilitate_workshop - set_conference - set_conference_registration! - @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless @workshop - return do_403 if @workshop.facilitator?(current_user) || !current_user - - @register_template = :workshops - render 'workshops/facilitate' - end - - def facilitate_request - set_conference - set_conference_registration! - workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless workshop - return do_403 if workshop.facilitator?(current_user) || !current_user - - # create the request by making the user a facilitator but making their role 'requested' - WorkshopFacilitator.create(user_id: current_user.id, workshop_id: workshop.id, role: :requested) - - UserMailer.send_mail :workshop_facilitator_request do - { - :args => [ workshop, current_user, params[:message] ] - } - end - - redirect_to sent_facilitate_workshop_url(@this_conference.slug, workshop.id) - end - - def sent_facilitate_request - set_conference - set_conference_registration! - @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless @workshop - return do_403 unless @workshop.requested_collaborator?(current_user) - - @register_template = :workshops - render 'workshops/facilitate_request_sent' - end - - def approve_facilitate_request - return do_403 unless logged_in? - set_conference - set_conference_registration! - workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - return do_404 unless workshop.present? - - user_id = params[:user_id].to_i - action = params[:approve_or_deny].to_sym - user = User.find(user_id) - case action - when :approve - if workshop.active_facilitator?(current_user) && workshop.requested_collaborator?(User.find(user_id)) - f = WorkshopFacilitator.find_by_workshop_id_and_user_id( - workshop.id, user_id) - f.role = :collaborator - f.save - UserMailer.send_mail :workshop_facilitator_request_approved, user.locale do - [ workshop, user ] - end - return redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - when :deny - if workshop.active_facilitator?(current_user) && workshop.requested_collaborator?(User.find(user_id)) - WorkshopFacilitator.delete_all( - :workshop_id => workshop.id, - :user_id => user_id) - UserMailer.send_mail :workshop_facilitator_request_denied, user.locale do - [ workshop, user ] - end - return redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - when :remove - if workshop.can_remove?(current_user, user) - WorkshopFacilitator.delete_all( - :workshop_id => workshop.id, - :user_id => user_id) - return redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - when :switch_ownership - if workshop.creator?(current_user) - f = WorkshopFacilitator.find_by_workshop_id_and_user_id( - workshop.id, current_user.id) - f.role = :collaborator - f.save - f = WorkshopFacilitator.find_by_workshop_id_and_user_id( - workshop.id, user_id) - f.role = :creator - f.save - return redirect_to view_workshop_url(@this_conference.slug, workshop.id) - end - end - - return do_403 - end - - def add_workshop_facilitator - set_conference - set_conference_registration! - - user = User.find_by_email(params[:email]) - - # create the user if they don't exist and send them a link to register - unless user - user = User.create(email: params[:email]) - generate_confirmation(user, register_path(@this_conference.slug)) - end - - workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - - return do_404 unless workshop && current_user - - unless workshop.facilitator?(user) - WorkshopFacilitator.create(user_id: user.id, workshop_id: workshop.id, role: :collaborator) - - UserMailer.send_mail :workshop_facilitator_request_approved, user.locale do - [ workshop, user ] - end - end - - return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id]) - end - - def add_comment - set_conference - set_conference_registration! - workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id) - - return do_404 unless workshop && current_user - - if params[:button] == 'reply' - comment = Comment.find_by!(id: params[:comment_id].to_i, model_type: :workshops, model_id: workshop.id) - new_comment = comment.add_comment(current_user, params[:reply]) - - unless comment.user.id == current_user.id - UserMailer.send_mail :workshop_comment, comment.user.locale do - [ workshop, new_comment, comment.user ] - end - end - elsif params[:button] = 'add_comment' - new_comment = workshop.add_comment(current_user, params[:comment]) - - workshop.active_facilitators.each do | u | - unless u.id == current_user.id - UserMailer.send_mail :workshop_comment, u.locale do - [ workshop, new_comment, u ] - end - end - end - else - return do_404 - end - - return redirect_to view_workshop_url(@this_conference.slug, workshop.id, anchor: "comment-#{new_comment.id}") - end - - helper_method :registration_steps - helper_method :current_registration_steps - helper_method :registration_complete? - - def registration_steps(conference = nil) - conference ||= @this_conference || @conference - status = conference.registration_status - # return [] unless status == :pre || status == :open - - steps = status == :pre || status == :open ? [ - :policy, - :contact_info, - :questions, - :hosting, - :payment, - :workshops - ] : [] - - steps -= [:questions] unless status == :open - steps -= [:payment] unless status == :open && conference.paypal_email_address.present? && conference.paypal_username.present? && conference.paypal_password.present? && conference.paypal_signature.present? - if @registration.present? - if view_context.same_city?(@registration.city, view_context.location(conference.location, conference.locale)) - steps -= [:questions] - - # if this is a housing provider that is not attending the conference, remove these steps - if @registration.is_attending == 'n' - steps -= [:payment, :workshops] - end - else - steps -= [:hosting] - end - else - steps -= [:hosting, :questions] - end - - steps += [:administration] if conference.host?(current_user) - - return steps - end - - def required_steps(conference = nil) - # return the intersection of current steps and required steps - registration_steps(conference || @this_conference || @conference) & # current steps - [:policy, :contact_info, :hosting, :questions] # all required steps - end - - def registration_complete?(registration = @registration) - completed_steps = registration.steps_completed || [] - required_steps(registration.conference).each do | step | - return true if step == :workshops - return false unless completed_steps.include?(step.to_s) - end - return true - end - - def current_registration_steps(registration = @registration) - return nil unless registration.present? - - steps = registration_steps(registration.conference) - current_steps = [] - disable_steps = false - completed_steps = registration.steps_completed || [] - registration_complete = registration_complete?(registration) - steps.each do | step | - # disable the step if we've already found an incomplete step - enabled = !disable_steps || registration_complete - # record whether or not we've found an incomplete step - disable_steps ||= !completed_steps.include?(step.to_s) - - current_steps << { - name: step, - enabled: enabled - } - end - return current_steps - end - - def current_step(registration = @registration) - completed_steps = registration.steps_completed || [] - (registration_steps(registration.conference) || []).each do | step | - return step unless completed_steps.include?(step.to_s) - end - return registration_steps(registration.conference).last - end - - rescue_from ActiveRecord::RecordNotFound do |exception| - do_404 - end - - rescue_from ActiveRecord::PremissionDenied do |exception| - if logged_in? - redirect_to :register - else - @register_template = :confirm_email - @page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details" - render :register - end - end - - private - # Use callbacks to share common setup or constraints between actions. - def set_conference - @this_conference = Conference.find_by!(slug: params[:conference_slug] || params[:slug]) - end - - def set_conference_registration - @registration = logged_in? ? ConferenceRegistration.find_by(:user_id => current_user.id, :conference_id => @this_conference.id) : nil - end - - def set_conference_registration! - @registration = set_conference_registration - raise ActiveRecord::PremissionDenied unless @registration.present? - end - - def set_or_create_conference_registration - set_conference_registration - return @registration if @registration.present? - - @registration ||= ConferenceRegistration.new( - conference: @this_conference, - user_id: current_user.id, - steps_completed: [] - ) - last_registration_data = ConferenceRegistration.where(user_id: current_user.id).order(created_at: :desc).limit(1).first - - if last_registration_data.present? - if last_registration_data['languages'].present? && current_user.languages.blank? - current_user.languages = JSON.parse(last_registration_data['languages']) - current_user.save! - end - - @registration.city = last_registration_data.city if last_registration_data.city.present? - end - end - - # Only allow a trusted parameter "white list" through. - def conference_params - params.require(:conference).permit(:title, :slug, :start_date, :end_date, :info, :poster, :cover, :workshop_schedule_published, :registration_status, :meals_provided, :meal_info, :travel_info, :conference_type_id, conference_types: [:id]) - end - - def update_field_position(field_id, position) - data = [] - for i in 0..@conference.conference_registration_form_fields.length - f = @conference.conference_registration_form_fields[i] - if f.registration_form_field_id == field_id - data << (f.registration_form_field_id.to_s + ' == ' + field_id.to_s + ' [position: ' + position.to_s + ' == ' + f.position.to_s + ']') - f.update_attributes(:position => position) - return - end - end - end - - def update_registration_data - if session[:registration][:registration_id] - registration = ConferenceRegistration.find(session[:registration][:registration_id]) - registration.data = YAML.load(registration.data).merge(session[:registration]).to_yaml - registration.save! - end - end - - def complete_registration - if session[:registration][:registration_id] - registration = ConferenceRegistration.find(session[:registration][:registration_id]) - session[:registration] = YAML.load(registration.data) - registration.completed = true - if registration.is_confirmed - registration.complete = true - - user = User.find_by(:email => session[:registration][:email]) - if !user - user = User.new(:email => session[:registration][:email], :username => session[:registration][:user][:username], :role => 'user') - end - user.firstname = session[:registration][:user][:firstname] - user.lastname = session[:registration][:user][:lastname] - user.save! - - if session[:registration][:is_participant] - UserOrganizationRelationship.destroy_all(:user_id => user.id) - session[:registration][:organizations].each { |org_id| - found = false - org = Organization.find(org_id.is_a?(Array) ? org_id.first : org_id) - org.user_organization_relationships.each {|rel| found = found && rel.user_id == user.id} - if !found - org.user_organization_relationships << UserOrganizationRelationship.new(:user_id => user.id, :relationship => UserOrganizationRelationship::Administrator) - end - org.save! - } - - if session[:registration][:new_organization] - session[:registration][:new_organization].each { |new_org| - found = false - org = Organization.find_by(:email_address => new_org[:email]) - if org.nil? - org = Organization.new( - :name => new_org[:name], - :email_address => new_org[:email], - :info => new_org[:info] - ) - org.locations << Location.new(:country => new_org[:country], :territory => new_org[:territory], :city => new_org[:city], :street => new_org[:street]) - end - org.user_organization_relationships.each {|rel| found = found && rel.user_id == user.id} - if !found - org.user_organization_relationships << UserOrganizationRelationship.new(:user_id => user.id, :relationship => UserOrganizationRelationship::Administrator) - end - org.save! - org.avatar = "#{request.protocol}#{request.host_with_port}/#{new_org[:logo]}" - cover = get_panoramio_image(org.locations.first) - org.cover = cover[:image] - org.cover_attribution_id = cover[:attribution_id] - org.cover_attribution_user_id = cover[:attribution_user_id] - org.cover_attribution_name = cover[:attribution_user_name] - org.cover_attribution_src = cover[:attribution_src] - org.save! - } - end - - if session[:registration][:is_workshop_host] && session[:registration][:workshop] - session[:registration][:workshop].each { |new_workshop| - workshop = Workshop.new( - :conference_id => @conference.id, - :title => new_workshop[:title], - :info => new_workshop[:info], - :workshop_stream_id => WorkshopStream.find_by(:slug => new_workshop[:stream]).id, - :workshop_presentation_style => WorkshopPresentationStyle.find_by(:slug => new_workshop[:presentation_style]) - ) - workshop.workshop_facilitators << WorkshopFacilitator.new(:user_id => user.id) - workshop.save! - } - end - end - - send_confirmation_confirmation(registration, session[:registration]) - - session.delete(:registration) - session[:registration] = Hash.new - session[:registration][:registration_id] = registration.id - end - registration.save! - end - end - - def create_registration - if session[:registration][:registration_id].blank? || !ConferenceRegistration.exists?(session[:registration][:registration_id]) - registration = ConferenceRegistration.new( - :conference_id => @conference.id, - :user_id => session[:registration][:user][:id], - :email => session[:registration][:email], - :is_attending => 'y', - :is_participant => session[:registration][:is_participant], - :is_volunteer => session[:registration][:is_volunteer], - :is_confirmed => false, - :complete => false, - :completed => false, - :confirmation_token => rand_hash(32, :conference_registration, :confirmation_token), - :payment_confirmation_token => rand_hash(32, :conference_registration, :payment_confirmation_token), - :data => session[:registration].to_yaml - ) - registration.save! - session[:registration][:registration_id] = registration.id - send_confirmation(registration, session[:registration]) - end - end - - def send_confirmation(registration = nil, data = nil) - registration ||= ConferenceRegistration.find(session[:registration][:registration_id]) - data ||= YAML.load(registration.data) - UserMailer.conference_registration_email(@conference, data, registration).deliver - end - - def send_confirmation_confirmation(registration = nil, data = nil) - registration ||= ConferenceRegistration.find(session[:registration][:registration_id]) - data ||= YAML.load(registration.data) - UserMailer.conference_registration_confirmed_email(@conference, data, registration).deliver - end - - def send_payment_received(registration = nil, data = nil) - registration ||= ConferenceRegistration.find(session[:registration][:registration_id]) - data ||= YAML.load(registration.data) - UserMailer.conference_registration_payment_received(@conference, data, registration).deliver - end - - def get_empty(hash, keys) - keys = [keys] unless keys.is_a?(Array) - keys.each do | key | - puts " ===== #{key} = #{hash[key]} ===== " - return key unless hash[key].present? - end - return nil - end - - def PayPal! - Paypal::Express::Request.new( - username: @this_conference.paypal_username, - password: @this_conference.paypal_password, - signature: @this_conference.paypal_signature - ) - end - - def PayPalRequest(amount) - Paypal::Payment::Request.new( - :currency_code => 'USD', # if nil, PayPal use USD as default - :description => 'Conference Registration', # item description - :quantity => 1, # item quantity - :amount => amount.to_f, # item value - :custom_fields => { - CARTBORDERCOLOR: "00ADEF", - LOGOIMG: "https://en.bikebike.org/assets/bblogo-paypal.png" - } - ) - end -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 54a0cdd..bb89c67 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -822,7 +822,7 @@ module ApplicationHelper locations = [] if @this_conference.event_locations.present? @this_conference.event_locations.each do | location | - locations << [ location.title, location.id ] + locations << [ location.title, location.id ] unless ((args[:invalid_locations] || []).include? location.id) end end selectfield :event_location, value, locations, args diff --git a/app/views/conferences/admin/_schedule.html.haml b/app/views/conferences/admin/_schedule.html.haml index 35a122d..8be059e 100644 --- a/app/views/conferences/admin/_schedule.html.haml +++ b/app/views/conferences/admin/_schedule.html.haml @@ -1,9 +1,9 @@ -- add_inline_script :schedule - conference = @this_conference || @conference - if conference.event_locations.blank? && @entire_page .warning-info=_'articles.admin.schedule.no_locations_warning' - else - if @entire_page + - add_inline_script :schedule = form_tag administration_update_path(conference.slug, :schedule) do - if conference.workshop_schedule_published %p=_'articles.conference_registration.paragraphs.admin.schedule.published', :p @@ -16,7 +16,7 @@ - @schedule.each do | day, data | %h4=date(day, :weekday) %table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]} - - if data[:locations].present? + - if data[:locations].present? && data[:locations].values.first != :add %thead %tr %th.corner @@ -29,40 +29,36 @@ - rowspan = (time_data[:length] * 2).to_i %th=time(time) - if time_data[:type] == :workshop - - if time_data[:item][:workshops].present? - - data[:locations].each do | id, location | - - if time_data[:item][:workshops][id].present? - - workshop = time_data[:item][:workshops][id][:workshop] - - status = time_data[:item][:workshops][id][:status] - - else - - workshop = status = nil - %td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: (time_data[:item][:block] + 1), day: day }} - - if workshop.present? && workshop.event_location.present? - = link_to off_screen(workshop.title), view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' - %template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }} - %h1.title=workshop.title - %p.address - = workshop.event_location.title + _!(': ') - = location_link workshop.event_location - .workshop-description= richtext workshop.info, 1 - .title=workshop.title - - if @can_edit - = form_tag administration_update_path(conference.slug, :schedule), class: 'js-xhr' do - .status - .conflict-score - %span.title Conflict Score: - %span.value="#{status[:conflict_score] * 100.0}%" - - if status[:errors].present? - .errors - - status[:errors].each do | error | - .error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars] - = hidden_field_tag :id, workshop.id - = button_tag :deschedule, value: :deschedule_workshop, class: [:delete, :small] - - elsif @can_edit - .title="Block #{time_data[:item][:block] + 1}" - - else - %td{class: [time_data[:type], :open], rowspan: rowspan, colspan: data[:locations].present? ? data[:locations].size : 1, data: { block: (time_data[:item][:block] + 1), day: day }} - - if @can_edit + - data[:locations].each do | id, location | + - if time_data[:item][:workshops][id].present? + - workshop = time_data[:item][:workshops][id][:workshop] + - status = time_data[:item][:workshops][id][:status] + - else + - workshop = status = nil + %td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }} + - if workshop.present? && workshop.event_location.present? + = link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do + .details + .title=workshop.title + %template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }} + %h1.title=workshop.title + %p.address + = workshop.event_location.title + _!(': ') + = location_link workshop.event_location + .workshop-description= richtext workshop.info, 1 + - if @can_edit + = form_tag administration_update_path(conference.slug, :schedule), class: 'deschedule-workshop' do + .status + .conflict-score + %span.title Conflict Score: + %span.value="#{status[:conflict_score] * 100.0}%" + - if status[:errors].present? + .errors + - status[:errors].each do | error | + .error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars] + = hidden_field_tag :id, workshop.id + = button_tag :deschedule, value: :deschedule_workshop, class: [:delete, :small] + - elsif @can_edit .title="Block #{time_data[:item][:block] + 1}" %td.status{rowspan: rowspan} - if time_data[:status].present? && time_data[:status][:errors].present? @@ -75,63 +71,30 @@ - when :meal - location = EventLocation.where(id: time_data[:item]['location'].to_i).first - if location.present? - %a.event-detail-link=off_screen(time_data[:item]['title']) + %a.event-detail-link + .details + .title= time_data[:item]['title'] + .location= location.title %template.event-details %h1.title=time_data[:item]['title'] %p.address = location.title + _!(': ') = location_link location - .title= time_data[:item]['title'] - .location= location.title - when :event - if time_data[:item].event_location.present? - %a.event-detail-link=off_screen(time_data[:item][:title]) + %a.event-detail-link + .details + .title= time_data[:item][:title] + .location= time_data[:item].event_location.title %template.event-details %h1.title=time_data[:item][:title] %p.address = time_data[:item].event_location.title + _!(': ') = location_link time_data[:item].event_location = richtext time_data[:item][:info], 1 - .title= time_data[:item][:title] - .location= time_data[:item].event_location.title %td.status{rowspan: rowspan} - if @entire_page - %ul.workshops-to-schedule - - @workshops.each do | workshop | - %li{id: "workshop-#{workshop.id}", class: workshop.block.present? ? 'booked' : 'not-booked'} - %h4.title= workshop.title - = form_tag administration_update_path(conference.slug, :schedule), class: 'js-xhr' do - .already-booked - .field-error='This block is already booked' - .workshop-description - .details - = data_set(:h5, 'articles.workshops.headings.interested_count') do - = workshop.interested_count - = data_set(:h5, 'articles.workshops.headings.facilitators') do - - facilitators = [] - - workshop.active_facilitators.each do | facilitator | - - facilitators << facilitator.name - = facilitators.join ', ' - = data_set(:h5, 'articles.workshops.headings.needs') do - - needs = [] - - JSON.parse(workshop.needs || '[]').each do | need | - - needs << (_"workshop.options.needs.#{need}") - = _!(needs.join ', ') - = data_set(:h5, 'articles.workshops.headings.theme') do - = Workshop.all_themes.include?((workshop.theme || '').to_sym) ? (_"workshop.options.theme.#{workshop.theme}") : workshop.theme - = data_set(:h5, 'articles.workshops.headings.space') do - = workshop.space.present? ? (_"workshop.options.space.#{workshop.space}") : '' - = data_set(:h5, 'forms.labels.generic.info') do - = link_info_dlg truncate(workshop.info), (richtext workshop.info.html_safe), workshop.title - - if workshop.notes.present? && strip_tags(workshop.notes).length > 0 - = data_set(:h5, 'forms.labels.generic.notes') do - = link_info_dlg truncate(workshop.notes), (richtext workshop.notes.html_safe), workshop.title - - = hidden_field_tag :id, workshop.id - .drop-downs - = location_select workshop.event_location_id, small: true - = block_select workshop.block.present? ? "#{workshop.block['day']}:#{workshop.block['block']}" : nil, small: true - .actions.next-prev - = button_tag :deschedule, value: :deschedule_workshop, class: [:delete, 'booked-only', :small] - = button_tag :reschedule, value: :schedule_workshop, class: [:secondary, 'booked-only', :small] - = button_tag :schedule_workshop, value: :schedule_workshop, class: ['not-booked-only', :small] + #workshop-selector + = form_tag administration_update_path(@this_conference.slug, :schedule), class: 'workshop-dlg', id: 'workshop-table-form' do + %h3 Select a Workshop + #table