inline_forms 8.1.21 → 8.1.42
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 +4 -4
- data/.forgejo/workflows/ci.yml +63 -0
- data/.forgejo/workflows/full-gate.yml +77 -0
- data/.gitignore +10 -5
- data/.rubocop.yml +31 -0
- data/.rubocop_todo.yml +151 -0
- data/CHANGELOG.md +305 -0
- data/CLAUDE.md +68 -0
- data/Gemfile +18 -2
- data/README.rdoc +23 -6
- data/Rakefile +53 -12
- data/app/assets/fonts/opensans-v44-latin-italic.woff2 +0 -0
- data/app/assets/fonts/opensans-v44-latin-regular.woff2 +0 -0
- data/app/assets/javascripts/inline_forms/inline_forms.js +30 -43
- data/app/assets/stylesheets/inline_forms/_foundation_icons.scss +6 -12
- data/app/assets/stylesheets/inline_forms/_theme.scss +134 -0
- data/app/assets/stylesheets/inline_forms/devise.scss +14 -13
- data/app/assets/stylesheets/inline_forms/foundation_and_overrides.scss +4 -0
- data/app/assets/stylesheets/inline_forms/inline_forms.scss +59 -68
- data/app/assets/stylesheets/inline_forms_fonts.css.erb +39 -0
- data/app/controllers/inline_forms_application_controller.rb +8 -4
- data/app/controllers/inline_forms_controller.rb +88 -14
- data/app/helpers/inline_forms_helper.rb +58 -15
- data/app/models/concerns/inline_forms/soft_deletable.rb +11 -12
- data/app/validators/curacao_id_number_validator.rb +5 -6
- data/app/validators/is_curacao_phone_validator.rb +2 -3
- data/app/validators/is_email_address_validator.rb +3 -3
- data/app/validators/must_be_a_value_validator.rb +6 -6
- data/app/views/inline_forms/_new.html.erb +4 -1
- data/app/views/inline_forms/_pending_migration_row.html.erb +15 -0
- data/app/views/inline_forms/_show.html.erb +5 -2
- data/app/views/inline_forms/field_pending.html.erb +10 -0
- data/app/views/layouts/application.html.erb +6 -3
- data/app/views/layouts/devise.html.erb +1 -0
- data/app/views/layouts/inline_forms.html.erb +7 -4
- data/archived/README.md +2 -0
- data/archived/form_elements/dns_records/README.md +25 -0
- data/archived/form_elements/question_list/README.md +25 -0
- data/inline_forms.gemspec +8 -7
- data/lib/generators/inline_forms_addto/USAGE +31 -0
- data/lib/generators/inline_forms_addto_generator.rb +198 -26
- data/lib/generators/inline_forms_attribute_overrides.rb +3 -2
- data/lib/generators/templates/application_record.rb +1 -1
- data/lib/inline_forms/archived_form_elements.rb +23 -10
- data/lib/inline_forms/attribute_list.rb +191 -0
- data/lib/inline_forms/form_element_from_callee.rb +1 -0
- data/lib/inline_forms/form_element_registry.rb +32 -32
- data/lib/inline_forms/form_elements/color_field_helper.rb +44 -0
- data/lib/inline_forms/form_elements/date_helper.rb +4 -1
- data/lib/inline_forms/form_elements/dropdown_with_other_helper.rb +25 -113
- data/lib/inline_forms/form_elements/month_year_picker_helper.rb +13 -2
- data/lib/inline_forms/form_elements/multi_image_field_helper.rb +18 -6
- data/lib/inline_forms/form_elements/slider_with_values_helper.rb +31 -64
- data/lib/inline_forms/form_elements/time_helper.rb +3 -1
- data/lib/inline_forms/gem_files.rb +27 -0
- data/lib/inline_forms/schema_apply.rb +85 -0
- data/lib/inline_forms/schema_intent.rb +76 -0
- data/lib/inline_forms/schema_label.rb +65 -0
- data/lib/inline_forms/schema_preview.rb +135 -0
- data/lib/inline_forms/tabs.rb +175 -0
- data/lib/inline_forms/turbo_tabs_builder.rb +20 -13
- data/lib/inline_forms/version.rb +2 -1
- data/lib/inline_forms.rb +145 -45
- data/lib/locales/inline_forms.en.yml +2 -0
- data/lib/locales/inline_forms.nl.yml +2 -0
- data/test/archived_form_elements_test.rb +34 -4
- data/test/attribute_list_test.rb +165 -0
- data/test/dummy/app/controllers/application_controller.rb +24 -0
- data/test/dummy/app/controllers/gizmos_controller.rb +4 -0
- data/test/dummy/app/controllers/machines_controller.rb +4 -0
- data/test/dummy/app/controllers/parts_controller.rb +4 -0
- data/test/dummy/app/controllers/widgets_controller.rb +4 -0
- data/test/dummy/app/helpers/application_helper.rb +13 -0
- data/test/dummy/app/models/application_record.rb +26 -0
- data/test/dummy/app/models/gizmo.rb +25 -0
- data/test/dummy/app/models/kind.rb +8 -0
- data/test/dummy/app/models/machine.rb +23 -0
- data/test/dummy/app/models/part.rb +16 -0
- data/test/dummy/app/models/widget.rb +39 -0
- data/test/dummy/app/views/_inline_forms_tabs.html.erb +40 -0
- data/test/dummy/config/application.rb +37 -0
- data/test/dummy/config/database.yml +3 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/initializers/inline_forms.rb +6 -0
- data/test/dummy/config/initializers/paper_trail_yaml_safe_load.rb +28 -0
- data/test/dummy/config/routes.rb +31 -0
- data/test/inline_forms_addto_generator_test.rb +220 -0
- data/test/integration/inline_forms_crud_test.rb +141 -0
- data/test/integration/legacy_elements_test.rb +42 -0
- data/test/integration/native_inputs_test.rb +138 -0
- data/test/integration/open_after_create_test.rb +85 -0
- data/test/integration/pending_migration_gate_test.rb +75 -0
- data/test/integration/schema_batch_pipeline_test.rb +189 -0
- data/test/integration/schema_edit_test.rb +141 -0
- data/test/integration/schema_preview_test.rb +65 -0
- data/test/integration_test_helper.rb +121 -0
- data/test/plain_text_configuration_test.rb +3 -3
- data/test/schema_apply_test.rb +73 -0
- data/test/schema_intent_test.rb +53 -0
- data/test/schema_label_test.rb +61 -0
- data/test/tabs_test.rb +98 -0
- data/test/user_model_config_test.rb +1 -0
- data/vendor/assets/javascripts/trix.min.js +7 -0
- data/vendor/assets/stylesheets/trix.css +470 -0
- metadata +91 -320
- data/app/assets/images/jquery-ui/animated-overlay.gif +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_20_6e4f1c_10x10.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_40_000000_10x10.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-medium_20_d34d17_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_25_c5ddfc_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_40_db4865_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_262626_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_93c3cd_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_ff3853_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-small_75_ccd232_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_0b3e6f_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_e69700_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_22_1484e6_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_26_2293f7_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_8_333333_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_90_eeeeee_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_95_ffdc2e_40x40.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_10_4f4221_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_20_372806_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_25_675423_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_25_d5ac5d_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_8_261803_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_diamond_8_443113_10x8.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-medium_30_0b58a2_4x4.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-medium_80_ffff38_4x4.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-small_20_333333_2x2.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-small_30_a32d00_2x2.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-small_35_35414f_2x2.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-small_40_00498f_2x2.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_eceadf_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_f8f7f6_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_eceadf_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_f7f3de_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_ffffff_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_65_654b24_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_fine-grain_68_b83400_60x60.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_303030_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_333333_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_4c4c4c_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_e69700_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_e6b900_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_0_eeeeee_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_15_cd0a0a_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_30_cccccc_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_40_292929_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_994d53_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_999999_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_c0402a_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_eeeeee_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_fafafa_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_55_ffffff_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_65_ffffff_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_75_aaaaaa_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_75_ba9217_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_75_ddd4b0_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_100_e4f1fb_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_100_f5f0e5_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_100_f8f8f8_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_15_5f391b_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_20_555555_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_25_cb842e_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_35_dddddd_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_40_0078a3_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_40_0a0a0a_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_40_111111_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_40_ffc73d_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_45_0078ae_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_50_3baae3_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_1c1c1c_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_f1fbe5_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_f8da4e_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_60_000000_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_60_eeeeee_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_70_ede4d4_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_75_79c9ec_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_80_d7ebf9_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_100_ece8da_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_16_121212_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_111111_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_1c160d_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_453326_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_3d3644_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_44372c_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_817865_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_e14f1c_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_50_6eac2c_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_000000_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_60_fece2f_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_70_ffdd57_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_75_2191c0_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_85_9fda58_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_90_fff9e5_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_gloss-wave_95_f6ecd5_500x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f2f5f7_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f4f0ec_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f5f3e5_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_fafaf4_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_459e00_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_888888_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_20_0972a5_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_30_285c00_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_55_555555_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_65_fee4bd_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_70_000000_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_75_f5f5b5_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-hard_95_cccccc_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_dcd9de_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_deedf7_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eae6ea_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f9f9f9_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_feeebd_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_201913_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_619226_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_30273a_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_67b021_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_ffef8f_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_003147_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_3a8104_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_222222_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_adadad_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_44_444444_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_45_5f5964_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_4eb305_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_4ca20b_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_dddddd_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_eeeeee_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_45_cd0a0a_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_55_ffeb80_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-hard_75_999999_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_100_f4f0ec_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_201913_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_285c00_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_121212_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_2b2922_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_25_000000_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_ffffff_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_inset-soft_50_c9c9c9_1x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_loop_25_000000_21x21.png +0 -0
- data/app/assets/images/jquery-ui/ui-bg_white-lines_85_f7f7ba_40x100.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_000000_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_004276_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_00498f_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_0073ea_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_0078ae_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_056b93_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_070603_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_0a82eb_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_0b54d5_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_1f1f1f_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_2694e8_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_3383bb_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_3572ac_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_3d3d3d_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_3d80b3_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_454545_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_4b8e0b_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_4ca300_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_4eb305_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_5fa5e3_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_666666_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_70b2e1_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_72a7cf_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_72b42d_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_734d99_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_808080_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_847e71_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_888888_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_88a206_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_8DC262_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_8c291d_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_8d78a5_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_98d2fb_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_999999_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_9bcc60_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_9ccdfc_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_9fda58_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_a83300_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_a8a3ae_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_aaaaaa_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_add978_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_b83400_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_b8ec79_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_bbbbbb_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_bd7b00_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_c02669_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_c47a23_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_c98000_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_cb672b_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_cc0000_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_cccccc_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_d19405_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_e0fdff_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_e1e463_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_e3ddc9_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_e8e2b5_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_e9cd86_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_eb990f_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ebccce_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ed9f26_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ededed_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_eeeeee_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_efec9f_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f08000_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f1fd86_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f29a00_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f2ec64_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f35f07_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f5e175_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f7a50d_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_f9f2bd_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_fadc7a_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_fbc856_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_fbdb93_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_fcd113_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_fcdd4a_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ff0084_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ff7519_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ffcf29_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ffe180_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ffeb33_256x240.png +0 -0
- data/app/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
- data/app/assets/stylesheets/jquery_ui/jquery.ui.accordion.css.scss +0 -39
- data/app/assets/stylesheets/jquery_ui/jquery.ui.all.css.scss +0 -14
- data/app/assets/stylesheets/jquery_ui/jquery.ui.autocomplete.css.scss +0 -17
- data/app/assets/stylesheets/jquery_ui/jquery.ui.base.css.scss +0 -27
- data/app/assets/stylesheets/jquery_ui/jquery.ui.button.css.scss +0 -115
- data/app/assets/stylesheets/jquery_ui/jquery.ui.core.css.scss +0 -92
- data/app/assets/stylesheets/jquery_ui/jquery.ui.datepicker.css.scss +0 -179
- data/app/assets/stylesheets/jquery_ui/jquery.ui.dialog.css.scss +0 -70
- data/app/assets/stylesheets/jquery_ui/jquery.ui.menu.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/jquery.ui.progressbar.css.scss +0 -29
- data/app/assets/stylesheets/jquery_ui/jquery.ui.resizable.css.scss +0 -79
- data/app/assets/stylesheets/jquery_ui/jquery.ui.selectable.css.scss +0 -16
- data/app/assets/stylesheets/jquery_ui/jquery.ui.slider.css.scss +0 -74
- data/app/assets/stylesheets/jquery_ui/jquery.ui.spinner.css.scss +0 -66
- data/app/assets/stylesheets/jquery_ui/jquery.ui.tabs.css.scss +0 -53
- data/app/assets/stylesheets/jquery_ui/jquery.ui.theme.css.scss +0 -408
- data/app/assets/stylesheets/jquery_ui/jquery.ui.tooltip.css.scss +0 -20
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.base.css.scss +0 -78
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.black-tie.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.blitzer.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.cupertino.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dark-hive.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dot-luv.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.eggplant.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.excite-bike.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.flick.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.hot-sneaks.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.humanity.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.le-frog.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.mint-choc.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.overcast.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.pepper-grinder.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.redmond.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.smoothness.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.south-street.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.start.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.sunny.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.swanky-purse.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.trontastic.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-darkness.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-lightness.css.scss +0 -80
- data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.vader.css.scss +0 -80
- /data/{lib → archived/form_elements/dns_records/lib}/inline_forms/form_elements/dns_records_helper.rb +0 -0
- /data/{lib → archived/form_elements/question_list/lib}/inline_forms/form_elements/question_list_helper.rb +0 -0
|
@@ -5,35 +5,34 @@ module InlineForms
|
|
|
5
5
|
module_eval(<<~'INLINE_FORMS_FORM_ELEMENT', __FILE__, __LINE__ + 1)
|
|
6
6
|
# -*- encoding : utf-8 -*-
|
|
7
7
|
|
|
8
|
-
# slider_with_values
|
|
8
|
+
# slider_with_values -- native <input type="range"> since 8.1.26 (replaces
|
|
9
|
+
# the jQuery UI slider and its inline <script>). The label text next to the
|
|
10
|
+
# slider is kept in sync by initInlineFormsWidgets (class hook
|
|
11
|
+
# `slider_with_values`, labels in data-slider-values, target <output> id in
|
|
12
|
+
# data-slider-output); helpers emit no per-field scripts.
|
|
9
13
|
def slider_with_values_show(object, attribute)
|
|
10
14
|
values = attribute_values(object, attribute)
|
|
11
15
|
value = object.send(attribute).to_i # should be an int
|
|
12
|
-
|
|
16
|
+
# values should be [ [ 0, value ], [ 3, value2 ] .... ] and we lookup the
|
|
17
|
+
# key, not the place in the array! A value with no entry (e.g. 0 when the
|
|
18
|
+
# values hash starts at 1) falls back to the bare number instead of
|
|
19
|
+
# crashing (pre-8.1.26 code did values.assoc(value)[1] unguarded).
|
|
20
|
+
display_value = (pair = values.assoc(value)) ? pair[1] : value.to_s
|
|
13
21
|
css_id = "#{object.class.to_s.underscore}_#{object.id}_#{attribute}"
|
|
14
22
|
if value == 0
|
|
15
23
|
out = "?" # we use this as the 'unknown' value. So in the data, 0 should always be the unknown value. This gives problems with sliders where the real value is 0.
|
|
16
24
|
else
|
|
25
|
+
# <progress> (not a disabled <input type=range>): the show panel is
|
|
26
|
+
# wrapped in the inline-edit link, and a disabled input would swallow
|
|
27
|
+
# the click; progress is non-interactive so the click-to-edit works.
|
|
17
28
|
out = "".html_safe
|
|
18
|
-
out <<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
$( "#slider_' + css_id + '" ).slider(
|
|
26
|
-
{
|
|
27
|
-
value:' + value.to_s + ',
|
|
28
|
-
range: "min",
|
|
29
|
-
disabled: true,
|
|
30
|
-
min: 0,
|
|
31
|
-
max: ' + values.length.to_s + ',
|
|
32
|
-
step: 1,
|
|
33
|
-
}
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
</script>').html_safe
|
|
29
|
+
out << content_tag(:progress, nil,
|
|
30
|
+
value: value,
|
|
31
|
+
max: values.collect(&:first).max.to_i,
|
|
32
|
+
class: "slider slider_#{attribute}",
|
|
33
|
+
id: "slider_#{css_id}")
|
|
34
|
+
out << content_tag(:div, display_value, class: 'slider_value', id: "value_#{css_id}")
|
|
35
|
+
out << "<div style='clear: both'></div>".html_safe
|
|
37
36
|
end
|
|
38
37
|
link_to_inline_edit object, attribute, out, from_callee: __callee__
|
|
39
38
|
end
|
|
@@ -43,56 +42,24 @@ module InlineForms
|
|
|
43
42
|
values = attribute_values(object, attribute)
|
|
44
43
|
value = object.send(attribute).to_i # should be an int, will be 0 if nil
|
|
45
44
|
css_id = "#{object.class.to_s.underscore}_#{object.id}_#{attribute}"
|
|
46
|
-
display_value = values.assoc(value)[1]
|
|
45
|
+
display_value = (pair = values.assoc(value)) ? pair[1] : value.to_s
|
|
46
|
+
labels = values.collect { |x| x[1] }
|
|
47
47
|
out = "".html_safe
|
|
48
|
-
out << "
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
value:' + value.to_s + ',
|
|
58
|
-
range: "min",
|
|
59
|
-
min: 0,
|
|
60
|
-
max: 5,
|
|
61
|
-
step: 1,
|
|
62
|
-
slide: function( event, ui ) {
|
|
63
|
-
$( "#input_' + css_id + '" ).val( ui.value );
|
|
64
|
-
$( "#value_' + css_id + '" ).html( displayvalues[ui.value] );
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
);').html_safe
|
|
68
|
-
out << ('$( "#value_' + css_id + '" ).html(displayvalues[' + value.to_s + ']);').html_safe
|
|
69
|
-
out << ('$( "#input_' + css_id + '" ).val(' + value.to_s + ');').html_safe
|
|
70
|
-
out << ('});
|
|
71
|
-
</script>').html_safe
|
|
48
|
+
out << range_field_tag("_#{object.class.to_s.underscore}[#{attribute}]", value,
|
|
49
|
+
id: "input_#{css_id}",
|
|
50
|
+
class: "slider slider_#{attribute} slider_with_values",
|
|
51
|
+
in: 0..(values.collect(&:first).max.to_i),
|
|
52
|
+
step: 1,
|
|
53
|
+
data: { slider_values: labels.to_json,
|
|
54
|
+
slider_output: "value_#{css_id}" })
|
|
55
|
+
out << content_tag(:output, display_value, class: 'slider_value', id: "value_#{css_id}")
|
|
56
|
+
out << "<div style='clear: both'></div>".html_safe
|
|
72
57
|
out
|
|
73
58
|
end
|
|
74
59
|
|
|
75
60
|
def slider_with_values_update(object, attribute)
|
|
76
61
|
object[attribute.to_sym] = params[('_' + object.class.to_s.underscore).to_sym][attribute.to_sym]
|
|
77
62
|
end
|
|
78
|
-
|
|
79
|
-
#<style>
|
|
80
|
-
# #demo-frame > div.demo { padding: 10px !important; };
|
|
81
|
-
# </style>
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#<div class="demo">
|
|
86
|
-
#
|
|
87
|
-
#<p>
|
|
88
|
-
# <label for="amount">Donation amount ($50 increments):</label>
|
|
89
|
-
# <input type="text" id="amount" style="border:0; color:#f6931f; font-weight:bold;" />
|
|
90
|
-
#</p>
|
|
91
|
-
#
|
|
92
|
-
#<div id="slider"></div>
|
|
93
|
-
#
|
|
94
|
-
#</div><!-- End demo -->
|
|
95
|
-
#
|
|
96
63
|
INLINE_FORMS_FORM_ELEMENT
|
|
97
64
|
end
|
|
98
65
|
end
|
|
@@ -10,9 +10,11 @@ module InlineForms
|
|
|
10
10
|
link_to_inline_edit object, attribute, object.send(attribute).nil? ? "<i class='fi-plus'></i>".html_safe : object.send(attribute).to_datetime.strftime("%l:%M%P"), from_callee: __callee__
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# Native <input type="time"> (8.1.25; replaces the jQuery timepicker).
|
|
14
|
+
# Submits 24h "HH:MM", which Active Record casts directly to a time column.
|
|
13
15
|
def time_select_edit(object, attribute)
|
|
14
16
|
css_id = 'timepicker_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + attribute.to_s
|
|
15
|
-
|
|
17
|
+
time_field_tag attribute, ( object.send(attribute).nil? ? "" : object.send(attribute).to_datetime.strftime("%H:%M") ), :id => css_id, :class => 'time_select'
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def time_select_update(object, attribute)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module InlineFormsGemFiles
|
|
3
4
|
INSTALLER_FILE_PREFIXES = %w[
|
|
4
5
|
bin/inline_forms
|
|
@@ -8,6 +9,24 @@ module InlineFormsGemFiles
|
|
|
8
9
|
inline_forms_installer.gemspec
|
|
9
10
|
].freeze
|
|
10
11
|
|
|
12
|
+
# The schema-GUI gem lives in its own subdirectory with its own gemspec
|
|
13
|
+
# (inline_forms_schema_edit/inline_forms_schema_edit.gemspec) and packages
|
|
14
|
+
# its files itself; exclude the whole subtree from BOTH gems here.
|
|
15
|
+
SCHEMA_GUI_FILE_PREFIXES = %w[
|
|
16
|
+
inline_forms_schema_edit/
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
# Scratch / local-notes dir. It holds working notes and, crucially, secrets
|
|
20
|
+
# such as stuff/forgejo-token (mode 0600, only used by CI pushes to forgejo).
|
|
21
|
+
# It must NEVER be packaged into a gem. Do not rely on git ignore for this:
|
|
22
|
+
# gem_files sweeps untracked files too, and the global excludes file that
|
|
23
|
+
# ignores stuff/ is per-machine (present here, absent on the release box), so
|
|
24
|
+
# the token leaked into `gem build` on the release machine. Exclude it hard,
|
|
25
|
+
# independent of any ignore configuration.
|
|
26
|
+
EXCLUDED_FILE_PREFIXES = %w[
|
|
27
|
+
stuff/
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
11
30
|
module_function
|
|
12
31
|
|
|
13
32
|
REPO_ROOT = File.expand_path("../..", __dir__)
|
|
@@ -31,6 +50,14 @@ module InlineFormsGemFiles
|
|
|
31
50
|
|
|
32
51
|
files.select! { |f| File.file?(File.join(REPO_ROOT, f)) }
|
|
33
52
|
|
|
53
|
+
files.reject! do |f|
|
|
54
|
+
EXCLUDED_FILE_PREFIXES.any? { |prefix| f == prefix || f.start_with?(prefix) }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
files.reject! do |f|
|
|
58
|
+
SCHEMA_GUI_FILE_PREFIXES.any? { |prefix| f == prefix || f.start_with?(prefix) }
|
|
59
|
+
end
|
|
60
|
+
|
|
34
61
|
files.reject do |f|
|
|
35
62
|
installer_file = INSTALLER_FILE_PREFIXES.any? { |prefix| f == prefix || f.start_with?(prefix) }
|
|
36
63
|
include_installer ? !installer_file : installer_file
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require "shellwords"
|
|
4
|
+
|
|
5
|
+
module InlineForms
|
|
6
|
+
# Skeleton of the "apply" step of the staging pipeline: turn an approved
|
|
7
|
+
# SchemaIntent into the ordered shell commands a developer would run by hand
|
|
8
|
+
# (generate the migration + model edit, migrate, test, commit, restart). This
|
|
9
|
+
# is the rare, expensive, deliberate step — see the staging doc.
|
|
10
|
+
#
|
|
11
|
+
# The engine does NOT execute these itself by default: which host runs them
|
|
12
|
+
# (a rake task on a single-server box, or a CI job after a PR on a clustered
|
|
13
|
+
# deploy) is an app decision. #commands returns the plan for inspection;
|
|
14
|
+
# #run! executes it via an injectable runner (defaults to Kernel#system) and
|
|
15
|
+
# stops at the first failure, so an app/rake task can opt in.
|
|
16
|
+
class SchemaApply
|
|
17
|
+
STEPS = %i[generate migrate].freeze
|
|
18
|
+
|
|
19
|
+
# In-process generate-only executor used by the schema GUI: runs the addto
|
|
20
|
+
# generator against the app's tree (edits the model, writes the migration
|
|
21
|
+
# file) but never migrates. Overridable so tests can record the args
|
|
22
|
+
# instead of mutating the working tree.
|
|
23
|
+
DEFAULT_GENERATE_EXECUTOR = lambda do |args, destination_root|
|
|
24
|
+
require "generators/inline_forms_addto_generator"
|
|
25
|
+
InlineFormsAddtoGenerator.start(args, destination_root: destination_root)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :intent
|
|
29
|
+
|
|
30
|
+
def initialize(intent, runner: nil)
|
|
31
|
+
@intent = intent
|
|
32
|
+
@runner = runner || ->(cmd) { system(*cmd) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Run the addto generator in-process (model edit + migration file) WITHOUT
|
|
36
|
+
# running db:migrate. Returns the path of the migration it created (or nil
|
|
37
|
+
# when the executor did not create one, e.g. a recording test executor).
|
|
38
|
+
# The caller (GUI) then tells the user to run `rails db:migrate` + restart;
|
|
39
|
+
# the pending-migration gate covers the interim.
|
|
40
|
+
def generate!(destination_root:, executor: DEFAULT_GENERATE_EXECUTOR)
|
|
41
|
+
before = addto_migrations(destination_root)
|
|
42
|
+
executor.call(intent.generator_args, destination_root)
|
|
43
|
+
# Only report a migration this run actually created. nil is correct and
|
|
44
|
+
# expected for a :header (no column -> no migration) and must NOT fall
|
|
45
|
+
# back to a pre-existing migration file.
|
|
46
|
+
(addto_migrations(destination_root) - before).max
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# `rails g inline_forms_addto <Model> <attr:fe> [--after=..]`.
|
|
50
|
+
def generator_command
|
|
51
|
+
%w[bundle exec rails g inline_forms_addto] + intent.generator_args
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def migrate_command
|
|
55
|
+
%w[bundle exec rails db:migrate]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Ordered plan (each value is an argv array).
|
|
59
|
+
def commands
|
|
60
|
+
{ generate: generator_command, migrate: migrate_command }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Human-readable plan (what an app would show before the user confirms).
|
|
64
|
+
def preview_plan
|
|
65
|
+
STEPS.map { |step| "#{step}: #{Shellwords.join(commands.fetch(step))}" }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Execute generate -> migrate, stopping at the first failure. Returns the
|
|
69
|
+
# step that failed, or nil on success. NOT run in tests (would shell out);
|
|
70
|
+
# an app/rake task calls this after approval + a git-clean check.
|
|
71
|
+
def run!
|
|
72
|
+
STEPS.each do |step|
|
|
73
|
+
ok = @runner.call(commands.fetch(step))
|
|
74
|
+
return step unless ok
|
|
75
|
+
end
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def addto_migrations(destination_root)
|
|
82
|
+
Dir.glob(File.join(destination_root.to_s, "db", "migrate", "*_inline_forms_add_to_*.rb"))
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module InlineForms
|
|
4
|
+
# A *proposed* schema change: "add attribute X of form-element Y to model Z,
|
|
5
|
+
# at this position". This is the unit the end-user-facing staging pipeline
|
|
6
|
+
# (see stuff/2026-07-11-end-user-schema-changes-staging-and-pending-gate.md)
|
|
7
|
+
# drafts, previews, and finally applies.
|
|
8
|
+
#
|
|
9
|
+
# It is a plain value object — deliberately NOT an ActiveRecord model. Where
|
|
10
|
+
# intents are persisted (a drafts table) and edited (a GUI) is an app-level
|
|
11
|
+
# concern; the engine only needs the structured description plus the mapping
|
|
12
|
+
# to the generator that realizes it. Nothing renders from an intent at
|
|
13
|
+
# runtime, so it is an audit/work-queue artifact, not config-as-data.
|
|
14
|
+
#
|
|
15
|
+
# STATUS is advisory metadata for a persisting app: draft -> approved ->
|
|
16
|
+
# applied (or failed).
|
|
17
|
+
class SchemaIntent
|
|
18
|
+
STATUSES = %i[draft approved applied failed].freeze
|
|
19
|
+
|
|
20
|
+
attr_reader :model_name, :attribute, :form_element, :values, :disabled, :after, :before
|
|
21
|
+
attr_accessor :status
|
|
22
|
+
|
|
23
|
+
def initialize(model_name:, attribute:, form_element:,
|
|
24
|
+
values: nil, disabled: nil, after: nil, before: nil, status: :draft)
|
|
25
|
+
@model_name = model_name.to_s
|
|
26
|
+
@attribute = attribute.to_sym
|
|
27
|
+
@form_element = form_element.to_sym
|
|
28
|
+
@values = values
|
|
29
|
+
@disabled = disabled
|
|
30
|
+
@after = after&.to_sym
|
|
31
|
+
@before = before&.to_sym
|
|
32
|
+
self.status = status
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def status=(value)
|
|
36
|
+
sym = value.to_sym
|
|
37
|
+
unless STATUSES.include?(sym)
|
|
38
|
+
raise ArgumentError, "unknown status #{value.inspect} (expected one of #{STATUSES.inspect})"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@status = sym
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The model class this intent targets. Raises NameError if it is not
|
|
45
|
+
# defined (an app should validate the name before drafting).
|
|
46
|
+
def model_class
|
|
47
|
+
model_name.constantize
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The `attr:form_element` token exactly as the generator expects it.
|
|
51
|
+
def column_token
|
|
52
|
+
"#{attribute}:#{form_element}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# argv for `rails g inline_forms_addto <Model> <attr:form_element> [--after=..]`.
|
|
56
|
+
def generator_args
|
|
57
|
+
args = [ model_name, column_token ]
|
|
58
|
+
args << "--after=#{after}" if after
|
|
59
|
+
args << "--before=#{before}" if before
|
|
60
|
+
args
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_h
|
|
64
|
+
{
|
|
65
|
+
model_name: model_name,
|
|
66
|
+
attribute: attribute,
|
|
67
|
+
form_element: form_element,
|
|
68
|
+
values: values,
|
|
69
|
+
disabled: disabled,
|
|
70
|
+
after: after,
|
|
71
|
+
before: before,
|
|
72
|
+
status: status
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
module InlineForms
|
|
7
|
+
# Writes a human label for a model attribute (or header) into a locale file,
|
|
8
|
+
# so `human_attribute_name` renders it. Used by the schema GUI's optional
|
|
9
|
+
# "Label" field. Like the header/field edits, this is a code/config change
|
|
10
|
+
# that lands in the working tree (git-tracked) — never the DB.
|
|
11
|
+
#
|
|
12
|
+
# The label is merged (not clobbered) into
|
|
13
|
+
# config/locales/inline_forms_labels.<locale>.yml
|
|
14
|
+
# under the key inline_forms renders from:
|
|
15
|
+
# <locale>: activerecord: attributes: <model_i18n_key>: <attribute>: "Label"
|
|
16
|
+
#
|
|
17
|
+
# A dedicated file (rather than editing an existing app locale file) keeps the
|
|
18
|
+
# write a whole-document load -> deep_merge -> dump, which is robust against
|
|
19
|
+
# comments/formatting concerns.
|
|
20
|
+
module SchemaLabel
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
def file_path(destination_root, locale)
|
|
24
|
+
File.join(destination_root.to_s, "config", "locales", "inline_forms_labels.#{locale}.yml")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def i18n_key_for(model_class)
|
|
28
|
+
if model_class.respond_to?(:model_name)
|
|
29
|
+
model_class.model_name.i18n_key.to_s
|
|
30
|
+
else
|
|
31
|
+
model_class.to_s.underscore
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Merge the label into the locale file and return its path.
|
|
36
|
+
def write(destination_root:, model_class:, attribute:, label:, locale:)
|
|
37
|
+
path = file_path(destination_root, locale)
|
|
38
|
+
key = i18n_key_for(model_class)
|
|
39
|
+
existing = load_document(path)
|
|
40
|
+
addition = {
|
|
41
|
+
locale.to_s => {
|
|
42
|
+
"activerecord" => {
|
|
43
|
+
"attributes" => {
|
|
44
|
+
key => { attribute.to_s => label.to_s }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
merged = existing.deep_merge(addition)
|
|
50
|
+
|
|
51
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
52
|
+
File.write(path, merged.to_yaml)
|
|
53
|
+
path
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def load_document(path)
|
|
57
|
+
return {} unless File.exist?(path)
|
|
58
|
+
|
|
59
|
+
loaded = YAML.safe_load(File.read(path))
|
|
60
|
+
loaded.is_a?(Hash) ? loaded : {}
|
|
61
|
+
rescue StandardError
|
|
62
|
+
{}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module InlineForms
|
|
4
|
+
# Cheap preview of a SchemaIntent, WITHOUT running a migration or booting a
|
|
5
|
+
# second app. The trick (see the staging doc): declare the proposed attribute
|
|
6
|
+
# as a *virtual* typed attribute on a throwaway subclass of the target model,
|
|
7
|
+
# so it reads/writes in memory with no column, and render the stock inline
|
|
8
|
+
# forms against an AttributeList that has the proposed row spliced in at the
|
|
9
|
+
# requested position. The real class and its table are untouched.
|
|
10
|
+
#
|
|
11
|
+
# obj, list = InlineForms::SchemaPreview.build(intent, existing_record)
|
|
12
|
+
# # render "inline_forms/show" with @object = obj,
|
|
13
|
+
# # @inline_forms_attribute_list = list (the controller already supports
|
|
14
|
+
# # this per-request override — see attr_writer :inline_forms_attribute_list)
|
|
15
|
+
#
|
|
16
|
+
# Scope of the stab: scalar attributes preview fully. Relation dropdowns
|
|
17
|
+
# (backed by a foreign key + association) and uploader/rich_text fields need
|
|
18
|
+
# model-side wiring the preview does not synthesize; #supported? reports this
|
|
19
|
+
# so a caller can fall back to a "available after apply" placeholder.
|
|
20
|
+
module SchemaPreview
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
# Map an AR column type (from the engine's form-element maps) to an
|
|
24
|
+
# ActiveModel::Type symbol for a virtual attribute.
|
|
25
|
+
COLUMN_TYPE_TO_VIRTUAL = {
|
|
26
|
+
string: :string,
|
|
27
|
+
text: :string,
|
|
28
|
+
integer: :integer,
|
|
29
|
+
decimal: :decimal,
|
|
30
|
+
float: :float,
|
|
31
|
+
boolean: :boolean,
|
|
32
|
+
date: :date,
|
|
33
|
+
time: :time,
|
|
34
|
+
datetime: :datetime,
|
|
35
|
+
timestamp: :datetime
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
# Form elements the GUI must not offer as "add a scalar field":
|
|
39
|
+
# * :header / :info are not real fields — :header is a display-only
|
|
40
|
+
# separator (adding one via addto would create a pointless string
|
|
41
|
+
# column), :info is read-only over an existing column.
|
|
42
|
+
# * uploaders need a mounted CarrierWave uploader; :money_field a
|
|
43
|
+
# monetize declaration; :devise_password_field a Devise model; :pdf_link
|
|
44
|
+
# a route — a virtual attribute alone cannot faithfully preview them.
|
|
45
|
+
PREVIEW_UNSUPPORTED_FORM_ELEMENTS = %i[
|
|
46
|
+
header
|
|
47
|
+
info
|
|
48
|
+
image_field
|
|
49
|
+
audio_field
|
|
50
|
+
file_field
|
|
51
|
+
multi_image_field
|
|
52
|
+
simple_file_field
|
|
53
|
+
pdf_link
|
|
54
|
+
money_field
|
|
55
|
+
devise_password_field
|
|
56
|
+
].freeze
|
|
57
|
+
|
|
58
|
+
# Returns [preview_object, attribute_list]. `base_record` seeds the preview
|
|
59
|
+
# object's existing attributes when given (so the rest of the form shows
|
|
60
|
+
# real data); otherwise a blank instance is used.
|
|
61
|
+
def build(intent, base_record = nil)
|
|
62
|
+
base_class = intent.model_class
|
|
63
|
+
list = attribute_list_for(base_class, intent)
|
|
64
|
+
preview = preview_class_for(base_class, intent)
|
|
65
|
+
|
|
66
|
+
object = base_record ? preview.new(base_record.attributes) : preview.new
|
|
67
|
+
object.inline_forms_attribute_list = list
|
|
68
|
+
[ object, list ]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# False when the intent's form element needs model-side wiring the preview
|
|
72
|
+
# cannot synthesize (relations, uploaders, rich_text).
|
|
73
|
+
def supported?(intent)
|
|
74
|
+
!virtual_type(intent.form_element).nil?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The sorted list of form elements the GUI offers (those that preview via a
|
|
78
|
+
# virtual attribute): scalar text/number/date/boolean/choice elements.
|
|
79
|
+
def supported_form_elements
|
|
80
|
+
candidates = InlineForms::SPECIAL_COLUMN_TYPES.keys +
|
|
81
|
+
InlineForms::DEFAULT_FORM_ELEMENTS.values
|
|
82
|
+
candidates.uniq.select { |fe| !virtual_type(fe).nil? }.sort
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The AttributeList the preview should render: the model's current list with
|
|
86
|
+
# the proposed row inserted at --after/--before (falling back to append).
|
|
87
|
+
def attribute_list_for(base_class, intent)
|
|
88
|
+
current = base_class.new.inline_forms_attribute_list
|
|
89
|
+
list = InlineForms::AttributeList.wrap(current.map(&:dup))
|
|
90
|
+
opts = { values: intent.values, disabled: intent.disabled }.compact
|
|
91
|
+
|
|
92
|
+
# Value-bearing choice elements need a values hash or their _edit/_show
|
|
93
|
+
# helper raises. Mirror the addto generator: inject a placeholder the user
|
|
94
|
+
# edits after apply (so preview and apply produce the same row).
|
|
95
|
+
if opts[:values].nil? && InlineForms::VALUE_BEARING_FORM_ELEMENTS.include?(intent.form_element)
|
|
96
|
+
opts[:values] = InlineForms::PLACEHOLDER_VALUES
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if intent.after && list.include_attribute?(intent.after)
|
|
100
|
+
list.insert_after(intent.after, intent.attribute, intent.form_element, **opts)
|
|
101
|
+
elsif intent.before && list.include_attribute?(intent.before)
|
|
102
|
+
list.insert_before(intent.before, intent.attribute, intent.form_element, **opts)
|
|
103
|
+
else
|
|
104
|
+
list.field(intent.attribute, intent.form_element, **opts)
|
|
105
|
+
end
|
|
106
|
+
list
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# A throwaway subclass with the proposed attribute declared virtual (when
|
|
110
|
+
# supported), masquerading as the base class so partials/routes resolve.
|
|
111
|
+
def preview_class_for(base_class, intent)
|
|
112
|
+
type = virtual_type(intent.form_element)
|
|
113
|
+
klass = Class.new(base_class)
|
|
114
|
+
klass.attribute(intent.attribute, type) if type
|
|
115
|
+
|
|
116
|
+
base_name = base_class.name
|
|
117
|
+
base_model_name = base_class.model_name
|
|
118
|
+
klass.define_singleton_method(:name) { base_name }
|
|
119
|
+
klass.define_singleton_method(:model_name) { base_model_name }
|
|
120
|
+
klass
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def virtual_type(form_element)
|
|
124
|
+
fe = form_element.to_sym
|
|
125
|
+
return nil if PREVIEW_UNSUPPORTED_FORM_ELEMENTS.include?(fe)
|
|
126
|
+
|
|
127
|
+
column_type =
|
|
128
|
+
InlineForms::SPECIAL_COLUMN_TYPES[fe] ||
|
|
129
|
+
(InlineForms::DEFAULT_FORM_ELEMENTS.value?(fe) ? :string : nil)
|
|
130
|
+
return nil if column_type.nil? || column_type == :no_migration || column_type == :belongs_to
|
|
131
|
+
|
|
132
|
+
COLUMN_TYPE_TO_VIRTUAL[column_type]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|