inline_forms 8.1.21 → 8.1.40

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 (400) hide show
  1. checksums.yaml +4 -4
  2. data/.forgejo/workflows/ci.yml +63 -0
  3. data/.forgejo/workflows/full-gate.yml +75 -0
  4. data/.gitignore +4 -3
  5. data/.rubocop.yml +30 -0
  6. data/.rubocop_todo.yml +151 -0
  7. data/CHANGELOG.md +261 -0
  8. data/Gemfile +14 -2
  9. data/README.rdoc +23 -6
  10. data/Rakefile +2 -2
  11. data/app/assets/fonts/opensans-v44-latin-italic.woff2 +0 -0
  12. data/app/assets/fonts/opensans-v44-latin-regular.woff2 +0 -0
  13. data/app/assets/javascripts/inline_forms/inline_forms.js +30 -43
  14. data/app/assets/stylesheets/inline_forms/_foundation_icons.scss +6 -12
  15. data/app/assets/stylesheets/inline_forms/_theme.scss +134 -0
  16. data/app/assets/stylesheets/inline_forms/devise.scss +14 -13
  17. data/app/assets/stylesheets/inline_forms/foundation_and_overrides.scss +4 -0
  18. data/app/assets/stylesheets/inline_forms/inline_forms.scss +59 -68
  19. data/app/assets/stylesheets/inline_forms_fonts.css.erb +39 -0
  20. data/app/controllers/inline_forms_application_controller.rb +8 -4
  21. data/app/controllers/inline_forms_controller.rb +73 -14
  22. data/app/helpers/inline_forms_helper.rb +58 -15
  23. data/app/models/concerns/inline_forms/soft_deletable.rb +11 -12
  24. data/app/validators/curacao_id_number_validator.rb +5 -6
  25. data/app/validators/is_curacao_phone_validator.rb +2 -3
  26. data/app/validators/is_email_address_validator.rb +3 -3
  27. data/app/validators/must_be_a_value_validator.rb +6 -6
  28. data/app/views/inline_forms/_show.html.erb +1 -1
  29. data/app/views/layouts/application.html.erb +6 -3
  30. data/app/views/layouts/devise.html.erb +1 -0
  31. data/app/views/layouts/inline_forms.html.erb +7 -4
  32. data/archived/README.md +2 -0
  33. data/archived/form_elements/dns_records/README.md +25 -0
  34. data/archived/form_elements/question_list/README.md +25 -0
  35. data/inline_forms.gemspec +8 -7
  36. data/lib/generators/inline_forms_attribute_overrides.rb +3 -2
  37. data/lib/generators/templates/application_record.rb +1 -1
  38. data/lib/inline_forms/archived_form_elements.rb +23 -10
  39. data/lib/inline_forms/form_element_from_callee.rb +1 -0
  40. data/lib/inline_forms/form_element_registry.rb +32 -32
  41. data/lib/inline_forms/form_elements/color_field_helper.rb +44 -0
  42. data/lib/inline_forms/form_elements/date_helper.rb +4 -1
  43. data/lib/inline_forms/form_elements/dropdown_with_other_helper.rb +25 -113
  44. data/lib/inline_forms/form_elements/month_year_picker_helper.rb +13 -2
  45. data/lib/inline_forms/form_elements/multi_image_field_helper.rb +18 -6
  46. data/lib/inline_forms/form_elements/slider_with_values_helper.rb +31 -64
  47. data/lib/inline_forms/form_elements/time_helper.rb +3 -1
  48. data/lib/inline_forms/gem_files.rb +1 -0
  49. data/lib/inline_forms/tabs.rb +175 -0
  50. data/lib/inline_forms/turbo_tabs_builder.rb +20 -13
  51. data/lib/inline_forms/version.rb +2 -1
  52. data/lib/inline_forms.rb +59 -45
  53. data/test/archived_form_elements_test.rb +34 -4
  54. data/test/dummy/app/controllers/application_controller.rb +24 -0
  55. data/test/dummy/app/controllers/machines_controller.rb +4 -0
  56. data/test/dummy/app/controllers/parts_controller.rb +4 -0
  57. data/test/dummy/app/controllers/widgets_controller.rb +4 -0
  58. data/test/dummy/app/helpers/application_helper.rb +13 -0
  59. data/test/dummy/app/models/application_record.rb +26 -0
  60. data/test/dummy/app/models/kind.rb +8 -0
  61. data/test/dummy/app/models/machine.rb +23 -0
  62. data/test/dummy/app/models/part.rb +16 -0
  63. data/test/dummy/app/models/widget.rb +39 -0
  64. data/test/dummy/app/views/_inline_forms_tabs.html.erb +40 -0
  65. data/test/dummy/config/application.rb +34 -0
  66. data/test/dummy/config/database.yml +3 -0
  67. data/test/dummy/config/environment.rb +5 -0
  68. data/test/dummy/config/initializers/inline_forms.rb +6 -0
  69. data/test/dummy/config/initializers/paper_trail_yaml_safe_load.rb +28 -0
  70. data/test/dummy/config/routes.rb +22 -0
  71. data/test/integration/inline_forms_crud_test.rb +141 -0
  72. data/test/integration/legacy_elements_test.rb +42 -0
  73. data/test/integration/native_inputs_test.rb +138 -0
  74. data/test/integration/open_after_create_test.rb +85 -0
  75. data/test/integration_test_helper.rb +80 -0
  76. data/test/plain_text_configuration_test.rb +3 -3
  77. data/test/tabs_test.rb +98 -0
  78. data/test/user_model_config_test.rb +1 -0
  79. data/vendor/assets/javascripts/trix.min.js +7 -0
  80. data/vendor/assets/stylesheets/trix.css +470 -0
  81. metadata +63 -320
  82. data/app/assets/images/jquery-ui/animated-overlay.gif +0 -0
  83. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_20_6e4f1c_10x10.png +0 -0
  84. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_40_000000_10x10.png +0 -0
  85. data/app/assets/images/jquery-ui/ui-bg_diagonals-medium_20_d34d17_40x40.png +0 -0
  86. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
  87. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_25_c5ddfc_40x40.png +0 -0
  88. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_40_db4865_40x40.png +0 -0
  89. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_262626_40x40.png +0 -0
  90. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_93c3cd_40x40.png +0 -0
  91. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_ff3853_40x40.png +0 -0
  92. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_75_ccd232_40x40.png +0 -0
  93. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_0b3e6f_40x40.png +0 -0
  94. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
  95. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  96. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  97. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_e69700_40x40.png +0 -0
  98. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_22_1484e6_40x40.png +0 -0
  99. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_26_2293f7_40x40.png +0 -0
  100. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
  101. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_8_333333_40x40.png +0 -0
  102. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_90_eeeeee_40x40.png +0 -0
  103. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_95_ffdc2e_40x40.png +0 -0
  104. data/app/assets/images/jquery-ui/ui-bg_diamond_10_4f4221_10x8.png +0 -0
  105. data/app/assets/images/jquery-ui/ui-bg_diamond_20_372806_10x8.png +0 -0
  106. data/app/assets/images/jquery-ui/ui-bg_diamond_25_675423_10x8.png +0 -0
  107. data/app/assets/images/jquery-ui/ui-bg_diamond_25_d5ac5d_10x8.png +0 -0
  108. data/app/assets/images/jquery-ui/ui-bg_diamond_8_261803_10x8.png +0 -0
  109. data/app/assets/images/jquery-ui/ui-bg_diamond_8_443113_10x8.png +0 -0
  110. data/app/assets/images/jquery-ui/ui-bg_dots-medium_30_0b58a2_4x4.png +0 -0
  111. data/app/assets/images/jquery-ui/ui-bg_dots-medium_80_ffff38_4x4.png +0 -0
  112. data/app/assets/images/jquery-ui/ui-bg_dots-small_20_333333_2x2.png +0 -0
  113. data/app/assets/images/jquery-ui/ui-bg_dots-small_30_a32d00_2x2.png +0 -0
  114. data/app/assets/images/jquery-ui/ui-bg_dots-small_35_35414f_2x2.png +0 -0
  115. data/app/assets/images/jquery-ui/ui-bg_dots-small_40_00498f_2x2.png +0 -0
  116. data/app/assets/images/jquery-ui/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
  117. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_eceadf_60x60.png +0 -0
  118. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_f8f7f6_60x60.png +0 -0
  119. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_eceadf_60x60.png +0 -0
  120. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_f7f3de_60x60.png +0 -0
  121. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_ffffff_60x60.png +0 -0
  122. data/app/assets/images/jquery-ui/ui-bg_fine-grain_65_654b24_60x60.png +0 -0
  123. data/app/assets/images/jquery-ui/ui-bg_fine-grain_68_b83400_60x60.png +0 -0
  124. data/app/assets/images/jquery-ui/ui-bg_flat_0_303030_40x100.png +0 -0
  125. data/app/assets/images/jquery-ui/ui-bg_flat_0_333333_40x100.png +0 -0
  126. data/app/assets/images/jquery-ui/ui-bg_flat_0_4c4c4c_40x100.png +0 -0
  127. data/app/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  128. data/app/assets/images/jquery-ui/ui-bg_flat_0_e69700_40x100.png +0 -0
  129. data/app/assets/images/jquery-ui/ui-bg_flat_0_e6b900_40x100.png +0 -0
  130. data/app/assets/images/jquery-ui/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  131. data/app/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  132. data/app/assets/images/jquery-ui/ui-bg_flat_15_cd0a0a_40x100.png +0 -0
  133. data/app/assets/images/jquery-ui/ui-bg_flat_30_cccccc_40x100.png +0 -0
  134. data/app/assets/images/jquery-ui/ui-bg_flat_40_292929_40x100.png +0 -0
  135. data/app/assets/images/jquery-ui/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  136. data/app/assets/images/jquery-ui/ui-bg_flat_55_994d53_40x100.png +0 -0
  137. data/app/assets/images/jquery-ui/ui-bg_flat_55_999999_40x100.png +0 -0
  138. data/app/assets/images/jquery-ui/ui-bg_flat_55_c0402a_40x100.png +0 -0
  139. data/app/assets/images/jquery-ui/ui-bg_flat_55_eeeeee_40x100.png +0 -0
  140. data/app/assets/images/jquery-ui/ui-bg_flat_55_fafafa_40x100.png +0 -0
  141. data/app/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  142. data/app/assets/images/jquery-ui/ui-bg_flat_55_ffffff_40x100.png +0 -0
  143. data/app/assets/images/jquery-ui/ui-bg_flat_65_ffffff_40x100.png +0 -0
  144. data/app/assets/images/jquery-ui/ui-bg_flat_75_aaaaaa_40x100.png +0 -0
  145. data/app/assets/images/jquery-ui/ui-bg_flat_75_ba9217_40x100.png +0 -0
  146. data/app/assets/images/jquery-ui/ui-bg_flat_75_ddd4b0_40x100.png +0 -0
  147. data/app/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png +0 -0
  148. data/app/assets/images/jquery-ui/ui-bg_glass_100_e4f1fb_1x400.png +0 -0
  149. data/app/assets/images/jquery-ui/ui-bg_glass_100_f5f0e5_1x400.png +0 -0
  150. data/app/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  151. data/app/assets/images/jquery-ui/ui-bg_glass_100_f8f8f8_1x400.png +0 -0
  152. data/app/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  153. data/app/assets/images/jquery-ui/ui-bg_glass_15_5f391b_1x400.png +0 -0
  154. data/app/assets/images/jquery-ui/ui-bg_glass_20_555555_1x400.png +0 -0
  155. data/app/assets/images/jquery-ui/ui-bg_glass_25_cb842e_1x400.png +0 -0
  156. data/app/assets/images/jquery-ui/ui-bg_glass_35_dddddd_1x400.png +0 -0
  157. data/app/assets/images/jquery-ui/ui-bg_glass_40_0078a3_1x400.png +0 -0
  158. data/app/assets/images/jquery-ui/ui-bg_glass_40_0a0a0a_1x400.png +0 -0
  159. data/app/assets/images/jquery-ui/ui-bg_glass_40_111111_1x400.png +0 -0
  160. data/app/assets/images/jquery-ui/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  161. data/app/assets/images/jquery-ui/ui-bg_glass_45_0078ae_1x400.png +0 -0
  162. data/app/assets/images/jquery-ui/ui-bg_glass_50_3baae3_1x400.png +0 -0
  163. data/app/assets/images/jquery-ui/ui-bg_glass_55_1c1c1c_1x400.png +0 -0
  164. data/app/assets/images/jquery-ui/ui-bg_glass_55_f1fbe5_1x400.png +0 -0
  165. data/app/assets/images/jquery-ui/ui-bg_glass_55_f8da4e_1x400.png +0 -0
  166. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
  167. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
  168. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  169. data/app/assets/images/jquery-ui/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  170. data/app/assets/images/jquery-ui/ui-bg_glass_60_000000_1x400.png +0 -0
  171. data/app/assets/images/jquery-ui/ui-bg_glass_60_eeeeee_1x400.png +0 -0
  172. data/app/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  173. data/app/assets/images/jquery-ui/ui-bg_glass_70_ede4d4_1x400.png +0 -0
  174. data/app/assets/images/jquery-ui/ui-bg_glass_75_79c9ec_1x400.png +0 -0
  175. data/app/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  176. data/app/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png +0 -0
  177. data/app/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  178. data/app/assets/images/jquery-ui/ui-bg_glass_80_d7ebf9_1x400.png +0 -0
  179. data/app/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  180. data/app/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  181. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_100_ece8da_500x100.png +0 -0
  182. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_16_121212_500x100.png +0 -0
  183. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_111111_500x100.png +0 -0
  184. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_1c160d_500x100.png +0 -0
  185. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  186. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_453326_500x100.png +0 -0
  187. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_3d3644_500x100.png +0 -0
  188. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_44372c_500x100.png +0 -0
  189. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  190. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_817865_500x100.png +0 -0
  191. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_e14f1c_500x100.png +0 -0
  192. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_50_6eac2c_500x100.png +0 -0
  193. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_000000_500x100.png +0 -0
  194. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  195. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_60_fece2f_500x100.png +0 -0
  196. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_70_ffdd57_500x100.png +0 -0
  197. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_75_2191c0_500x100.png +0 -0
  198. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_85_9fda58_500x100.png +0 -0
  199. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_90_fff9e5_500x100.png +0 -0
  200. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_95_f6ecd5_500x100.png +0 -0
  201. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
  202. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f2f5f7_1x100.png +0 -0
  203. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f4f0ec_1x100.png +0 -0
  204. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f5f3e5_1x100.png +0 -0
  205. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
  206. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
  207. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_fafaf4_1x100.png +0 -0
  208. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_459e00_1x100.png +0 -0
  209. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_888888_1x100.png +0 -0
  210. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_20_0972a5_1x100.png +0 -0
  211. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_30_285c00_1x100.png +0 -0
  212. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png +0 -0
  213. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_55_555555_1x100.png +0 -0
  214. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_65_fee4bd_1x100.png +0 -0
  215. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_70_000000_1x100.png +0 -0
  216. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_75_f5f5b5_1x100.png +0 -0
  217. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_95_cccccc_1x100.png +0 -0
  218. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_dcd9de_1x100.png +0 -0
  219. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_deedf7_1x100.png +0 -0
  220. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eae6ea_1x100.png +0 -0
  221. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  222. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  223. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f9f9f9_1x100.png +0 -0
  224. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_feeebd_1x100.png +0 -0
  225. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
  226. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_201913_1x100.png +0 -0
  227. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_619226_1x100.png +0 -0
  228. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  229. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_30273a_1x100.png +0 -0
  230. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_67b021_1x100.png +0 -0
  231. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_ffef8f_1x100.png +0 -0
  232. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_003147_1x100.png +0 -0
  233. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_3a8104_1x100.png +0 -0
  234. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_222222_1x100.png +0 -0
  235. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_adadad_1x100.png +0 -0
  236. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_44_444444_1x100.png +0 -0
  237. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_45_5f5964_1x100.png +0 -0
  238. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_4eb305_1x100.png +0 -0
  239. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png +0 -0
  240. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  241. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_4ca20b_1x100.png +0 -0
  242. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_dddddd_1x100.png +0 -0
  243. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  244. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  245. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  246. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  247. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_eeeeee_1x100.png +0 -0
  248. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  249. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  250. data/app/assets/images/jquery-ui/ui-bg_inset-hard_45_cd0a0a_1x100.png +0 -0
  251. data/app/assets/images/jquery-ui/ui-bg_inset-hard_55_ffeb80_1x100.png +0 -0
  252. data/app/assets/images/jquery-ui/ui-bg_inset-hard_75_999999_1x100.png +0 -0
  253. data/app/assets/images/jquery-ui/ui-bg_inset-soft_100_f4f0ec_1x100.png +0 -0
  254. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_201913_1x100.png +0 -0
  255. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_285c00_1x100.png +0 -0
  256. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_121212_1x100.png +0 -0
  257. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_2b2922_1x100.png +0 -0
  258. data/app/assets/images/jquery-ui/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  259. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  260. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_ffffff_1x100.png +0 -0
  261. data/app/assets/images/jquery-ui/ui-bg_inset-soft_50_c9c9c9_1x100.png +0 -0
  262. data/app/assets/images/jquery-ui/ui-bg_loop_25_000000_21x21.png +0 -0
  263. data/app/assets/images/jquery-ui/ui-bg_white-lines_85_f7f7ba_40x100.png +0 -0
  264. data/app/assets/images/jquery-ui/ui-icons_000000_256x240.png +0 -0
  265. data/app/assets/images/jquery-ui/ui-icons_004276_256x240.png +0 -0
  266. data/app/assets/images/jquery-ui/ui-icons_00498f_256x240.png +0 -0
  267. data/app/assets/images/jquery-ui/ui-icons_0073ea_256x240.png +0 -0
  268. data/app/assets/images/jquery-ui/ui-icons_0078ae_256x240.png +0 -0
  269. data/app/assets/images/jquery-ui/ui-icons_056b93_256x240.png +0 -0
  270. data/app/assets/images/jquery-ui/ui-icons_070603_256x240.png +0 -0
  271. data/app/assets/images/jquery-ui/ui-icons_0a82eb_256x240.png +0 -0
  272. data/app/assets/images/jquery-ui/ui-icons_0b54d5_256x240.png +0 -0
  273. data/app/assets/images/jquery-ui/ui-icons_1f1f1f_256x240.png +0 -0
  274. data/app/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  275. data/app/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  276. data/app/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  277. data/app/assets/images/jquery-ui/ui-icons_2694e8_256x240.png +0 -0
  278. data/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  279. data/app/assets/images/jquery-ui/ui-icons_3383bb_256x240.png +0 -0
  280. data/app/assets/images/jquery-ui/ui-icons_3572ac_256x240.png +0 -0
  281. data/app/assets/images/jquery-ui/ui-icons_3d3d3d_256x240.png +0 -0
  282. data/app/assets/images/jquery-ui/ui-icons_3d80b3_256x240.png +0 -0
  283. data/app/assets/images/jquery-ui/ui-icons_454545_256x240.png +0 -0
  284. data/app/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  285. data/app/assets/images/jquery-ui/ui-icons_4b8e0b_256x240.png +0 -0
  286. data/app/assets/images/jquery-ui/ui-icons_4ca300_256x240.png +0 -0
  287. data/app/assets/images/jquery-ui/ui-icons_4eb305_256x240.png +0 -0
  288. data/app/assets/images/jquery-ui/ui-icons_5fa5e3_256x240.png +0 -0
  289. data/app/assets/images/jquery-ui/ui-icons_666666_256x240.png +0 -0
  290. data/app/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  291. data/app/assets/images/jquery-ui/ui-icons_70b2e1_256x240.png +0 -0
  292. data/app/assets/images/jquery-ui/ui-icons_72a7cf_256x240.png +0 -0
  293. data/app/assets/images/jquery-ui/ui-icons_72b42d_256x240.png +0 -0
  294. data/app/assets/images/jquery-ui/ui-icons_734d99_256x240.png +0 -0
  295. data/app/assets/images/jquery-ui/ui-icons_808080_256x240.png +0 -0
  296. data/app/assets/images/jquery-ui/ui-icons_847e71_256x240.png +0 -0
  297. data/app/assets/images/jquery-ui/ui-icons_888888_256x240.png +0 -0
  298. data/app/assets/images/jquery-ui/ui-icons_88a206_256x240.png +0 -0
  299. data/app/assets/images/jquery-ui/ui-icons_8DC262_256x240.png +0 -0
  300. data/app/assets/images/jquery-ui/ui-icons_8c291d_256x240.png +0 -0
  301. data/app/assets/images/jquery-ui/ui-icons_8d78a5_256x240.png +0 -0
  302. data/app/assets/images/jquery-ui/ui-icons_98d2fb_256x240.png +0 -0
  303. data/app/assets/images/jquery-ui/ui-icons_999999_256x240.png +0 -0
  304. data/app/assets/images/jquery-ui/ui-icons_9bcc60_256x240.png +0 -0
  305. data/app/assets/images/jquery-ui/ui-icons_9ccdfc_256x240.png +0 -0
  306. data/app/assets/images/jquery-ui/ui-icons_9fda58_256x240.png +0 -0
  307. data/app/assets/images/jquery-ui/ui-icons_a83300_256x240.png +0 -0
  308. data/app/assets/images/jquery-ui/ui-icons_a8a3ae_256x240.png +0 -0
  309. data/app/assets/images/jquery-ui/ui-icons_aaaaaa_256x240.png +0 -0
  310. data/app/assets/images/jquery-ui/ui-icons_add978_256x240.png +0 -0
  311. data/app/assets/images/jquery-ui/ui-icons_b83400_256x240.png +0 -0
  312. data/app/assets/images/jquery-ui/ui-icons_b8ec79_256x240.png +0 -0
  313. data/app/assets/images/jquery-ui/ui-icons_bbbbbb_256x240.png +0 -0
  314. data/app/assets/images/jquery-ui/ui-icons_bd7b00_256x240.png +0 -0
  315. data/app/assets/images/jquery-ui/ui-icons_c02669_256x240.png +0 -0
  316. data/app/assets/images/jquery-ui/ui-icons_c47a23_256x240.png +0 -0
  317. data/app/assets/images/jquery-ui/ui-icons_c98000_256x240.png +0 -0
  318. data/app/assets/images/jquery-ui/ui-icons_cb672b_256x240.png +0 -0
  319. data/app/assets/images/jquery-ui/ui-icons_cc0000_256x240.png +0 -0
  320. data/app/assets/images/jquery-ui/ui-icons_cccccc_256x240.png +0 -0
  321. data/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  322. data/app/assets/images/jquery-ui/ui-icons_d19405_256x240.png +0 -0
  323. data/app/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  324. data/app/assets/images/jquery-ui/ui-icons_e0fdff_256x240.png +0 -0
  325. data/app/assets/images/jquery-ui/ui-icons_e1e463_256x240.png +0 -0
  326. data/app/assets/images/jquery-ui/ui-icons_e3ddc9_256x240.png +0 -0
  327. data/app/assets/images/jquery-ui/ui-icons_e8e2b5_256x240.png +0 -0
  328. data/app/assets/images/jquery-ui/ui-icons_e9cd86_256x240.png +0 -0
  329. data/app/assets/images/jquery-ui/ui-icons_eb990f_256x240.png +0 -0
  330. data/app/assets/images/jquery-ui/ui-icons_ebccce_256x240.png +0 -0
  331. data/app/assets/images/jquery-ui/ui-icons_ed9f26_256x240.png +0 -0
  332. data/app/assets/images/jquery-ui/ui-icons_ededed_256x240.png +0 -0
  333. data/app/assets/images/jquery-ui/ui-icons_eeeeee_256x240.png +0 -0
  334. data/app/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  335. data/app/assets/images/jquery-ui/ui-icons_efec9f_256x240.png +0 -0
  336. data/app/assets/images/jquery-ui/ui-icons_f08000_256x240.png +0 -0
  337. data/app/assets/images/jquery-ui/ui-icons_f1fd86_256x240.png +0 -0
  338. data/app/assets/images/jquery-ui/ui-icons_f29a00_256x240.png +0 -0
  339. data/app/assets/images/jquery-ui/ui-icons_f2ec64_256x240.png +0 -0
  340. data/app/assets/images/jquery-ui/ui-icons_f35f07_256x240.png +0 -0
  341. data/app/assets/images/jquery-ui/ui-icons_f5e175_256x240.png +0 -0
  342. data/app/assets/images/jquery-ui/ui-icons_f7a50d_256x240.png +0 -0
  343. data/app/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  344. data/app/assets/images/jquery-ui/ui-icons_f9f2bd_256x240.png +0 -0
  345. data/app/assets/images/jquery-ui/ui-icons_fadc7a_256x240.png +0 -0
  346. data/app/assets/images/jquery-ui/ui-icons_fbc856_256x240.png +0 -0
  347. data/app/assets/images/jquery-ui/ui-icons_fbdb93_256x240.png +0 -0
  348. data/app/assets/images/jquery-ui/ui-icons_fcd113_256x240.png +0 -0
  349. data/app/assets/images/jquery-ui/ui-icons_fcdd4a_256x240.png +0 -0
  350. data/app/assets/images/jquery-ui/ui-icons_ff0084_256x240.png +0 -0
  351. data/app/assets/images/jquery-ui/ui-icons_ff7519_256x240.png +0 -0
  352. data/app/assets/images/jquery-ui/ui-icons_ffcf29_256x240.png +0 -0
  353. data/app/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  354. data/app/assets/images/jquery-ui/ui-icons_ffe180_256x240.png +0 -0
  355. data/app/assets/images/jquery-ui/ui-icons_ffeb33_256x240.png +0 -0
  356. data/app/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  357. data/app/assets/stylesheets/jquery_ui/jquery.ui.accordion.css.scss +0 -39
  358. data/app/assets/stylesheets/jquery_ui/jquery.ui.all.css.scss +0 -14
  359. data/app/assets/stylesheets/jquery_ui/jquery.ui.autocomplete.css.scss +0 -17
  360. data/app/assets/stylesheets/jquery_ui/jquery.ui.base.css.scss +0 -27
  361. data/app/assets/stylesheets/jquery_ui/jquery.ui.button.css.scss +0 -115
  362. data/app/assets/stylesheets/jquery_ui/jquery.ui.core.css.scss +0 -92
  363. data/app/assets/stylesheets/jquery_ui/jquery.ui.datepicker.css.scss +0 -179
  364. data/app/assets/stylesheets/jquery_ui/jquery.ui.dialog.css.scss +0 -70
  365. data/app/assets/stylesheets/jquery_ui/jquery.ui.menu.css.scss +0 -80
  366. data/app/assets/stylesheets/jquery_ui/jquery.ui.progressbar.css.scss +0 -29
  367. data/app/assets/stylesheets/jquery_ui/jquery.ui.resizable.css.scss +0 -79
  368. data/app/assets/stylesheets/jquery_ui/jquery.ui.selectable.css.scss +0 -16
  369. data/app/assets/stylesheets/jquery_ui/jquery.ui.slider.css.scss +0 -74
  370. data/app/assets/stylesheets/jquery_ui/jquery.ui.spinner.css.scss +0 -66
  371. data/app/assets/stylesheets/jquery_ui/jquery.ui.tabs.css.scss +0 -53
  372. data/app/assets/stylesheets/jquery_ui/jquery.ui.theme.css.scss +0 -408
  373. data/app/assets/stylesheets/jquery_ui/jquery.ui.tooltip.css.scss +0 -20
  374. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.base.css.scss +0 -78
  375. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.black-tie.css.scss +0 -80
  376. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.blitzer.css.scss +0 -80
  377. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.cupertino.css.scss +0 -80
  378. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dark-hive.css.scss +0 -80
  379. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dot-luv.css.scss +0 -80
  380. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.eggplant.css.scss +0 -80
  381. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.excite-bike.css.scss +0 -80
  382. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.flick.css.scss +0 -80
  383. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.hot-sneaks.css.scss +0 -80
  384. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.humanity.css.scss +0 -80
  385. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.le-frog.css.scss +0 -80
  386. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.mint-choc.css.scss +0 -80
  387. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.overcast.css.scss +0 -80
  388. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.pepper-grinder.css.scss +0 -80
  389. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.redmond.css.scss +0 -80
  390. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.smoothness.css.scss +0 -80
  391. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.south-street.css.scss +0 -80
  392. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.start.css.scss +0 -80
  393. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.sunny.css.scss +0 -80
  394. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.swanky-purse.css.scss +0 -80
  395. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.trontastic.css.scss +0 -80
  396. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-darkness.css.scss +0 -80
  397. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-lightness.css.scss +0 -80
  398. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.vader.css.scss +0 -80
  399. /data/{lib → archived/form_elements/dns_records/lib}/inline_forms/form_elements/dns_records_helper.rb +0 -0
  400. /data/{lib → archived/form_elements/question_list/lib}/inline_forms/form_elements/question_list_helper.rb +0 -0
@@ -0,0 +1,40 @@
1
+ <div class="contain-to-grid fixed" id="inline_forms_model_top_bar_container">
2
+ <nav id="inline_forms_model_top_bar" class="top-bar">
3
+ <div class="top-bar-left">
4
+ <ul class="menu">
5
+ <li class="menu-text" id="inline_forms_menu">
6
+ <h1 style="margin: 0; font-size: inherit;">
7
+ <a>
8
+ <%= t(controller_name) %>
9
+ </a>
10
+ </h1>
11
+ </li>
12
+ </ul>
13
+ </div>
14
+ <div class="top-bar-right">
15
+ <ul class="menu">
16
+ <li>
17
+ <%= form_tag request.path, :method => 'get' do %>
18
+ <div class="row collapse">
19
+ <div class="large-1 small-1 columns">
20
+ <%= link_to "<i class='fi-x'></i>".html_safe, request.path, :title => 'reset', :class => "button expanded inline_forms_model_top_bar_buttons" %>
21
+ </div>
22
+ <div class="large-6 small-6 columns">
23
+ <%= text_field_tag :search, params[:search], :placeholder => 'zoek op naam...', :id => 'input_search' %>
24
+ </div>
25
+ <div class="large-3 small-3 columns">
26
+ <%= submit_tag 'zoek', :class => "button expanded inline_forms_model_top_bar_buttons" %>
27
+ </div>
28
+ <div class="large-2 small-2 columns">
29
+ &nbsp;
30
+ </div>
31
+ </div>
32
+ <% end %>
33
+ </li>
34
+ <li>
35
+ <%= link_to_new_record(@Klass, "new_#{@Klass.to_s.singularize.underscore}_path", @Klass.to_s.pluralize.downcase + '_list') %>
36
+ </li>
37
+ </ul>
38
+ </div>
39
+ </nav>
40
+ </div>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Minimal host app for the engine's integration tests (test/integration/).
4
+ # Boots the inline_forms engine against an in-memory SQLite database with the
5
+ # host-side gems the engine expects (will_paginate, paper_trail, turbo-rails)
6
+ # but without Devise, CanCanCan, Sprockets or ActionText: authorization is
7
+ # optional in the engine (cancan_enabled? rescues NameError), tests drive the
8
+ # UI through Turbo-Frame requests (the frame layout never renders the
9
+ # current_user header), and the asset-precompile initializer skips hosts
10
+ # without a pipeline.
11
+ require "rails"
12
+ require "active_record/railtie"
13
+ require "action_controller/railtie"
14
+ require "action_view/railtie"
15
+
16
+ Bundler.require(*Rails.groups)
17
+
18
+ require "inline_forms"
19
+
20
+ module Dummy
21
+ class Application < Rails::Application
22
+ config.load_defaults 8.1
23
+ config.root = File.expand_path("..", __dir__)
24
+ config.eager_load = false
25
+ config.secret_key_base = "inline_forms_dummy_test_secret"
26
+ config.logger = ActiveSupport::Logger.new(File::NULL)
27
+ config.active_support.deprecation = :stderr
28
+ config.action_controller.allow_forgery_protection = false
29
+ # Schema is defined by test/integration_test_helper.rb on the in-memory DB.
30
+ config.active_record.maintain_test_schema = false
31
+ # Raise in-place so integration failures carry the real backtrace.
32
+ config.action_dispatch.show_exceptions = :none
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "application"
4
+
5
+ Rails.application.initialize!
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Mirrors the initializer the installer seeds in host apps; the header
4
+ # (`inline_forms/_header`) iterates MODEL_TABS for admin users. Kept empty so
5
+ # the dummy needs no CanCan (`can?` is only called per entry).
6
+ MODEL_TABS = %w[].freeze
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Mirrors the initializer the installer writes into generated apps
4
+ # (installer_core.rb): PaperTrail serializes object/object_changes as YAML,
5
+ # and Psych safe-loading needs these classes permitted or version.changeset /
6
+ # version.reify silently degrade (empty changeset) or raise.
7
+ permitted = [
8
+ Symbol,
9
+ Date,
10
+ Time,
11
+ BigDecimal,
12
+ ActiveSupport::TimeWithZone,
13
+ ActiveSupport::TimeZone,
14
+ ActiveSupport::HashWithIndifferentAccess
15
+ ]
16
+
17
+ %w[
18
+ ActiveRecord::Type::Time::Value
19
+ ActiveRecord::Type::Date::Value
20
+ ActiveRecord::Type::DateTime::Value
21
+ ].each do |const_name|
22
+ klass = const_name.safe_constantize
23
+ permitted << klass if klass
24
+ end
25
+
26
+ Rails.application.config.active_record.yaml_column_permitted_classes ||= []
27
+ Rails.application.config.active_record.yaml_column_permitted_classes |= permitted
28
+ ActiveRecord.yaml_column_permitted_classes |= Rails.application.config.active_record.yaml_column_permitted_classes
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Mirrors the routes `rails g inline_forms` injects for each resource.
4
+ Rails.application.routes.draw do
5
+ # Devise stand-in: the inline_forms header links destroy_user_session_path.
6
+ delete "logout", to: proc { [ 204, {}, [] ] }, as: :destroy_user_session
7
+
8
+ resources :widgets do
9
+ post "revert", on: :member
10
+ get "list_versions", on: :member
11
+ end
12
+
13
+ resources :machines do
14
+ post "revert", on: :member
15
+ get "list_versions", on: :member
16
+ end
17
+
18
+ resources :parts do
19
+ post "revert", on: :member
20
+ get "list_versions", on: :member
21
+ end
22
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../integration_test_helper"
4
+
5
+ # End-to-end (controller + views + Turbo frames) CRUD through the engine's
6
+ # InlineFormsController, running against the test/dummy host app.
7
+ class InlineFormsCrudTest < InlineFormsIntegrationTestCase
8
+ setup do
9
+ @widget = Widget.create!(name: "Alpha", priority: 2)
10
+ end
11
+
12
+ test "index lists rows inside the list turbo-frame" do
13
+ get widgets_path(update: "widgets_list"), headers: frame_headers("widgets_list")
14
+
15
+ assert_response :success
16
+ assert_includes response.body, %(<turbo-frame id="widgets_list" class="list_container">)
17
+ assert_includes response.body, %(<turbo-frame id="widget_#{@widget.id}">)
18
+ assert_includes response.body, "Alpha"
19
+ end
20
+
21
+ test "index applies inline_forms_search when ?search= is passed" do
22
+ Widget.create!(name: "Beta")
23
+
24
+ get widgets_path(update: "widgets_list", search: "Alp"),
25
+ headers: frame_headers("widgets_list")
26
+
27
+ assert_response :success
28
+ assert_includes response.body, "Alpha"
29
+ refute_includes response.body, "Beta"
30
+ end
31
+
32
+ test "row show renders attribute frames" do
33
+ frame = "widget_#{@widget.id}"
34
+ get widget_path(@widget, update: frame), headers: frame_headers(frame)
35
+
36
+ assert_response :success
37
+ assert_includes response.body, %(<turbo-frame id="#{frame}">)
38
+ assert_includes response.body, %(<turbo-frame id="widget_#{@widget.id}_name">)
39
+ end
40
+
41
+ test "attribute edit renders the input in its frame" do
42
+ frame = "widget_#{@widget.id}_name"
43
+ get edit_widget_path(@widget, attribute: "name", form_element: "text_field",
44
+ update: frame),
45
+ headers: frame_headers(frame)
46
+
47
+ assert_response :success
48
+ assert_includes response.body, %(<turbo-frame id="#{frame}">)
49
+ assert_includes response.body, %(name="name")
50
+ assert_includes response.body, %(value="Alpha")
51
+ end
52
+
53
+ test "attribute update persists and renders the show state" do
54
+ frame = "widget_#{@widget.id}_name"
55
+ put widget_path(@widget, attribute: "name", form_element: "text_field",
56
+ update: frame),
57
+ params: { name: "Renamed" }, headers: frame_headers(frame)
58
+
59
+ assert_response :success
60
+ assert_equal "Renamed", @widget.reload.name
61
+ assert_includes response.body, "Renamed"
62
+ end
63
+
64
+ test "failed save re-renders the edit state, not a fake show (8.1.19)" do
65
+ frame = "widget_#{@widget.id}_name"
66
+ put widget_path(@widget, attribute: "name", form_element: "text_field",
67
+ update: frame),
68
+ params: { name: "" }, headers: frame_headers(frame)
69
+
70
+ assert_response :success
71
+ assert_equal "Alpha", @widget.reload.name, "blank name must not persist"
72
+ assert_includes response.body, %(name="name"),
73
+ "expected the edit input to be re-rendered after a failed save"
74
+ end
75
+
76
+ test "destroy responds with the destroyed-row state and an undo pointing at the destroy version" do
77
+ frame = "widget_#{@widget.id}"
78
+ assert_difference -> { Widget.count }, -1 do
79
+ delete widget_path(@widget, update: frame), headers: frame_headers(frame)
80
+ end
81
+ assert_response :success
82
+
83
+ destroy_version = PaperTrail::Version.where(item_type: "Widget",
84
+ item_id: @widget.id,
85
+ event: "destroy").last
86
+ assert destroy_version, "expected a PaperTrail destroy version"
87
+ assert_includes response.body, "/widgets/#{destroy_version.id}/revert",
88
+ "undo link must target the destroy version (8.1.13)"
89
+ end
90
+
91
+ # revert responds with turbo_stream (replaces row + versions panel at once,
92
+ # see render_revert_response); the undo/Restore links request that format.
93
+ def turbo_stream_headers(frame_id)
94
+ frame_headers(frame_id).merge("Accept" => "text/vnd.turbo-stream.html")
95
+ end
96
+
97
+ test "revert of a destroy version restores the row (undo)" do
98
+ frame = "widget_#{@widget.id}"
99
+ delete widget_path(@widget, update: frame), headers: frame_headers(frame)
100
+ destroy_version = PaperTrail::Version.where(item_type: "Widget",
101
+ item_id: @widget.id,
102
+ event: "destroy").last
103
+
104
+ assert_difference -> { Widget.count }, +1 do
105
+ post revert_widget_path(destroy_version.id, update: "widgets_list"),
106
+ headers: turbo_stream_headers("widgets_list")
107
+ end
108
+ assert_response :success
109
+ assert Widget.exists?(@widget.id), "undo must restore the destroyed row"
110
+ assert_equal "Alpha", Widget.find(@widget.id).name
111
+ end
112
+
113
+ test "revert of a destroy version is idempotent when the row already exists (8.1.17)" do
114
+ frame = "widget_#{@widget.id}"
115
+ delete widget_path(@widget, update: frame), headers: frame_headers(frame)
116
+ destroy_version = PaperTrail::Version.where(item_type: "Widget",
117
+ item_id: @widget.id,
118
+ event: "destroy").last
119
+
120
+ post revert_widget_path(destroy_version.id, update: "widgets_list"),
121
+ headers: turbo_stream_headers("widgets_list")
122
+ assert Widget.exists?(@widget.id)
123
+
124
+ # Replaying the same restore must not raise RecordNotUnique.
125
+ post revert_widget_path(destroy_version.id, update: "widgets_list"),
126
+ headers: turbo_stream_headers("widgets_list")
127
+ assert_response :success
128
+ assert_equal 1, Widget.where(id: @widget.id).count
129
+ end
130
+
131
+ test "versions panel lists an update event" do
132
+ @widget.update!(name: "Renamed once")
133
+ frame = "widget_#{@widget.id}"
134
+
135
+ get list_versions_widget_path(@widget, update: frame),
136
+ headers: frame_headers(frame)
137
+
138
+ assert_response :success
139
+ assert_includes response.body, "Renamed once"
140
+ end
141
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../integration_test_helper"
4
+
5
+ # First-ever render coverage for two legacy display elements that no example
6
+ # app exercises (see stuff/improvement-plan.md §4): simple_file_field (raw
7
+ # filename column + host-provided download route) and pdf_link (host-provided
8
+ # /:attribute/:id report route).
9
+ class LegacyElementsTest < InlineFormsIntegrationTestCase
10
+ setup do
11
+ @widget = Widget.create!(name: "Legacy")
12
+ end
13
+
14
+ test "simple_file_field blank state renders the inline-edit plus link" do
15
+ frame = "widget_#{@widget.id}"
16
+ get widget_path(@widget, update: frame), headers: frame_headers(frame)
17
+
18
+ assert_response :success
19
+ assert_includes response.body, %(<turbo-frame id="widget_#{@widget.id}_manual">)
20
+ assert_includes response.body, "fi-plus"
21
+ end
22
+
23
+ test "simple_file_field edit renders a file input" do
24
+ frame = "widget_#{@widget.id}_manual"
25
+ get edit_widget_path(@widget, attribute: "manual",
26
+ form_element: "simple_file_field", update: frame),
27
+ headers: frame_headers(frame)
28
+
29
+ assert_response :success
30
+ assert_includes response.body, %(type="file")
31
+ assert_includes response.body, %(name="manual")
32
+ end
33
+
34
+ test "pdf_link show renders preview and pdf links for the attribute route" do
35
+ frame = "widget_#{@widget.id}"
36
+ get widget_path(@widget, update: frame), headers: frame_headers(frame)
37
+
38
+ assert_response :success
39
+ assert_includes response.body, %(href="/report/#{@widget.id}")
40
+ assert_includes response.body, %(href="/report/#{@widget.id}.pdf")
41
+ end
42
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../integration_test_helper"
4
+
5
+ # Engine-level render coverage for the native-input form elements introduced
6
+ # in 8.1.25/8.1.26 (previously only covered by the example-app gate).
7
+ class NativeInputsTest < InlineFormsIntegrationTestCase
8
+ setup do
9
+ @widget = Widget.create!(
10
+ name: "Native",
11
+ released_on: Date.new(2026, 5, 17),
12
+ meeting_at: Time.utc(2000, 1, 1, 9, 15),
13
+ start_month: Date.new(2026, 5, 1),
14
+ priority: 2,
15
+ rating: 3
16
+ )
17
+ end
18
+
19
+ def edit_attribute(attribute, form_element)
20
+ frame = "widget_#{@widget.id}_#{attribute}"
21
+ get edit_widget_path(@widget, attribute: attribute, form_element: form_element,
22
+ update: frame),
23
+ headers: frame_headers(frame)
24
+ assert_response :success
25
+ response.body
26
+ end
27
+
28
+ test "date_select renders a native date input with ISO value" do
29
+ body = edit_attribute("released_on", "date_select")
30
+ assert_includes body, %(type="date")
31
+ assert_includes body, %(value="2026-05-17")
32
+ refute_includes body, "<script"
33
+ end
34
+
35
+ test "time_select renders a native time input with HH:MM value" do
36
+ body = edit_attribute("meeting_at", "time_select")
37
+ assert_includes body, %(type="time")
38
+ assert_includes body, %(value="09:15")
39
+ end
40
+
41
+ test "month_year_picker renders a native month input with YYYY-MM value" do
42
+ body = edit_attribute("start_month", "month_year_picker")
43
+ assert_includes body, %(type="month")
44
+ assert_includes body, %(value="2026-05")
45
+ end
46
+
47
+ test "month_year_picker update accepts native and legacy formats" do
48
+ frame = "widget_#{@widget.id}_start_month"
49
+
50
+ put widget_path(@widget, attribute: "start_month",
51
+ form_element: "month_year_picker", update: frame),
52
+ params: { start_month: "2026-09" }, headers: frame_headers(frame)
53
+ assert_equal Date.new(2026, 9, 1), @widget.reload.start_month
54
+
55
+ put widget_path(@widget, attribute: "start_month",
56
+ form_element: "month_year_picker", update: frame),
57
+ params: { start_month: "November 2027" }, headers: frame_headers(frame)
58
+ assert_equal Date.new(2027, 11, 1), @widget.reload.start_month
59
+ end
60
+
61
+ test "dropdown_with_other renders a datalist-backed combobox without inline scripts" do
62
+ Kind.create!(name: "Gadget")
63
+ Kind.create!(name: "Gizmo")
64
+
65
+ body = edit_attribute("kind", "dropdown_with_other")
66
+ assert_includes body, "<datalist"
67
+ assert_includes body, %(<option value="Gadget">)
68
+ assert_includes body, %(<option value="Gizmo">)
69
+ assert_includes body, %(name="_widget[kind_other]")
70
+ refute_includes body, "<script"
71
+ end
72
+
73
+ test "dropdown_with_other update matches an existing record by name" do
74
+ kind = Kind.create!(name: "Gadget")
75
+ frame = "widget_#{@widget.id}_kind"
76
+
77
+ put widget_path(@widget, attribute: "kind",
78
+ form_element: "dropdown_with_other", update: frame),
79
+ params: { _widget: { kind_other: "Gadget" } }, headers: frame_headers(frame)
80
+
81
+ assert_response :success
82
+ @widget.reload
83
+ assert_equal kind.id, @widget.kind_id
84
+ assert_nil @widget.kind_other
85
+ end
86
+
87
+ test "dropdown_with_other update stores unmatched text as the other value" do
88
+ Kind.create!(name: "Gadget")
89
+ frame = "widget_#{@widget.id}_kind"
90
+
91
+ put widget_path(@widget, attribute: "kind",
92
+ form_element: "dropdown_with_other", update: frame),
93
+ params: { _widget: { kind_other: "Completely new thing" } },
94
+ headers: frame_headers(frame)
95
+
96
+ assert_response :success
97
+ @widget.reload
98
+ assert_equal 0, @widget.kind_id
99
+ assert_equal "Completely new thing", @widget.kind_other
100
+ end
101
+
102
+ test "slider_with_values renders a native range input with label data" do
103
+ body = edit_attribute("rating", "slider_with_values")
104
+ assert_includes body, %(type="range")
105
+ assert_includes body, "slider_with_values"
106
+ assert_includes body, "data-slider-values"
107
+ assert_includes body, %(<output)
108
+ refute_includes body, "<script"
109
+ end
110
+
111
+ test "slider_with_values show renders a progress bar (clickable, non-interactive)" do
112
+ frame = "widget_#{@widget.id}"
113
+ get widget_path(@widget, update: frame), headers: frame_headers(frame)
114
+
115
+ assert_response :success
116
+ assert_includes response.body, "<progress"
117
+ end
118
+
119
+ test "color_field renders a native color input and round-trips a hex value" do
120
+ @widget.update!(accent: "#a3381e")
121
+ body = edit_attribute("accent", "color_field")
122
+ assert_includes body, %(type="color")
123
+ assert_includes body, %(value="#a3381e")
124
+
125
+ frame = "widget_#{@widget.id}_accent"
126
+ put widget_path(@widget, attribute: "accent", form_element: "color_field",
127
+ update: frame),
128
+ params: { accent: "#2563EB" }, headers: frame_headers(frame)
129
+ assert_response :success
130
+ assert_equal "#2563eb", @widget.reload.accent, "hex is normalized to lowercase"
131
+
132
+ # Junk input is rejected server-side (stored as nil), not persisted raw.
133
+ put widget_path(@widget, attribute: "accent", form_element: "color_field",
134
+ update: frame),
135
+ params: { accent: "red; background:url(x)" }, headers: frame_headers(frame)
136
+ assert_nil @widget.reload.accent
137
+ end
138
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../integration_test_helper"
4
+
5
+ # "Open after create" (stuff/2026-07-10-nested-creation-options.md, Option A):
6
+ # a successful top-level create of a class with an :associated (has_many)
7
+ # panel responds with Turbo Streams that refresh the list and open the new
8
+ # record's row, so the nested panel is immediately usable. Everything else
9
+ # (classes without :associated, nested creates, failed saves, non-stream
10
+ # clients) keeps the plain frame responses.
11
+ class OpenAfterCreateTest < InlineFormsIntegrationTestCase
12
+ # Turbo form submissions advertise turbo-stream before text/html.
13
+ def stream_headers(frame_id)
14
+ { "Turbo-Frame" => frame_id,
15
+ "Accept" => "text/vnd.turbo-stream.html, text/html" }
16
+ end
17
+
18
+ test "top-level create with an associated panel streams the list and the opened row" do
19
+ assert_difference -> { Machine.count }, +1 do
20
+ post machines_path(update: "machines_list"),
21
+ params: { name: "Lathe" },
22
+ headers: stream_headers("machines_list")
23
+ end
24
+ assert_response :success
25
+ assert_equal "text/vnd.turbo-stream.html", response.media_type
26
+
27
+ machine = Machine.find_by!(name: "Lathe")
28
+ assert_includes response.body,
29
+ %(<turbo-stream action="replace" target="machines_list">)
30
+ assert_includes response.body,
31
+ %(<turbo-stream action="replace" target="machine_#{machine.id}">)
32
+
33
+ # The opened row exposes the parts panel with its "new part" link,
34
+ # carrying the freshly created parent's id.
35
+ assert_includes response.body, %(id="machine_#{machine.id}_parts_list_auto_header")
36
+ assert_match(
37
+ %r{/parts/new\?[^"]*parent_id=#{machine.id}},
38
+ response.body,
39
+ "expected the associated panel's new-record link for the created parent"
40
+ )
41
+ end
42
+
43
+ test "top-level create without turbo-stream accept keeps the list frame response" do
44
+ post machines_path(update: "machines_list"),
45
+ params: { name: "Mill" },
46
+ headers: frame_headers("machines_list")
47
+ assert_response :success
48
+ assert_equal "text/html", response.media_type
49
+ assert_includes response.body, %(<turbo-frame id="machines_list">)
50
+ end
51
+
52
+ test "create of a class without an associated panel is unchanged" do
53
+ post parts_path(update: "parts_list"),
54
+ params: { name: "Plain" },
55
+ headers: stream_headers("parts_list")
56
+ assert_response :success
57
+ assert_equal "text/html", response.media_type
58
+ assert_includes response.body, %(<turbo-frame id="parts_list">)
59
+ end
60
+
61
+ test "nested create under a parent keeps the frame response" do
62
+ machine = Machine.create!(name: "Host")
63
+ frame = "machine_#{machine.id}_parts"
64
+
65
+ assert_difference -> { Part.count }, +1 do
66
+ post parts_path(update: frame, parent_class: "Machine", parent_id: machine.id),
67
+ params: { name: "Bolt" },
68
+ headers: stream_headers(frame)
69
+ end
70
+ assert_response :success
71
+ assert_equal "text/html", response.media_type
72
+ assert_equal machine.id, Part.find_by!(name: "Bolt").machine_id
73
+ end
74
+
75
+ test "failed top-level create re-renders the new form, not streams" do
76
+ assert_no_difference -> { Machine.count } do
77
+ post machines_path(update: "machines_list"),
78
+ params: { name: "" },
79
+ headers: stream_headers("machines_list")
80
+ end
81
+ assert_response :success
82
+ assert_equal "text/html", response.media_type
83
+ assert_includes response.body, 'class="edit_form"'
84
+ end
85
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Boots the test/dummy host app for the engine's integration tests. Fast path
4
+ # (seconds) next to the full release gate (build gems -> inline_forms create
5
+ # MyApp --example -> rails test); catches controller/view/Turbo regressions
6
+ # without an install cycle. See stuff/prompt/test-the-example-app.md for the
7
+ # release gate, which remains authoritative.
8
+ ENV["RAILS_ENV"] = "test"
9
+
10
+ require_relative "dummy/config/environment"
11
+ require "rails/test_help"
12
+ require "minitest/autorun"
13
+
14
+ # In-memory SQLite: define the schema on every boot (maintain_test_schema is
15
+ # off; there are no migration files to run).
16
+ ActiveRecord::Schema.verbose = false
17
+ ActiveRecord::Schema.define do
18
+ create_table :widgets, force: true do |t|
19
+ t.string :name
20
+ t.text :notes
21
+ t.date :released_on
22
+ t.time :meeting_at
23
+ t.date :start_month
24
+ t.integer :priority
25
+ t.boolean :active
26
+ t.integer :kind_id
27
+ t.string :kind_other
28
+ t.integer :rating
29
+ t.string :manual
30
+ t.string :accent
31
+ t.timestamps
32
+ end
33
+
34
+ create_table :kinds, force: true do |t|
35
+ t.string :name
36
+ t.timestamps
37
+ end
38
+
39
+ # Machine has_many :parts with an :associated panel (open-after-create).
40
+ create_table :machines, force: true do |t|
41
+ t.string :name
42
+ t.timestamps
43
+ end
44
+
45
+ create_table :parts, force: true do |t|
46
+ t.string :name
47
+ t.integer :machine_id
48
+ t.timestamps
49
+ end
50
+ add_index :parts, :machine_id
51
+
52
+ # PaperTrail (paper_trail 17.x shape).
53
+ create_table :versions, force: true do |t|
54
+ t.string :item_type, null: false
55
+ t.bigint :item_id, null: false
56
+ t.string :event, null: false
57
+ t.string :whodunnit
58
+ t.text :object, limit: 1_073_741_823
59
+ t.text :object_changes, limit: 1_073_741_823
60
+ t.datetime :created_at
61
+ end
62
+ add_index :versions, [ :item_type, :item_id ]
63
+ end
64
+
65
+ class InlineFormsIntegrationTestCase < ActionDispatch::IntegrationTest
66
+ # The inline UI drives every request through a <turbo-frame>; the frame
67
+ # layout (turbo_rails/frame) also spares the dummy the full chrome (header
68
+ # needs current_user, assets, ...).
69
+ def frame_headers(frame_id)
70
+ { "Turbo-Frame" => frame_id, "Accept" => "text/html" }
71
+ end
72
+
73
+ setup do
74
+ Widget.delete_all
75
+ Kind.delete_all
76
+ Part.delete_all
77
+ Machine.delete_all
78
+ PaperTrail::Version.delete_all
79
+ end
80
+ end
@@ -20,7 +20,7 @@ class PlainTextConfigurationTest < Minitest::Test
20
20
 
21
21
  def inline_forms_attribute_list
22
22
  [
23
- [:description, :plain_text]
23
+ [ :description, :plain_text ]
24
24
  ]
25
25
  end
26
26
  end
@@ -40,7 +40,7 @@ class PlainTextConfigurationTest < Minitest::Test
40
40
 
41
41
  def inline_forms_attribute_list
42
42
  [
43
- [:description, :plain_text]
43
+ [ :description, :plain_text ]
44
44
  ]
45
45
  end
46
46
  end
@@ -56,7 +56,7 @@ class PlainTextConfigurationTest < Minitest::Test
56
56
 
57
57
  def inline_forms_attribute_list
58
58
  [
59
- [:description, :rich_text]
59
+ [ :description, :rich_text ]
60
60
  ]
61
61
  end
62
62
  end