hackathon_manager 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +90 -0
- data/Rakefile +36 -0
- data/app/assets/config/hackathon_manager_manifest.js +0 -0
- data/app/assets/javascripts/hackathon_manager/application.js +16 -0
- data/app/assets/javascripts/hackathon_manager/jquery.transit.min.js +1 -0
- data/app/assets/javascripts/hackathon_manager/main.js +237 -0
- data/app/assets/javascripts/hackathon_manager/manage/application.js +20 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/emailEvents.js +25 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.bulkRowSelect.js +13 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.bulkRowedit.js +42 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.chartkickAutoReload.js +8 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/setupDataTables.js +98 -0
- data/app/assets/javascripts/hackathon_manager/manage/lib/setupHighcharts.js +34 -0
- data/app/assets/javascripts/hackathon_manager/manage/map.js +58 -0
- data/app/assets/javascripts/hackathon_manager/registrations.js +26 -0
- data/app/assets/javascripts/hackathon_manager/us.json +1 -0
- data/app/assets/javascripts/hackathon_manager/vendor/buttons.html5.min.js +22 -0
- data/app/assets/javascripts/hackathon_manager/vendor/d3.v3.min.js +5 -0
- data/app/assets/javascripts/hackathon_manager/vendor/dataTables.buttons.min.js +35 -0
- data/app/assets/javascripts/hackathon_manager/vendor/jquery.dataTables.min.js +164 -0
- data/app/assets/javascripts/hackathon_manager/vendor/pdfmake.min.js +22 -0
- data/app/assets/javascripts/hackathon_manager/vendor/queue.v1.min.js +1 -0
- data/app/assets/javascripts/hackathon_manager/vendor/topojson.v1.min.js +1 -0
- data/app/assets/javascripts/hackathon_manager/vendor/vfs_fonts.js +1 -0
- data/app/assets/stylesheets/hackathon_manager/core.sass +20 -0
- data/app/assets/stylesheets/hackathon_manager/datatables/buttons.dataTables.min.css +1 -0
- data/app/assets/stylesheets/hackathon_manager/datatables/jquery.dataTables.min.css +1 -0
- data/app/assets/stylesheets/hackathon_manager/forms/_confirmation.sass +21 -0
- data/app/assets/stylesheets/hackathon_manager/forms/_forms.sass +243 -0
- data/app/assets/stylesheets/hackathon_manager/general/_base.sass +105 -0
- data/app/assets/stylesheets/hackathon_manager/general/_button.sass +49 -0
- data/app/assets/stylesheets/hackathon_manager/general/_footer.sass +21 -0
- data/app/assets/stylesheets/hackathon_manager/general/_main.sass +4 -0
- data/app/assets/stylesheets/hackathon_manager/general/_media-queries.sass +52 -0
- data/app/assets/stylesheets/hackathon_manager/general/_mixins.sass +58 -0
- data/app/assets/stylesheets/hackathon_manager/general/_mlh.sass +13 -0
- data/app/assets/stylesheets/hackathon_manager/general/_sidebar.sass +70 -0
- data/app/assets/stylesheets/hackathon_manager/general/_status-colors.sass +14 -0
- data/app/assets/stylesheets/hackathon_manager/general/_table.sass +26 -0
- data/app/assets/stylesheets/hackathon_manager/mailer.sass +108 -0
- data/app/assets/stylesheets/hackathon_manager/manage.sass +119 -0
- data/app/assets/stylesheets/hackathon_manager/scaffolds.scss +50 -0
- data/app/assets/stylesheets/variables.sass +41 -0
- data/app/controllers/bus_lists_controller.rb +37 -0
- data/app/controllers/concerns/questionnaires_controllable.rb +15 -0
- data/app/controllers/manage/admins_controller.rb +55 -0
- data/app/controllers/manage/application_controller.rb +13 -0
- data/app/controllers/manage/bus_lists_controller.rb +71 -0
- data/app/controllers/manage/dashboard_controller.rb +112 -0
- data/app/controllers/manage/messages_controller.rb +88 -0
- data/app/controllers/manage/questionnaires_controller.rb +172 -0
- data/app/controllers/manage/schools_controller.rb +87 -0
- data/app/controllers/manage/stats_controller.rb +77 -0
- data/app/controllers/questionnaires_controller.rb +145 -0
- data/app/controllers/rsvps_controller.rb +97 -0
- data/app/controllers/users/omniauth_callbacks_controller.rb +18 -0
- data/app/controllers/users/registrations_controller.rb +63 -0
- data/app/datatables/admin_datatable.rb +29 -0
- data/app/datatables/message_datatable.rb +30 -0
- data/app/datatables/questionnaire_datatable.rb +39 -0
- data/app/datatables/school_datatable.rb +34 -0
- data/app/helpers/hackathon_manager_helper.rb +36 -0
- data/app/helpers/manage/dashboard_helper.rb +9 -0
- data/app/inputs/deletable_attachment_input.rb +11 -0
- data/app/inputs/formatted_boolean_input.rb +26 -0
- data/app/inputs/school_selection_input.rb +9 -0
- data/app/mailers/application_mailer.rb +4 -0
- data/app/mailers/mail_preview.rb +42 -0
- data/app/mailers/mailer.rb +84 -0
- data/app/models/bus_list.rb +24 -0
- data/app/models/deletable_attachment.rb +17 -0
- data/app/models/fips.rb +3 -0
- data/app/models/message.rb +76 -0
- data/app/models/questionnaire.rb +166 -0
- data/app/models/schedule.rb +53 -0
- data/app/models/school.rb +31 -0
- data/app/models/school_name_duplicate.rb +7 -0
- data/app/models/user.rb +52 -0
- data/app/views/application/_bus_list_info.html.haml +20 -0
- data/app/views/application/_bus_list_stats.html.haml +9 -0
- data/app/views/application/_questionnaire_summary.html.haml +54 -0
- data/app/views/bus_lists/show.html.haml +45 -0
- data/app/views/devise/passwords/_form.html.haml +9 -0
- data/app/views/devise/passwords/edit.html.haml +14 -0
- data/app/views/devise/passwords/new.html.haml +5 -0
- data/app/views/devise/registrations/_form.html.haml +8 -0
- data/app/views/devise/registrations/edit.html.haml +20 -0
- data/app/views/devise/registrations/new.html.haml +18 -0
- data/app/views/devise/sessions/_form.html.haml +8 -0
- data/app/views/devise/sessions/new.html.haml +9 -0
- data/app/views/layouts/_shared_footer.html.haml +1 -0
- data/app/views/layouts/_sidebar.html.haml +22 -0
- data/app/views/layouts/blank.html.haml +12 -0
- data/app/views/layouts/dayof.html.haml +12 -0
- data/app/views/layouts/hackathon_manager.html.haml +12 -0
- data/app/views/layouts/mailer.html.erb +51 -0
- data/app/views/layouts/manage/application.html.haml +26 -0
- data/app/views/mailer/_getting_there.html.erb +14 -0
- data/app/views/mailer/_questions.html.erb +2 -0
- data/app/views/mailer/accepted_email.html.erb +13 -0
- data/app/views/mailer/application_confirmation_email.html.erb +13 -0
- data/app/views/mailer/bulk_message_email.html.erb +1 -0
- data/app/views/mailer/bulk_templates/_default.html.erb +1 -0
- data/app/views/mailer/bus_captain_confirmation_email.html.erb +12 -0
- data/app/views/mailer/bus_list_update_email.html.erb +7 -0
- data/app/views/mailer/denied_email.html.erb +5 -0
- data/app/views/mailer/incomplete_reminder_email.html.erb +6 -0
- data/app/views/mailer/rsvp_confirmation_email.html.erb +8 -0
- data/app/views/mailer/slack_invite_email.html.erb +10 -0
- data/app/views/manage/admins/_form.html.haml +18 -0
- data/app/views/manage/admins/edit.html.haml +12 -0
- data/app/views/manage/admins/index.html.haml +15 -0
- data/app/views/manage/admins/new.html.haml +8 -0
- data/app/views/manage/admins/show.html.haml +17 -0
- data/app/views/manage/bus_lists/_form.html.haml +14 -0
- data/app/views/manage/bus_lists/edit.html.haml +8 -0
- data/app/views/manage/bus_lists/index.html.haml +26 -0
- data/app/views/manage/bus_lists/new.html.haml +6 -0
- data/app/views/manage/bus_lists/show.html.haml +92 -0
- data/app/views/manage/dashboard/index.html.haml +64 -0
- data/app/views/manage/dashboard/map_data.tsv.erb +48 -0
- data/app/views/manage/messages/_form.html.haml +15 -0
- data/app/views/manage/messages/edit.html.haml +10 -0
- data/app/views/manage/messages/index.html.haml +17 -0
- data/app/views/manage/messages/new.html.haml +8 -0
- data/app/views/manage/messages/show.html.haml +50 -0
- data/app/views/manage/questionnaires/_form.html.haml +54 -0
- data/app/views/manage/questionnaires/edit.html.haml +12 -0
- data/app/views/manage/questionnaires/index.html.haml +36 -0
- data/app/views/manage/questionnaires/new.html.haml +8 -0
- data/app/views/manage/questionnaires/show.html.haml +63 -0
- data/app/views/manage/schools/_form.html.haml +16 -0
- data/app/views/manage/schools/edit.html.haml +12 -0
- data/app/views/manage/schools/index.html.haml +18 -0
- data/app/views/manage/schools/merge.html.haml +35 -0
- data/app/views/manage/schools/new.html.haml +8 -0
- data/app/views/manage/schools/show.html.haml +52 -0
- data/app/views/manage/stats/index.html.haml +55 -0
- data/app/views/questionnaires/_form.html.haml +70 -0
- data/app/views/questionnaires/edit.html.haml +10 -0
- data/app/views/questionnaires/new.html.haml +7 -0
- data/app/views/questionnaires/show.html.haml +30 -0
- data/app/views/rsvps/show.html.haml +61 -0
- data/app/workers/bulk_message_worker.rb +86 -0
- data/app/workers/slack_invite_worker.rb +49 -0
- data/config/blazer.yml +56 -0
- data/config/initializers/ajax_datatables_rails.rb +7 -0
- data/config/initializers/chartkick.rb +4 -0
- data/config/initializers/devise.rb +265 -0
- data/config/initializers/hackathon.rb +9 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/new_framework_defaults.rb +20 -0
- data/config/initializers/sidekiq.rb +11 -0
- data/config/initializers/simple_form.rb +164 -0
- data/config/initializers/static_data.rb +7 -0
- data/config/initializers/wrap_parameters.rb +14 -0
- data/config/routes.rb +74 -0
- data/db/migrate/20141011210642_create_participants.rb +18 -0
- data/db/migrate/20141029055313_create_schools.rb +12 -0
- data/db/migrate/20150104071608_add_shirt_and_dietary_medical_to_participants.rb +6 -0
- data/db/migrate/20150104190233_add_attachment_resume_to_participants.rb +13 -0
- data/db/migrate/20150110020958_add_international_to_participants.rb +5 -0
- data/db/migrate/20150110215933_change_participants_to_registration.rb +5 -0
- data/db/migrate/20150110222214_create_users.rb +5 -0
- data/db/migrate/20150110222455_add_portfolio_and_vcs_urls_to_registrations.rb +6 -0
- data/db/migrate/20150110222655_add_devise_to_users.rb +48 -0
- data/db/migrate/20150111000224_change_resgistrations_to_questionnaire.rb +5 -0
- data/db/migrate/20150111012709_add_questionnaire_ref_to_users.rb +8 -0
- data/db/migrate/20150113205638_add_amin_to_users.rb +5 -0
- data/db/migrate/20150113233730_add_questionnaire_count_to_schools.rb +12 -0
- data/db/migrate/20150125213100_set_default_admin_value.rb +17 -0
- data/db/migrate/20150216232155_add_agreement_accepted_to_questionnaires.rb +5 -0
- data/db/migrate/20150218051450_add_admin_read_only_to_users.rb +5 -0
- data/db/migrate/20150221165513_create_messages.rb +15 -0
- data/db/migrate/20150225235817_add_status_to_user.rb +7 -0
- data/db/migrate/20150302011457_create_fips.rb +11 -0
- data/db/migrate/20150326031423_add_template_to_message.rb +5 -0
- data/db/migrate/20150410175056_create_bus_lists.rb +12 -0
- data/db/migrate/20150411161432_add_capacity_notes_captain_to_bus_lists.rb +8 -0
- data/db/migrate/20150415165844_add_is_bus_captain_to_questionnaire.rb +5 -0
- data/db/migrate/20150415181114_add_check_in_data_to_questionnaire.rb +8 -0
- data/db/migrate/20151224015223_change_read_only_user_to_limited.rb +5 -0
- data/db/migrate/20160110012217_add_code_of_conduct_accepted_to_questionnaire.rb +5 -0
- data/db/migrate/20160110222639_add_omniauth_to_users.rb +8 -0
- data/db/migrate/20160111020817_update_questionnaire_for_my_mlh.rb +14 -0
- data/db/migrate/20160112222137_add_option_for_alt_travel_to_questionnaire.rb +6 -0
- data/db/migrate/20160208061253_rename_can_share_resume_to_info.rb +5 -0
- data/db/migrate/20161020032736_remove_resume_from_questionnaires.rb +14 -0
- data/db/migrate/20161024145452_add_data_sharing_to_questionnaire.rb +5 -0
- data/db/migrate/20161206073921_rename_graduation_to_level_of_study.rb +6 -0
- data/db/migrate/20161206084722_add_reminder_sent_at_to_users.rb +5 -0
- data/db/migrate/20161208055809_add_attachment_resume_to_questionnaires.rb +11 -0
- data/db/migrate/20161212030010_add_interest_to_questionnaire.rb +5 -0
- data/db/migrate/20170107210122_create_school_name_duplicates.rb +10 -0
- data/db/migrate/20170128063020_install_blazer.rb +45 -0
- data/db/schools.csv +1 -0
- data/db/seeds.rb +17 -0
- data/lib/hackathon_manager/engine.rb +35 -0
- data/lib/hackathon_manager/version.rb +3 -0
- data/lib/hackathon_manager.rb +5 -0
- data/lib/tasks/coverage.rake +14 -0
- data/lib/tasks/hackathon_manager_tasks.rake +4 -0
- metadata +667 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
class Questionnaire < ApplicationRecord
|
2
|
+
include ActiveModel::Dirty
|
3
|
+
|
4
|
+
before_validation :consolidate_school_names
|
5
|
+
after_save :update_school_questionnaire_count
|
6
|
+
after_destroy :update_school_questionnaire_count
|
7
|
+
|
8
|
+
validates_presence_of :first_name, :last_name, :phone, :date_of_birth, :school_id, :experience, :shirt_size, :interest
|
9
|
+
validates_presence_of :gender, :major, :level_of_study
|
10
|
+
validates_presence_of :agreement_accepted, message: "Must accept"
|
11
|
+
validates_presence_of :code_of_conduct_accepted, message: "Must accept"
|
12
|
+
validates_presence_of :data_sharing_accepted, message: "Must accept"
|
13
|
+
|
14
|
+
has_attached_file :resume
|
15
|
+
validates_attachment_content_type :resume, content_type: %w(application/pdf), message: "Invalid file type"
|
16
|
+
validates_attachment_size :resume, in: 0..2.megabytes, message: "File size is too big"
|
17
|
+
|
18
|
+
include DeletableAttachment
|
19
|
+
|
20
|
+
validates :portfolio_url, url: { allow_blank: true }
|
21
|
+
validates :vcs_url, url: { allow_blank: true }
|
22
|
+
validates_format_of :vcs_url, with: /((github.com\/\w+\/?)|(bitbucket.org\/\w+\/?))/, allow_blank: true, message: "Must be a GitHub or BitBucket url"
|
23
|
+
|
24
|
+
belongs_to :school
|
25
|
+
|
26
|
+
strip_attributes
|
27
|
+
|
28
|
+
POSSIBLE_EXPERIENCES = {
|
29
|
+
"first" => "This is my 1st hackathon!",
|
30
|
+
"experienced" => "My feet are wet. (1-5 hackathons)",
|
31
|
+
"expert" => "I'm a veteran hacker. (6+ hackathons)"
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
POSSIBLE_INTERESTS = {
|
35
|
+
"design" => "Design",
|
36
|
+
"software" => "Software",
|
37
|
+
"hardware" => "Hardware",
|
38
|
+
"combination" => "Combination of everything!"
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
POSSIBLE_SHIRT_SIZES = [
|
42
|
+
"Women's - XS",
|
43
|
+
"Women's - S",
|
44
|
+
"Women's - M",
|
45
|
+
"Women's - L",
|
46
|
+
"Women's - XL",
|
47
|
+
"Unisex - XS",
|
48
|
+
"Unisex - S",
|
49
|
+
"Unisex - M",
|
50
|
+
"Unisex - L",
|
51
|
+
"Unisex - XL"
|
52
|
+
].freeze
|
53
|
+
|
54
|
+
POSSIBLE_ACC_STATUS = {
|
55
|
+
"pending" => "Pending Review",
|
56
|
+
"accepted" => "Accepted",
|
57
|
+
"waitlist" => "Waitlisted",
|
58
|
+
"denied" => "Denied",
|
59
|
+
"late_waitlist" => "Waitlisted, Late",
|
60
|
+
"rsvp_confirmed" => "RSVP Confirmed",
|
61
|
+
"rsvp_denied" => "RSVP Denied"
|
62
|
+
}.freeze
|
63
|
+
|
64
|
+
validates_inclusion_of :experience, in: POSSIBLE_EXPERIENCES
|
65
|
+
validates_inclusion_of :interest, in: POSSIBLE_INTERESTS
|
66
|
+
# validates_inclusion_of :school_id, :in => School.select(:id)
|
67
|
+
validates_inclusion_of :shirt_size, in: POSSIBLE_SHIRT_SIZES
|
68
|
+
validates_inclusion_of :acc_status, in: POSSIBLE_ACC_STATUS
|
69
|
+
|
70
|
+
belongs_to :user
|
71
|
+
|
72
|
+
def email
|
73
|
+
user.email
|
74
|
+
end
|
75
|
+
|
76
|
+
def portfolio_url=(value)
|
77
|
+
value = "http://" + value if !value.blank? && !value.include?("http://") && !value.include?("https://")
|
78
|
+
super value
|
79
|
+
end
|
80
|
+
|
81
|
+
def vcs_url=(value)
|
82
|
+
value = "http://" + value if !value.blank? && !value.include?("http://") && !value.include?("https://")
|
83
|
+
super value
|
84
|
+
end
|
85
|
+
|
86
|
+
def school
|
87
|
+
School.find(school_id) if school_id
|
88
|
+
end
|
89
|
+
|
90
|
+
def full_name
|
91
|
+
"#{first_name} #{last_name}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def full_location
|
95
|
+
"#{school.city}, #{school.state}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def date_of_birth_formatted
|
99
|
+
date_of_birth.strftime("%B %-d, %Y")
|
100
|
+
end
|
101
|
+
|
102
|
+
def acc_status_author
|
103
|
+
return unless acc_status_author_id.present?
|
104
|
+
User.find(acc_status_author_id)
|
105
|
+
end
|
106
|
+
|
107
|
+
def checked_in?
|
108
|
+
checked_in_at.present?
|
109
|
+
end
|
110
|
+
|
111
|
+
def checked_in_by
|
112
|
+
return unless checked_in_by_id.present?
|
113
|
+
User.find(checked_in_by_id)
|
114
|
+
end
|
115
|
+
|
116
|
+
def fips_code
|
117
|
+
Fips.where(city: school.city, state: school.state).first
|
118
|
+
end
|
119
|
+
|
120
|
+
def can_rsvp?
|
121
|
+
["accepted", "rsvp_confirmed", "rsvp_denied"].include? acc_status
|
122
|
+
end
|
123
|
+
|
124
|
+
def did_rsvp?
|
125
|
+
['rsvp_confirmed', 'rsvp_denied'].include? acc_status
|
126
|
+
end
|
127
|
+
|
128
|
+
def eligible_for_a_bus?
|
129
|
+
school.present? && school.bus_list_id?
|
130
|
+
end
|
131
|
+
|
132
|
+
def bus_list
|
133
|
+
return unless eligible_for_a_bus?
|
134
|
+
school.bus_list
|
135
|
+
end
|
136
|
+
|
137
|
+
def message_events
|
138
|
+
return [] unless ENV['SPARKPOST_API_KEY']
|
139
|
+
|
140
|
+
simple_spark = SimpleSpark::Client.new
|
141
|
+
simple_spark.message_events.search(recipients: email)
|
142
|
+
end
|
143
|
+
|
144
|
+
def invite_to_slack
|
145
|
+
SlackInviteWorker.perform_async(id)
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def consolidate_school_names
|
151
|
+
return if school.blank?
|
152
|
+
duplicate = SchoolNameDuplicate.find_by(name: school.name)
|
153
|
+
return if duplicate.blank?
|
154
|
+
self.school_id = duplicate.school_id
|
155
|
+
end
|
156
|
+
|
157
|
+
def update_school_questionnaire_count
|
158
|
+
if destroyed?
|
159
|
+
School.decrement_counter(:questionnaire_count, school_id)
|
160
|
+
elsif saved_change_to_school_id?
|
161
|
+
old_school_id = saved_changes['school_id'].first
|
162
|
+
School.decrement_counter(:questionnaire_count, old_school_id) if old_school_id.present?
|
163
|
+
School.increment_counter(:questionnaire_count, school_id)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
SHEETS_KEY = ENV['GOOGLESHEETS_KEY']
|
3
|
+
SHEETS_URL = "https://sheets.googleapis.com/v4/spreadsheets/".freeze
|
4
|
+
SHEETS_FIELDS = "fields=sheets(data.rowData.values.userEnteredValue)".freeze
|
5
|
+
SECTION = ":section".freeze
|
6
|
+
ITEM = ":item".freeze
|
7
|
+
|
8
|
+
class Schedule
|
9
|
+
def initialize(spreadsheet_id, sheet = 0)
|
10
|
+
cache_key = "schedule/#{spreadsheet_id}"
|
11
|
+
parsed_response = Rails.cache.fetch(cache_key, expires_in: 1.hour) do
|
12
|
+
response = HTTParty.get(SHEETS_URL + "#{spreadsheet_id}?#{SHEETS_FIELDS}&key=#{SHEETS_KEY}")
|
13
|
+
response ? response.parsed_response.to_hash : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
unless parsed_response && parsed_response["error"].nil?
|
17
|
+
Rails.logger.error "Error reading Google Sheet #{spreadsheet_id}"
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
@sheet = parsed_response["sheets"][sheet]
|
22
|
+
end
|
23
|
+
|
24
|
+
def rows
|
25
|
+
@sheet ? @sheet["data"][0]["rowData"] : []
|
26
|
+
end
|
27
|
+
|
28
|
+
def sections
|
29
|
+
section = []
|
30
|
+
sections = []
|
31
|
+
rows.each do |row|
|
32
|
+
if row["values"][0]["userEnteredValue"]["stringValue"] == SECTION
|
33
|
+
sections << section unless section.count.zero?
|
34
|
+
section = [row["values"][1]["userEnteredValue"]["stringValue"]]
|
35
|
+
else
|
36
|
+
fill_section(section, row)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
sections << section unless section.empty?
|
40
|
+
sections
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def fill_section(section, row)
|
46
|
+
r = []
|
47
|
+
row["values"].map do |col|
|
48
|
+
next if !col.empty? && col["userEnteredValue"]["stringValue"] == ITEM
|
49
|
+
r << (col.empty? ? '' : col["userEnteredValue"]["stringValue"])
|
50
|
+
end
|
51
|
+
section << r unless r.count.zero?
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class School < ApplicationRecord
|
2
|
+
validates_presence_of :name
|
3
|
+
|
4
|
+
validates_uniqueness_of :name
|
5
|
+
|
6
|
+
strip_attributes
|
7
|
+
|
8
|
+
has_many :questionnaires
|
9
|
+
belongs_to :bus_list, optional: true
|
10
|
+
|
11
|
+
def full_name
|
12
|
+
out = ""
|
13
|
+
out << name
|
14
|
+
if city.present? || state.present?
|
15
|
+
out << " in "
|
16
|
+
out << city if city.present?
|
17
|
+
out << ", " if city.present? && state.present?
|
18
|
+
out << state if state.present?
|
19
|
+
end
|
20
|
+
out
|
21
|
+
end
|
22
|
+
|
23
|
+
def bus_list
|
24
|
+
return unless bus_list_id
|
25
|
+
BusList.find(bus_list_id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def fips_code
|
29
|
+
Fips.where(city: city, state: state).first
|
30
|
+
end
|
31
|
+
end
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
class User < ApplicationRecord
|
2
|
+
devise :database_authenticatable, :registerable,
|
3
|
+
:recoverable, :rememberable, :trackable, :validatable,
|
4
|
+
:omniauthable, omniauth_providers: [:mlh]
|
5
|
+
|
6
|
+
has_one :questionnaire
|
7
|
+
|
8
|
+
def active_for_authentication?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def send_devise_notification(notification, *args)
|
13
|
+
devise_mailer.send(notification, self, *args).deliver_later
|
14
|
+
end
|
15
|
+
|
16
|
+
def queue_reminder_email
|
17
|
+
return if reminder_sent_at
|
18
|
+
Mailer.delay_for(1.day).incomplete_reminder_email(id)
|
19
|
+
update_attribute(:reminder_sent_at, Time.now)
|
20
|
+
end
|
21
|
+
|
22
|
+
def email=(value)
|
23
|
+
super value.try(:downcase)
|
24
|
+
end
|
25
|
+
|
26
|
+
def first_name
|
27
|
+
return "" if questionnaire.blank?
|
28
|
+
questionnaire.first_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_name
|
32
|
+
return "" if questionnaire.blank?
|
33
|
+
questionnaire.last_name
|
34
|
+
end
|
35
|
+
|
36
|
+
def full_name
|
37
|
+
return "" if questionnaire.blank?
|
38
|
+
questionnaire.full_name
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_omniauth(auth)
|
42
|
+
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
|
43
|
+
user.uid = auth.uid
|
44
|
+
user.email = auth.info.email
|
45
|
+
user.password = Devise.friendly_token[0, 20]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.without_questionnaire
|
50
|
+
User.left_outer_joins(:questionnaire).where(questionnaires: { id: nil }, admin: false)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
%fieldset
|
2
|
+
%legend Bus Captians
|
3
|
+
- if bus_list.captains.empty?
|
4
|
+
%p
|
5
|
+
%em TBD
|
6
|
+
- bus_list.captains.each do |p|
|
7
|
+
%p
|
8
|
+
%strong= p.full_name
|
9
|
+
%br
|
10
|
+
%em= p.school.name
|
11
|
+
%br
|
12
|
+
Phone:
|
13
|
+
= p.phone
|
14
|
+
%br
|
15
|
+
Email:
|
16
|
+
= p.email
|
17
|
+
|
18
|
+
%fieldset
|
19
|
+
%legend Bus Notes
|
20
|
+
= bus_list.notes.present? ? markdown(bus_list.notes.html_safe) : "<p>(none)</p>".html_safe
|
@@ -0,0 +1,9 @@
|
|
1
|
+
%p
|
2
|
+
- accepted = Questionnaire.joins(:school).where("schools.bus_list_id = '#{bus_list.id}' AND acc_status = 'accepted'").count
|
3
|
+
= pluralize(accepted, 'person has', 'people have')
|
4
|
+
been accepted but not yet RSVP'd.
|
5
|
+
|
6
|
+
%p
|
7
|
+
- accepted = Questionnaire.joins(:school).where("schools.bus_list_id = '#{bus_list.id}' AND acc_status = 'rsvp_confirmed' AND riding_bus = false").count
|
8
|
+
= pluralize(accepted, 'person has', 'people have')
|
9
|
+
RSVP'd as attending but didn't sign up for the bus.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
%p
|
2
|
+
%b Experience:
|
3
|
+
= Questionnaire::POSSIBLE_EXPERIENCES[@questionnaire.experience]
|
4
|
+
%p
|
5
|
+
%b Portfolio link:
|
6
|
+
= @questionnaire.portfolio_url? ? link_to(@questionnaire.portfolio_url, @questionnaire.portfolio_url, target: '_blank') : 'Not provided'
|
7
|
+
%p
|
8
|
+
%b GitHub/BitBucket link:
|
9
|
+
= @questionnaire.vcs_url? ? link_to(@questionnaire.vcs_url, @questionnaire.vcs_url, target: '_blank') : 'Not provided'
|
10
|
+
%p
|
11
|
+
%b Resume:
|
12
|
+
= @questionnaire.resume? ? link_to("Download »".html_safe, @questionnaire.resume.url) : 'Not provided'
|
13
|
+
%p
|
14
|
+
%b Traveling from:
|
15
|
+
= @questionnaire.travel_not_from_school ? "Somewhere else (#{@questionnaire.travel_location})" : "My school (#{@questionnaire.school.full_name})"
|
16
|
+
|
17
|
+
%fieldset
|
18
|
+
%legend Provided by My MLH
|
19
|
+
%p
|
20
|
+
%b First name:
|
21
|
+
= @questionnaire.first_name
|
22
|
+
%p
|
23
|
+
%b Last name:
|
24
|
+
= @questionnaire.last_name
|
25
|
+
%p
|
26
|
+
%b Email:
|
27
|
+
= @questionnaire.email
|
28
|
+
%p
|
29
|
+
%b Phone:
|
30
|
+
= @questionnaire.phone
|
31
|
+
%p
|
32
|
+
%b Date of birth:
|
33
|
+
= @questionnaire.date_of_birth_formatted
|
34
|
+
%p
|
35
|
+
%b Gender:
|
36
|
+
= @questionnaire.gender
|
37
|
+
%p
|
38
|
+
%b School:
|
39
|
+
= @questionnaire.school.full_name
|
40
|
+
%p
|
41
|
+
%b Major:
|
42
|
+
= @questionnaire.major
|
43
|
+
%p
|
44
|
+
%b Level of study:
|
45
|
+
= @questionnaire.level_of_study
|
46
|
+
%p
|
47
|
+
%b Shirt size:
|
48
|
+
= @questionnaire.shirt_size
|
49
|
+
%p
|
50
|
+
%b Dietary restrictions
|
51
|
+
= @questionnaire.dietary_restrictions || "<i>(none)</i>".html_safe
|
52
|
+
%p
|
53
|
+
%b Special needs
|
54
|
+
= @questionnaire.special_needs || "<i>(none)</i>".html_safe
|
@@ -0,0 +1,45 @@
|
|
1
|
+
%section.section{ style: "padding-left: 20px; padding-right: 20px" }
|
2
|
+
%h1.section-title= title "Bus List"
|
3
|
+
%p#notice= notice
|
4
|
+
|
5
|
+
%p Thank you for being a bus captain! Below is any information you may need about your passengers.
|
6
|
+
|
7
|
+
%ul
|
8
|
+
%li Only students on this list may board the bus. <strong>No exceptions</strong>- this is to ensure everyone goes through the application process & has signed RIT's waivers.
|
9
|
+
%li If a student was accepted but didn't RSVP or sign up for the bus, they can go to <strong>https://brickhack.io/rsvp</strong> to do so.
|
10
|
+
%li If any emergencies arise, call our travel director, <strong>Velizar Demirev</strong>, at <strong>(413) 221-2420</strong>.
|
11
|
+
%li
|
12
|
+
If you have any other questions, please feel free to email
|
13
|
+
= link_to "travel@codeRIT.org", "mailto:travel@codeRIT.org"
|
14
|
+
!
|
15
|
+
|
16
|
+
%p
|
17
|
+
%b Bus List Name:
|
18
|
+
= @bus_list.name
|
19
|
+
|
20
|
+
= render partial: 'bus_list_info', locals: { bus_list: @bus_list }
|
21
|
+
|
22
|
+
%p
|
23
|
+
%strong Passengers:
|
24
|
+
= "(#{@bus_list.passengers.count} total, #{@bus_list.checked_in_passengers.count} checked in)"
|
25
|
+
|
26
|
+
%table.table
|
27
|
+
%thead
|
28
|
+
%tr
|
29
|
+
%th First Name
|
30
|
+
%th Last Name
|
31
|
+
%th Email
|
32
|
+
%th Phone Number
|
33
|
+
%th School
|
34
|
+
%th Checked in?
|
35
|
+
%tbody
|
36
|
+
- @bus_list.passengers.each do |p|
|
37
|
+
%tr
|
38
|
+
%td= p.first_name
|
39
|
+
%td= p.last_name
|
40
|
+
%td= p.email
|
41
|
+
%td= phone_link_to p.phone
|
42
|
+
%td= p.school.name
|
43
|
+
%td= p.checked_in? ? '<span class="acc-status-accepted">Yes</span>'.html_safe : 'No'
|
44
|
+
|
45
|
+
= render partial: 'bus_list_stats', locals: { bus_list: @bus_list }
|
@@ -0,0 +1,9 @@
|
|
1
|
+
%div{class:'form-container'}
|
2
|
+
= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
|
3
|
+
= f.error_notification
|
4
|
+
.form-inputs
|
5
|
+
= f.input :email, required: true, autofocus: true
|
6
|
+
.center
|
7
|
+
.form-actions
|
8
|
+
= f.button :submit, "Send Reset Instructions"
|
9
|
+
= render "devise/shared/links"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
%section{class:'section'}
|
2
|
+
%div{class:'container'}
|
3
|
+
%h1{class:'section-title'} Change your password
|
4
|
+
%div{class:'form-container'}
|
5
|
+
= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
|
6
|
+
= f.error_notification
|
7
|
+
= f.input :reset_password_token, as: :hidden
|
8
|
+
= f.full_error :reset_password_token
|
9
|
+
.form-inputs
|
10
|
+
= f.input :password, label: "New Password", required: true, autofocus: true
|
11
|
+
= f.input :password_confirmation, label: "Confirm", required: true
|
12
|
+
.form-actions
|
13
|
+
= f.button :submit, "Change My Password"
|
14
|
+
= render "devise/shared/links"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
|
2
|
+
.form-actions
|
3
|
+
.center
|
4
|
+
= btn_link_to "Sign Up with My MLH »".html_safe, user_mlh_omniauth_authorize_path
|
5
|
+
%p.center
|
6
|
+
Already applied?
|
7
|
+
%br
|
8
|
+
= btn_link_to "Sign In »".html_safe, user_mlh_omniauth_authorize_path
|
@@ -0,0 +1,20 @@
|
|
1
|
+
%section.section
|
2
|
+
.container
|
3
|
+
%h1.section-title Edit Account
|
4
|
+
.form-container
|
5
|
+
= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
|
6
|
+
= f.error_notification
|
7
|
+
.form-inputs
|
8
|
+
= f.input :email, required: true, autofocus: true
|
9
|
+
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
|
10
|
+
%p
|
11
|
+
Currently waiting confirmation for: #{resource.unconfirmed_email}
|
12
|
+
= f.input :password, autocomplete: "off", hint: "leave blank if you don't want to change it", required: false
|
13
|
+
= f.input :password_confirmation, required: false
|
14
|
+
= f.input :current_password, required: true
|
15
|
+
.form-actions
|
16
|
+
= f.button :submit, "Update"
|
17
|
+
.form-container
|
18
|
+
%p
|
19
|
+
Unhappy? #{link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure? Your account and application will be permanently erased." }, method: :delete}
|
20
|
+
= link_to "Back", :back
|
@@ -0,0 +1,18 @@
|
|
1
|
+
%section.section
|
2
|
+
.container
|
3
|
+
.form-container.signup
|
4
|
+
%h1.section-title Sign Up or Sign In
|
5
|
+
|
6
|
+
#disclaimer
|
7
|
+
- unless Rails.configuration.hackathon['registration_is_open']
|
8
|
+
.center
|
9
|
+
%strong Registration is now closed. Thanks to everyone who applied!
|
10
|
+
%br
|
11
|
+
%br
|
12
|
+
Registration is simplified with #{link_to "My MLH", "https://my.mlh.io", style: "color: #f5f5f5; text-decoration: underline;"}! Click below to sign into your existing My MLH account, or create one. You'll be redirected back to BrickHack to finish your application afterwards.
|
13
|
+
%ul
|
14
|
+
%li Applicants must be 18 years of age by February 11th
|
15
|
+
%li RIT students must still apply
|
16
|
+
%li International applicants are welcome
|
17
|
+
|
18
|
+
= render 'form'
|
@@ -0,0 +1 @@
|
|
1
|
+
%link{ href:'//fonts.googleapis.com/css?family=Open+Sans:300,400,600', rel: 'stylesheet', type: 'text/css' }
|
@@ -0,0 +1,22 @@
|
|
1
|
+
%div{ class:"sidebar #{controller.controller_name}" }
|
2
|
+
%span#sidebar-toggle
|
3
|
+
%i.fa.fa-navicon
|
4
|
+
.pusher
|
5
|
+
- if Rails.configuration.hackathon['logo_asset']
|
6
|
+
#logo-cta
|
7
|
+
= link_to root_path do
|
8
|
+
= image_tag Rails.configuration.hackathon['logo_asset'], id: "logo", alt: "BrickHack", title: "BrickHack"
|
9
|
+
- if user_signed_in?
|
10
|
+
%div
|
11
|
+
- if current_user.admin?
|
12
|
+
= btn_link_to "Manage", manage_root_path
|
13
|
+
- else
|
14
|
+
= btn_link_to "Review", new_questionnaires_path
|
15
|
+
- else
|
16
|
+
%div
|
17
|
+
= btn_link_to "Login", new_user_session_path
|
18
|
+
%div
|
19
|
+
= btn_link_to "Register", new_user_registration_path
|
20
|
+
- if user_signed_in?
|
21
|
+
%div
|
22
|
+
= btn_link_to "Sign Out", destroy_user_session_path, method: :delete
|
@@ -0,0 +1,12 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title BrickHack 3 - Feb 11-12, 2017
|
5
|
+
= render "layouts/shared_head"
|
6
|
+
= stylesheet_link_tag "application", :media => "all"
|
7
|
+
= csrf_meta_tags
|
8
|
+
|
9
|
+
%body
|
10
|
+
= yield
|
11
|
+
= javascript_include_tag "application"
|
12
|
+
= render "layouts/shared_footer"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title BrickHack
|
5
|
+
= render "layouts/shared_head"
|
6
|
+
= stylesheet_link_tag "application", :media => "all"
|
7
|
+
= csrf_meta_tags
|
8
|
+
%body
|
9
|
+
%div{class:'day-of'}
|
10
|
+
= yield
|
11
|
+
= javascript_include_tag "application"
|
12
|
+
= javascript_include_tag "vendor/owl.carousel.min.js"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title= yield(:title) || "BrickHack 3 - Feb 11-12, 2017"
|
5
|
+
= stylesheet_link_tag "hackathon_manager/manage", media: "all"
|
6
|
+
= csrf_meta_tags
|
7
|
+
|
8
|
+
%body
|
9
|
+
= render "layouts/sidebar"
|
10
|
+
#main
|
11
|
+
= yield
|
12
|
+
= javascript_include_tag "hackathon_manager/manage/application"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
3
|
+
<title></title>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
5
|
+
<style type="text/css">
|
6
|
+
<%= Rails.env == "production" ? File.read(Rails.root.join("public" + ActionController::Base.helpers.asset_path("mailer.css"))).html_safe : Rails.application.assets["mailer"].to_s.html_safe %>
|
7
|
+
</style>
|
8
|
+
<meta name="robots" content="noindex,nofollow">
|
9
|
+
</head>
|
10
|
+
|
11
|
+
|
12
|
+
<body>
|
13
|
+
<div id="content">
|
14
|
+
<!--head-->
|
15
|
+
<%= image_tag 'email_banner.jpg', class: 'banner' %>
|
16
|
+
|
17
|
+
<!--content-->
|
18
|
+
<div id="main-content">
|
19
|
+
<%= yield %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<!--footer-->
|
23
|
+
<div class="email-footer">
|
24
|
+
<table border="0" >
|
25
|
+
<tr>
|
26
|
+
<td>
|
27
|
+
<span>
|
28
|
+
<%= link_to 'BrickHack', 'https://brickhack.io' %>
|
29
|
+
</span>
|
30
|
+
<span>
|
31
|
+
<%= link_to 'Facebook', 'https://www.facebook.com/brickhackrit' %>
|
32
|
+
</span>
|
33
|
+
<span>
|
34
|
+
<%= link_to 'Twitter', 'https://twitter.com/brickhackrit' %>
|
35
|
+
</span>
|
36
|
+
</td>
|
37
|
+
<td>
|
38
|
+
<span>
|
39
|
+
<%= link_to 'http://coderit.org', class: 'nodecor' do %>
|
40
|
+
Student run by <img class="coderit-logo" src="<%= image_url('coderit_logo.png') %>" />
|
41
|
+
<% end %>
|
42
|
+
</span>
|
43
|
+
</td>
|
44
|
+
</tr>
|
45
|
+
</table>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
|
49
|
+
</body>
|
50
|
+
|
51
|
+
</html>
|