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.
Files changed (424) hide show
  1. checksums.yaml +4 -4
  2. data/.forgejo/workflows/ci.yml +63 -0
  3. data/.forgejo/workflows/full-gate.yml +77 -0
  4. data/.gitignore +10 -5
  5. data/.rubocop.yml +31 -0
  6. data/.rubocop_todo.yml +151 -0
  7. data/CHANGELOG.md +305 -0
  8. data/CLAUDE.md +68 -0
  9. data/Gemfile +18 -2
  10. data/README.rdoc +23 -6
  11. data/Rakefile +53 -12
  12. data/app/assets/fonts/opensans-v44-latin-italic.woff2 +0 -0
  13. data/app/assets/fonts/opensans-v44-latin-regular.woff2 +0 -0
  14. data/app/assets/javascripts/inline_forms/inline_forms.js +30 -43
  15. data/app/assets/stylesheets/inline_forms/_foundation_icons.scss +6 -12
  16. data/app/assets/stylesheets/inline_forms/_theme.scss +134 -0
  17. data/app/assets/stylesheets/inline_forms/devise.scss +14 -13
  18. data/app/assets/stylesheets/inline_forms/foundation_and_overrides.scss +4 -0
  19. data/app/assets/stylesheets/inline_forms/inline_forms.scss +59 -68
  20. data/app/assets/stylesheets/inline_forms_fonts.css.erb +39 -0
  21. data/app/controllers/inline_forms_application_controller.rb +8 -4
  22. data/app/controllers/inline_forms_controller.rb +88 -14
  23. data/app/helpers/inline_forms_helper.rb +58 -15
  24. data/app/models/concerns/inline_forms/soft_deletable.rb +11 -12
  25. data/app/validators/curacao_id_number_validator.rb +5 -6
  26. data/app/validators/is_curacao_phone_validator.rb +2 -3
  27. data/app/validators/is_email_address_validator.rb +3 -3
  28. data/app/validators/must_be_a_value_validator.rb +6 -6
  29. data/app/views/inline_forms/_new.html.erb +4 -1
  30. data/app/views/inline_forms/_pending_migration_row.html.erb +15 -0
  31. data/app/views/inline_forms/_show.html.erb +5 -2
  32. data/app/views/inline_forms/field_pending.html.erb +10 -0
  33. data/app/views/layouts/application.html.erb +6 -3
  34. data/app/views/layouts/devise.html.erb +1 -0
  35. data/app/views/layouts/inline_forms.html.erb +7 -4
  36. data/archived/README.md +2 -0
  37. data/archived/form_elements/dns_records/README.md +25 -0
  38. data/archived/form_elements/question_list/README.md +25 -0
  39. data/inline_forms.gemspec +8 -7
  40. data/lib/generators/inline_forms_addto/USAGE +31 -0
  41. data/lib/generators/inline_forms_addto_generator.rb +198 -26
  42. data/lib/generators/inline_forms_attribute_overrides.rb +3 -2
  43. data/lib/generators/templates/application_record.rb +1 -1
  44. data/lib/inline_forms/archived_form_elements.rb +23 -10
  45. data/lib/inline_forms/attribute_list.rb +191 -0
  46. data/lib/inline_forms/form_element_from_callee.rb +1 -0
  47. data/lib/inline_forms/form_element_registry.rb +32 -32
  48. data/lib/inline_forms/form_elements/color_field_helper.rb +44 -0
  49. data/lib/inline_forms/form_elements/date_helper.rb +4 -1
  50. data/lib/inline_forms/form_elements/dropdown_with_other_helper.rb +25 -113
  51. data/lib/inline_forms/form_elements/month_year_picker_helper.rb +13 -2
  52. data/lib/inline_forms/form_elements/multi_image_field_helper.rb +18 -6
  53. data/lib/inline_forms/form_elements/slider_with_values_helper.rb +31 -64
  54. data/lib/inline_forms/form_elements/time_helper.rb +3 -1
  55. data/lib/inline_forms/gem_files.rb +27 -0
  56. data/lib/inline_forms/schema_apply.rb +85 -0
  57. data/lib/inline_forms/schema_intent.rb +76 -0
  58. data/lib/inline_forms/schema_label.rb +65 -0
  59. data/lib/inline_forms/schema_preview.rb +135 -0
  60. data/lib/inline_forms/tabs.rb +175 -0
  61. data/lib/inline_forms/turbo_tabs_builder.rb +20 -13
  62. data/lib/inline_forms/version.rb +2 -1
  63. data/lib/inline_forms.rb +145 -45
  64. data/lib/locales/inline_forms.en.yml +2 -0
  65. data/lib/locales/inline_forms.nl.yml +2 -0
  66. data/test/archived_form_elements_test.rb +34 -4
  67. data/test/attribute_list_test.rb +165 -0
  68. data/test/dummy/app/controllers/application_controller.rb +24 -0
  69. data/test/dummy/app/controllers/gizmos_controller.rb +4 -0
  70. data/test/dummy/app/controllers/machines_controller.rb +4 -0
  71. data/test/dummy/app/controllers/parts_controller.rb +4 -0
  72. data/test/dummy/app/controllers/widgets_controller.rb +4 -0
  73. data/test/dummy/app/helpers/application_helper.rb +13 -0
  74. data/test/dummy/app/models/application_record.rb +26 -0
  75. data/test/dummy/app/models/gizmo.rb +25 -0
  76. data/test/dummy/app/models/kind.rb +8 -0
  77. data/test/dummy/app/models/machine.rb +23 -0
  78. data/test/dummy/app/models/part.rb +16 -0
  79. data/test/dummy/app/models/widget.rb +39 -0
  80. data/test/dummy/app/views/_inline_forms_tabs.html.erb +40 -0
  81. data/test/dummy/config/application.rb +37 -0
  82. data/test/dummy/config/database.yml +3 -0
  83. data/test/dummy/config/environment.rb +5 -0
  84. data/test/dummy/config/initializers/inline_forms.rb +6 -0
  85. data/test/dummy/config/initializers/paper_trail_yaml_safe_load.rb +28 -0
  86. data/test/dummy/config/routes.rb +31 -0
  87. data/test/inline_forms_addto_generator_test.rb +220 -0
  88. data/test/integration/inline_forms_crud_test.rb +141 -0
  89. data/test/integration/legacy_elements_test.rb +42 -0
  90. data/test/integration/native_inputs_test.rb +138 -0
  91. data/test/integration/open_after_create_test.rb +85 -0
  92. data/test/integration/pending_migration_gate_test.rb +75 -0
  93. data/test/integration/schema_batch_pipeline_test.rb +189 -0
  94. data/test/integration/schema_edit_test.rb +141 -0
  95. data/test/integration/schema_preview_test.rb +65 -0
  96. data/test/integration_test_helper.rb +121 -0
  97. data/test/plain_text_configuration_test.rb +3 -3
  98. data/test/schema_apply_test.rb +73 -0
  99. data/test/schema_intent_test.rb +53 -0
  100. data/test/schema_label_test.rb +61 -0
  101. data/test/tabs_test.rb +98 -0
  102. data/test/user_model_config_test.rb +1 -0
  103. data/vendor/assets/javascripts/trix.min.js +7 -0
  104. data/vendor/assets/stylesheets/trix.css +470 -0
  105. metadata +91 -320
  106. data/app/assets/images/jquery-ui/animated-overlay.gif +0 -0
  107. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_20_6e4f1c_10x10.png +0 -0
  108. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_40_000000_10x10.png +0 -0
  109. data/app/assets/images/jquery-ui/ui-bg_diagonals-medium_20_d34d17_40x40.png +0 -0
  110. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
  111. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_25_c5ddfc_40x40.png +0 -0
  112. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_40_db4865_40x40.png +0 -0
  113. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_262626_40x40.png +0 -0
  114. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_93c3cd_40x40.png +0 -0
  115. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_ff3853_40x40.png +0 -0
  116. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_75_ccd232_40x40.png +0 -0
  117. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_0b3e6f_40x40.png +0 -0
  118. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
  119. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  120. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  121. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_e69700_40x40.png +0 -0
  122. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_22_1484e6_40x40.png +0 -0
  123. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_26_2293f7_40x40.png +0 -0
  124. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
  125. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_8_333333_40x40.png +0 -0
  126. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_90_eeeeee_40x40.png +0 -0
  127. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_95_ffdc2e_40x40.png +0 -0
  128. data/app/assets/images/jquery-ui/ui-bg_diamond_10_4f4221_10x8.png +0 -0
  129. data/app/assets/images/jquery-ui/ui-bg_diamond_20_372806_10x8.png +0 -0
  130. data/app/assets/images/jquery-ui/ui-bg_diamond_25_675423_10x8.png +0 -0
  131. data/app/assets/images/jquery-ui/ui-bg_diamond_25_d5ac5d_10x8.png +0 -0
  132. data/app/assets/images/jquery-ui/ui-bg_diamond_8_261803_10x8.png +0 -0
  133. data/app/assets/images/jquery-ui/ui-bg_diamond_8_443113_10x8.png +0 -0
  134. data/app/assets/images/jquery-ui/ui-bg_dots-medium_30_0b58a2_4x4.png +0 -0
  135. data/app/assets/images/jquery-ui/ui-bg_dots-medium_80_ffff38_4x4.png +0 -0
  136. data/app/assets/images/jquery-ui/ui-bg_dots-small_20_333333_2x2.png +0 -0
  137. data/app/assets/images/jquery-ui/ui-bg_dots-small_30_a32d00_2x2.png +0 -0
  138. data/app/assets/images/jquery-ui/ui-bg_dots-small_35_35414f_2x2.png +0 -0
  139. data/app/assets/images/jquery-ui/ui-bg_dots-small_40_00498f_2x2.png +0 -0
  140. data/app/assets/images/jquery-ui/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
  141. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_eceadf_60x60.png +0 -0
  142. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_f8f7f6_60x60.png +0 -0
  143. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_eceadf_60x60.png +0 -0
  144. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_f7f3de_60x60.png +0 -0
  145. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_ffffff_60x60.png +0 -0
  146. data/app/assets/images/jquery-ui/ui-bg_fine-grain_65_654b24_60x60.png +0 -0
  147. data/app/assets/images/jquery-ui/ui-bg_fine-grain_68_b83400_60x60.png +0 -0
  148. data/app/assets/images/jquery-ui/ui-bg_flat_0_303030_40x100.png +0 -0
  149. data/app/assets/images/jquery-ui/ui-bg_flat_0_333333_40x100.png +0 -0
  150. data/app/assets/images/jquery-ui/ui-bg_flat_0_4c4c4c_40x100.png +0 -0
  151. data/app/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  152. data/app/assets/images/jquery-ui/ui-bg_flat_0_e69700_40x100.png +0 -0
  153. data/app/assets/images/jquery-ui/ui-bg_flat_0_e6b900_40x100.png +0 -0
  154. data/app/assets/images/jquery-ui/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  155. data/app/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  156. data/app/assets/images/jquery-ui/ui-bg_flat_15_cd0a0a_40x100.png +0 -0
  157. data/app/assets/images/jquery-ui/ui-bg_flat_30_cccccc_40x100.png +0 -0
  158. data/app/assets/images/jquery-ui/ui-bg_flat_40_292929_40x100.png +0 -0
  159. data/app/assets/images/jquery-ui/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  160. data/app/assets/images/jquery-ui/ui-bg_flat_55_994d53_40x100.png +0 -0
  161. data/app/assets/images/jquery-ui/ui-bg_flat_55_999999_40x100.png +0 -0
  162. data/app/assets/images/jquery-ui/ui-bg_flat_55_c0402a_40x100.png +0 -0
  163. data/app/assets/images/jquery-ui/ui-bg_flat_55_eeeeee_40x100.png +0 -0
  164. data/app/assets/images/jquery-ui/ui-bg_flat_55_fafafa_40x100.png +0 -0
  165. data/app/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  166. data/app/assets/images/jquery-ui/ui-bg_flat_55_ffffff_40x100.png +0 -0
  167. data/app/assets/images/jquery-ui/ui-bg_flat_65_ffffff_40x100.png +0 -0
  168. data/app/assets/images/jquery-ui/ui-bg_flat_75_aaaaaa_40x100.png +0 -0
  169. data/app/assets/images/jquery-ui/ui-bg_flat_75_ba9217_40x100.png +0 -0
  170. data/app/assets/images/jquery-ui/ui-bg_flat_75_ddd4b0_40x100.png +0 -0
  171. data/app/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png +0 -0
  172. data/app/assets/images/jquery-ui/ui-bg_glass_100_e4f1fb_1x400.png +0 -0
  173. data/app/assets/images/jquery-ui/ui-bg_glass_100_f5f0e5_1x400.png +0 -0
  174. data/app/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  175. data/app/assets/images/jquery-ui/ui-bg_glass_100_f8f8f8_1x400.png +0 -0
  176. data/app/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  177. data/app/assets/images/jquery-ui/ui-bg_glass_15_5f391b_1x400.png +0 -0
  178. data/app/assets/images/jquery-ui/ui-bg_glass_20_555555_1x400.png +0 -0
  179. data/app/assets/images/jquery-ui/ui-bg_glass_25_cb842e_1x400.png +0 -0
  180. data/app/assets/images/jquery-ui/ui-bg_glass_35_dddddd_1x400.png +0 -0
  181. data/app/assets/images/jquery-ui/ui-bg_glass_40_0078a3_1x400.png +0 -0
  182. data/app/assets/images/jquery-ui/ui-bg_glass_40_0a0a0a_1x400.png +0 -0
  183. data/app/assets/images/jquery-ui/ui-bg_glass_40_111111_1x400.png +0 -0
  184. data/app/assets/images/jquery-ui/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  185. data/app/assets/images/jquery-ui/ui-bg_glass_45_0078ae_1x400.png +0 -0
  186. data/app/assets/images/jquery-ui/ui-bg_glass_50_3baae3_1x400.png +0 -0
  187. data/app/assets/images/jquery-ui/ui-bg_glass_55_1c1c1c_1x400.png +0 -0
  188. data/app/assets/images/jquery-ui/ui-bg_glass_55_f1fbe5_1x400.png +0 -0
  189. data/app/assets/images/jquery-ui/ui-bg_glass_55_f8da4e_1x400.png +0 -0
  190. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
  191. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
  192. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  193. data/app/assets/images/jquery-ui/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  194. data/app/assets/images/jquery-ui/ui-bg_glass_60_000000_1x400.png +0 -0
  195. data/app/assets/images/jquery-ui/ui-bg_glass_60_eeeeee_1x400.png +0 -0
  196. data/app/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  197. data/app/assets/images/jquery-ui/ui-bg_glass_70_ede4d4_1x400.png +0 -0
  198. data/app/assets/images/jquery-ui/ui-bg_glass_75_79c9ec_1x400.png +0 -0
  199. data/app/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  200. data/app/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png +0 -0
  201. data/app/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  202. data/app/assets/images/jquery-ui/ui-bg_glass_80_d7ebf9_1x400.png +0 -0
  203. data/app/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  204. data/app/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  205. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_100_ece8da_500x100.png +0 -0
  206. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_16_121212_500x100.png +0 -0
  207. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_111111_500x100.png +0 -0
  208. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_1c160d_500x100.png +0 -0
  209. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  210. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_453326_500x100.png +0 -0
  211. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_3d3644_500x100.png +0 -0
  212. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_44372c_500x100.png +0 -0
  213. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  214. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_817865_500x100.png +0 -0
  215. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_e14f1c_500x100.png +0 -0
  216. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_50_6eac2c_500x100.png +0 -0
  217. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_000000_500x100.png +0 -0
  218. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  219. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_60_fece2f_500x100.png +0 -0
  220. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_70_ffdd57_500x100.png +0 -0
  221. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_75_2191c0_500x100.png +0 -0
  222. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_85_9fda58_500x100.png +0 -0
  223. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_90_fff9e5_500x100.png +0 -0
  224. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_95_f6ecd5_500x100.png +0 -0
  225. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
  226. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f2f5f7_1x100.png +0 -0
  227. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f4f0ec_1x100.png +0 -0
  228. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f5f3e5_1x100.png +0 -0
  229. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
  230. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
  231. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_fafaf4_1x100.png +0 -0
  232. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_459e00_1x100.png +0 -0
  233. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_888888_1x100.png +0 -0
  234. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_20_0972a5_1x100.png +0 -0
  235. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_30_285c00_1x100.png +0 -0
  236. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png +0 -0
  237. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_55_555555_1x100.png +0 -0
  238. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_65_fee4bd_1x100.png +0 -0
  239. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_70_000000_1x100.png +0 -0
  240. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_75_f5f5b5_1x100.png +0 -0
  241. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_95_cccccc_1x100.png +0 -0
  242. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_dcd9de_1x100.png +0 -0
  243. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_deedf7_1x100.png +0 -0
  244. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eae6ea_1x100.png +0 -0
  245. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  246. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  247. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f9f9f9_1x100.png +0 -0
  248. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_feeebd_1x100.png +0 -0
  249. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
  250. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_201913_1x100.png +0 -0
  251. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_619226_1x100.png +0 -0
  252. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  253. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_30273a_1x100.png +0 -0
  254. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_67b021_1x100.png +0 -0
  255. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_ffef8f_1x100.png +0 -0
  256. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_003147_1x100.png +0 -0
  257. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_3a8104_1x100.png +0 -0
  258. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_222222_1x100.png +0 -0
  259. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_adadad_1x100.png +0 -0
  260. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_44_444444_1x100.png +0 -0
  261. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_45_5f5964_1x100.png +0 -0
  262. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_4eb305_1x100.png +0 -0
  263. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png +0 -0
  264. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  265. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_4ca20b_1x100.png +0 -0
  266. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_dddddd_1x100.png +0 -0
  267. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  268. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  269. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  270. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  271. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_eeeeee_1x100.png +0 -0
  272. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  273. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  274. data/app/assets/images/jquery-ui/ui-bg_inset-hard_45_cd0a0a_1x100.png +0 -0
  275. data/app/assets/images/jquery-ui/ui-bg_inset-hard_55_ffeb80_1x100.png +0 -0
  276. data/app/assets/images/jquery-ui/ui-bg_inset-hard_75_999999_1x100.png +0 -0
  277. data/app/assets/images/jquery-ui/ui-bg_inset-soft_100_f4f0ec_1x100.png +0 -0
  278. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_201913_1x100.png +0 -0
  279. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_285c00_1x100.png +0 -0
  280. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_121212_1x100.png +0 -0
  281. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_2b2922_1x100.png +0 -0
  282. data/app/assets/images/jquery-ui/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  283. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  284. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_ffffff_1x100.png +0 -0
  285. data/app/assets/images/jquery-ui/ui-bg_inset-soft_50_c9c9c9_1x100.png +0 -0
  286. data/app/assets/images/jquery-ui/ui-bg_loop_25_000000_21x21.png +0 -0
  287. data/app/assets/images/jquery-ui/ui-bg_white-lines_85_f7f7ba_40x100.png +0 -0
  288. data/app/assets/images/jquery-ui/ui-icons_000000_256x240.png +0 -0
  289. data/app/assets/images/jquery-ui/ui-icons_004276_256x240.png +0 -0
  290. data/app/assets/images/jquery-ui/ui-icons_00498f_256x240.png +0 -0
  291. data/app/assets/images/jquery-ui/ui-icons_0073ea_256x240.png +0 -0
  292. data/app/assets/images/jquery-ui/ui-icons_0078ae_256x240.png +0 -0
  293. data/app/assets/images/jquery-ui/ui-icons_056b93_256x240.png +0 -0
  294. data/app/assets/images/jquery-ui/ui-icons_070603_256x240.png +0 -0
  295. data/app/assets/images/jquery-ui/ui-icons_0a82eb_256x240.png +0 -0
  296. data/app/assets/images/jquery-ui/ui-icons_0b54d5_256x240.png +0 -0
  297. data/app/assets/images/jquery-ui/ui-icons_1f1f1f_256x240.png +0 -0
  298. data/app/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  299. data/app/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  300. data/app/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  301. data/app/assets/images/jquery-ui/ui-icons_2694e8_256x240.png +0 -0
  302. data/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  303. data/app/assets/images/jquery-ui/ui-icons_3383bb_256x240.png +0 -0
  304. data/app/assets/images/jquery-ui/ui-icons_3572ac_256x240.png +0 -0
  305. data/app/assets/images/jquery-ui/ui-icons_3d3d3d_256x240.png +0 -0
  306. data/app/assets/images/jquery-ui/ui-icons_3d80b3_256x240.png +0 -0
  307. data/app/assets/images/jquery-ui/ui-icons_454545_256x240.png +0 -0
  308. data/app/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  309. data/app/assets/images/jquery-ui/ui-icons_4b8e0b_256x240.png +0 -0
  310. data/app/assets/images/jquery-ui/ui-icons_4ca300_256x240.png +0 -0
  311. data/app/assets/images/jquery-ui/ui-icons_4eb305_256x240.png +0 -0
  312. data/app/assets/images/jquery-ui/ui-icons_5fa5e3_256x240.png +0 -0
  313. data/app/assets/images/jquery-ui/ui-icons_666666_256x240.png +0 -0
  314. data/app/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  315. data/app/assets/images/jquery-ui/ui-icons_70b2e1_256x240.png +0 -0
  316. data/app/assets/images/jquery-ui/ui-icons_72a7cf_256x240.png +0 -0
  317. data/app/assets/images/jquery-ui/ui-icons_72b42d_256x240.png +0 -0
  318. data/app/assets/images/jquery-ui/ui-icons_734d99_256x240.png +0 -0
  319. data/app/assets/images/jquery-ui/ui-icons_808080_256x240.png +0 -0
  320. data/app/assets/images/jquery-ui/ui-icons_847e71_256x240.png +0 -0
  321. data/app/assets/images/jquery-ui/ui-icons_888888_256x240.png +0 -0
  322. data/app/assets/images/jquery-ui/ui-icons_88a206_256x240.png +0 -0
  323. data/app/assets/images/jquery-ui/ui-icons_8DC262_256x240.png +0 -0
  324. data/app/assets/images/jquery-ui/ui-icons_8c291d_256x240.png +0 -0
  325. data/app/assets/images/jquery-ui/ui-icons_8d78a5_256x240.png +0 -0
  326. data/app/assets/images/jquery-ui/ui-icons_98d2fb_256x240.png +0 -0
  327. data/app/assets/images/jquery-ui/ui-icons_999999_256x240.png +0 -0
  328. data/app/assets/images/jquery-ui/ui-icons_9bcc60_256x240.png +0 -0
  329. data/app/assets/images/jquery-ui/ui-icons_9ccdfc_256x240.png +0 -0
  330. data/app/assets/images/jquery-ui/ui-icons_9fda58_256x240.png +0 -0
  331. data/app/assets/images/jquery-ui/ui-icons_a83300_256x240.png +0 -0
  332. data/app/assets/images/jquery-ui/ui-icons_a8a3ae_256x240.png +0 -0
  333. data/app/assets/images/jquery-ui/ui-icons_aaaaaa_256x240.png +0 -0
  334. data/app/assets/images/jquery-ui/ui-icons_add978_256x240.png +0 -0
  335. data/app/assets/images/jquery-ui/ui-icons_b83400_256x240.png +0 -0
  336. data/app/assets/images/jquery-ui/ui-icons_b8ec79_256x240.png +0 -0
  337. data/app/assets/images/jquery-ui/ui-icons_bbbbbb_256x240.png +0 -0
  338. data/app/assets/images/jquery-ui/ui-icons_bd7b00_256x240.png +0 -0
  339. data/app/assets/images/jquery-ui/ui-icons_c02669_256x240.png +0 -0
  340. data/app/assets/images/jquery-ui/ui-icons_c47a23_256x240.png +0 -0
  341. data/app/assets/images/jquery-ui/ui-icons_c98000_256x240.png +0 -0
  342. data/app/assets/images/jquery-ui/ui-icons_cb672b_256x240.png +0 -0
  343. data/app/assets/images/jquery-ui/ui-icons_cc0000_256x240.png +0 -0
  344. data/app/assets/images/jquery-ui/ui-icons_cccccc_256x240.png +0 -0
  345. data/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  346. data/app/assets/images/jquery-ui/ui-icons_d19405_256x240.png +0 -0
  347. data/app/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  348. data/app/assets/images/jquery-ui/ui-icons_e0fdff_256x240.png +0 -0
  349. data/app/assets/images/jquery-ui/ui-icons_e1e463_256x240.png +0 -0
  350. data/app/assets/images/jquery-ui/ui-icons_e3ddc9_256x240.png +0 -0
  351. data/app/assets/images/jquery-ui/ui-icons_e8e2b5_256x240.png +0 -0
  352. data/app/assets/images/jquery-ui/ui-icons_e9cd86_256x240.png +0 -0
  353. data/app/assets/images/jquery-ui/ui-icons_eb990f_256x240.png +0 -0
  354. data/app/assets/images/jquery-ui/ui-icons_ebccce_256x240.png +0 -0
  355. data/app/assets/images/jquery-ui/ui-icons_ed9f26_256x240.png +0 -0
  356. data/app/assets/images/jquery-ui/ui-icons_ededed_256x240.png +0 -0
  357. data/app/assets/images/jquery-ui/ui-icons_eeeeee_256x240.png +0 -0
  358. data/app/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  359. data/app/assets/images/jquery-ui/ui-icons_efec9f_256x240.png +0 -0
  360. data/app/assets/images/jquery-ui/ui-icons_f08000_256x240.png +0 -0
  361. data/app/assets/images/jquery-ui/ui-icons_f1fd86_256x240.png +0 -0
  362. data/app/assets/images/jquery-ui/ui-icons_f29a00_256x240.png +0 -0
  363. data/app/assets/images/jquery-ui/ui-icons_f2ec64_256x240.png +0 -0
  364. data/app/assets/images/jquery-ui/ui-icons_f35f07_256x240.png +0 -0
  365. data/app/assets/images/jquery-ui/ui-icons_f5e175_256x240.png +0 -0
  366. data/app/assets/images/jquery-ui/ui-icons_f7a50d_256x240.png +0 -0
  367. data/app/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  368. data/app/assets/images/jquery-ui/ui-icons_f9f2bd_256x240.png +0 -0
  369. data/app/assets/images/jquery-ui/ui-icons_fadc7a_256x240.png +0 -0
  370. data/app/assets/images/jquery-ui/ui-icons_fbc856_256x240.png +0 -0
  371. data/app/assets/images/jquery-ui/ui-icons_fbdb93_256x240.png +0 -0
  372. data/app/assets/images/jquery-ui/ui-icons_fcd113_256x240.png +0 -0
  373. data/app/assets/images/jquery-ui/ui-icons_fcdd4a_256x240.png +0 -0
  374. data/app/assets/images/jquery-ui/ui-icons_ff0084_256x240.png +0 -0
  375. data/app/assets/images/jquery-ui/ui-icons_ff7519_256x240.png +0 -0
  376. data/app/assets/images/jquery-ui/ui-icons_ffcf29_256x240.png +0 -0
  377. data/app/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  378. data/app/assets/images/jquery-ui/ui-icons_ffe180_256x240.png +0 -0
  379. data/app/assets/images/jquery-ui/ui-icons_ffeb33_256x240.png +0 -0
  380. data/app/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  381. data/app/assets/stylesheets/jquery_ui/jquery.ui.accordion.css.scss +0 -39
  382. data/app/assets/stylesheets/jquery_ui/jquery.ui.all.css.scss +0 -14
  383. data/app/assets/stylesheets/jquery_ui/jquery.ui.autocomplete.css.scss +0 -17
  384. data/app/assets/stylesheets/jquery_ui/jquery.ui.base.css.scss +0 -27
  385. data/app/assets/stylesheets/jquery_ui/jquery.ui.button.css.scss +0 -115
  386. data/app/assets/stylesheets/jquery_ui/jquery.ui.core.css.scss +0 -92
  387. data/app/assets/stylesheets/jquery_ui/jquery.ui.datepicker.css.scss +0 -179
  388. data/app/assets/stylesheets/jquery_ui/jquery.ui.dialog.css.scss +0 -70
  389. data/app/assets/stylesheets/jquery_ui/jquery.ui.menu.css.scss +0 -80
  390. data/app/assets/stylesheets/jquery_ui/jquery.ui.progressbar.css.scss +0 -29
  391. data/app/assets/stylesheets/jquery_ui/jquery.ui.resizable.css.scss +0 -79
  392. data/app/assets/stylesheets/jquery_ui/jquery.ui.selectable.css.scss +0 -16
  393. data/app/assets/stylesheets/jquery_ui/jquery.ui.slider.css.scss +0 -74
  394. data/app/assets/stylesheets/jquery_ui/jquery.ui.spinner.css.scss +0 -66
  395. data/app/assets/stylesheets/jquery_ui/jquery.ui.tabs.css.scss +0 -53
  396. data/app/assets/stylesheets/jquery_ui/jquery.ui.theme.css.scss +0 -408
  397. data/app/assets/stylesheets/jquery_ui/jquery.ui.tooltip.css.scss +0 -20
  398. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.base.css.scss +0 -78
  399. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.black-tie.css.scss +0 -80
  400. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.blitzer.css.scss +0 -80
  401. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.cupertino.css.scss +0 -80
  402. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dark-hive.css.scss +0 -80
  403. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dot-luv.css.scss +0 -80
  404. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.eggplant.css.scss +0 -80
  405. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.excite-bike.css.scss +0 -80
  406. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.flick.css.scss +0 -80
  407. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.hot-sneaks.css.scss +0 -80
  408. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.humanity.css.scss +0 -80
  409. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.le-frog.css.scss +0 -80
  410. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.mint-choc.css.scss +0 -80
  411. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.overcast.css.scss +0 -80
  412. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.pepper-grinder.css.scss +0 -80
  413. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.redmond.css.scss +0 -80
  414. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.smoothness.css.scss +0 -80
  415. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.south-street.css.scss +0 -80
  416. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.start.css.scss +0 -80
  417. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.sunny.css.scss +0 -80
  418. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.swanky-purse.css.scss +0 -80
  419. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.trontastic.css.scss +0 -80
  420. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-darkness.css.scss +0 -80
  421. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-lightness.css.scss +0 -80
  422. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.vader.css.scss +0 -80
  423. /data/{lib → archived/form_elements/dns_records/lib}/inline_forms/form_elements/dns_records_helper.rb +0 -0
  424. /data/{lib → archived/form_elements/question_list/lib}/inline_forms/form_elements/question_list_helper.rb +0 -0
@@ -0,0 +1,191 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module InlineForms
4
+ # A structured, mutable view over a model's `inline_forms_attribute_list`.
5
+ #
6
+ # The list has always been (and remains) an Array of positional rows:
7
+ #
8
+ # [ :name, :text_field ]
9
+ # [ :priority, :dropdown_with_values, { 1 => 'low', 2 => 'high' } ]
10
+ # [ :priority2, :dropdown_with_values, { 1 => 'low', 2 => 'high' }, [ 2 ] ]
11
+ #
12
+ # where index 0 is the attribute, index 1 the form element, index 2 an
13
+ # optional values hash, and index 3 an optional disabled-options array.
14
+ #
15
+ # Every downstream consumer relies on that shape: the views destructure
16
+ # `|attribute, form_element|`, and the helpers/validator fetch the values
17
+ # hash positionally with `list.assoc(attr)[2]`. `AttributeList` therefore
18
+ # *subclasses Array* and keeps rows as plain arrays — so an `AttributeList`
19
+ # IS a valid attribute list everywhere the old literal array was, with zero
20
+ # migration. What it adds is a small DSL/API for building and editing the
21
+ # list procedurally (append / insert / remove / move / replace) instead of
22
+ # hand-editing an array literal or regex-surgery on model source.
23
+ #
24
+ # Build fresh:
25
+ #
26
+ # InlineForms::AttributeList.build do
27
+ # header :basics
28
+ # field :name, :text_field
29
+ # field :priority, :dropdown_with_values, values: { 1 => 'low', 2 => 'high' }
30
+ # info :created_at, :updated_at
31
+ # end
32
+ #
33
+ # Wrap and edit an existing list (what generators / the staging pipeline do):
34
+ #
35
+ # InlineForms::AttributeList.wrap(model.inline_forms_attribute_list)
36
+ # .insert_after(:name, :internal_note, :text_field)
37
+ # .remove(:legacy_field)
38
+ #
39
+ # Mutating methods return self, so calls chain.
40
+ class AttributeList < Array
41
+ # Build a list from a block evaluated in the list's context.
42
+ def self.build(&block)
43
+ list = new
44
+ list.instance_eval(&block) if block
45
+ list
46
+ end
47
+
48
+ # Return `rows` as an AttributeList without copying when it already is one.
49
+ def self.wrap(rows)
50
+ return rows if rows.is_a?(self)
51
+
52
+ new(rows || [])
53
+ end
54
+
55
+ # -- builder / append -------------------------------------------------
56
+
57
+ # Append a row. `values` becomes index 2, `disabled` index 3 (disabled
58
+ # requires values, since the slot is positional).
59
+ def field(name, form_element, values: nil, disabled: nil)
60
+ push(build_row(name, form_element, values, disabled))
61
+ self
62
+ end
63
+ alias add field
64
+
65
+ # Append a `:header` pseudo-row (no column, no form element behavior).
66
+ def header(name)
67
+ field(name, :header)
68
+ end
69
+
70
+ # Append one or more read-only `:info` rows.
71
+ def info(*names)
72
+ names.each { |n| field(n, :info) }
73
+ self
74
+ end
75
+
76
+ # -- insertion --------------------------------------------------------
77
+
78
+ def insert_after(anchor, name, form_element, values: nil, disabled: nil)
79
+ insert_relative(anchor, 1, build_row(name, form_element, values, disabled))
80
+ end
81
+
82
+ def insert_before(anchor, name, form_element, values: nil, disabled: nil)
83
+ insert_relative(anchor, 0, build_row(name, form_element, values, disabled))
84
+ end
85
+
86
+ # -- removal ----------------------------------------------------------
87
+
88
+ # Remove every row for `name`. Idempotent: absent name is a no-op.
89
+ def remove(name)
90
+ sym = name.to_sym
91
+ reject! { |row| row_name(row) == sym }
92
+ self
93
+ end
94
+
95
+ # -- reordering -------------------------------------------------------
96
+
97
+ def move_after(name, anchor)
98
+ relocate(name, anchor, 1)
99
+ end
100
+
101
+ def move_before(name, anchor)
102
+ relocate(name, anchor, 0)
103
+ end
104
+
105
+ # -- replacement ------------------------------------------------------
106
+
107
+ # Swap the form element (and optional values/disabled) for an existing
108
+ # attribute, preserving its position. No-op if the attribute is absent.
109
+ def replace_element(name, form_element, values: nil, disabled: nil)
110
+ idx = index_of(name)
111
+ return self unless idx
112
+
113
+ self[idx] = build_row(name, form_element, values, disabled)
114
+ self
115
+ end
116
+
117
+ # -- queries ----------------------------------------------------------
118
+
119
+ def index_of(name)
120
+ sym = name.to_sym
121
+ index { |row| row_name(row) == sym }
122
+ end
123
+
124
+ def include_attribute?(name)
125
+ !index_of(name).nil?
126
+ end
127
+
128
+ def row_for(name)
129
+ sym = name.to_sym
130
+ find { |row| row_name(row) == sym }
131
+ end
132
+
133
+ # The form element symbol for `name`, or nil.
134
+ def form_element_for(name)
135
+ row = row_for(name)
136
+ row && row[1]
137
+ end
138
+
139
+ # The values hash for `name` (row index 2), or nil.
140
+ def values_for(name)
141
+ row = row_for(name)
142
+ row && row[2]
143
+ end
144
+
145
+ def names
146
+ map { |row| row_name(row) }
147
+ end
148
+
149
+ private
150
+
151
+ def row_name(row)
152
+ first = row.respond_to?(:first) ? row.first : nil
153
+ first&.to_sym
154
+ end
155
+
156
+ def build_row(name, form_element, values, disabled)
157
+ raise ArgumentError, "disabled: requires values: (the row slot is positional)" if !disabled.nil? && values.nil?
158
+
159
+ row = [ name.to_sym, form_element.to_sym ]
160
+ row << values unless values.nil?
161
+ row << disabled unless disabled.nil?
162
+ row
163
+ end
164
+
165
+ def insert_relative(anchor, offset, row)
166
+ idx = index_of(anchor)
167
+ raise ArgumentError, "insert anchor :#{anchor} not found in attribute list" unless idx
168
+
169
+ insert(idx + offset, row)
170
+ self
171
+ end
172
+
173
+ def relocate(name, anchor, offset)
174
+ row = row_for(name)
175
+ raise ArgumentError, "move target :#{name} not found in attribute list" unless row
176
+ raise ArgumentError, "cannot move :#{name} relative to itself" if name.to_sym == anchor.to_sym
177
+
178
+ remove(name)
179
+ idx = index_of(anchor)
180
+ raise ArgumentError, "move anchor :#{anchor} not found in attribute list" unless idx
181
+
182
+ insert(idx + offset, row)
183
+ self
184
+ end
185
+ end
186
+
187
+ # Convenience entry point mirroring AttributeList.build.
188
+ def self.attribute_list(&block)
189
+ AttributeList.build(&block)
190
+ end
191
+ end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+
2
3
  module InlineForms
3
4
  # Maps +__callee__+ from a +*_show+ helper to the +params[:form_element]+ string
4
5
  # (e.g. +:text_field_show+ → +"text_field"+).
@@ -3,38 +3,38 @@
3
3
  module InlineForms
4
4
  module FormElementRegistry
5
5
  ENTRIES = {
6
- :audio_field => :string,
7
- :check_box => :boolean,
8
- :check_list => :no_migration,
9
- :date_select => :date,
10
- :decimal_field => :decimal,
11
- :devise_password_field => :string,
12
- :dropdown => :belongs_to,
13
- :dropdown_with_integers => :integer,
14
- :dropdown_with_other => :belongs_to,
15
- :dropdown_with_values => :integer,
16
- :dropdown_with_values_with_stars => :integer,
17
- :file_field => :string,
18
- :header => :string,
19
- :image_field => :string,
20
- :info => :string,
21
- :integer_field => :integer,
22
- :money_field => :integer,
23
- :month_select => :integer,
24
- :month_year_picker => :date,
25
- :multi_image_field => :string,
26
- :plain_text => :text,
27
- :plain_text_area => :text,
28
- :question_list => :no_migration,
29
- :radio_button => :integer,
30
- :rich_text => :no_migration,
31
- :scale_with_integers => :integer,
32
- :scale_with_values => :integer,
33
- :simple_file_field => :string,
34
- :slider_with_values => :integer,
35
- :text_area => :text,
36
- :text_field => :string,
37
- :time_select => :time,
6
+ audio_field: :string,
7
+ check_box: :boolean,
8
+ check_list: :no_migration,
9
+ color_field: :string,
10
+ date_select: :date,
11
+ decimal_field: :decimal,
12
+ devise_password_field: :string,
13
+ dropdown: :belongs_to,
14
+ dropdown_with_integers: :integer,
15
+ dropdown_with_other: :belongs_to,
16
+ dropdown_with_values: :integer,
17
+ dropdown_with_values_with_stars: :integer,
18
+ file_field: :string,
19
+ header: :string,
20
+ image_field: :string,
21
+ info: :string,
22
+ integer_field: :integer,
23
+ money_field: :integer,
24
+ month_select: :integer,
25
+ month_year_picker: :date,
26
+ multi_image_field: :string,
27
+ plain_text: :text,
28
+ plain_text_area: :text,
29
+ radio_button: :integer,
30
+ rich_text: :no_migration,
31
+ scale_with_integers: :integer,
32
+ scale_with_values: :integer,
33
+ simple_file_field: :string,
34
+ slider_with_values: :integer,
35
+ text_area: :text,
36
+ text_field: :string,
37
+ time_select: :time
38
38
  }.freeze
39
39
 
40
40
  def self.apply!
@@ -0,0 +1,44 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module InlineForms
3
+ module FormElements
4
+ module ColorFieldHelper
5
+ module_eval(<<~'INLINE_FORMS_FORM_ELEMENT', __FILE__, __LINE__ + 1)
6
+ # -*- encoding : utf-8 -*-
7
+
8
+ # color_field (8.1.32): hex color stored as "#rrggbb" in a string column,
9
+ # edited with the native <input type="color"> picker. Introduced for the
10
+ # per-user theme color overrides (Pattern 2), usable anywhere.
11
+ def color_field_show(object, attribute)
12
+ value = object.send(attribute).to_s
13
+ display =
14
+ if value.match?(/\A#\h{6}\z/)
15
+ # Swatch + hex text. The value is validated above, so the inline
16
+ # style cannot carry anything but the color.
17
+ ("<span class='color_swatch' style='display:inline-block;width:1em;height:1em;" \
18
+ "vertical-align:-0.15em;border:1px solid #8888;background-color:#{value};'></span> " \
19
+ "#{value}").html_safe
20
+ else
21
+ "<i class='fi-plus'></i>".html_safe
22
+ end
23
+ link_to_inline_edit object, attribute, display, from_callee: __callee__
24
+ end
25
+
26
+ def color_field_edit(object, attribute)
27
+ css_id = 'color_field_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + attribute.to_s
28
+ current = object.send(attribute).to_s
29
+ current = "#000000" unless current.match?(/\A#\h{6}\z/)
30
+ color_field_tag attribute, current, :id => css_id, :class => 'color_field'
31
+ end
32
+
33
+ def color_field_update(object, attribute)
34
+ raw = params[attribute.to_sym].to_s.strip.downcase
35
+ object[attribute.to_sym] = raw.match?(/\A#\h{6}\z/) ? raw : nil
36
+ end
37
+
38
+ def color_field_info(object, attribute)
39
+ object.send(attribute).to_s
40
+ end
41
+ INLINE_FORMS_FORM_ELEMENT
42
+ end
43
+ end
44
+ end
@@ -10,9 +10,12 @@ 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_date.strftime("%d-%m-%Y"), from_callee: __callee__
11
11
  end
12
12
 
13
+ # Native <input type="date"> (8.1.25; replaces jQuery UI datepicker).
14
+ # The browser shows a locale-formatted date but always submits ISO 8601
15
+ # (YYYY-MM-DD), which Active Record casts directly.
13
16
  def date_select_edit(object, attribute)
14
17
  css_id = 'datepicker_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + attribute.to_s
15
- out = text_field_tag attribute, ( object.send(attribute).nil? ? "" : object.send(attribute).to_date.strftime("%d-%m-%Y") ), :id => css_id, :class =>'datepicker'
18
+ date_field_tag attribute, ( object.send(attribute).nil? ? "" : object.send(attribute).to_date.strftime("%F") ), :id => css_id, :class => 'date_select'
16
19
  end
17
20
 
18
21
  def date_select_update(object, attribute)
@@ -19,124 +19,38 @@ module InlineForms
19
19
  link_to_inline_edit object, attribute, attribute_value, from_callee: __callee__
20
20
  end
21
21
 
22
+ # Native combobox (8.1.26; replaces the jQuery UI autocomplete widget and
23
+ # its inline <script>): a text input backed by a <datalist> of the existing
24
+ # records. Typing a listed presentation picks that record; any other text
25
+ # becomes the free-form "other" value. The old hidden <select> is gone --
26
+ # dropdown_with_other_update never read the posted foreign key anyway (it
27
+ # re-derives it by name lookup from the submitted text).
22
28
  def dropdown_with_other_edit(object, attribute)
23
29
  attribute = attribute.to_s
24
30
  foreign_key = object.class.reflect_on_association(attribute.to_sym).options[:foreign_key] || attribute.foreign_key.to_sym
25
31
  o = attribute.camelcase.constantize
26
32
  values = o.all
27
33
  values = o.accessible_by(current_ability) if cancan_enabled?
28
- values.each do |v|
29
- v.name = v._presentation
30
- end
31
- # values.sort_by(&:name)
32
34
 
33
- collection = values.map {|v|[v.name, v.id]}
34
- collection << [object[attribute + '_other'], 0] unless object[attribute + '_other'].nil? || object[attribute + '_other'].empty?
35
- out = '<div class="ui-widget">'
36
- out << select('_' + object.class.to_s.underscore, foreign_key.to_sym, collection, {selected: object[foreign_key.to_sym]}, {id: '_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + foreign_key.to_s})
37
- out << '</div>
38
- <script>
39
- (function( $ ) {
40
- $.widget( "custom.combobox", {
41
- _create: function() {
42
- this.wrapper = $( "<span>" )
43
- .addClass( "custom-combobox" )
44
- .insertAfter( this.element );
45
-
46
- this.element.hide();
47
- this._createAutocomplete();
48
- this._createShowAllButton();
49
- },
50
-
51
- _createAutocomplete: function() {
52
- var selected = this.element.children( ":selected" ),
53
- value = selected.val() ? selected.text() : "";
54
-
55
- this.input = $( "<input name=\''
56
-
57
- out << '_' + object.class.to_s.underscore + '[' + attribute + '_other]'
58
-
59
- out << '\'>" )
60
- .appendTo( this.wrapper )
61
- .val( value )
62
- .attr( "title", "" )
63
- .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
64
- .autocomplete({
65
- delay: 0,
66
- minLength: 0,
67
- source: $.proxy( this, "_source" )
68
- })
69
- .tooltip({
70
- tooltipClass: "ui-state-highlight"
71
- });
72
-
73
- this._on( this.input, {
74
- autocompleteselect: function( event, ui ) {
75
- ui.item.option.selected = true;
76
- this._trigger( "select", event, {
77
- item: ui.item.option
78
- });
79
- }
80
- });
81
- },
82
-
83
- _createShowAllButton: function() {
84
- var input = this.input,
85
- wasOpen = false;
86
-
87
- $( "<a>" )
88
- .attr( "tabIndex", -1 )
89
- .attr( "title", "Show All Items" )
90
- .tooltip()
91
- .appendTo( this.wrapper )
92
- .button({
93
- icons: {
94
- primary: "ui-icon-triangle-1-s"
95
- },
96
- text: false
97
- })
98
- .removeClass( "ui-corner-all" )
99
- .addClass( "custom-combobox-toggle ui-corner-right" )
100
- .mousedown(function() {
101
- wasOpen = input.autocomplete( "widget" ).is( ":visible" );
102
- })
103
- .click(function() {
104
- input.focus();
105
-
106
- // Close if already visible
107
- if ( wasOpen ) {
108
- return;
109
- }
110
-
111
- // Pass empty string as value to search for, displaying all results
112
- input.autocomplete( "search", "" );
113
- });
114
- },
115
-
116
- _source: function( request, response ) {
117
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
118
- response( this.element.children( "option" ).map(function() {
119
- var text = $( this ).text();
120
- if ( this.value && ( !request.term || matcher.test(text) ) )
121
- return {
122
- label: text,
123
- value: text,
124
- option: this
125
- };
126
- }) );
127
- },
128
- });
129
- })( jQuery );
130
-
131
- $(function() {
132
- $( "'
133
- out << '#_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + attribute.foreign_key.to_s
134
- out << '" ).combobox();
135
- });
136
- </script>'
137
- out.html_safe
138
-
139
-
35
+ current =
36
+ if object[foreign_key].to_i == 0
37
+ object[attribute + '_other'].to_s
38
+ else
39
+ (object.send(attribute)._presentation rescue '')
40
+ end
41
+
42
+ input_name = '_' + object.class.to_s.underscore + '[' + attribute + '_other]'
43
+ input_id = '_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + foreign_key.to_s
44
+ datalist_id = input_id + '_options'
45
+
46
+ options = values.map { |v| content_tag(:option, nil, value: v._presentation) }.join.html_safe
47
+
48
+ text_field_tag(input_name, current,
49
+ id: input_id,
50
+ list: datalist_id,
51
+ class: 'dropdown_with_other',
52
+ autocomplete: 'off') +
53
+ content_tag(:datalist, options, id: datalist_id)
140
54
  end
141
55
 
142
56
  def dropdown_with_other_update(object, attribute)
@@ -148,9 +62,7 @@ module InlineForms
148
62
  lookup_model = attribute.camelcase.constantize
149
63
  name_field = 'name_' + I18n.locale.to_s
150
64
  name_field = 'name' unless lookup_model.new.respond_to? name_field
151
- puts 'XXXXXXXXXXXXXXXXXXXX ' + name_field.inspect
152
65
  match = lookup_model.where(name_field.to_sym => other).first # problem if there are dupes!
153
- puts 'XXXXXXXXXXXXXXXXXXXX ' + match.inspect
154
66
  match.nil? ? object[foreign_key] = 0 : object[foreign_key] = match.id # problem if there is a record with id: 0 !
155
67
  match.nil? ? object[attribute + '_other'] = other : object[attribute + '_other'] = nil
156
68
  end
@@ -10,14 +10,25 @@ module InlineForms
10
10
  link_to_inline_edit object, attribute, object.send(attribute).nil? ? "<i class='fi-plus'></i>".html_safe : object.send(attribute).strftime("%B %Y"), from_callee: __callee__
11
11
  end
12
12
 
13
+ # Native <input type="month"> (8.1.25; replaces the jQuery UI month/year
14
+ # datepicker hack). Submits ISO "YYYY-MM"; stored as the first of month.
13
15
  def month_year_picker_edit(object, attribute)
14
16
  css_id = 'datepicker_' + object.class.to_s.underscore + '_' + object.id.to_s + '_' + attribute.to_s
15
- out = text_field_tag attribute, ( object.send(attribute).nil? ? "" : object.send(attribute).strftime("%B %Y") ), :id => css_id, :class =>'datepicker datepicker-month-year'
17
+ month_field_tag attribute, ( object.send(attribute).nil? ? "" : object.send(attribute).strftime("%Y-%m") ), :id => css_id, :class => 'month_year_picker'
16
18
  end
17
19
 
18
20
  def month_year_picker_update(object, attribute)
19
21
  raw = params[attribute.to_sym].to_s
20
- object[attribute.to_sym] = raw.empty? ? nil : Date.parse(raw).strftime("%F").to_s
22
+ object[attribute.to_sym] =
23
+ if raw.empty?
24
+ nil
25
+ elsif raw.match?(/\A\d{4}-\d{2}\z/)
26
+ # <input type="month"> value; Date.parse would raise on it.
27
+ Date.strptime(raw, "%Y-%m").strftime("%F")
28
+ else
29
+ # Legacy "September 2026" style (pre-8.1.25 clients / tests).
30
+ Date.parse(raw).strftime("%F")
31
+ end
21
32
  rescue Date::Error
22
33
  object[attribute.to_sym] = nil
23
34
  end
@@ -5,25 +5,37 @@ module InlineForms
5
5
  module_eval(<<~'INLINE_FORMS_FORM_ELEMENT', __FILE__, __LINE__ + 1)
6
6
  # -*- encoding : utf-8 -*-
7
7
 
8
+ # A `mount_uploaders` (plural) column returns an *array* of uploaders; the
9
+ # pre-8.1.28 code called `.url` on that array and raised NoMethodError the
10
+ # moment a multi_image_field actually held images. Render every image
11
+ # (using the `palm` thumb version when the uploader defines one), and keep
12
+ # accepting a bare single uploader for backward compatibility.
8
13
  def multi_image_field_show(object, attribute)
9
14
  o = object.send(attribute)
10
15
  msg = "<i class='fi-plus'></i>".html_safe
11
16
  if o.send(:present?)
12
- if o.respond_to? :palm
13
- msg = image_tag(o.send(:palm).send(:url))
14
- else
15
- msg = image_tag(o.send(:url))
17
+ uploads = o.is_a?(Array) ? o : [o]
18
+ rendered = uploads.filter_map do |u|
19
+ next unless u.respond_to?(:url) && u.url.present?
20
+ u.respond_to?(:palm) ? image_tag(u.palm.url) : image_tag(u.url)
16
21
  end
22
+ msg = safe_join(rendered) unless rendered.empty?
17
23
  end
18
24
  link_to_inline_edit object, attribute, msg, from_callee: __callee__
19
25
  end
20
26
 
27
+ # `name="gallery[]"`: file_field_tag with `multiple:` does not add the []
28
+ # itself, and without it Rack keeps only the last file — the update then
29
+ # stored a single image. With [] the params value is an array, which is
30
+ # what a mount_uploaders (plural) setter expects.
21
31
  def multi_image_field_edit(object, attribute)
22
- file_field_tag attribute, multiple: true, class: 'input_text_field multi_image_field'
32
+ file_field_tag "#{attribute}[]", multiple: true, class: 'input_text_field multi_image_field'
23
33
  end
24
34
 
25
35
  def multi_image_field_update(object, attribute)
26
- object.send(attribute.to_s + '=', params[attribute.to_sym])
36
+ files = params[attribute.to_sym]
37
+ return if files.blank?
38
+ object.send(attribute.to_s + '=', Array(files))
27
39
  end
28
40
  INLINE_FORMS_FORM_ELEMENT
29
41
  end