fe 0.0.4 → 2.0.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 (456) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +4 -4
  3. data/Rakefile +16 -36
  4. data/app/assets/config/fe/manifest.js +3 -0
  5. data/app/assets/config/manifest.js +3 -0
  6. data/app/assets/javascripts/application.js.erb +1 -1
  7. data/app/assets/javascripts/fe/admin.js +0 -2
  8. data/app/assets/javascripts/fe/fe.admin.js +40 -20
  9. data/app/assets/javascripts/fe/fe.common.js.erb +98 -0
  10. data/app/assets/javascripts/fe/fe.public.js +2 -416
  11. data/app/assets/javascripts/fe/fe.public.nojquery.js.erb +526 -0
  12. data/app/assets/javascripts/fe/jquery.html5_upload.js +258 -0
  13. data/app/assets/javascripts/fe/jquery.validate.pack.js +3 -15
  14. data/app/assets/stylesheets/fe/fe.screen.css.scss.erb +90 -10
  15. data/app/assets/stylesheets/fe/validation.css +5 -1
  16. data/app/controllers/concerns/fe/admin/question_sheets_controller_concern.rb +111 -0
  17. data/app/controllers/concerns/fe/answer_pages_controller_concern.rb +131 -0
  18. data/app/controllers/{fe/concerns → concerns/fe}/answer_sheets_controller_concern.rb +15 -7
  19. data/app/controllers/{fe/concerns → concerns/fe}/application_controller_concern.rb +15 -2
  20. data/app/controllers/fe/admin/elements_controller.rb +102 -64
  21. data/app/controllers/fe/admin/email_templates_controller.rb +7 -7
  22. data/app/controllers/fe/admin/question_pages_controller.rb +9 -9
  23. data/app/controllers/fe/admin/question_sheets_controller.rb +2 -103
  24. data/app/controllers/fe/reference_pages_controller.rb +11 -11
  25. data/app/controllers/fe/reference_sheets_controller.rb +6 -4
  26. data/app/controllers/fe/references_controller.rb +20 -19
  27. data/app/controllers/fe/submit_pages_controller.rb +5 -5
  28. data/app/helpers/fe/answer_pages_helper.rb +1 -1
  29. data/app/helpers/fe/application_helper.rb +8 -3
  30. data/app/jobs/fe/update_reference_sheet_visibility_job.rb +11 -0
  31. data/app/mailers/fe/notifier.rb +12 -5
  32. data/app/models/answer_sheet.rb +2 -0
  33. data/app/models/application_record.rb +3 -0
  34. data/app/models/{fe/concerns → concerns/fe}/answer_concern.rb +2 -2
  35. data/app/models/{fe/concerns → concerns/fe}/answer_pages_presenter_concern.rb +15 -5
  36. data/app/models/concerns/fe/answer_sheet_concern.rb +125 -0
  37. data/app/models/{fe/concerns → concerns/fe}/choice_field_concern.rb +56 -31
  38. data/app/models/fe/address.rb +2 -2
  39. data/app/models/fe/answer.rb +1 -1
  40. data/app/models/fe/answer_sheet.rb +1 -1
  41. data/app/models/fe/answer_sheet_question_sheet.rb +2 -2
  42. data/app/models/fe/application.rb +15 -10
  43. data/app/models/fe/condition.rb +4 -4
  44. data/app/models/fe/date_field.rb +2 -2
  45. data/app/models/fe/element.rb +201 -45
  46. data/app/models/fe/email_address.rb +2 -2
  47. data/app/models/fe/email_template.rb +1 -1
  48. data/app/models/fe/page.rb +138 -31
  49. data/app/models/fe/page_element.rb +8 -3
  50. data/app/models/fe/page_link.rb +6 -3
  51. data/app/models/fe/paragraph.rb +1 -1
  52. data/app/models/fe/person.rb +16 -13
  53. data/app/models/fe/phone_number.rb +1 -1
  54. data/app/models/fe/question.rb +64 -44
  55. data/app/models/fe/question_grid.rb +16 -4
  56. data/app/models/fe/question_grid_with_total.rb +15 -0
  57. data/app/models/fe/question_set.rb +54 -14
  58. data/app/models/fe/question_sheet.rb +54 -19
  59. data/app/models/fe/reference_question.rb +9 -13
  60. data/app/models/fe/reference_sheet.rb +113 -54
  61. data/app/models/fe/state_chooser.rb +2 -2
  62. data/app/models/fe/text_field.rb +2 -2
  63. data/app/models/fe/user.rb +1 -1
  64. data/app/models/staff.rb +8 -6
  65. data/app/validators/email_validator.rb +11 -0
  66. data/app/views/fe/admin/elements/create.js.erb +4 -3
  67. data/app/views/fe/admin/elements/destroy.js.erb +1 -1
  68. data/app/views/fe/admin/elements/drop.js.erb +2 -1
  69. data/app/views/fe/admin/elements/duplicate.js.erb +2 -1
  70. data/app/views/fe/admin/elements/edit.js.erb +1 -1
  71. data/app/views/fe/admin/elements/error.js.erb +1 -1
  72. data/app/views/fe/admin/elements/new.js.erb +13 -6
  73. data/app/views/fe/admin/elements/update.js.erb +1 -1
  74. data/app/views/fe/admin/email_templates/_form.html.erb +3 -3
  75. data/app/views/fe/admin/email_templates/edit.html.erb +3 -3
  76. data/app/views/fe/admin/email_templates/index.html.erb +3 -3
  77. data/app/views/fe/admin/email_templates/new.html.erb +3 -3
  78. data/app/views/fe/admin/panels/_advanced_options.html.erb +16 -10
  79. data/app/views/fe/admin/panels/_common_boolean_fields.html.erb +1 -0
  80. data/app/views/fe/admin/panels/_common_boolean_fields_default.html.erb +11 -0
  81. data/app/views/fe/admin/panels/_common_fields.html.erb +18 -19
  82. data/app/views/fe/admin/panels/_condition.html.erb +1 -1
  83. data/app/views/fe/admin/panels/_insert.html.erb +25 -25
  84. data/app/views/fe/admin/panels/_nav_controls.html.erb +4 -4
  85. data/app/views/fe/admin/panels/_page.html.erb +2 -2
  86. data/app/views/fe/admin/panels/_pages_list.html.erb +3 -3
  87. data/app/views/fe/admin/panels/_prop_attachment_field.html.erb +2 -2
  88. data/app/views/fe/admin/panels/_prop_choice_field.html.erb +52 -24
  89. data/app/views/fe/admin/panels/_prop_date_field.html.erb +1 -1
  90. data/app/views/fe/admin/panels/_prop_element.html.erb +7 -14
  91. data/app/views/fe/admin/panels/_prop_page.html.erb +11 -6
  92. data/app/views/fe/admin/panels/_prop_paragraph.html.erb +38 -24
  93. data/app/views/fe/admin/panels/_prop_question_grid.html.erb +7 -2
  94. data/app/views/fe/admin/panels/_prop_question_grid_with_total.html.erb +2 -2
  95. data/app/views/fe/admin/panels/_prop_reference_question.html.erb +3 -3
  96. data/app/views/fe/admin/panels/_prop_section.html.erb +8 -2
  97. data/app/views/fe/admin/panels/_prop_sheet.html.erb +7 -4
  98. data/app/views/fe/admin/panels/_prop_text_field.html.erb +12 -12
  99. data/app/views/fe/admin/question_pages/_element.html.erb +16 -6
  100. data/app/views/fe/admin/question_pages/_element_show.html.erb +2 -2
  101. data/app/views/fe/admin/question_pages/_question_page.html.erb +4 -4
  102. data/app/views/fe/admin/question_pages/create.js.erb +3 -3
  103. data/app/views/fe/admin/question_pages/destroy.js.erb +3 -3
  104. data/app/views/fe/admin/question_pages/edit.js.erb +1 -1
  105. data/app/views/fe/admin/question_pages/error.js.erb +1 -1
  106. data/app/views/fe/admin/question_pages/show.js.erb +2 -2
  107. data/app/views/fe/admin/question_pages/show_panel.js.erb +1 -1
  108. data/app/views/fe/admin/question_pages/update.js.erb +1 -1
  109. data/app/views/fe/admin/question_sheets/edit.js.erb +1 -1
  110. data/app/views/fe/admin/question_sheets/error.js.erb +1 -1
  111. data/app/views/fe/admin/question_sheets/index.html.erb +8 -8
  112. data/app/views/fe/admin/question_sheets/new.html.erb +3 -3
  113. data/app/views/fe/admin/question_sheets/show.html.erb +5 -5
  114. data/app/views/fe/admin/question_sheets/update.js.erb +1 -1
  115. data/app/views/fe/answer_pages/_answer_page.html.erb +14 -14
  116. data/app/views/fe/answer_pages/_element.html.erb +25 -6
  117. data/app/views/fe/answer_pages/_page_name.html.erb +1 -0
  118. data/app/views/fe/answer_pages/show.html.erb +39 -0
  119. data/app/views/fe/answer_pages/update.js.erb +11 -3
  120. data/app/views/fe/answer_sheets/_answer_sheet.html.erb +6 -6
  121. data/app/views/fe/answer_sheets/_element.html.erb +55 -35
  122. data/app/views/fe/answer_sheets/_incomplete.html.erb +1 -1
  123. data/app/views/fe/answer_sheets/_page_link.html.erb +9 -7
  124. data/app/views/fe/answer_sheets/_pages_list.html.erb +4 -4
  125. data/app/views/fe/answer_sheets/_submit_to.html.erb +1 -0
  126. data/app/views/fe/answer_sheets/_title.html.erb +1 -1
  127. data/app/views/fe/answer_sheets/edit.html.erb +24 -24
  128. data/app/views/fe/answer_sheets/incomplete.js.erb +9 -3
  129. data/app/views/fe/answer_sheets/index.html.erb +3 -3
  130. data/app/views/fe/answer_sheets/show.html.erb +1 -1
  131. data/app/views/fe/applications/_logout.html.erb +1 -0
  132. data/app/views/fe/applications/show.html.erb +1 -0
  133. data/app/views/fe/questions/fe/_acceptance.html.erb +11 -10
  134. data/app/views/fe/questions/fe/_attachment_field.html.erb +133 -10
  135. data/app/views/fe/questions/fe/_checkbox_field.html.erb +34 -30
  136. data/app/views/fe/questions/fe/_country.html.erb +6 -6
  137. data/app/views/fe/questions/fe/_date_field.html.erb +5 -5
  138. data/app/views/fe/questions/fe/_date_field_mmyy.html.erb +8 -8
  139. data/app/views/fe/questions/fe/_drop_down_field.html.erb +7 -6
  140. data/app/views/fe/questions/fe/_paragraph.html.erb +1 -1
  141. data/app/views/fe/questions/fe/_question_grid.html.erb +21 -16
  142. data/app/views/fe/questions/fe/_question_grid_with_total.html.erb +25 -18
  143. data/app/views/fe/questions/fe/_questions.html.erb +11 -5
  144. data/app/views/fe/questions/fe/_radio_button_field.html.erb +42 -25
  145. data/app/views/fe/questions/fe/_rating.html.erb +57 -18
  146. data/app/views/fe/questions/fe/_reference_discipler.html.erb +1 -1
  147. data/app/views/fe/questions/fe/_reference_friend.html.erb +1 -1
  148. data/app/views/fe/questions/fe/_reference_parent.html.erb +1 -1
  149. data/app/views/fe/questions/fe/_reference_peer.html.erb +1 -1
  150. data/app/views/fe/questions/fe/_reference_question.html.erb +44 -21
  151. data/app/views/fe/questions/fe/_reference_roommate.html.erb +1 -1
  152. data/app/views/fe/questions/fe/_reference_spiritual.html.erb +1 -1
  153. data/app/views/fe/questions/fe/_reference_staff.html.erb +1 -1
  154. data/app/views/fe/questions/fe/_section.html.erb +1 -1
  155. data/app/views/fe/questions/fe/_state_chooser.html.erb +6 -6
  156. data/app/views/fe/questions/fe/_text_area_field.html.erb +17 -6
  157. data/app/views/fe/questions/fe/_text_field.html.erb +7 -6
  158. data/app/views/fe/questions/fe/_yes_no.html.erb +8 -8
  159. data/app/views/fe/questions/fe/_yes_no_field.erb +12 -9
  160. data/app/views/fe/reference_pages/_reference.html.erb +15 -15
  161. data/app/views/fe/reference_pages/edit.html.erb +9 -9
  162. data/app/views/fe/reference_sheets/done.html.erb +2 -2
  163. data/app/views/fe/reference_sheets/not_found.html.erb +4 -4
  164. data/app/views/fe/references/edit.html.erb +6 -6
  165. data/app/views/fe/references/show.html.erb +8 -8
  166. data/app/views/fe/references/submit.js.erb +3 -3
  167. data/app/views/fe/submit_pages/_thankyou.html.erb +1 -1
  168. data/app/views/fe/submit_pages/edit.html.erb +12 -12
  169. data/app/views/fe/submit_pages/error.js.erb +1 -1
  170. data/app/views/fe/submit_pages/submit.js.erb +2 -2
  171. data/app/views/layouts/fe/_error_messages_for.html.erb +7 -0
  172. data/app/views/layouts/fe/application.html.erb +4 -5
  173. data/app/views/layouts/fe/fe_admin.html.erb +30 -0
  174. data/app/views.current/fe/admin/elements/_errors.html.erb +11 -0
  175. data/app/views.current/fe/admin/elements/create.js.erb +12 -0
  176. data/app/views.current/fe/admin/elements/destroy.js.erb +4 -0
  177. data/app/views.current/fe/admin/elements/drop.js.erb +3 -0
  178. data/app/views.current/fe/admin/elements/duplicate.js.erb +3 -0
  179. data/app/views.current/fe/admin/elements/edit.js.erb +4 -0
  180. data/app/views.current/fe/admin/elements/error.js.erb +4 -0
  181. data/app/views.current/fe/admin/elements/new.js.erb +17 -0
  182. data/app/views.current/fe/admin/elements/reorder.js.erb +0 -0
  183. data/app/views.current/fe/admin/elements/update.js.erb +9 -0
  184. data/app/views.current/fe/admin/email_templates/_form.html.erb +8 -0
  185. data/app/views.current/fe/admin/email_templates/edit.html.erb +13 -0
  186. data/app/views.current/fe/admin/email_templates/index.html.erb +20 -0
  187. data/app/views.current/fe/admin/email_templates/new.html.erb +11 -0
  188. data/app/views.current/fe/admin/panels/_advanced_options.html.erb +49 -0
  189. data/app/views.current/fe/admin/panels/_common_boolean_fields.html.erb +1 -0
  190. data/app/views.current/fe/admin/panels/_common_boolean_fields_default.html.erb +11 -0
  191. data/app/views.current/fe/admin/panels/_common_fields.html.erb +23 -0
  192. data/app/views.current/fe/admin/panels/_condition.html.erb +6 -0
  193. data/app/views.current/fe/admin/panels/_insert.html.erb +39 -0
  194. data/app/views.current/fe/admin/panels/_nav_controls.html.erb +6 -0
  195. data/app/views.current/fe/admin/panels/_page.html.erb +3 -0
  196. data/app/views.current/fe/admin/panels/_pages_list.html.erb +16 -0
  197. data/app/views.current/fe/admin/panels/_prop_attachment_field.html.erb +2 -0
  198. data/app/views.current/fe/admin/panels/_prop_choice_field.html.erb +74 -0
  199. data/app/views.current/fe/admin/panels/_prop_date_field.html.erb +7 -0
  200. data/app/views.current/fe/admin/panels/_prop_element.html.erb +23 -0
  201. data/app/views.current/fe/admin/panels/_prop_page.html.erb +26 -0
  202. data/app/views.current/fe/admin/panels/_prop_paragraph.html.erb +46 -0
  203. data/app/views.current/fe/admin/panels/_prop_question_grid.html.erb +28 -0
  204. data/app/views.current/fe/admin/panels/_prop_question_grid_with_total.html.erb +14 -0
  205. data/app/views.current/fe/admin/panels/_prop_reference_question.html.erb +12 -0
  206. data/app/views.current/fe/admin/panels/_prop_section.html.erb +8 -0
  207. data/app/views.current/fe/admin/panels/_prop_sheet.html.erb +20 -0
  208. data/app/views.current/fe/admin/panels/_prop_text_field.html.erb +20 -0
  209. data/app/views.current/fe/admin/question_pages/_element.html.erb +28 -0
  210. data/app/views.current/fe/admin/question_pages/_element_show.html.erb +10 -0
  211. data/app/views.current/fe/admin/question_pages/_errors.html.erb +10 -0
  212. data/app/views.current/fe/admin/question_pages/_question_page.html.erb +13 -0
  213. data/app/views.current/fe/admin/question_pages/create.js.erb +11 -0
  214. data/app/views.current/fe/admin/question_pages/destroy.js.erb +5 -0
  215. data/app/views.current/fe/admin/question_pages/edit.js.erb +3 -0
  216. data/app/views.current/fe/admin/question_pages/error.js.erb +4 -0
  217. data/app/views.current/fe/admin/question_pages/show.js.erb +9 -0
  218. data/app/views.current/fe/admin/question_pages/show_panel.js.erb +3 -0
  219. data/app/views.current/fe/admin/question_pages/update.js.erb +2 -0
  220. data/app/views.current/fe/admin/question_sheets/_errors.html.erb +11 -0
  221. data/app/views.current/fe/admin/question_sheets/edit.js.erb +3 -0
  222. data/app/views.current/fe/admin/question_sheets/error.js.erb +5 -0
  223. data/app/views.current/fe/admin/question_sheets/index.html.erb +41 -0
  224. data/app/views.current/fe/admin/question_sheets/new.html.erb +15 -0
  225. data/app/views.current/fe/admin/question_sheets/show.html.erb +27 -0
  226. data/app/views.current/fe/admin/question_sheets/update.js.erb +2 -0
  227. data/app/views.current/fe/answer_pages/_answer_page.html.erb +53 -0
  228. data/app/views.current/fe/answer_pages/_element.html.erb +32 -0
  229. data/app/views.current/fe/answer_pages/_page_name.html.erb +1 -0
  230. data/app/views.current/fe/answer_pages/show.html.erb +39 -0
  231. data/app/views.current/fe/answer_pages/update.js.erb +13 -0
  232. data/app/views.current/fe/answer_sheets/_answer_sheet.html.erb +26 -0
  233. data/app/views.current/fe/answer_sheets/_element.html.erb +74 -0
  234. data/app/views.current/fe/answer_sheets/_incomplete.html.erb +10 -0
  235. data/app/views.current/fe/answer_sheets/_page_link.html.erb +9 -0
  236. data/app/views.current/fe/answer_sheets/_pages_list.html.erb +11 -0
  237. data/app/views.current/fe/answer_sheets/_submit_to.html.erb +1 -0
  238. data/app/views.current/fe/answer_sheets/_title.html.erb +1 -0
  239. data/app/views.current/fe/answer_sheets/edit.html.erb +66 -0
  240. data/app/views.current/fe/answer_sheets/incomplete.js.erb +11 -0
  241. data/app/views.current/fe/answer_sheets/index.html.erb +18 -0
  242. data/app/views.current/fe/answer_sheets/send_reference_invite.js.erb +8 -0
  243. data/app/views.current/fe/answer_sheets/show.html.erb +13 -0
  244. data/app/views.current/fe/applications/_logout.html.erb +1 -0
  245. data/app/views.current/fe/applications/show.html.erb +1 -0
  246. data/app/views.current/fe/help/builder.html +33 -0
  247. data/app/views.current/fe/help/question_grid.html +18 -0
  248. data/app/views.current/fe/questions/fe/_acceptance.html.erb +14 -0
  249. data/app/views.current/fe/questions/fe/_attachment_field.html.erb +165 -0
  250. data/app/views.current/fe/questions/fe/_checkbox_field.html.erb +53 -0
  251. data/app/views.current/fe/questions/fe/_country.html.erb +7 -0
  252. data/app/views.current/fe/questions/fe/_date_field.html.erb +7 -0
  253. data/app/views.current/fe/questions/fe/_date_field_mmyy.html.erb +9 -0
  254. data/app/views.current/fe/questions/fe/_drop_down_field.html.erb +8 -0
  255. data/app/views.current/fe/questions/fe/_paragraph.html.erb +1 -0
  256. data/app/views.current/fe/questions/fe/_question_grid.html.erb +70 -0
  257. data/app/views.current/fe/questions/fe/_question_grid_with_total.html.erb +64 -0
  258. data/app/views.current/fe/questions/fe/_questions.html.erb +15 -0
  259. data/app/views.current/fe/questions/fe/_radio_button_field.html.erb +60 -0
  260. data/app/views.current/fe/questions/fe/_rating.html.erb +64 -0
  261. data/app/views.current/fe/questions/fe/_reference_discipler.html.erb +1 -0
  262. data/app/views.current/fe/questions/fe/_reference_friend.html.erb +1 -0
  263. data/app/views.current/fe/questions/fe/_reference_parent.html.erb +1 -0
  264. data/app/views.current/fe/questions/fe/_reference_peer.html.erb +1 -0
  265. data/app/views.current/fe/questions/fe/_reference_question.html.erb +61 -0
  266. data/app/views.current/fe/questions/fe/_reference_roommate.html.erb +1 -0
  267. data/app/views.current/fe/questions/fe/_reference_spiritual.html.erb +1 -0
  268. data/app/views.current/fe/questions/fe/_reference_staff.html.erb +1 -0
  269. data/app/views.current/fe/questions/fe/_section.html.erb +1 -0
  270. data/app/views.current/fe/questions/fe/_state_chooser.html.erb +7 -0
  271. data/app/views.current/fe/questions/fe/_text_area_field.html.erb +17 -0
  272. data/app/views.current/fe/questions/fe/_text_field.html.erb +9 -0
  273. data/app/views.current/fe/questions/fe/_yes_no.html.erb +17 -0
  274. data/app/views.current/fe/questions/fe/_yes_no_field.erb +20 -0
  275. data/app/views.current/fe/reference_pages/_reference.html.erb +31 -0
  276. data/app/views.current/fe/reference_pages/edit.html.erb +24 -0
  277. data/app/views.current/fe/reference_sheets/done.html.erb +2 -0
  278. data/app/views.current/fe/reference_sheets/not_found.html.erb +5 -0
  279. data/app/views.current/fe/reference_sheets/submitted.js.erb +1 -0
  280. data/app/views.current/fe/references/edit.html.erb +8 -0
  281. data/app/views.current/fe/references/send_invite.js.erb +7 -0
  282. data/app/views.current/fe/references/show.html.erb +18 -0
  283. data/app/views.current/fe/references/submit.js.erb +3 -0
  284. data/app/views.current/fe/submit_pages/_errors.html.erb +1 -0
  285. data/app/views.current/fe/submit_pages/_thankyou.html.erb +2 -0
  286. data/app/views.current/fe/submit_pages/edit.html.erb +36 -0
  287. data/app/views.current/fe/submit_pages/error.js.erb +1 -0
  288. data/app/views.current/fe/submit_pages/submit.js.erb +3 -0
  289. data/app/views.current/layouts/fe/_error_messages_for.html.erb +7 -0
  290. data/app/views.current/layouts/fe/application.html.erb +47 -0
  291. data/app/{views/layouts/fe/fe.admin.html.erb → views.current/layouts/fe/fe_admin.html.erb} +4 -4
  292. data/config/initializers/paper_trail.rb +3 -0
  293. data/config/routes.rb +3 -37
  294. data/db/migrate/20131003041856_core.rb +23 -23
  295. data/db/migrate/20131003044250_create_reference_sheets.rb +2 -1
  296. data/db/migrate/20131003044436_add_element_and_answer_fields.rb +3 -3
  297. data/db/migrate/20131003044518_create_email_templates.rb +2 -2
  298. data/db/migrate/20131003044621_add_max_lengths.rb +1 -1
  299. data/db/migrate/20131003044714_create_join_table.rb +1 -1
  300. data/db/migrate/20131016162128_remove_question_id_from_element.rb +1 -1
  301. data/db/migrate/20140623153424_create_fe_people.rb +2 -2
  302. data/db/migrate/20140624180246_create_fe_addresses.rb +2 -2
  303. data/db/migrate/{20140624182216_create_create_fe_phone_numbers.rb → 20140624182216_create_fe_phone_numbers.rb} +2 -2
  304. data/db/migrate/20140625160545_create_fe_users.rb +2 -2
  305. data/db/migrate/20140808202507_add_conditional_type_to_elements.rb +1 -1
  306. data/db/migrate/20140808203609_add_conditional_answer_to_elements.rb +1 -1
  307. data/db/migrate/20141103204704_remove_short_value_column.rb +1 -1
  308. data/db/migrate/20141109154522_move_conditional_ids_used_for_choice_field_to_their_own_column.rb +1 -1
  309. data/db/migrate/20150504221439_add_all_element_ids_to_pages.rb +5 -0
  310. data/db/migrate/20150713022326_add_locale_columns.rb +9 -0
  311. data/db/migrate/20150714220730_add_locale_to_answer_sheet.rb +5 -0
  312. data/db/migrate/20150925181652_add_share_to_elements.rb +5 -0
  313. data/db/migrate/20150928085325_change_pages_all_element_ids_to_text.rb +5 -0
  314. data/db/migrate/20150930191538_add_locale_to_reference_sheets.rb +5 -0
  315. data/db/migrate/20151021181928_switch_conditional_answer_separator_to_semicolon.rb +7 -0
  316. data/db/migrate/20151021184250_add_question_sheet_id_in_refs.rb +12 -0
  317. data/db/migrate/20160201185838_add_visible_and_visibility_cache_key_to_reference_sheets.rb +6 -0
  318. data/db/migrate/20160805221415_add_rating_extra_labels.rb +10 -0
  319. data/db/migrate/20181108201746_create_versions.rb +80 -0
  320. data/db/migrate/20181218201130_increase_slug_length.rb +5 -0
  321. data/lib/access_key_generator.rb +12 -0
  322. data/lib/distinct_distinct_patch.rb +20 -0
  323. data/lib/fe/engine.rb +26 -14
  324. data/lib/fe/version.rb +1 -1
  325. data/lib/fe.rb +11 -1
  326. data/spec/controllers/fe/admin/elements_controller_spec.rb +211 -1
  327. data/spec/controllers/fe/admin/email_templates_controller_spec.rb +26 -1
  328. data/spec/controllers/fe/admin/question_pages_controller_spec.rb +8 -1
  329. data/spec/controllers/fe/admin/question_sheets_controller_spec.rb +48 -1
  330. data/spec/controllers/fe/answer_pages_controller_spec.rb +129 -1
  331. data/spec/controllers/fe/answer_sheets_controller_spec.rb +136 -1
  332. data/spec/controllers/fe/reference_pages_controller.rb +4 -0
  333. data/spec/controllers/fe/references_controller_spec.rb +4 -0
  334. data/spec/controllers/fe/submit_pages_controller_spec.rb +4 -0
  335. data/spec/dummy/app/assets/config/manifest.js +0 -0
  336. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  337. data/spec/dummy/app/helpers/application_helper.rb +9 -0
  338. data/spec/dummy/app/models/application.rb +3 -0
  339. data/spec/dummy/app/models/person.rb +11 -0
  340. data/spec/dummy/app/models/user.rb +3 -0
  341. data/spec/dummy/app/views/layouts/application.html.erb +2 -2
  342. data/spec/dummy/config/application.rb +3 -1
  343. data/spec/dummy/config/database.yml +20 -17
  344. data/spec/dummy/config/environments/production.rb +1 -5
  345. data/spec/dummy/config/environments/test.rb +4 -2
  346. data/spec/dummy/config/initializers/assets.rb +5 -2
  347. data/spec/dummy/config/initializers/fast_gettext.rb +5 -0
  348. data/spec/dummy/config/initializers/to_unsafe_h.rb +5 -0
  349. data/spec/dummy/config/initializers/to_unsafe_h.rb.new +5 -0
  350. data/spec/dummy/config/secrets.yml +2 -2
  351. data/spec/dummy/db/migrate/20141203214017_core.fe_engine.rb +92 -0
  352. data/spec/dummy/db/migrate/20141203214018_create_reference_sheets.fe_engine.rb +25 -0
  353. data/spec/dummy/db/migrate/20141203214019_add_element_and_answer_fields.fe_engine.rb +11 -0
  354. data/spec/dummy/db/migrate/20141203214020_create_email_templates.fe_engine.rb +18 -0
  355. data/spec/dummy/db/migrate/20141203214021_add_max_lengths.fe_engine.rb +9 -0
  356. data/spec/dummy/db/migrate/20141203214022_create_join_table.fe_engine.rb +12 -0
  357. data/spec/dummy/db/migrate/20141203214023_remove_question_id_from_element.fe_engine.rb +10 -0
  358. data/spec/dummy/db/migrate/20141203214024_create_fe_people.fe_engine.rb +13 -0
  359. data/spec/dummy/db/migrate/20141203214025_create_fe_addresses.fe_engine.rb +21 -0
  360. data/spec/dummy/db/migrate/20141203214027_create_fe_users.fe_engine.rb +13 -0
  361. data/spec/dummy/db/migrate/20141203214028_add_conditional_type_to_elements.fe_engine.rb +6 -0
  362. data/spec/dummy/db/migrate/20141203214029_add_conditional_answer_to_elements.fe_engine.rb +6 -0
  363. data/spec/dummy/db/migrate/20141203214030_remove_short_value_column.fe_engine.rb +6 -0
  364. data/spec/dummy/db/migrate/20141203214031_move_conditional_ids_used_for_choice_field_to_their_own_column.fe_engine.rb +8 -0
  365. data/spec/dummy/db/migrate/20150123215803_create_users.rb +9 -0
  366. data/spec/dummy/db/migrate/20150504222619_add_all_element_ids_to_pages.fe_engine.rb +6 -0
  367. data/spec/dummy/db/migrate/20150925192557_add_share_to_elements.fe_engine.rb +6 -0
  368. data/spec/dummy/db/migrate/20150930190001_create_fe_phone_numbers.fe_engine.rb +20 -0
  369. data/spec/dummy/db/migrate/20150930190002_add_locale_columns.fe_engine.rb +10 -0
  370. data/spec/dummy/db/migrate/20150930190003_add_locale_to_answer_sheet.fe_engine.rb +6 -0
  371. data/spec/dummy/db/migrate/20150930190004_change_pages_all_element_ids_to_text.fe_engine.rb +6 -0
  372. data/spec/dummy/db/migrate/20150930191756_add_locale_to_reference_sheets.fe_engine.rb +6 -0
  373. data/spec/dummy/db/migrate/20151021190027_add_question_sheet_id_in_refs.fe_engine.rb +13 -0
  374. data/spec/dummy/db/migrate/20160204164612_switch_conditional_answer_separator_to_semicolon.fe_engine.rb +8 -0
  375. data/spec/dummy/db/migrate/20160204164613_add_visible_and_visibility_cache_key_to_reference_sheets.fe_engine.rb +7 -0
  376. data/spec/dummy/db/migrate/20181108201746_create_versions.rb +80 -0
  377. data/spec/dummy/db/schema.rb +91 -69
  378. data/spec/dummy/log/test.log +101278 -419
  379. data/spec/factories/answer_sheet_question_sheets.rb +1 -1
  380. data/spec/factories/answer_sheets.rb +2 -2
  381. data/spec/factories/answers.rb +1 -1
  382. data/spec/factories/applications.rb +3 -4
  383. data/spec/factories/dummy_applications.rb +6 -0
  384. data/spec/factories/dummy_people.rb +6 -0
  385. data/spec/factories/dummy_users.rb +6 -0
  386. data/spec/factories/elements.rb +35 -10
  387. data/spec/factories/email_templates.rb +5 -0
  388. data/spec/factories/fe_addresses.rb +10 -10
  389. data/spec/factories/fe_email_addresses.rb +3 -3
  390. data/spec/factories/fe_email_templates.rb +9 -0
  391. data/spec/factories/fe_people.rb +5 -7
  392. data/spec/factories/fe_phone_numbers.rb +3 -3
  393. data/spec/factories/fe_user.rb +6 -0
  394. data/spec/factories/page.rb +1 -1
  395. data/spec/factories/page_elements.rb +1 -1
  396. data/spec/factories/paragraphs.rb +1 -1
  397. data/spec/factories/question_sheet.rb +3 -3
  398. data/spec/factories/reference_questions.rb +1 -1
  399. data/spec/factories/reference_sheets.rb +9 -0
  400. data/spec/jobs/fe/update_reference_sheet_visibility_job_spec.rb +40 -0
  401. data/spec/mailers/fe/notifier_spec.rb +39 -0
  402. data/spec/models/fe/answer_sheet_question_sheet_spec.rb +1 -1
  403. data/spec/models/fe/answer_spec.rb +2 -2
  404. data/spec/models/fe/application_spec.rb +94 -1
  405. data/spec/models/fe/choice_field_spec.rb +66 -0
  406. data/spec/models/fe/condition_spec.rb +2 -2
  407. data/spec/models/fe/element_spec.rb +414 -37
  408. data/spec/models/fe/email_template_spec.rb +1 -1
  409. data/spec/models/fe/page_element_spec.rb +1 -1
  410. data/spec/models/fe/page_spec.rb +168 -11
  411. data/spec/models/fe/person_spec.rb +1 -1
  412. data/spec/models/fe/question_set_spec.rb +91 -0
  413. data/spec/models/fe/question_sheet_spec.rb +103 -1
  414. data/spec/models/fe/question_spec.rb +73 -6
  415. data/spec/models/fe/reference_question_spec.rb +20 -0
  416. data/spec/models/fe/reference_sheet_spec.rb +305 -2
  417. data/spec/models/fe/text_field_spec.rb +22 -0
  418. data/spec/rails_helper.rb +85 -54
  419. data/spec/support/choices.xml +6 -0
  420. metadata +310 -84
  421. data/app/assets/javascripts/fe/fe.common.js +0 -57
  422. data/app/assets/javascripts/fe/jquery.scrollTo-min.js +0 -7
  423. data/app/assets/javascripts/fe/rails.extra.js +0 -6
  424. data/app/controllers/fe/applications_controller.rb +0 -183
  425. data/app/controllers/fe/concerns/answer_pages_controller_concern.rb +0 -83
  426. data/app/controllers/fe/payments_controller.rb +0 -184
  427. data/app/models/fe/concerns/answer_sheet_concern.rb +0 -55
  428. data/app/models/fe/payment.rb +0 -77
  429. data/app/models/fe/payment_question.rb +0 -22
  430. data/app/views/fe/admin/panels/_prop_payment_question.html.erb +0 -1
  431. data/app/views/fe/application/_logout.html.erb +0 -1
  432. data/app/views/fe/payment_pages/_credit.html.erb +0 -47
  433. data/app/views/fe/payment_pages/_mail.html.erb +0 -27
  434. data/app/views/fe/payment_pages/_payment.html.erb +0 -6
  435. data/app/views/fe/payment_pages/_staff.html.erb +0 -25
  436. data/app/views/fe/payment_pages/_staff_results.html.erb +0 -17
  437. data/app/views/fe/payment_pages/edit.html.erb +0 -75
  438. data/app/views/fe/payment_pages/staff_search.js.erb +0 -2
  439. data/app/views/fe/payments/_credit.html.erb +0 -47
  440. data/app/views/fe/payments/_errors.html.erb +0 -1
  441. data/app/views/fe/payments/_payment.html.erb +0 -13
  442. data/app/views/fe/payments/_staff.html.erb +0 -21
  443. data/app/views/fe/payments/_staff_results.html.erb +0 -18
  444. data/app/views/fe/payments/approve.js.erb +0 -3
  445. data/app/views/fe/payments/create.js.erb +0 -19
  446. data/app/views/fe/payments/destroy.js.erb +0 -7
  447. data/app/views/fe/payments/edit.html.erb +0 -56
  448. data/app/views/fe/payments/error.js.erb +0 -3
  449. data/app/views/fe/payments/no_access.html.erb +0 -7
  450. data/app/views/fe/payments/staff_search.js.erb +0 -1
  451. data/app/views/fe/payments/update.html.erb +0 -24
  452. data/app/views/fe/questions/fe/_payment_question.html.erb +0 -70
  453. data/db/migrate/20140828045339_create_payments.rb +0 -13
  454. data/spec/dummy/db/test.sqlite3 +0 -0
  455. data/spec/factories/payments.rb +0 -7
  456. data/spec/models/fe/payment_question_spec.rb +0 -65
@@ -1,45 +1,51 @@
1
1
  require 'acts_as_list'
2
2
  module Fe
3
- class Page < ActiveRecord::Base
3
+ class Page < ApplicationRecord
4
4
  self.table_name = self.table_name.sub('fe_', Fe.table_name_prefix)
5
5
 
6
+ attr_accessor :old_id
7
+
6
8
  belongs_to :question_sheet
7
9
 
8
10
  has_many :page_elements, -> { order(:position) },
9
- :dependent => :destroy
11
+ dependent: :destroy
10
12
 
11
13
  has_many :elements, -> { order(Fe::PageElement.table_name + '.position') },
12
- :through => :page_elements
14
+ through: :page_elements
13
15
 
14
16
  has_many :question_grid_with_totals, -> { where("kind = 'Fe::QuestionGridWithTotal'") },
15
- :through => :page_elements,
16
- :source => :element
17
+ through: :page_elements,
18
+ source: :element
17
19
 
18
- has_many :questions, -> { where("kind NOT IN('Fe::Paragraph', 'Fe::Section', 'Fe::QuestionGrid', 'Fe::QuestionGridWithTotal')") },
19
- :through => :page_elements,
20
- :source => :element
20
+ has_many :questions, -> { questions.order(Fe::PageElement.table_name + '.position') },
21
+ through: :page_elements,
22
+ source: :element
21
23
 
22
24
  has_many :question_grids, -> { where("kind = 'Fe::QuestionGrid'") },
23
- :through => :page_elements,
24
- :source => :element
25
+ through: :page_elements,
26
+ source: :element
25
27
 
26
- # has_many :conditions, :class_name => "Condition", :foreign_key => "toggle_page_id", # conditions associated with page as a whole
27
- # :conditions => 'toggle_id is NULL', :dependent => :nullify
28
+ # has_many :conditions, class_name: "Condition", foreign_key: "toggle_page_id", # conditions associated with page as a whole
29
+ # conditions: 'toggle_id is NULL', dependent: :nullify
28
30
 
29
- acts_as_list :column => :number, :scope => :question_sheet_id
31
+ acts_as_list column: :number, scope: :question_sheet_id
30
32
 
31
- scope :visible, -> { where(:hidden => false) }
33
+ scope :visible, -> { where(hidden: false) }
32
34
 
33
35
  # callbacks
34
- before_validation :set_default_label, :on => :create # Page x
36
+ before_validation :set_default_label, on: :create # Page x
35
37
 
36
38
  # validation
37
39
  validates_presence_of :label, :number
38
- validates_length_of :label, :maximum => 100, :allow_nil => true
40
+ validates_length_of :label, maximum: 100, allow_nil: true
41
+
42
+ # validates_uniqueness_of :number, scope: :question_sheet_id
39
43
 
40
- # validates_uniqueness_of :number, :scope => :question_sheet_id
44
+ validates_numericality_of :number, only_integer: true
41
45
 
42
- validates_numericality_of :number, :only_integer => true
46
+ # NOTE: You may need config.active_record.yaml_column_permitted_classes = [Hash, ActiveSupport::HashWithIndifferentAccess]
47
+ # in config/application.rb or you may get Psych::DisallowedClass trying to use label_translations
48
+ serialize :label_translations, Hash
43
49
 
44
50
  # a page is disabled if there is a condition, and that condition evaluates to false
45
51
  # could set multiple conditions to influence this question, in which case all must be met
@@ -52,8 +58,27 @@ module Fe
52
58
  # false
53
59
  # end
54
60
 
61
+ def conditionally_visible?
62
+ question_sheet&.all_elements&.where(conditional_type: 'Fe::Page', conditional_id: self)&.any?
63
+ end
64
+
65
+ # any page that's conditionally visible should not use cache, there are race conditions otherwise
66
+ # that happen when the conditional value is set and the now visible page loaded in ajax
67
+ def no_cache
68
+ conditionally_visible? || self[:no_cache]
69
+ end
70
+
71
+ def label(locale = nil)
72
+ label_translations[locale] || self[:label]
73
+ end
74
+
75
+ # returns true if there is a question element on the page, including one inside a grid
55
76
  def has_questions?
56
- questions.present? || question_grids.present? || question_grid_with_totals.present?
77
+ all_questions.any?
78
+ end
79
+
80
+ def all_questions
81
+ all_elements.questions
57
82
  end
58
83
 
59
84
  def questions_before_position(position)
@@ -62,38 +87,120 @@ module Fe
62
87
 
63
88
  # Include nested elements
64
89
  def all_elements
65
- (elements + elements.collect(&:all_elements)).flatten
90
+ ids = all_element_ids_arr
91
+ order = ids.collect{ |id| "id=#{id} DESC" }.join(', ')
92
+ ids.present? ? Element.where(id: ids).order(Arel.sql(order)) : Element.where("1 = 0")
93
+ end
94
+
95
+ def all_element_ids
96
+ rebuild_all_element_ids if self[:all_element_ids].nil?
97
+ self[:all_element_ids]
98
+ end
99
+
100
+ def all_element_ids_arr
101
+ @all_element_ids_arr ||= all_element_ids.split(',').collect(&:to_i)
102
+ end
103
+
104
+ def rebuild_all_element_ids
105
+ self.update_column :all_element_ids, elements.collect{ |e| [e] + e.all_elements }.flatten.collect(&:id).join(',')
66
106
  end
67
107
 
68
108
  def copy_to(question_sheet)
69
109
  new_page = Fe::Page.new(self.attributes.merge(id: nil))
70
110
  new_page.question_sheet_id = question_sheet.id
71
- new_page.save(:validate => false)
111
+ new_page.save(validate: false)
72
112
  self.elements.each do |element|
73
113
  if !question_sheet.archived? && element.reuseable?
74
- Fe::PageElement.create(:element => element, :page => new_page)
114
+ Fe::PageElement.create(element: element, page: new_page)
75
115
  else
76
116
  element.duplicate(new_page)
77
117
  end
78
118
  end
119
+ new_page.rebuild_all_element_ids
120
+ new_page
121
+ end
122
+
123
+ def hidden?(answer_sheet)
124
+ return true if hidden
125
+
126
+ @hidden_cache ||= {}
127
+ return @hidden_cache[answer_sheet] if !@hidden_cache[answer_sheet].nil?
128
+
129
+ unless conditionally_visible?
130
+ @hidden_cache[answer_sheet] = false
131
+ return false
132
+ end
133
+
134
+ # if any of the conditional questions matches, it's visible
135
+ r = !question_sheet.all_elements.where(conditional_type: 'Fe::Page', conditional_id: self).any?{ |e|
136
+ e.visible?(answer_sheet) && e.conditional_match(answer_sheet)
137
+ }
138
+ @hidden_cache[answer_sheet] = r
139
+ return r
140
+ end
141
+
142
+ def clear_hidden_cache
143
+ @hidden_cache = nil
79
144
  end
80
145
 
81
146
  def complete?(answer_sheet)
82
- return true if question_sheet.hidden_pages(answer_sheet).include?(self)
83
- prev_el = nil
84
- all_elements.all? {|e|
85
- complete = !e.required? || (prev_el && prev_el.conditional == e && !prev_el.conditional_match(answer_sheet)) || e.has_response?(answer_sheet)
86
- prev_el = e
87
- complete
147
+ return true if hidden?(answer_sheet)
148
+
149
+ all_elements.all? {|e|
150
+ e.hidden?(answer_sheet, self) || !e.required?(answer_sheet, self) || e.has_response?(answer_sheet)
88
151
  }
89
152
  end
90
153
 
91
154
  def started?(answer_sheet)
92
- all_elements.any? {|e| e.has_response?(answer_sheet)}
155
+ all_questions.any? {|e| e.has_response?(answer_sheet)}
93
156
  end
94
157
 
95
- def has_questions?
96
- all_elements.any? {|e| e.is_a?(Question)}
158
+ def all_hidden_elements(answer_sheet)
159
+ @all_hidden_elements ||= {}
160
+ @all_hidden_elements[answer_sheet.cache_key] ||= build_all_hidden_elements(answer_sheet)
161
+ end
162
+
163
+ def build_all_hidden_elements(answer_sheet)
164
+ @all_hidden_elements ||= {}
165
+ @all_hidden_elements[answer_sheet.cache_key] = []
166
+ all_elements.each do |e|
167
+ next if @all_hidden_elements[answer_sheet.cache_key].include?(e)
168
+ if e.hidden_by_choice_field?(answer_sheet) || e.hidden_by_conditional?(answer_sheet, self)
169
+ @all_hidden_elements[answer_sheet.cache_key] += ([e] + e.all_elements)
170
+ @all_hidden_elements[answer_sheet.cache_key].uniq!
171
+ end
172
+ end
173
+ @all_hidden_elements[answer_sheet.cache_key]
174
+ end
175
+
176
+ def clear_all_hidden_elements
177
+ @all_hidden_elements = nil
178
+ end
179
+
180
+ def export_hash
181
+ base_attributes = self.attributes.to_hash
182
+ base_attributes[:elements] = elements.collect(&:export_hash)
183
+ base_attributes.delete(:id)
184
+ base_attributes[:question_sheet_id] = :question_sheet_id
185
+ base_attributes
186
+ end
187
+
188
+ def export_to_yaml
189
+ export_hash.to_yaml
190
+ end
191
+
192
+ def self.create_from_import(page_data, question_sheet)
193
+ elements = page_data.delete(:elements)
194
+ page_data.delete(:all_element_ids) # this can get build again
195
+ page_data[:old_id] = page_data.delete('id')
196
+ page_data[:question_sheet_id] = question_sheet.id
197
+ puts("Import page from data #{page_data}")
198
+ page = Fe::Page.create!(page_data)
199
+ elements.each do |el|
200
+ page.elements << Fe::Element.create_from_import(el, page, question_sheet)
201
+ end
202
+ page.rebuild_all_element_ids
203
+ page
97
204
  end
98
205
 
99
206
  private
@@ -1,13 +1,14 @@
1
1
  require 'acts_as_list'
2
2
  module Fe
3
- class PageElement < ActiveRecord::Base
3
+ class PageElement < ApplicationRecord
4
4
  self.table_name = self.table_name.sub('fe_', Fe.table_name_prefix)
5
- acts_as_list :scope => :page_id
6
- belongs_to :page
5
+ acts_as_list scope: :page_id
6
+ belongs_to :page, touch: true
7
7
  belongs_to :element
8
8
 
9
9
  after_save :save_element
10
10
  before_create :set_position
11
+ after_destroy :rebuild_page_all_element_ids
11
12
 
12
13
  def set_position
13
14
  self.position ||= (page.page_elements.last.try(:position) + 1) || page.elements.last.try(:position) || 0
@@ -17,5 +18,9 @@ module Fe
17
18
  def save_element
18
19
  element.save!
19
20
  end
21
+
22
+ def rebuild_page_all_element_ids
23
+ page.rebuild_all_element_ids
24
+ end
20
25
  end
21
26
  end
@@ -1,15 +1,18 @@
1
1
  # represents a link to a page for the page_list sidebar or next page links
2
2
  module Fe
3
3
  class PageLink
4
- attr_accessor :dom_id, :label, :load_path, :page
4
+ attr_accessor :dom_id, :load_path, :page
5
5
  attr_accessor :save_path # to save current page
6
6
 
7
- def initialize(label, load_path, dom_id, page)
8
- @label = label
7
+ def initialize(load_path, dom_id, page)
9
8
  @load_path = load_path
10
9
  @dom_id = dom_id
11
10
  @page = page
12
11
  end
13
12
 
13
+ def label(locale = nil)
14
+ page.label(locale)
15
+ end
16
+
14
17
  end
15
18
  end
@@ -5,6 +5,6 @@
5
5
  # :content - instructions, agreements, etc. to display
6
6
  module Fe
7
7
  class Paragraph < Element
8
- validates_presence_of :content, :on => :update
8
+ validates_presence_of :content, on: :update
9
9
  end
10
10
  end
@@ -1,14 +1,13 @@
1
1
  module Fe
2
- class Person < ActiveRecord::Base
3
- belongs_to :user, :foreign_key => "fk_ssmUserId" # TODO need to migrate person columns to be more rails-like
4
- has_one :current_address, -> { where("address_type = 'current'") }, :class_name => "Fe::Address"
5
- has_many :email_addresses, :foreign_key => "person_id", :class_name => '::EmailAddress', dependent: :destroy
6
- has_many :phone_numbers, :foreign_key => "person_id", :class_name => '::PhoneNumber', dependent: :destroy
7
- has_one :current_address, -> { where("address_type = 'current'") }, :foreign_key => "person_id", :class_name => '::Fe::Address'
8
- has_one :permanent_address, -> { where("address_type = 'permanent'") }, :foreign_key => "person_id", :class_name => '::Fe::Address'
9
- has_one :emergency_address1, -> { where("address_type = 'emergency1'") }, :foreign_key => "person_id", :class_name => 'Fe::Address'
10
- has_many :addresses, :foreign_key => "person_id", dependent: :destroy
11
- has_one :application, :foreign_key => "applicant_id"
2
+ class Person < ApplicationRecord
3
+ belongs_to :user, optional: true, foreign_key: "fk_ssmUserId" # TODO need to migrate person columns to be more rails-like
4
+ has_many :email_addresses, class_name: '::EmailAddress', dependent: :destroy
5
+ has_many :phone_numbers, class_name: '::PhoneNumber', dependent: :destroy
6
+ has_one :current_address, -> { where("address_type = 'current'") }, class_name: '::Fe::Address', dependent: :destroy
7
+ has_one :permanent_address, -> { where("address_type = 'permanent'") }, class_name: '::Fe::Address', dependent: :destroy
8
+ has_one :emergency_address1, -> { where("address_type = 'emergency1'") }, class_name: 'Fe::Address', dependent: :destroy
9
+ has_many :addresses, dependent: :destroy
10
+ has_many :applications, class_name: Fe.answer_sheet_class
12
11
 
13
12
  def emergency_address
14
13
  emergency_address1
@@ -18,15 +17,19 @@ module Fe
18
17
  end
19
18
 
20
19
  def create_emergency_address
21
- Address.create(:person_id => self.id, :address_type => 'emergency1')
20
+ Address.create(person_id: self.id, address_type: 'emergency1')
22
21
  end
23
22
 
24
23
  def create_current_address
25
- Address.create(:person_id => self.id, :address_type => 'current')
24
+ Address.create(person_id: self.id, address_type: 'current')
26
25
  end
27
26
 
28
27
  def create_permanent_address
29
- Address.create(:person_id => self.id, :address_type => 'permanent')
28
+ Address.create(person_id: self.id, address_type: 'permanent')
29
+ end
30
+
31
+ def name
32
+ [ first_name, last_name ].join(' ')
30
33
  end
31
34
  end
32
35
 
@@ -1,4 +1,4 @@
1
- class Fe::PhoneNumber < ActiveRecord::Base
1
+ class Fe::PhoneNumber < ApplicationRecord
2
2
  belongs_to :person
3
3
 
4
4
  self.table_name = "phone_numbers"
@@ -12,34 +12,40 @@ module Fe
12
12
  class Question < Element
13
13
  include ActionView::RecordIdentifier # dom_id
14
14
  has_many :conditions,
15
- :class_name => "Condition",
16
- :foreign_key => "toggle_id",
17
- :dependent => :nullify
15
+ class_name: "Condition",
16
+ foreign_key: "toggle_id",
17
+ dependent: :nullify
18
18
 
19
19
  has_many :dependents,
20
- :class_name => "Condition",
21
- :foreign_key => "trigger_id",
22
- :dependent => :nullify
20
+ class_name: "Condition",
21
+ foreign_key: "trigger_id",
22
+ dependent: :nullify
23
23
 
24
24
  has_many :sheet_answers,
25
- :class_name => "Answer",
26
- :foreign_key => "question_id",
27
- :dependent => :destroy
25
+ class_name: "Answer",
26
+ foreign_key: "question_id",
27
+ dependent: :destroy
28
28
 
29
29
  belongs_to :related_question_sheet,
30
- :class_name => "QuestionSheet",
31
- :foreign_key => "related_question_sheet_id"
30
+ optional: true,
31
+ class_name: "QuestionSheet",
32
+ foreign_key: "related_question_sheet_id"
32
33
 
33
- # validates_inclusion_of :required, :in => [false, true]
34
+ # validates_inclusion_of :required, in: [false, true]
34
35
 
35
- validates_format_of :slug, :with => /\A[a-z_][a-z0-9_]*\z/,
36
- :allow_nil => true, :if => Proc.new { |q| !q.slug.blank? },
37
- :message => 'may only contain lowercase letters, digits and underscores; and cannot begin with a digit.' # enforcing lowercase because javascript is case-sensitive
38
- validates_length_of :slug, :in => 4..36,
39
- :allow_nil => true, :if => Proc.new { |q| !q.slug.blank? }
40
- validates_uniqueness_of :slug,
41
- :allow_nil => true, :if => Proc.new { |q| !q.slug.blank? },
42
- :message => 'must be unique.'
36
+ validates_format_of :slug, with: /\A[a-z_][a-z0-9_]*\z/,
37
+ allow_nil: true, if: Proc.new { |q| !q.slug.blank? },
38
+ message: 'may only contain lowercase letters, digits and underscores; and cannot begin with a digit.' # enforcing lowercase because javascript is case-sensitive
39
+ validates_length_of :slug, in: 4..128,
40
+ allow_nil: true, if: Proc.new { |q| !q.slug.blank? }
41
+
42
+ validates_each :slug, allow_nil: true, allow_blank: true do |record, attr, value|
43
+ record.pages_on.collect(&:question_sheet).uniq.each do |qs|
44
+ if qs.all_elements.where(slug: record.slug).where("id != ?", record.id).any?
45
+ record.errors.add(attr, "must be unique (within the question sheet)")
46
+ end
47
+ end
48
+ end
43
49
 
44
50
  # a question has one response per AnswerSheet (that is, an instance of a user filling out the question)
45
51
  # generally the response is a single answer
@@ -66,9 +72,9 @@ module Fe
66
72
  # expression = new_conditions[i]["expression"]
67
73
  # trigger_id = new_conditions[i]["trigger_id"].to_i
68
74
  # unless expression.blank? || !page.questions.collect(&:id).include?(trigger_id) || conditions.collect(&:trigger_id).include?(trigger_id)
69
- # conditions.create(:question_sheet_id => question_sheet_id, :trigger_id => trigger_id,
70
- # :expression => expression, :toggle_page_id => page_id,
71
- # :toggle_id => self.id)
75
+ # conditions.create(question_sheet_id: question_sheet_id, trigger_id: trigger_id,
76
+ # expression: expression, toggle_page_id: page_id,
77
+ # toggle_id: self.id)
72
78
  # end
73
79
  # end
74
80
  # end
@@ -78,8 +84,10 @@ module Fe
78
84
  true
79
85
  end
80
86
 
81
- def locked?(params, answer_sheet, presenter)
82
- return true unless ['fe/answer_pages', 'fe/reference_sheets'].include?(params['controller']) && params['action'] == 'edit'
87
+ # NOTE: current_person is passed in for the benefit of enclosing apps that override locked?
88
+ # and need to lock an element depending on who the current person is
89
+ def locked?(params, answer_sheet, presenter, current_person)
90
+ return true unless params['action'] == 'edit'
83
91
  if self.object_name == 'person.current_address' && ['address1','address2','city','zip','email','state','country'].include?(self.attribute_name)
84
92
  # Billing Address
85
93
  return false
@@ -90,13 +98,14 @@ module Fe
90
98
  # Relationship & Country & Email Address
91
99
  return false
92
100
  else
93
- return answer_sheet.frozen? && !presenter.reference?
101
+ return answer_sheet.frozen? && !presenter.reference? &&
102
+ !@answer_sheet.try(:reference?)
94
103
  end
95
104
  end
96
105
 
97
106
  # css class names for javascript-based validation
98
- def validation_class(answer_sheet = nil)
99
- if required?(answer_sheet)
107
+ def validation_class(answer_sheet = nil, page = nil)
108
+ if required?(answer_sheet, page)
100
109
  ' required '
101
110
  else
102
111
  ''
@@ -147,8 +156,9 @@ module Fe
147
156
  [eval("obj." + attribute_name)]
148
157
  end
149
158
  else
150
- #answer_sheet.answers_by_question[id] || []
151
- Fe::Answer.where(:answer_sheet_id => answer_sheet.id, :question_id => self.id).to_a
159
+ answers = sheet_answers.where(answer_sheet: answer_sheet)
160
+ answers = answers.where("value IS NOT NULL AND value != ''")
161
+ answers.to_a
152
162
  end
153
163
  end
154
164
 
@@ -169,7 +179,7 @@ module Fe
169
179
  value = values.first
170
180
  if self.is_a?(Fe::DateField) && value.present?
171
181
  begin
172
- value = Date.strptime(value, (I18n.t 'date.formats.default'))
182
+ value = Date.strptime(value, '%Y-%m-%d')
173
183
  rescue
174
184
  raise "invalid date - " + value.inspect
175
185
  end
@@ -180,7 +190,8 @@ module Fe
180
190
  # raise object_name.inspect + ' == ' + attribute_name.inspect
181
191
  # end
182
192
  else
183
- @answers ||= []
193
+ @answers = sheet_answers.where(answer_sheet_id: answer_sheet.id).to_a
194
+ @answer_sheet_answers_are_for = answer_sheet
184
195
  @mark_for_destroy ||= []
185
196
  # go through existing answers (in reverse order, as we delete)
186
197
  (@answers.length - 1).downto(0) do |index|
@@ -195,7 +206,7 @@ module Fe
195
206
  # insert any new answers
196
207
  for value in values
197
208
  if @mark_for_destroy.empty?
198
- answer = Fe::Answer.new(:question_id => self.id)
209
+ answer = Fe::Answer.new(question_id: self.id)
199
210
  else
200
211
  # re-use marked answers (an update vs. a delete+insert)
201
212
  answer = @mark_for_destroy.pop
@@ -206,13 +217,26 @@ module Fe
206
217
  end
207
218
  end
208
219
 
220
+ def check_answer_sheet_matches_set_response_answer_sheet(answer_sheet)
221
+ if @answer_sheet_answers_are_for && @answer_sheet_answers_are_for != answer_sheet
222
+ fail("Trying to save answers to a different answer sheet than the one given in set_response")
223
+ end
224
+ end
225
+
209
226
  def save_file(answer_sheet, file)
227
+ check_answer_sheet_matches_set_response_answer_sheet(answer_sheet)
210
228
  @answers.collect(&:destroy) if @answers
211
- Fe::Answer.create!(:question_id => self.id, :answer_sheet_id => answer_sheet.id, :attachment => file)
229
+ Fe::Answer.create!(question_id: self.id, answer_sheet_id: answer_sheet.id, attachment: file)
230
+ end
231
+
232
+ def delete_file(answer_sheet, answer)
233
+ check_answer_sheet_matches_set_response_answer_sheet(answer_sheet)
234
+ answer.destroy
212
235
  end
213
236
 
214
237
  # save this question's @answers to database
215
238
  def save_response(answer_sheet)
239
+ check_answer_sheet_matches_set_response_answer_sheet(answer_sheet)
216
240
  unless @answers.nil?
217
241
  for answer in @answers
218
242
  if answer.is_a?(Fe::Answer)
@@ -229,28 +253,24 @@ module Fe
229
253
  end
230
254
  @mark_for_destroy.clear
231
255
  end
256
+
257
+ # clear hidden elements cache on page since this answer might modify which elements are hidden
258
+ pages_on.each do |p| p.clear_all_hidden_elements; end
259
+
232
260
  rescue TypeError
233
261
  raise answer.inspect
234
262
  end
235
263
 
236
264
  # has any sort of non-empty response?
237
265
  def has_response?(answer_sheet = nil)
238
- if answer_sheet.present?
239
- answers = responses(answer_sheet)
240
- else
241
- answers = Fe::Answer.where(:question_id => self.id)
242
- end
266
+ answers = answer_sheet.present? ? responses(answer_sheet) : sheet_answers
243
267
  return false if answers.length == 0
244
- answers.each do |answer| # loop through Answers
268
+ answers.each do |answer|
245
269
  value = answer.is_a?(Fe::Answer) ? answer.value : answer
246
270
  return true if (value.is_a?(FalseClass) && value === false) || value.present?
247
271
  end
248
272
  false
249
273
  end
250
274
 
251
- def required?(answer_sheet = nil)
252
- super
253
- end
254
-
255
275
  end
256
276
  end
@@ -7,10 +7,10 @@
7
7
  module Fe
8
8
  class QuestionGrid < Element
9
9
 
10
- has_many :elements, -> { order('position') },
11
- :class_name => "Element",
12
- :foreign_key => "question_grid_id",
13
- :dependent => :nullify
10
+ has_many :elements, -> { order('position asc, id asc') },
11
+ class_name: "Element",
12
+ foreign_key: "question_grid_id",
13
+ dependent: :nullify
14
14
 
15
15
  def num_cols
16
16
  num = cols.to_s.split(';').length
@@ -21,5 +21,17 @@ module Fe
21
21
  def has_response?(answer_sheet = nil)
22
22
  elements.any? {|e| e.has_response?(answer_sheet)}
23
23
  end
24
+
25
+ def export_hash
26
+ super_hash = super
27
+ children = elements.collect do |e|
28
+ h = e.export_hash
29
+ h[:question_grid_id] = :parent_id
30
+ h
31
+ end
32
+
33
+ super_hash[:children] += children
34
+ super_hash
35
+ end
24
36
  end
25
37
  end
@@ -7,5 +7,20 @@
7
7
 
8
8
  module Fe
9
9
  class QuestionGridWithTotal < QuestionGrid
10
+ def totals(app)
11
+ totals = []
12
+ col = 0
13
+ row = []
14
+ elements.each do |el|
15
+ value = el.display_response(app) if el.respond_to?(:display_response) && el.display_response(app).present?
16
+
17
+ if value && value.present? # keep totals nil until there actually is a value, so that we can only display a total only if at least one row had a value
18
+ value = value.tr("^0-9.", '').to_f
19
+ totals[col] = (totals[col].present? ? totals[col] + value : value)
20
+ end
21
+ col = (col + 1) % num_cols
22
+ end
23
+ totals
24
+ end
10
25
  end
11
26
  end