hackathon_manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +90 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/hackathon_manager_manifest.js +0 -0
  6. data/app/assets/javascripts/hackathon_manager/application.js +16 -0
  7. data/app/assets/javascripts/hackathon_manager/jquery.transit.min.js +1 -0
  8. data/app/assets/javascripts/hackathon_manager/main.js +237 -0
  9. data/app/assets/javascripts/hackathon_manager/manage/application.js +20 -0
  10. data/app/assets/javascripts/hackathon_manager/manage/lib/emailEvents.js +25 -0
  11. data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.bulkRowSelect.js +13 -0
  12. data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.bulkRowedit.js +42 -0
  13. data/app/assets/javascripts/hackathon_manager/manage/lib/jquery.chartkickAutoReload.js +8 -0
  14. data/app/assets/javascripts/hackathon_manager/manage/lib/setupDataTables.js +98 -0
  15. data/app/assets/javascripts/hackathon_manager/manage/lib/setupHighcharts.js +34 -0
  16. data/app/assets/javascripts/hackathon_manager/manage/map.js +58 -0
  17. data/app/assets/javascripts/hackathon_manager/registrations.js +26 -0
  18. data/app/assets/javascripts/hackathon_manager/us.json +1 -0
  19. data/app/assets/javascripts/hackathon_manager/vendor/buttons.html5.min.js +22 -0
  20. data/app/assets/javascripts/hackathon_manager/vendor/d3.v3.min.js +5 -0
  21. data/app/assets/javascripts/hackathon_manager/vendor/dataTables.buttons.min.js +35 -0
  22. data/app/assets/javascripts/hackathon_manager/vendor/jquery.dataTables.min.js +164 -0
  23. data/app/assets/javascripts/hackathon_manager/vendor/pdfmake.min.js +22 -0
  24. data/app/assets/javascripts/hackathon_manager/vendor/queue.v1.min.js +1 -0
  25. data/app/assets/javascripts/hackathon_manager/vendor/topojson.v1.min.js +1 -0
  26. data/app/assets/javascripts/hackathon_manager/vendor/vfs_fonts.js +1 -0
  27. data/app/assets/stylesheets/hackathon_manager/core.sass +20 -0
  28. data/app/assets/stylesheets/hackathon_manager/datatables/buttons.dataTables.min.css +1 -0
  29. data/app/assets/stylesheets/hackathon_manager/datatables/jquery.dataTables.min.css +1 -0
  30. data/app/assets/stylesheets/hackathon_manager/forms/_confirmation.sass +21 -0
  31. data/app/assets/stylesheets/hackathon_manager/forms/_forms.sass +243 -0
  32. data/app/assets/stylesheets/hackathon_manager/general/_base.sass +105 -0
  33. data/app/assets/stylesheets/hackathon_manager/general/_button.sass +49 -0
  34. data/app/assets/stylesheets/hackathon_manager/general/_footer.sass +21 -0
  35. data/app/assets/stylesheets/hackathon_manager/general/_main.sass +4 -0
  36. data/app/assets/stylesheets/hackathon_manager/general/_media-queries.sass +52 -0
  37. data/app/assets/stylesheets/hackathon_manager/general/_mixins.sass +58 -0
  38. data/app/assets/stylesheets/hackathon_manager/general/_mlh.sass +13 -0
  39. data/app/assets/stylesheets/hackathon_manager/general/_sidebar.sass +70 -0
  40. data/app/assets/stylesheets/hackathon_manager/general/_status-colors.sass +14 -0
  41. data/app/assets/stylesheets/hackathon_manager/general/_table.sass +26 -0
  42. data/app/assets/stylesheets/hackathon_manager/mailer.sass +108 -0
  43. data/app/assets/stylesheets/hackathon_manager/manage.sass +119 -0
  44. data/app/assets/stylesheets/hackathon_manager/scaffolds.scss +50 -0
  45. data/app/assets/stylesheets/variables.sass +41 -0
  46. data/app/controllers/bus_lists_controller.rb +37 -0
  47. data/app/controllers/concerns/questionnaires_controllable.rb +15 -0
  48. data/app/controllers/manage/admins_controller.rb +55 -0
  49. data/app/controllers/manage/application_controller.rb +13 -0
  50. data/app/controllers/manage/bus_lists_controller.rb +71 -0
  51. data/app/controllers/manage/dashboard_controller.rb +112 -0
  52. data/app/controllers/manage/messages_controller.rb +88 -0
  53. data/app/controllers/manage/questionnaires_controller.rb +172 -0
  54. data/app/controllers/manage/schools_controller.rb +87 -0
  55. data/app/controllers/manage/stats_controller.rb +77 -0
  56. data/app/controllers/questionnaires_controller.rb +145 -0
  57. data/app/controllers/rsvps_controller.rb +97 -0
  58. data/app/controllers/users/omniauth_callbacks_controller.rb +18 -0
  59. data/app/controllers/users/registrations_controller.rb +63 -0
  60. data/app/datatables/admin_datatable.rb +29 -0
  61. data/app/datatables/message_datatable.rb +30 -0
  62. data/app/datatables/questionnaire_datatable.rb +39 -0
  63. data/app/datatables/school_datatable.rb +34 -0
  64. data/app/helpers/hackathon_manager_helper.rb +36 -0
  65. data/app/helpers/manage/dashboard_helper.rb +9 -0
  66. data/app/inputs/deletable_attachment_input.rb +11 -0
  67. data/app/inputs/formatted_boolean_input.rb +26 -0
  68. data/app/inputs/school_selection_input.rb +9 -0
  69. data/app/mailers/application_mailer.rb +4 -0
  70. data/app/mailers/mail_preview.rb +42 -0
  71. data/app/mailers/mailer.rb +84 -0
  72. data/app/models/bus_list.rb +24 -0
  73. data/app/models/deletable_attachment.rb +17 -0
  74. data/app/models/fips.rb +3 -0
  75. data/app/models/message.rb +76 -0
  76. data/app/models/questionnaire.rb +166 -0
  77. data/app/models/schedule.rb +53 -0
  78. data/app/models/school.rb +31 -0
  79. data/app/models/school_name_duplicate.rb +7 -0
  80. data/app/models/user.rb +52 -0
  81. data/app/views/application/_bus_list_info.html.haml +20 -0
  82. data/app/views/application/_bus_list_stats.html.haml +9 -0
  83. data/app/views/application/_questionnaire_summary.html.haml +54 -0
  84. data/app/views/bus_lists/show.html.haml +45 -0
  85. data/app/views/devise/passwords/_form.html.haml +9 -0
  86. data/app/views/devise/passwords/edit.html.haml +14 -0
  87. data/app/views/devise/passwords/new.html.haml +5 -0
  88. data/app/views/devise/registrations/_form.html.haml +8 -0
  89. data/app/views/devise/registrations/edit.html.haml +20 -0
  90. data/app/views/devise/registrations/new.html.haml +18 -0
  91. data/app/views/devise/sessions/_form.html.haml +8 -0
  92. data/app/views/devise/sessions/new.html.haml +9 -0
  93. data/app/views/layouts/_shared_footer.html.haml +1 -0
  94. data/app/views/layouts/_sidebar.html.haml +22 -0
  95. data/app/views/layouts/blank.html.haml +12 -0
  96. data/app/views/layouts/dayof.html.haml +12 -0
  97. data/app/views/layouts/hackathon_manager.html.haml +12 -0
  98. data/app/views/layouts/mailer.html.erb +51 -0
  99. data/app/views/layouts/manage/application.html.haml +26 -0
  100. data/app/views/mailer/_getting_there.html.erb +14 -0
  101. data/app/views/mailer/_questions.html.erb +2 -0
  102. data/app/views/mailer/accepted_email.html.erb +13 -0
  103. data/app/views/mailer/application_confirmation_email.html.erb +13 -0
  104. data/app/views/mailer/bulk_message_email.html.erb +1 -0
  105. data/app/views/mailer/bulk_templates/_default.html.erb +1 -0
  106. data/app/views/mailer/bus_captain_confirmation_email.html.erb +12 -0
  107. data/app/views/mailer/bus_list_update_email.html.erb +7 -0
  108. data/app/views/mailer/denied_email.html.erb +5 -0
  109. data/app/views/mailer/incomplete_reminder_email.html.erb +6 -0
  110. data/app/views/mailer/rsvp_confirmation_email.html.erb +8 -0
  111. data/app/views/mailer/slack_invite_email.html.erb +10 -0
  112. data/app/views/manage/admins/_form.html.haml +18 -0
  113. data/app/views/manage/admins/edit.html.haml +12 -0
  114. data/app/views/manage/admins/index.html.haml +15 -0
  115. data/app/views/manage/admins/new.html.haml +8 -0
  116. data/app/views/manage/admins/show.html.haml +17 -0
  117. data/app/views/manage/bus_lists/_form.html.haml +14 -0
  118. data/app/views/manage/bus_lists/edit.html.haml +8 -0
  119. data/app/views/manage/bus_lists/index.html.haml +26 -0
  120. data/app/views/manage/bus_lists/new.html.haml +6 -0
  121. data/app/views/manage/bus_lists/show.html.haml +92 -0
  122. data/app/views/manage/dashboard/index.html.haml +64 -0
  123. data/app/views/manage/dashboard/map_data.tsv.erb +48 -0
  124. data/app/views/manage/messages/_form.html.haml +15 -0
  125. data/app/views/manage/messages/edit.html.haml +10 -0
  126. data/app/views/manage/messages/index.html.haml +17 -0
  127. data/app/views/manage/messages/new.html.haml +8 -0
  128. data/app/views/manage/messages/show.html.haml +50 -0
  129. data/app/views/manage/questionnaires/_form.html.haml +54 -0
  130. data/app/views/manage/questionnaires/edit.html.haml +12 -0
  131. data/app/views/manage/questionnaires/index.html.haml +36 -0
  132. data/app/views/manage/questionnaires/new.html.haml +8 -0
  133. data/app/views/manage/questionnaires/show.html.haml +63 -0
  134. data/app/views/manage/schools/_form.html.haml +16 -0
  135. data/app/views/manage/schools/edit.html.haml +12 -0
  136. data/app/views/manage/schools/index.html.haml +18 -0
  137. data/app/views/manage/schools/merge.html.haml +35 -0
  138. data/app/views/manage/schools/new.html.haml +8 -0
  139. data/app/views/manage/schools/show.html.haml +52 -0
  140. data/app/views/manage/stats/index.html.haml +55 -0
  141. data/app/views/questionnaires/_form.html.haml +70 -0
  142. data/app/views/questionnaires/edit.html.haml +10 -0
  143. data/app/views/questionnaires/new.html.haml +7 -0
  144. data/app/views/questionnaires/show.html.haml +30 -0
  145. data/app/views/rsvps/show.html.haml +61 -0
  146. data/app/workers/bulk_message_worker.rb +86 -0
  147. data/app/workers/slack_invite_worker.rb +49 -0
  148. data/config/blazer.yml +56 -0
  149. data/config/initializers/ajax_datatables_rails.rb +7 -0
  150. data/config/initializers/chartkick.rb +4 -0
  151. data/config/initializers/devise.rb +265 -0
  152. data/config/initializers/hackathon.rb +9 -0
  153. data/config/initializers/mime_types.rb +5 -0
  154. data/config/initializers/new_framework_defaults.rb +20 -0
  155. data/config/initializers/sidekiq.rb +11 -0
  156. data/config/initializers/simple_form.rb +164 -0
  157. data/config/initializers/static_data.rb +7 -0
  158. data/config/initializers/wrap_parameters.rb +14 -0
  159. data/config/routes.rb +74 -0
  160. data/db/migrate/20141011210642_create_participants.rb +18 -0
  161. data/db/migrate/20141029055313_create_schools.rb +12 -0
  162. data/db/migrate/20150104071608_add_shirt_and_dietary_medical_to_participants.rb +6 -0
  163. data/db/migrate/20150104190233_add_attachment_resume_to_participants.rb +13 -0
  164. data/db/migrate/20150110020958_add_international_to_participants.rb +5 -0
  165. data/db/migrate/20150110215933_change_participants_to_registration.rb +5 -0
  166. data/db/migrate/20150110222214_create_users.rb +5 -0
  167. data/db/migrate/20150110222455_add_portfolio_and_vcs_urls_to_registrations.rb +6 -0
  168. data/db/migrate/20150110222655_add_devise_to_users.rb +48 -0
  169. data/db/migrate/20150111000224_change_resgistrations_to_questionnaire.rb +5 -0
  170. data/db/migrate/20150111012709_add_questionnaire_ref_to_users.rb +8 -0
  171. data/db/migrate/20150113205638_add_amin_to_users.rb +5 -0
  172. data/db/migrate/20150113233730_add_questionnaire_count_to_schools.rb +12 -0
  173. data/db/migrate/20150125213100_set_default_admin_value.rb +17 -0
  174. data/db/migrate/20150216232155_add_agreement_accepted_to_questionnaires.rb +5 -0
  175. data/db/migrate/20150218051450_add_admin_read_only_to_users.rb +5 -0
  176. data/db/migrate/20150221165513_create_messages.rb +15 -0
  177. data/db/migrate/20150225235817_add_status_to_user.rb +7 -0
  178. data/db/migrate/20150302011457_create_fips.rb +11 -0
  179. data/db/migrate/20150326031423_add_template_to_message.rb +5 -0
  180. data/db/migrate/20150410175056_create_bus_lists.rb +12 -0
  181. data/db/migrate/20150411161432_add_capacity_notes_captain_to_bus_lists.rb +8 -0
  182. data/db/migrate/20150415165844_add_is_bus_captain_to_questionnaire.rb +5 -0
  183. data/db/migrate/20150415181114_add_check_in_data_to_questionnaire.rb +8 -0
  184. data/db/migrate/20151224015223_change_read_only_user_to_limited.rb +5 -0
  185. data/db/migrate/20160110012217_add_code_of_conduct_accepted_to_questionnaire.rb +5 -0
  186. data/db/migrate/20160110222639_add_omniauth_to_users.rb +8 -0
  187. data/db/migrate/20160111020817_update_questionnaire_for_my_mlh.rb +14 -0
  188. data/db/migrate/20160112222137_add_option_for_alt_travel_to_questionnaire.rb +6 -0
  189. data/db/migrate/20160208061253_rename_can_share_resume_to_info.rb +5 -0
  190. data/db/migrate/20161020032736_remove_resume_from_questionnaires.rb +14 -0
  191. data/db/migrate/20161024145452_add_data_sharing_to_questionnaire.rb +5 -0
  192. data/db/migrate/20161206073921_rename_graduation_to_level_of_study.rb +6 -0
  193. data/db/migrate/20161206084722_add_reminder_sent_at_to_users.rb +5 -0
  194. data/db/migrate/20161208055809_add_attachment_resume_to_questionnaires.rb +11 -0
  195. data/db/migrate/20161212030010_add_interest_to_questionnaire.rb +5 -0
  196. data/db/migrate/20170107210122_create_school_name_duplicates.rb +10 -0
  197. data/db/migrate/20170128063020_install_blazer.rb +45 -0
  198. data/db/schools.csv +1 -0
  199. data/db/seeds.rb +17 -0
  200. data/lib/hackathon_manager/engine.rb +35 -0
  201. data/lib/hackathon_manager/version.rb +3 -0
  202. data/lib/hackathon_manager.rb +5 -0
  203. data/lib/tasks/coverage.rake +14 -0
  204. data/lib/tasks/hackathon_manager_tasks.rake +4 -0
  205. 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
@@ -0,0 +1,7 @@
1
+ class SchoolNameDuplicate < ApplicationRecord
2
+ validates_uniqueness_of :name
3
+
4
+ strip_attributes
5
+
6
+ belongs_to :school
7
+ end
@@ -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 &raquo;".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,5 @@
1
+ %section{class:'section'}
2
+ %div{class:'container'}
3
+ %h1{class:'section-title'} Password Reset
4
+
5
+ = render 'form'
@@ -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 &raquo;".html_safe, user_mlh_omniauth_authorize_path
5
+ %p.center
6
+ Already applied?
7
+ %br
8
+ = btn_link_to "Sign In &raquo;".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,8 @@
1
+ .form-actions
2
+ .center
3
+ %p
4
+ = btn_link_to "Sign In with My MLH &raquo;".html_safe, user_mlh_omniauth_authorize_path
5
+ %p
6
+ Need an account?
7
+ %br
8
+ = btn_link_to "Sign Up &raquo;".html_safe, new_user_registration_path
@@ -0,0 +1,9 @@
1
+ .section
2
+ .container
3
+ .form-container.login
4
+ %h1.section-title Log In
5
+ - if notice
6
+ .form-success
7
+ .success_message
8
+ %p#notice= notice
9
+ = 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>