fe 1.0.0 → 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.
- checksums.yaml +5 -5
- data/README.md +4 -4
- data/app/assets/config/fe/manifest.js +3 -0
- data/app/assets/config/manifest.js +3 -0
- data/app/assets/javascripts/application.js.erb +1 -1
- data/app/assets/javascripts/fe/admin.js +0 -1
- data/app/assets/javascripts/fe/fe.admin.js +2 -6
- data/app/assets/javascripts/fe/{fe.common.js → fe.common.js.erb} +14 -7
- data/app/assets/javascripts/fe/fe.public.js +1 -2
- data/app/assets/javascripts/fe/{fe.public.nojquery.js → fe.public.nojquery.js.erb} +152 -76
- data/app/assets/javascripts/fe/jquery.html5_upload.js +258 -0
- data/app/assets/stylesheets/fe/fe.screen.css.scss.erb +22 -1
- data/app/assets/stylesheets/fe/validation.css +5 -1
- data/app/controllers/{fe/concerns → concerns/fe}/admin/question_sheets_controller_concern.rb +15 -16
- data/app/controllers/concerns/fe/answer_pages_controller_concern.rb +131 -0
- data/app/controllers/{fe/concerns → concerns/fe}/answer_sheets_controller_concern.rb +14 -6
- data/app/controllers/{fe/concerns → concerns/fe}/application_controller_concern.rb +3 -3
- data/app/controllers/fe/admin/elements_controller.rb +46 -24
- data/app/controllers/fe/admin/email_templates_controller.rb +5 -5
- data/app/controllers/fe/admin/question_pages_controller.rb +8 -8
- data/app/controllers/fe/reference_pages_controller.rb +11 -11
- data/app/controllers/fe/reference_sheets_controller.rb +4 -4
- data/app/controllers/fe/references_controller.rb +19 -19
- data/app/controllers/fe/submit_pages_controller.rb +5 -5
- data/app/helpers/fe/answer_pages_helper.rb +1 -1
- data/app/helpers/fe/application_helper.rb +3 -3
- data/app/jobs/fe/update_reference_sheet_visibility_job.rb +11 -0
- data/app/mailers/fe/notifier.rb +4 -4
- data/app/models/answer_sheet.rb +1 -1
- data/app/models/application_record.rb +3 -0
- data/app/models/{fe/concerns → concerns/fe}/answer_concern.rb +2 -2
- data/app/models/{fe/concerns → concerns/fe}/answer_pages_presenter_concern.rb +6 -5
- data/app/models/concerns/fe/answer_sheet_concern.rb +125 -0
- data/app/models/{fe/concerns → concerns/fe}/choice_field_concern.rb +41 -23
- data/app/models/fe/address.rb +2 -2
- data/app/models/fe/answer.rb +1 -1
- data/app/models/fe/answer_sheet.rb +1 -1
- data/app/models/fe/answer_sheet_question_sheet.rb +2 -2
- data/app/models/fe/application.rb +14 -10
- data/app/models/fe/condition.rb +4 -4
- data/app/models/fe/date_field.rb +1 -1
- data/app/models/fe/element.rb +126 -44
- data/app/models/fe/email_address.rb +2 -2
- data/app/models/fe/email_template.rb +1 -1
- data/app/models/fe/page.rb +94 -19
- data/app/models/fe/page_element.rb +2 -2
- data/app/models/fe/paragraph.rb +1 -1
- data/app/models/fe/person.rb +5 -5
- data/app/models/fe/phone_number.rb +1 -1
- data/app/models/fe/question.rb +62 -38
- data/app/models/fe/question_grid.rb +15 -3
- data/app/models/fe/question_set.rb +53 -13
- data/app/models/fe/question_sheet.rb +49 -16
- data/app/models/fe/reference_question.rb +9 -3
- data/app/models/fe/reference_sheet.rb +102 -47
- data/app/models/fe/state_chooser.rb +2 -2
- data/app/models/fe/text_field.rb +2 -2
- data/app/models/fe/user.rb +1 -1
- data/app/models/staff.rb +6 -6
- data/app/views/fe/admin/elements/create.js.erb +3 -3
- data/app/views/fe/admin/elements/destroy.js.erb +1 -1
- data/app/views/fe/admin/elements/drop.js.erb +1 -1
- data/app/views/fe/admin/elements/duplicate.js.erb +1 -1
- data/app/views/fe/admin/elements/edit.js.erb +1 -1
- data/app/views/fe/admin/elements/error.js.erb +1 -1
- data/app/views/fe/admin/elements/new.js.erb +13 -6
- data/app/views/fe/admin/elements/update.js.erb +1 -1
- data/app/views/fe/admin/email_templates/_form.html.erb +3 -3
- data/app/views/fe/admin/email_templates/edit.html.erb +3 -3
- data/app/views/fe/admin/email_templates/index.html.erb +3 -3
- data/app/views/fe/admin/email_templates/new.html.erb +3 -3
- data/app/views/fe/admin/panels/_advanced_options.html.erb +8 -8
- data/app/views/fe/admin/panels/_common_boolean_fields.html.erb +1 -0
- data/app/views/fe/admin/panels/_common_boolean_fields_default.html.erb +11 -0
- data/app/views/fe/admin/panels/_common_fields.html.erb +2 -17
- data/app/views/fe/admin/panels/_condition.html.erb +1 -1
- data/app/views/fe/admin/panels/_insert.html.erb +25 -25
- data/app/views/fe/admin/panels/_nav_controls.html.erb +4 -4
- data/app/views/fe/admin/panels/_page.html.erb +1 -1
- data/app/views/fe/admin/panels/_pages_list.html.erb +3 -3
- data/app/views/fe/admin/panels/_prop_attachment_field.html.erb +2 -2
- data/app/views/fe/admin/panels/_prop_choice_field.html.erb +36 -17
- data/app/views/fe/admin/panels/_prop_date_field.html.erb +1 -1
- data/app/views/fe/admin/panels/_prop_element.html.erb +5 -5
- data/app/views/fe/admin/panels/_prop_page.html.erb +3 -3
- data/app/views/fe/admin/panels/_prop_paragraph.html.erb +8 -8
- data/app/views/fe/admin/panels/_prop_question_grid.html.erb +7 -2
- data/app/views/fe/admin/panels/_prop_question_grid_with_total.html.erb +2 -2
- data/app/views/fe/admin/panels/_prop_reference_question.html.erb +3 -3
- data/app/views/fe/admin/panels/_prop_section.html.erb +1 -1
- data/app/views/fe/admin/panels/_prop_sheet.html.erb +3 -3
- data/app/views/fe/admin/panels/_prop_text_field.html.erb +12 -12
- data/app/views/fe/admin/question_pages/_element.html.erb +7 -7
- data/app/views/fe/admin/question_pages/_element_show.html.erb +2 -2
- data/app/views/fe/admin/question_pages/_question_page.html.erb +4 -4
- data/app/views/fe/admin/question_pages/create.js.erb +3 -3
- data/app/views/fe/admin/question_pages/destroy.js.erb +3 -3
- data/app/views/fe/admin/question_pages/edit.js.erb +1 -1
- data/app/views/fe/admin/question_pages/error.js.erb +1 -1
- data/app/views/fe/admin/question_pages/show.js.erb +2 -2
- data/app/views/fe/admin/question_pages/show_panel.js.erb +1 -1
- data/app/views/fe/admin/question_pages/update.js.erb +1 -1
- data/app/views/fe/admin/question_sheets/edit.js.erb +1 -1
- data/app/views/fe/admin/question_sheets/error.js.erb +1 -1
- data/app/views/fe/admin/question_sheets/index.html.erb +8 -8
- data/app/views/fe/admin/question_sheets/new.html.erb +3 -3
- data/app/views/fe/admin/question_sheets/show.html.erb +5 -5
- data/app/views/fe/admin/question_sheets/update.js.erb +1 -1
- data/app/views/fe/answer_pages/_answer_page.html.erb +13 -14
- data/app/views/fe/answer_pages/_element.html.erb +22 -2
- data/app/views/fe/answer_pages/_page_name.html.erb +1 -1
- data/app/views/fe/answer_pages/show.html.erb +39 -0
- data/app/views/fe/answer_pages/update.js.erb +10 -2
- data/app/views/fe/answer_sheets/_answer_sheet.html.erb +4 -4
- data/app/views/fe/answer_sheets/_element.html.erb +9 -7
- data/app/views/fe/answer_sheets/_incomplete.html.erb +1 -1
- data/app/views/fe/answer_sheets/_page_link.html.erb +9 -7
- data/app/views/fe/answer_sheets/_pages_list.html.erb +3 -3
- data/app/views/fe/answer_sheets/_submit_to.html.erb +1 -1
- data/app/views/fe/answer_sheets/_title.html.erb +1 -1
- data/app/views/fe/answer_sheets/edit.html.erb +18 -18
- data/app/views/fe/answer_sheets/incomplete.js.erb +7 -4
- data/app/views/fe/answer_sheets/index.html.erb +1 -1
- data/app/views/fe/answer_sheets/show.html.erb +1 -1
- data/app/views/fe/applications/_logout.html.erb +1 -1
- data/app/views/fe/questions/fe/_acceptance.html.erb +10 -9
- data/app/views/fe/questions/fe/_attachment_field.html.erb +129 -10
- data/app/views/fe/questions/fe/_checkbox_field.html.erb +18 -16
- data/app/views/fe/questions/fe/_country.html.erb +6 -6
- data/app/views/fe/questions/fe/_date_field.html.erb +5 -4
- data/app/views/fe/questions/fe/_date_field_mmyy.html.erb +8 -8
- data/app/views/fe/questions/fe/_drop_down_field.html.erb +5 -5
- data/app/views/fe/questions/fe/_question_grid.html.erb +10 -10
- data/app/views/fe/questions/fe/_question_grid_with_total.html.erb +8 -8
- data/app/views/fe/questions/fe/_questions.html.erb +11 -5
- data/app/views/fe/questions/fe/_radio_button_field.html.erb +35 -19
- data/app/views/fe/questions/fe/_rating.html.erb +56 -18
- data/app/views/fe/questions/fe/_reference_discipler.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_friend.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_parent.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_peer.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_question.html.erb +40 -24
- data/app/views/fe/questions/fe/_reference_roommate.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_spiritual.html.erb +1 -1
- data/app/views/fe/questions/fe/_reference_staff.html.erb +1 -1
- data/app/views/fe/questions/fe/_state_chooser.html.erb +6 -6
- data/app/views/fe/questions/fe/_text_area_field.html.erb +14 -10
- data/app/views/fe/questions/fe/_text_field.html.erb +7 -6
- data/app/views/fe/questions/fe/_yes_no.html.erb +8 -8
- data/app/views/fe/questions/fe/_yes_no_field.erb +11 -8
- data/app/views/fe/reference_pages/_reference.html.erb +12 -12
- data/app/views/fe/reference_pages/edit.html.erb +4 -4
- data/app/views/fe/reference_sheets/done.html.erb +2 -2
- data/app/views/fe/reference_sheets/not_found.html.erb +3 -3
- data/app/views/fe/references/edit.html.erb +5 -5
- data/app/views/fe/references/show.html.erb +3 -3
- data/app/views/fe/references/submit.js.erb +3 -3
- data/app/views/fe/submit_pages/_thankyou.html.erb +1 -1
- data/app/views/fe/submit_pages/edit.html.erb +9 -9
- data/app/views/fe/submit_pages/error.js.erb +1 -1
- data/app/views/fe/submit_pages/submit.js.erb +2 -2
- data/app/views/layouts/fe/_error_messages_for.html.erb +1 -1
- data/app/views/layouts/fe/application.html.erb +3 -4
- data/app/views/layouts/fe/fe_admin.html.erb +30 -0
- data/app/views.current/fe/admin/elements/_errors.html.erb +11 -0
- data/app/views.current/fe/admin/elements/create.js.erb +12 -0
- data/app/views.current/fe/admin/elements/destroy.js.erb +4 -0
- data/app/views.current/fe/admin/elements/drop.js.erb +3 -0
- data/app/views.current/fe/admin/elements/duplicate.js.erb +3 -0
- data/app/views.current/fe/admin/elements/edit.js.erb +4 -0
- data/app/views.current/fe/admin/elements/error.js.erb +4 -0
- data/app/views.current/fe/admin/elements/new.js.erb +17 -0
- data/app/views.current/fe/admin/elements/update.js.erb +9 -0
- data/app/views.current/fe/admin/email_templates/_form.html.erb +8 -0
- data/app/views.current/fe/admin/email_templates/edit.html.erb +13 -0
- data/app/views.current/fe/admin/email_templates/index.html.erb +20 -0
- data/app/views.current/fe/admin/email_templates/new.html.erb +11 -0
- data/app/views.current/fe/admin/panels/_advanced_options.html.erb +49 -0
- data/app/views.current/fe/admin/panels/_common_boolean_fields.html.erb +1 -0
- data/app/views.current/fe/admin/panels/_common_boolean_fields_default.html.erb +11 -0
- data/app/views.current/fe/admin/panels/_common_fields.html.erb +23 -0
- data/app/views.current/fe/admin/panels/_condition.html.erb +6 -0
- data/app/views.current/fe/admin/panels/_insert.html.erb +39 -0
- data/app/views.current/fe/admin/panels/_nav_controls.html.erb +6 -0
- data/app/views.current/fe/admin/panels/_page.html.erb +3 -0
- data/app/views.current/fe/admin/panels/_pages_list.html.erb +16 -0
- data/app/views.current/fe/admin/panels/_prop_attachment_field.html.erb +2 -0
- data/app/views.current/fe/admin/panels/_prop_choice_field.html.erb +74 -0
- data/app/views.current/fe/admin/panels/_prop_date_field.html.erb +7 -0
- data/app/views.current/fe/admin/panels/_prop_element.html.erb +23 -0
- data/app/views.current/fe/admin/panels/_prop_page.html.erb +26 -0
- data/app/views.current/fe/admin/panels/_prop_paragraph.html.erb +46 -0
- data/app/views.current/fe/admin/panels/_prop_question_grid.html.erb +28 -0
- data/app/views.current/fe/admin/panels/_prop_question_grid_with_total.html.erb +14 -0
- data/app/views.current/fe/admin/panels/_prop_reference_question.html.erb +12 -0
- data/app/views.current/fe/admin/panels/_prop_section.html.erb +8 -0
- data/app/views.current/fe/admin/panels/_prop_sheet.html.erb +20 -0
- data/app/views.current/fe/admin/panels/_prop_text_field.html.erb +20 -0
- data/app/views.current/fe/admin/question_pages/_element.html.erb +28 -0
- data/app/views.current/fe/admin/question_pages/_element_show.html.erb +10 -0
- data/app/views.current/fe/admin/question_pages/_errors.html.erb +10 -0
- data/app/views.current/fe/admin/question_pages/_question_page.html.erb +13 -0
- data/app/views.current/fe/admin/question_pages/create.js.erb +11 -0
- data/app/views.current/fe/admin/question_pages/destroy.js.erb +5 -0
- data/app/views.current/fe/admin/question_pages/edit.js.erb +3 -0
- data/app/views.current/fe/admin/question_pages/error.js.erb +4 -0
- data/app/views.current/fe/admin/question_pages/show.js.erb +9 -0
- data/app/views.current/fe/admin/question_pages/show_panel.js.erb +3 -0
- data/app/views.current/fe/admin/question_pages/update.js.erb +2 -0
- data/app/views.current/fe/admin/question_sheets/_errors.html.erb +11 -0
- data/app/views.current/fe/admin/question_sheets/edit.js.erb +3 -0
- data/app/views.current/fe/admin/question_sheets/error.js.erb +5 -0
- data/app/views.current/fe/admin/question_sheets/index.html.erb +41 -0
- data/app/views.current/fe/admin/question_sheets/new.html.erb +15 -0
- data/app/views.current/fe/admin/question_sheets/show.html.erb +27 -0
- data/app/views.current/fe/admin/question_sheets/update.js.erb +2 -0
- data/app/views.current/fe/answer_pages/_answer_page.html.erb +53 -0
- data/app/views.current/fe/answer_pages/_element.html.erb +32 -0
- data/app/views.current/fe/answer_pages/_page_name.html.erb +1 -0
- data/app/views.current/fe/answer_pages/show.html.erb +39 -0
- data/app/views.current/fe/answer_pages/update.js.erb +13 -0
- data/app/views.current/fe/answer_sheets/_answer_sheet.html.erb +26 -0
- data/app/views.current/fe/answer_sheets/_element.html.erb +74 -0
- data/app/views.current/fe/answer_sheets/_incomplete.html.erb +10 -0
- data/app/views.current/fe/answer_sheets/_page_link.html.erb +9 -0
- data/app/views.current/fe/answer_sheets/_pages_list.html.erb +11 -0
- data/app/views.current/fe/answer_sheets/_submit_to.html.erb +1 -0
- data/app/views.current/fe/answer_sheets/_title.html.erb +1 -0
- data/app/views.current/fe/answer_sheets/edit.html.erb +66 -0
- data/app/views.current/fe/answer_sheets/incomplete.js.erb +11 -0
- data/app/views.current/fe/answer_sheets/index.html.erb +18 -0
- data/app/views.current/fe/answer_sheets/send_reference_invite.js.erb +8 -0
- data/app/views.current/fe/answer_sheets/show.html.erb +13 -0
- data/app/views.current/fe/applications/_logout.html.erb +1 -0
- data/app/views.current/fe/applications/show.html.erb +1 -0
- data/app/views.current/fe/help/builder.html +33 -0
- data/app/views.current/fe/help/question_grid.html +18 -0
- data/app/views.current/fe/questions/fe/_acceptance.html.erb +14 -0
- data/app/views.current/fe/questions/fe/_attachment_field.html.erb +165 -0
- data/app/views.current/fe/questions/fe/_checkbox_field.html.erb +53 -0
- data/app/views.current/fe/questions/fe/_country.html.erb +7 -0
- data/app/views.current/fe/questions/fe/_date_field.html.erb +7 -0
- data/app/views.current/fe/questions/fe/_date_field_mmyy.html.erb +9 -0
- data/app/views.current/fe/questions/fe/_drop_down_field.html.erb +8 -0
- data/app/views.current/fe/questions/fe/_paragraph.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_question_grid.html.erb +70 -0
- data/app/views.current/fe/questions/fe/_question_grid_with_total.html.erb +64 -0
- data/app/views.current/fe/questions/fe/_questions.html.erb +15 -0
- data/app/views.current/fe/questions/fe/_radio_button_field.html.erb +60 -0
- data/app/views.current/fe/questions/fe/_rating.html.erb +64 -0
- data/app/views.current/fe/questions/fe/_reference_discipler.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_friend.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_parent.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_peer.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_question.html.erb +61 -0
- data/app/views.current/fe/questions/fe/_reference_roommate.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_spiritual.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_reference_staff.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_section.html.erb +1 -0
- data/app/views.current/fe/questions/fe/_state_chooser.html.erb +7 -0
- data/app/views.current/fe/questions/fe/_text_area_field.html.erb +17 -0
- data/app/views.current/fe/questions/fe/_text_field.html.erb +9 -0
- data/app/views.current/fe/questions/fe/_yes_no.html.erb +17 -0
- data/app/views.current/fe/questions/fe/_yes_no_field.erb +20 -0
- data/app/views.current/fe/reference_pages/_reference.html.erb +31 -0
- data/app/views.current/fe/reference_pages/edit.html.erb +24 -0
- data/app/views.current/fe/reference_sheets/done.html.erb +2 -0
- data/app/views.current/fe/reference_sheets/not_found.html.erb +5 -0
- data/app/views.current/fe/reference_sheets/submitted.js.erb +1 -0
- data/app/views.current/fe/references/edit.html.erb +8 -0
- data/app/views.current/fe/references/send_invite.js.erb +7 -0
- data/app/views.current/fe/references/show.html.erb +18 -0
- data/app/views.current/fe/references/submit.js.erb +3 -0
- data/app/views.current/fe/submit_pages/_errors.html.erb +1 -0
- data/app/views.current/fe/submit_pages/_thankyou.html.erb +2 -0
- data/app/views.current/fe/submit_pages/edit.html.erb +36 -0
- data/app/views.current/fe/submit_pages/error.js.erb +1 -0
- data/app/views.current/fe/submit_pages/submit.js.erb +3 -0
- data/app/views.current/layouts/fe/_error_messages_for.html.erb +7 -0
- data/app/views.current/layouts/fe/application.html.erb +47 -0
- data/app/{views/layouts/fe/fe.admin.html.erb → views.current/layouts/fe/fe_admin.html.erb} +4 -4
- data/config/initializers/paper_trail.rb +3 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20131003041856_core.rb +23 -23
- data/db/migrate/20131003044250_create_reference_sheets.rb +1 -1
- data/db/migrate/20131003044436_add_element_and_answer_fields.rb +3 -3
- data/db/migrate/20131003044518_create_email_templates.rb +2 -2
- data/db/migrate/20131003044621_add_max_lengths.rb +1 -1
- data/db/migrate/20131003044714_create_join_table.rb +1 -1
- data/db/migrate/20131016162128_remove_question_id_from_element.rb +1 -1
- data/db/migrate/20140623153424_create_fe_people.rb +1 -1
- data/db/migrate/20140624180246_create_fe_addresses.rb +1 -1
- data/db/migrate/20140624182216_create_fe_phone_numbers.rb +1 -1
- data/db/migrate/20140625160545_create_fe_users.rb +1 -1
- data/db/migrate/20140808202507_add_conditional_type_to_elements.rb +1 -1
- data/db/migrate/20140808203609_add_conditional_answer_to_elements.rb +1 -1
- data/db/migrate/20141103204704_remove_short_value_column.rb +1 -1
- data/db/migrate/20141109154522_move_conditional_ids_used_for_choice_field_to_their_own_column.rb +1 -1
- data/db/migrate/20150504221439_add_all_element_ids_to_pages.rb +1 -1
- data/db/migrate/20150713022326_add_locale_columns.rb +1 -1
- data/db/migrate/20150714220730_add_locale_to_answer_sheet.rb +1 -1
- data/db/migrate/20150925181652_add_share_to_elements.rb +5 -0
- data/db/migrate/20150928085325_change_pages_all_element_ids_to_text.rb +1 -1
- data/db/migrate/20150930191538_add_locale_to_reference_sheets.rb +1 -1
- data/db/migrate/20151021181928_switch_conditional_answer_separator_to_semicolon.rb +7 -0
- data/db/migrate/20151021184250_add_question_sheet_id_in_refs.rb +12 -0
- data/db/migrate/20160201185838_add_visible_and_visibility_cache_key_to_reference_sheets.rb +6 -0
- data/db/migrate/20160805221415_add_rating_extra_labels.rb +10 -0
- data/db/migrate/20181108201746_create_versions.rb +80 -0
- data/db/migrate/20181218201130_increase_slug_length.rb +5 -0
- data/lib/fe/engine.rb +10 -10
- data/lib/fe/version.rb +1 -1
- data/lib/fe.rb +7 -1
- data/spec/controllers/fe/admin/elements_controller_spec.rb +30 -20
- data/spec/controllers/fe/admin/email_templates_controller_spec.rb +2 -2
- data/spec/controllers/fe/admin/question_pages_controller_spec.rb +1 -1
- data/spec/controllers/fe/admin/question_sheets_controller_spec.rb +4 -4
- data/spec/controllers/fe/answer_pages_controller_spec.rb +86 -30
- data/spec/controllers/fe/answer_sheets_controller_spec.rb +65 -9
- data/spec/dummy/app/assets/config/manifest.js +0 -0
- data/spec/dummy/app/models/user.rb +1 -1
- data/spec/dummy/app/views/layouts/application.html.erb +2 -2
- data/spec/dummy/config/application.rb +1 -0
- data/spec/dummy/config/environments/test.rb +3 -3
- data/spec/dummy/config/initializers/assets.rb +5 -2
- data/spec/dummy/config/initializers/fast_gettext.rb +1 -1
- data/spec/dummy/config/initializers/to_unsafe_h.rb +5 -0
- data/spec/dummy/config/initializers/to_unsafe_h.rb.new +5 -0
- data/spec/dummy/db/migrate/20141203214017_core.fe_engine.rb +23 -23
- data/spec/dummy/db/migrate/20141203214018_create_reference_sheets.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214019_add_element_and_answer_fields.fe_engine.rb +3 -3
- data/spec/dummy/db/migrate/20141203214020_create_email_templates.fe_engine.rb +2 -2
- data/spec/dummy/db/migrate/20141203214021_add_max_lengths.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214022_create_join_table.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214023_remove_question_id_from_element.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214024_create_fe_people.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214025_create_fe_addresses.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214027_create_fe_users.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214028_add_conditional_type_to_elements.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214029_add_conditional_answer_to_elements.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214030_remove_short_value_column.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20141203214031_move_conditional_ids_used_for_choice_field_to_their_own_column.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150123215803_create_users.rb +1 -1
- data/spec/dummy/db/migrate/20150504222619_add_all_element_ids_to_pages.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150925192557_add_share_to_elements.fe_engine.rb +6 -0
- data/spec/dummy/db/migrate/20150930190001_create_fe_phone_numbers.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150930190002_add_locale_columns.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150930190003_add_locale_to_answer_sheet.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150930190004_change_pages_all_element_ids_to_text.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20150930191756_add_locale_to_reference_sheets.fe_engine.rb +1 -1
- data/spec/dummy/db/migrate/20151021190027_add_question_sheet_id_in_refs.fe_engine.rb +13 -0
- data/spec/dummy/db/migrate/20160204164612_switch_conditional_answer_separator_to_semicolon.fe_engine.rb +8 -0
- data/spec/dummy/db/migrate/20160204164613_add_visible_and_visibility_cache_key_to_reference_sheets.fe_engine.rb +7 -0
- data/spec/dummy/db/migrate/20181108201746_create_versions.rb +80 -0
- data/spec/dummy/db/schema.rb +71 -79
- data/spec/dummy/log/test.log +101278 -419
- data/spec/factories/answer_sheet_question_sheets.rb +1 -1
- data/spec/factories/answer_sheets.rb +2 -2
- data/spec/factories/answers.rb +1 -1
- data/spec/factories/applications.rb +3 -3
- data/spec/factories/dummy_applications.rb +3 -3
- data/spec/factories/dummy_people.rb +3 -3
- data/spec/factories/dummy_users.rb +3 -3
- data/spec/factories/elements.rb +21 -21
- data/spec/factories/email_templates.rb +3 -3
- data/spec/factories/fe_addresses.rb +10 -10
- data/spec/factories/fe_email_addresses.rb +3 -3
- data/spec/factories/fe_email_templates.rb +4 -4
- data/spec/factories/fe_people.rb +5 -5
- data/spec/factories/fe_phone_numbers.rb +3 -3
- data/spec/factories/fe_user.rb +3 -3
- data/spec/factories/page.rb +1 -1
- data/spec/factories/page_elements.rb +1 -1
- data/spec/factories/paragraphs.rb +1 -1
- data/spec/factories/question_sheet.rb +2 -2
- data/spec/factories/reference_questions.rb +1 -1
- data/spec/factories/reference_sheets.rb +1 -1
- data/spec/jobs/fe/update_reference_sheet_visibility_job_spec.rb +40 -0
- data/spec/models/fe/answer_sheet_question_sheet_spec.rb +1 -1
- data/spec/models/fe/answer_spec.rb +2 -2
- data/spec/models/fe/application_spec.rb +94 -1
- data/spec/models/fe/choice_field_spec.rb +47 -1
- data/spec/models/fe/condition_spec.rb +2 -2
- data/spec/models/fe/element_spec.rb +252 -60
- data/spec/models/fe/email_template_spec.rb +1 -1
- data/spec/models/fe/page_element_spec.rb +1 -1
- data/spec/models/fe/page_spec.rb +57 -12
- data/spec/models/fe/person_spec.rb +1 -1
- data/spec/models/fe/question_set_spec.rb +91 -0
- data/spec/models/fe/question_sheet_spec.rb +11 -15
- data/spec/models/fe/question_spec.rb +73 -6
- data/spec/models/fe/reference_question_spec.rb +20 -0
- data/spec/models/fe/reference_sheet_spec.rb +287 -4
- data/spec/models/fe/text_field_spec.rb +22 -0
- data/spec/rails_helper.rb +79 -76
- metadata +195 -57
- data/app/assets/javascripts/fe/jquery.scrollTo-min.js +0 -7
- data/app/controllers/fe/concerns/answer_pages_controller_concern.rb +0 -84
- data/app/models/fe/concerns/answer_sheet_concern.rb +0 -85
- data/spec/dummy/db/migrate/20141203214026_create_create_fe_phone_numbers.fe_engine.rb +0 -17
- data/spec/dummy/log/development.log +0 -5
- /data/app/{assets/stylesheets/360front.css → views.current/fe/admin/elements/reorder.js.erb} +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Fe
|
|
2
|
+
module AnswerSheetConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
included do
|
|
7
|
+
has_many :answer_sheet_question_sheets, foreign_key: 'answer_sheet_id', class_name: '::Fe::AnswerSheetQuestionSheet'
|
|
8
|
+
has_many :question_sheets, through: :answer_sheet_question_sheets, class_name: 'Fe::QuestionSheet'
|
|
9
|
+
has_many :answers, ->(answer_sheet) {
|
|
10
|
+
question_sheet_ids = answer_sheet.question_sheet_ids
|
|
11
|
+
|
|
12
|
+
if question_sheet_ids.any?
|
|
13
|
+
element_ids = Fe::Page.joins(:question_sheet).where(question_sheet_id: question_sheet_ids).pluck(:all_element_ids).compact
|
|
14
|
+
element_ids = element_ids.collect{ |e| e.split(',') }.flatten
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
unless question_sheet_ids.any? && element_ids.any?
|
|
18
|
+
# an answer sheet not assigned to a question sheet, or assigned to
|
|
19
|
+
# a question sheet with no elements should not return any answers
|
|
20
|
+
return where('false')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
where('question_id' => element_ids)
|
|
24
|
+
|
|
25
|
+
}, foreign_key: 'answer_sheet_id', class_name: '::Fe::Answer'
|
|
26
|
+
has_many :reference_sheets, foreign_key: 'applicant_answer_sheet_id', class_name: 'Fe::ReferenceSheet'
|
|
27
|
+
has_many :payments, foreign_key: 'application_id', class_name: 'Fe::Payment'
|
|
28
|
+
end
|
|
29
|
+
rescue ActiveSupport::Concern::MultipleIncludedBlocks
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def languages
|
|
33
|
+
return [] unless question_sheets.first
|
|
34
|
+
|
|
35
|
+
unless @languages
|
|
36
|
+
@languages = question_sheets.first.languages
|
|
37
|
+
question_sheets[1..-1].each { |qs| @languages &= qs.languages.select(&:present?) }
|
|
38
|
+
end
|
|
39
|
+
@languages
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def complete?
|
|
43
|
+
!completed_at.nil?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# answers for this sheet, grouped by question id
|
|
47
|
+
def answers_by_question
|
|
48
|
+
@answers_by_question ||= answers.group_by { |answer| answer.question_id }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Convenience method if there is only one question sheet in your system
|
|
52
|
+
def question_sheet
|
|
53
|
+
question_sheets.first
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pages
|
|
57
|
+
Page.where(question_sheet_id: question_sheets.collect(&:id)).visible.order('number')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def completely_filled_out?
|
|
61
|
+
pages.all? {|p| p.complete?(self)}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def has_answer_for?(question_id)
|
|
65
|
+
!answers_by_question[question_id].nil?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def reference?
|
|
69
|
+
false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def percent_complete(required_only = true, restrict_to_pages = [])
|
|
73
|
+
# build an element to page lookup using page's cached all_element_ids
|
|
74
|
+
# this will make the hidden? calls on element faster because we can pass the page
|
|
75
|
+
# (the page builds a list of hidden elements for quick lookup)
|
|
76
|
+
elements_to_pages = {}
|
|
77
|
+
pages = question_sheets.collect(&:pages).flatten
|
|
78
|
+
pages = pages & restrict_to_pages if restrict_to_pages.present?
|
|
79
|
+
pages.each do |p|
|
|
80
|
+
p.all_element_ids_arr.each do |e_id|
|
|
81
|
+
elements_to_pages[e_id] = p
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# determine which questions should count towards the questions total in the percent calculation
|
|
86
|
+
countable_questions = question_sheets.collect{ |qs| qs.all_elements.questions }.flatten
|
|
87
|
+
countable_questions.select!{ |e| elements_to_pages[e.id] } if restrict_to_pages.present?
|
|
88
|
+
countable_questions.reject!{ |e| e.hidden?(self, elements_to_pages[e.id]) }
|
|
89
|
+
countable_questions.select!{ |e| e.required } if required_only
|
|
90
|
+
|
|
91
|
+
# no progress if there are no questions
|
|
92
|
+
num_questions = countable_questions.length
|
|
93
|
+
return 0 if num_questions == 0
|
|
94
|
+
|
|
95
|
+
# count questions with answers in Fe::Answer
|
|
96
|
+
answers = self.answers.where("(question_id IN (?) AND value IS NOT NULL) AND (value != '')", countable_questions.collect(&:id))
|
|
97
|
+
answered_question_ids = answers.pluck(Arel.sql('distinct(question_id)'))
|
|
98
|
+
|
|
99
|
+
# need to look for answers for the remaining questions using has_response?
|
|
100
|
+
# so that questions with object_name/attribute_name set are counted
|
|
101
|
+
other_answered_questions = countable_questions.reject{ |e| answered_question_ids.include?(e.id) }
|
|
102
|
+
other_answered_questions.select!{ |e| e.has_response?(self) }
|
|
103
|
+
|
|
104
|
+
# count total
|
|
105
|
+
num_answers = answered_question_ids.count + other_answered_questions.count
|
|
106
|
+
[ [ (num_answers.to_f / num_questions.to_f * 100.0).to_i, 100 ].min, 0 ].max
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def collat_title() "" end
|
|
110
|
+
|
|
111
|
+
def question_sheet_ids
|
|
112
|
+
question_sheets.collect(&:id)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def question_sheets_all_reference_elements
|
|
116
|
+
# forms are generally not changed often so caching on the last updated elementd
|
|
117
|
+
# will provide a good balance of speed and cache invalidation
|
|
118
|
+
element_ids = Rails.cache.fetch(question_sheets + ['answer_sheet#answer_sheet_all_reference_elements', Fe::Element.order('updated_at desc, id desc').first]) do
|
|
119
|
+
question_sheets.compact.collect { |q| q.all_elements.reference_kinds.pluck(:id) }.flatten
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
Fe::Element.find(element_ids)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -13,11 +13,32 @@ module Fe
|
|
|
13
13
|
|
|
14
14
|
begin
|
|
15
15
|
included do
|
|
16
|
-
has_many :elements, :
|
|
16
|
+
has_many :elements, class_name: "Element", foreign_key: "choice_field_id", dependent: :nullify#, order: :position
|
|
17
|
+
serialize :rating_before_label_translations, Hash
|
|
18
|
+
serialize :rating_after_label_translations, Hash
|
|
19
|
+
serialize :rating_na_label_translations, Hash
|
|
17
20
|
end
|
|
18
21
|
rescue ActiveSupport::Concern::MultipleIncludedBlocks
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
def rating_before_label(locale = nil)
|
|
25
|
+
rating_before_label_translations &&
|
|
26
|
+
rating_before_label_translations[locale].present? ?
|
|
27
|
+
rating_before_label_translations[locale] : self[:rating_before_label]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rating_after_label(locale = nil)
|
|
31
|
+
rating_after_label_translations &&
|
|
32
|
+
rating_after_label_translations[locale].present? ?
|
|
33
|
+
rating_after_label_translations[locale] : self[:rating_after_label]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def rating_na_label(locale = nil)
|
|
37
|
+
rating_na_label_translations &&
|
|
38
|
+
rating_na_label_translations[locale].present? ?
|
|
39
|
+
rating_na_label_translations[locale] : self[:rating_na_label]
|
|
40
|
+
end
|
|
41
|
+
|
|
21
42
|
# Returns choices stored one per line in content field
|
|
22
43
|
def choices(locale = nil)
|
|
23
44
|
retVal = Array.new
|
|
@@ -34,7 +55,7 @@ module Fe
|
|
|
34
55
|
retVal = [ doc.elements.collect(text_xpath){|c|c.text}, doc.elements.collect(value_xpath){|c|c.text} ].transpose
|
|
35
56
|
end
|
|
36
57
|
elsif content.present?
|
|
37
|
-
choices =
|
|
58
|
+
choices = content(locale)
|
|
38
59
|
choices.split("\n").each do |opt|
|
|
39
60
|
pair = opt.strip.split(";").reverse!
|
|
40
61
|
pair[1] ||= pair[0]
|
|
@@ -44,19 +65,19 @@ module Fe
|
|
|
44
65
|
return retVal
|
|
45
66
|
end
|
|
46
67
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
when is_true(r) then is_true(choice)
|
|
54
|
-
when is_false(r) then is_false(choice)
|
|
55
|
-
else
|
|
56
|
-
r.to_s == choice.to_s
|
|
57
|
-
end
|
|
68
|
+
# choices can be an array, in which case any match returns true
|
|
69
|
+
def has_answer?(choice, answer_sheet)
|
|
70
|
+
if choice.is_a?(Array)
|
|
71
|
+
return choice.any? { |c|
|
|
72
|
+
has_answer?(c, answer_sheet)
|
|
73
|
+
}
|
|
58
74
|
end
|
|
59
|
-
|
|
75
|
+
|
|
76
|
+
responses(answer_sheet).any? { |r|
|
|
77
|
+
is_true(r) && is_true(choice) ||
|
|
78
|
+
is_false(r) && is_false(choice) ||
|
|
79
|
+
r.to_s.strip == choice.to_s.strip
|
|
80
|
+
}
|
|
60
81
|
end
|
|
61
82
|
|
|
62
83
|
# which view to render this element?
|
|
@@ -89,8 +110,8 @@ module Fe
|
|
|
89
110
|
end
|
|
90
111
|
|
|
91
112
|
# css class names for javascript-based validation
|
|
92
|
-
def validation_class(answer_sheet)
|
|
93
|
-
if self.required?(answer_sheet)
|
|
113
|
+
def validation_class(answer_sheet, page = nil)
|
|
114
|
+
if self.required?(answer_sheet, page)
|
|
94
115
|
if self.style == 'drop-down'
|
|
95
116
|
'validate-selection required'
|
|
96
117
|
elsif self.style == 'rating'
|
|
@@ -105,9 +126,8 @@ module Fe
|
|
|
105
126
|
end
|
|
106
127
|
end
|
|
107
128
|
|
|
108
|
-
def display_response(app=nil)
|
|
129
|
+
def display_response(app = nil)
|
|
109
130
|
r = responses(app)
|
|
110
|
-
r.reject! {|a| a.class == Answer && a.value.blank?}
|
|
111
131
|
if r.blank?
|
|
112
132
|
""
|
|
113
133
|
elsif self.style == 'yes-no'
|
|
@@ -120,15 +140,13 @@ module Fe
|
|
|
120
140
|
elsif self.style == 'acceptance'
|
|
121
141
|
"Accepted" # if not blank, it's accepted
|
|
122
142
|
else
|
|
123
|
-
r.compact.join(
|
|
143
|
+
r.compact.join(', ')
|
|
124
144
|
end
|
|
125
145
|
end
|
|
126
146
|
|
|
127
147
|
def conditional_match(answer_sheet)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
(is_response_false(answer_sheet) && is_false(conditional_answer)) ||
|
|
131
|
-
(displayed_response == conditional_answer)
|
|
148
|
+
has_answer?(conditional_answers, answer_sheet) ||
|
|
149
|
+
(responses(answer_sheet).empty? && conditional_answers.empty?)
|
|
132
150
|
end
|
|
133
151
|
|
|
134
152
|
def is_response_false(answer_sheet)
|
data/app/models/fe/address.rb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
class Fe::Address <
|
|
2
|
-
belongs_to :person
|
|
1
|
+
class Fe::Address < ApplicationRecord
|
|
2
|
+
belongs_to :person, optional: true
|
|
3
3
|
end
|
data/app/models/fe/answer.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Fe
|
|
2
|
-
class AnswerSheetQuestionSheet <
|
|
2
|
+
class AnswerSheetQuestionSheet < ApplicationRecord
|
|
3
3
|
self.table_name = self.table_name.sub('fe_', Fe.table_name_prefix)
|
|
4
4
|
belongs_to :answer_sheet, class_name: Fe.answer_sheet_class
|
|
5
|
-
belongs_to :question_sheet, class_name: 'Fe::QuestionSheet'
|
|
5
|
+
belongs_to :question_sheet, optional: true, class_name: 'Fe::QuestionSheet'
|
|
6
6
|
end
|
|
7
7
|
end
|
|
@@ -5,12 +5,16 @@ class Fe::Application < Fe::AnswerSheet
|
|
|
5
5
|
|
|
6
6
|
self.table_name = "#{Fe.table_name_prefix}applications"
|
|
7
7
|
|
|
8
|
-
belongs_to :applicant, foreign_key: 'person_id', class_name: "Person"
|
|
9
|
-
has_many :references, :
|
|
10
|
-
has_one :answer_sheet_question_sheet, :
|
|
11
|
-
has_many :answer_sheet_question_sheets, :
|
|
12
|
-
has_many :question_sheets, :
|
|
13
|
-
|
|
8
|
+
belongs_to :applicant, optional: true, foreign_key: 'person_id', class_name: "Person"
|
|
9
|
+
has_many :references, class_name: 'ReferenceSheet', foreign_key: :applicant_answer_sheet_id, dependent: :destroy
|
|
10
|
+
has_one :answer_sheet_question_sheet, foreign_key: "answer_sheet_id"
|
|
11
|
+
has_many :answer_sheet_question_sheets, foreign_key: 'answer_sheet_id'
|
|
12
|
+
has_many :question_sheets, through: :answer_sheet_question_sheets
|
|
13
|
+
|
|
14
|
+
has_paper_trail on: [], ignore: [:updated_at]
|
|
15
|
+
|
|
16
|
+
alias_method :all_references, :references
|
|
17
|
+
|
|
14
18
|
# This will be overridden by the state machine defined in the enclosing app
|
|
15
19
|
def completed?
|
|
16
20
|
raise "completed? should be implemented by the extending class"
|
|
@@ -35,7 +39,7 @@ class Fe::Application < Fe::AnswerSheet
|
|
|
35
39
|
end
|
|
36
40
|
return Fe::ReferenceSheet.new()
|
|
37
41
|
end
|
|
38
|
-
|
|
42
|
+
|
|
39
43
|
def answer_sheets
|
|
40
44
|
a_sheets = [self]
|
|
41
45
|
references.each do |r|
|
|
@@ -43,7 +47,7 @@ class Fe::Application < Fe::AnswerSheet
|
|
|
43
47
|
end
|
|
44
48
|
a_sheets
|
|
45
49
|
end
|
|
46
|
-
|
|
50
|
+
|
|
47
51
|
def reference_answer_sheets
|
|
48
52
|
r_sheets = Array.new()
|
|
49
53
|
references.each do |r|
|
|
@@ -51,9 +55,9 @@ class Fe::Application < Fe::AnswerSheet
|
|
|
51
55
|
end
|
|
52
56
|
r_sheets
|
|
53
57
|
end
|
|
54
|
-
|
|
58
|
+
|
|
55
59
|
def has_references?
|
|
56
60
|
self.references.size > 0
|
|
57
61
|
end
|
|
58
|
-
|
|
62
|
+
|
|
59
63
|
end
|
data/app/models/fe/condition.rb
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
# i.e. "answer == 'yes'"
|
|
4
4
|
# a question can have more than one answer (choose many) in which case ANY answer will do (find)
|
|
5
5
|
module Fe
|
|
6
|
-
class Condition <
|
|
6
|
+
class Condition < ApplicationRecord
|
|
7
7
|
self.table_name = self.table_name.sub('fe_', Fe.table_name_prefix)
|
|
8
8
|
|
|
9
9
|
belongs_to :question_sheet
|
|
10
10
|
|
|
11
11
|
belongs_to :trigger,
|
|
12
|
-
:
|
|
13
|
-
:
|
|
12
|
+
class_name: "Question",
|
|
13
|
+
foreign_key: "trigger_id"
|
|
14
14
|
|
|
15
15
|
validates_presence_of :expression
|
|
16
|
-
validates_length_of :expression, :
|
|
16
|
+
validates_length_of :expression, maximum: 255, allow_nil: true
|
|
17
17
|
|
|
18
18
|
# evaluate triggering element against expression and return match|nil
|
|
19
19
|
def evaluate?
|
data/app/models/fe/date_field.rb
CHANGED
data/app/models/fe/element.rb
CHANGED
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
# Element represents a section, question or content element on the question sheet
|
|
2
2
|
module Fe
|
|
3
|
-
class Element <
|
|
3
|
+
class Element < 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_grid,
|
|
7
|
-
class_name: "Fe::QuestionGrid"
|
|
9
|
+
optional: true, class_name: "Fe::QuestionGrid"
|
|
8
10
|
|
|
9
11
|
belongs_to :question_grid_with_total,
|
|
10
|
-
class_name: "Fe::QuestionGridWithTotal",
|
|
12
|
+
optional: true, class_name: "Fe::QuestionGridWithTotal",
|
|
11
13
|
foreign_key: "question_grid_id"
|
|
12
14
|
|
|
13
15
|
belongs_to :choice_field,
|
|
14
|
-
class_name: "Fe::ChoiceField"
|
|
16
|
+
optional: true, class_name: "Fe::ChoiceField"
|
|
15
17
|
|
|
16
18
|
has_many :choice_field_children, foreign_key: 'choice_field_id',
|
|
17
19
|
class_name: 'Fe::Element'
|
|
18
20
|
|
|
19
|
-
belongs_to :question_sheet, :foreign_key
|
|
21
|
+
belongs_to :question_sheet, optional: true, foreign_key: "related_question_sheet_id"
|
|
20
22
|
|
|
21
|
-
belongs_to :conditional, polymorphic: true
|
|
23
|
+
belongs_to :conditional, optional: true, polymorphic: true
|
|
22
24
|
|
|
23
25
|
self.inheritance_column = :kind
|
|
24
26
|
|
|
25
27
|
has_many :page_elements, dependent: :destroy
|
|
26
28
|
has_many :pages, through: :page_elements
|
|
27
29
|
|
|
28
|
-
scope :active, -> { select("distinct(#{Fe::Element.table_name}.id), #{Fe::Element.table_name}.*").where(Fe::QuestionSheet.table_name + '.archived' => false).joins({:
|
|
30
|
+
scope :active, -> { select("distinct(#{Fe::Element.table_name}.id), #{Fe::Element.table_name}.*").where(Fe::QuestionSheet.table_name + '.archived' => false).joins({pages: :question_sheet}) }
|
|
29
31
|
scope :questions, -> { where("kind NOT IN('Fe::Paragraph', 'Fe::Section', 'Fe::QuestionGrid', 'Fe::QuestionGridWithTotal')") }
|
|
32
|
+
scope :shared, -> { where(share: true) }
|
|
33
|
+
scope :grid_kinds, -> { where(kind: ['Fe::QuestionGrid', 'Fe::QuestionGridWithTotal']) }
|
|
34
|
+
scope :reference_kinds, -> { where(kind: 'Fe::ReferenceQuestion') }
|
|
30
35
|
|
|
31
36
|
validates_presence_of :kind
|
|
32
37
|
validates_presence_of :style
|
|
33
|
-
# validates_presence_of :label, :style, :
|
|
38
|
+
# validates_presence_of :label, :style, on: :update
|
|
34
39
|
|
|
35
|
-
validates_length_of :kind, :
|
|
36
|
-
validates_length_of :style, :
|
|
37
|
-
# validates_length_of :label, :
|
|
40
|
+
validates_length_of :kind, maximum: 40, allow_nil: true
|
|
41
|
+
validates_length_of :style, maximum: 40, allow_nil: true
|
|
42
|
+
# validates_length_of :label, maximum: 255, allow_nil: true
|
|
38
43
|
|
|
39
|
-
before_validation :set_defaults, :
|
|
44
|
+
before_validation :set_defaults, on: :create
|
|
40
45
|
before_save :set_conditional_element
|
|
41
46
|
after_save :update_page_all_element_ids
|
|
42
47
|
after_save :update_any_previous_conditional_elements
|
|
@@ -46,22 +51,22 @@ module Fe
|
|
|
46
51
|
serialize :content_translations, Hash
|
|
47
52
|
|
|
48
53
|
# HUMANIZED_ATTRIBUTES = {
|
|
49
|
-
# :
|
|
54
|
+
# slug: "Variable"
|
|
50
55
|
# }changed.include?('address1')
|
|
51
56
|
#
|
|
52
57
|
# def self.human_attrib_name(attr)
|
|
53
58
|
# HUMANIZED_ATTRIBUTES[attr.to_sym] || super
|
|
54
59
|
# end
|
|
55
60
|
def label(locale = nil)
|
|
56
|
-
label_translations[locale]
|
|
61
|
+
label_translations[locale].present? ? label_translations[locale] : self[:label]
|
|
57
62
|
end
|
|
58
63
|
|
|
59
64
|
def content(locale = nil)
|
|
60
|
-
content_translations[locale]
|
|
65
|
+
content_translations[locale].present? ? content_translations[locale] : self[:content]
|
|
61
66
|
end
|
|
62
67
|
|
|
63
68
|
def tooltip(locale = nil)
|
|
64
|
-
tip_translations[locale]
|
|
69
|
+
tip_translations[locale].present? ? tip_translations[locale] : self[:tooltip]
|
|
65
70
|
end
|
|
66
71
|
|
|
67
72
|
# returns all pages this element is on, whether that be directly, through a grid, or as a choice field conditional option
|
|
@@ -89,12 +94,10 @@ module Fe
|
|
|
89
94
|
end
|
|
90
95
|
|
|
91
96
|
# assume each element is on a question sheet only once to make things simpler. if not, just take the first one
|
|
97
|
+
# NOTE: getting the previous_element isn't an expensive operation any more because of the all_elements_id cache
|
|
92
98
|
def previous_element(question_sheet, page = nil)
|
|
93
|
-
unless
|
|
94
|
-
|
|
95
|
-
return unless page_element
|
|
96
|
-
page = page_element.page
|
|
97
|
-
end
|
|
99
|
+
return false unless question_sheet
|
|
100
|
+
page ||= pages_on.detect{ |p| p.question_sheet == question_sheet }
|
|
98
101
|
|
|
99
102
|
index = page.all_element_ids_arr.index(self.id)
|
|
100
103
|
unless index
|
|
@@ -105,13 +108,46 @@ module Fe
|
|
|
105
108
|
index = page.all_element_ids_arr.index(self.id)
|
|
106
109
|
end
|
|
107
110
|
if index && index > 0 && prev_el_id = page.all_element_ids_arr[index-1]
|
|
108
|
-
|
|
111
|
+
# occasionally the all_elements_ids_arr can get out of sync here, resulting in no element found
|
|
112
|
+
el = Fe::Element.find_by(id: prev_el_id)
|
|
113
|
+
unless el
|
|
114
|
+
page.rebuild_all_element_ids
|
|
115
|
+
index = page.all_element_ids_arr.index(self.id)
|
|
116
|
+
prev_el_id = page.all_element_ids_arr[index-1]
|
|
117
|
+
el = Fe::Element.find(prev_el_id) # give an error at this point if it's not found
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
return el
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# return an array of all elements whose answers or visibility might affect
|
|
125
|
+
# the visibility of this element
|
|
126
|
+
def visibility_affecting_element_ids
|
|
127
|
+
return @visibility_affecting_element_ids if @visibility_affecting_element_ids
|
|
128
|
+
|
|
129
|
+
# the form doesn't change much so caching on the last updated element will
|
|
130
|
+
# provide a good balance of speed and cache invalidation
|
|
131
|
+
Rails.cache.fetch([self, 'element#visibility_affecting_element_ids', Fe::Element.order('updated_at desc, id desc').first]) do
|
|
132
|
+
elements = []
|
|
133
|
+
|
|
134
|
+
elements << question_grid if question_grid
|
|
135
|
+
elements << choice_field if choice_field
|
|
136
|
+
elements += Fe::Element.where(conditional_type: 'Fe::Element', conditional_id: id)
|
|
137
|
+
element_ids = elements.collect(&:id) +
|
|
138
|
+
elements.collect { |e| e.visibility_affecting_element_ids }.flatten
|
|
139
|
+
element_ids.uniq
|
|
109
140
|
end
|
|
110
141
|
end
|
|
111
142
|
|
|
112
|
-
def
|
|
113
|
-
(
|
|
114
|
-
|
|
143
|
+
def visibility_affecting_questions
|
|
144
|
+
Fe::Question.where(id: visibility_affecting_element_ids)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def hidden_by_conditional?(answer_sheet, page)
|
|
148
|
+
return false unless answer_sheet.question_sheets.include?(page.question_sheet)
|
|
149
|
+
prev_el = previous_element(page.question_sheet, page)
|
|
150
|
+
prev_el.is_a?(Fe::Question) &&
|
|
115
151
|
prev_el.conditional == self &&
|
|
116
152
|
!prev_el.conditional_match(answer_sheet)
|
|
117
153
|
end
|
|
@@ -122,21 +158,21 @@ module Fe
|
|
|
122
158
|
choice_field.is_response_false(answer_sheet)
|
|
123
159
|
end
|
|
124
160
|
|
|
125
|
-
# use
|
|
126
|
-
def visible?(answer_sheet = nil, page = nil
|
|
127
|
-
!hidden?(answer_sheet, page
|
|
161
|
+
# use page if it's passed in, otherwise it will revert to the first page in answer_sheet
|
|
162
|
+
def visible?(answer_sheet = nil, page = nil)
|
|
163
|
+
!hidden?(answer_sheet, page)
|
|
128
164
|
end
|
|
129
165
|
|
|
130
|
-
# use
|
|
131
|
-
def hidden?(answer_sheet = nil, page = nil
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
166
|
+
# use page if it's passed in, otherwise it will revert to the first page in answer_sheet
|
|
167
|
+
def hidden?(answer_sheet = nil, page = nil)
|
|
168
|
+
page ||= pages_on.detect{ |p| answer_sheet.question_sheets.include?(p.question_sheet) }
|
|
169
|
+
return true if !page || page.hidden?(answer_sheet)
|
|
170
|
+
return page.all_hidden_elements(answer_sheet).include?(self)
|
|
135
171
|
end
|
|
136
172
|
|
|
137
|
-
# use
|
|
138
|
-
def required?(answer_sheet = nil, page = nil
|
|
139
|
-
if hidden?(answer_sheet, page
|
|
173
|
+
# use page if it's passed in, otherwise it will revert to the first page in answer_sheet
|
|
174
|
+
def required?(answer_sheet = nil, page = nil)
|
|
175
|
+
if answer_sheet && hidden?(answer_sheet, page)
|
|
140
176
|
return false
|
|
141
177
|
else
|
|
142
178
|
required == true
|
|
@@ -145,7 +181,7 @@ module Fe
|
|
|
145
181
|
|
|
146
182
|
def position(page = nil)
|
|
147
183
|
if page
|
|
148
|
-
page_elements.where(:
|
|
184
|
+
page_elements.where(page_id: page.id).first.try(:position)
|
|
149
185
|
else
|
|
150
186
|
self[:position]
|
|
151
187
|
end
|
|
@@ -153,7 +189,7 @@ module Fe
|
|
|
153
189
|
|
|
154
190
|
def set_position(position, page = nil)
|
|
155
191
|
if page
|
|
156
|
-
pe = page_elements.where(:
|
|
192
|
+
pe = page_elements.where(page_id: page.id).first
|
|
157
193
|
pe.update_attribute(:position, position) if pe
|
|
158
194
|
else
|
|
159
195
|
self[:position] = position
|
|
@@ -189,8 +225,8 @@ module Fe
|
|
|
189
225
|
new_element.choice_field_id = parent.id
|
|
190
226
|
end
|
|
191
227
|
new_element.position = parent.elements.maximum(:position).to_i + 1 if parent
|
|
192
|
-
new_element.save!(:
|
|
193
|
-
Fe::PageElement.create(:
|
|
228
|
+
new_element.save!(validate: false)
|
|
229
|
+
Fe::PageElement.create(element: new_element, page: page) unless parent
|
|
194
230
|
|
|
195
231
|
# duplicate children
|
|
196
232
|
if respond_to?(:elements) && elements.present?
|
|
@@ -204,7 +240,10 @@ module Fe
|
|
|
204
240
|
def all_elements
|
|
205
241
|
if respond_to?(:elements)
|
|
206
242
|
elements.reload
|
|
207
|
-
(elements + elements.collect(&:all_elements)).flatten
|
|
243
|
+
#(elements + elements.collect(&:all_elements)).flatten
|
|
244
|
+
elements.collect{ |el|
|
|
245
|
+
[el, el.all_elements]
|
|
246
|
+
}.flatten
|
|
208
247
|
else
|
|
209
248
|
[]
|
|
210
249
|
end
|
|
@@ -215,10 +254,14 @@ module Fe
|
|
|
215
254
|
(self.is_a?(Fe::Question) || self.is_a?(Fe::QuestionGrid) || self.is_a?(Fe::QuestionGridWithTotal))
|
|
216
255
|
end
|
|
217
256
|
|
|
257
|
+
def conditional_answers
|
|
258
|
+
conditional_answer.split(';').collect(&:strip)
|
|
259
|
+
end
|
|
260
|
+
|
|
218
261
|
def conditional_match(answer_sheet)
|
|
219
262
|
displayed_response = display_response(answer_sheet)
|
|
220
263
|
return false unless displayed_response && conditional_answer
|
|
221
|
-
(displayed_response
|
|
264
|
+
conditional_answers.include?(displayed_response)
|
|
222
265
|
end
|
|
223
266
|
|
|
224
267
|
def self.max_label_length
|
|
@@ -232,7 +275,7 @@ module Fe
|
|
|
232
275
|
|
|
233
276
|
if index = page.all_element_ids_arr.index(self.id)
|
|
234
277
|
self.conditional_id = page.all_element_ids_arr[index+1]
|
|
235
|
-
else
|
|
278
|
+
else
|
|
236
279
|
self.conditional_id = nil
|
|
237
280
|
end
|
|
238
281
|
end
|
|
@@ -255,13 +298,52 @@ module Fe
|
|
|
255
298
|
end
|
|
256
299
|
|
|
257
300
|
def update_page_all_element_ids
|
|
258
|
-
[question_grid, question_grid_with_total].compact.each do |field|
|
|
301
|
+
[question_grid, question_grid_with_total, choice_field].compact.each do |field|
|
|
259
302
|
field.update_page_all_element_ids
|
|
260
303
|
end
|
|
261
304
|
|
|
262
305
|
pages.reload.each do |p| p.rebuild_all_element_ids end
|
|
263
306
|
end
|
|
264
307
|
|
|
308
|
+
# matches in an AND method; if requested we can add a second filter method later
|
|
309
|
+
# to match on an OR basis
|
|
310
|
+
def matches_filter(filter)
|
|
311
|
+
filter.all? { |method| self.send(method) }
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def css_classes
|
|
315
|
+
css_class.to_s.split(' ').collect(&:strip)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def self.create_from_import(element_data, page, question_sheet)
|
|
319
|
+
element_data[:old_id] = element_data.delete('id')
|
|
320
|
+
children = element_data.delete(:children)
|
|
321
|
+
element = element_data['kind'].constantize.create!(element_data)
|
|
322
|
+
question_sheet.element_id_mappings[element.old_id] = element.id
|
|
323
|
+
children.each do |child|
|
|
324
|
+
byebug unless child.class == Hash
|
|
325
|
+
child_element = create_from_import(child, page, question_sheet)
|
|
326
|
+
if child['choice_field_id'].present?
|
|
327
|
+
child_element.choice_field_id = element.id
|
|
328
|
+
end
|
|
329
|
+
byebug if child_element.label == 'Your Name:'
|
|
330
|
+
if child['question_grid_id'].present?
|
|
331
|
+
child_element.question_grid_id = element.id
|
|
332
|
+
end
|
|
333
|
+
child_element.save!
|
|
334
|
+
end
|
|
335
|
+
element
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def export_hash
|
|
339
|
+
children = choice_field_children.collect(&:export_hash)
|
|
340
|
+
self.attributes.to_hash.merge(children: children)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def export_to_yaml
|
|
344
|
+
export_hash.to_yaml
|
|
345
|
+
end
|
|
346
|
+
|
|
265
347
|
protected
|
|
266
348
|
|
|
267
349
|
def set_defaults
|