inline_forms 6.3.3 → 7.2.10

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 (364) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/CHANGELOG.md +270 -0
  4. data/README.rdoc +8 -0
  5. data/app/assets/fonts/foundation-icons.svg +970 -0
  6. data/app/assets/fonts/foundation-icons.ttf +0 -0
  7. data/app/assets/fonts/foundation-icons.woff +0 -0
  8. data/app/assets/images/jquery-ui/animated-overlay.gif +0 -0
  9. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_20_6e4f1c_10x10.png +0 -0
  10. data/app/assets/images/jquery-ui/ui-bg_diagonal-maze_40_000000_10x10.png +0 -0
  11. data/app/assets/images/jquery-ui/ui-bg_diagonals-medium_20_d34d17_40x40.png +0 -0
  12. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
  13. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_25_c5ddfc_40x40.png +0 -0
  14. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_40_db4865_40x40.png +0 -0
  15. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_262626_40x40.png +0 -0
  16. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_93c3cd_40x40.png +0 -0
  17. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_50_ff3853_40x40.png +0 -0
  18. data/app/assets/images/jquery-ui/ui-bg_diagonals-small_75_ccd232_40x40.png +0 -0
  19. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_0b3e6f_40x40.png +0 -0
  20. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
  21. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  22. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  23. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_20_e69700_40x40.png +0 -0
  24. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_22_1484e6_40x40.png +0 -0
  25. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_26_2293f7_40x40.png +0 -0
  26. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
  27. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_8_333333_40x40.png +0 -0
  28. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_90_eeeeee_40x40.png +0 -0
  29. data/app/assets/images/jquery-ui/ui-bg_diagonals-thick_95_ffdc2e_40x40.png +0 -0
  30. data/app/assets/images/jquery-ui/ui-bg_diamond_10_4f4221_10x8.png +0 -0
  31. data/app/assets/images/jquery-ui/ui-bg_diamond_20_372806_10x8.png +0 -0
  32. data/app/assets/images/jquery-ui/ui-bg_diamond_25_675423_10x8.png +0 -0
  33. data/app/assets/images/jquery-ui/ui-bg_diamond_25_d5ac5d_10x8.png +0 -0
  34. data/app/assets/images/jquery-ui/ui-bg_diamond_8_261803_10x8.png +0 -0
  35. data/app/assets/images/jquery-ui/ui-bg_diamond_8_443113_10x8.png +0 -0
  36. data/app/assets/images/jquery-ui/ui-bg_dots-medium_30_0b58a2_4x4.png +0 -0
  37. data/app/assets/images/jquery-ui/ui-bg_dots-medium_80_ffff38_4x4.png +0 -0
  38. data/app/assets/images/jquery-ui/ui-bg_dots-small_20_333333_2x2.png +0 -0
  39. data/app/assets/images/jquery-ui/ui-bg_dots-small_30_a32d00_2x2.png +0 -0
  40. data/app/assets/images/jquery-ui/ui-bg_dots-small_35_35414f_2x2.png +0 -0
  41. data/app/assets/images/jquery-ui/ui-bg_dots-small_40_00498f_2x2.png +0 -0
  42. data/app/assets/images/jquery-ui/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
  43. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_eceadf_60x60.png +0 -0
  44. data/app/assets/images/jquery-ui/ui-bg_fine-grain_10_f8f7f6_60x60.png +0 -0
  45. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_eceadf_60x60.png +0 -0
  46. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_f7f3de_60x60.png +0 -0
  47. data/app/assets/images/jquery-ui/ui-bg_fine-grain_15_ffffff_60x60.png +0 -0
  48. data/app/assets/images/jquery-ui/ui-bg_fine-grain_65_654b24_60x60.png +0 -0
  49. data/app/assets/images/jquery-ui/ui-bg_fine-grain_68_b83400_60x60.png +0 -0
  50. data/app/assets/images/jquery-ui/ui-bg_flat_0_303030_40x100.png +0 -0
  51. data/app/assets/images/jquery-ui/ui-bg_flat_0_333333_40x100.png +0 -0
  52. data/app/assets/images/jquery-ui/ui-bg_flat_0_4c4c4c_40x100.png +0 -0
  53. data/app/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  54. data/app/assets/images/jquery-ui/ui-bg_flat_0_e69700_40x100.png +0 -0
  55. data/app/assets/images/jquery-ui/ui-bg_flat_0_e6b900_40x100.png +0 -0
  56. data/app/assets/images/jquery-ui/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  57. data/app/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  58. data/app/assets/images/jquery-ui/ui-bg_flat_15_cd0a0a_40x100.png +0 -0
  59. data/app/assets/images/jquery-ui/ui-bg_flat_30_cccccc_40x100.png +0 -0
  60. data/app/assets/images/jquery-ui/ui-bg_flat_40_292929_40x100.png +0 -0
  61. data/app/assets/images/jquery-ui/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  62. data/app/assets/images/jquery-ui/ui-bg_flat_55_994d53_40x100.png +0 -0
  63. data/app/assets/images/jquery-ui/ui-bg_flat_55_999999_40x100.png +0 -0
  64. data/app/assets/images/jquery-ui/ui-bg_flat_55_c0402a_40x100.png +0 -0
  65. data/app/assets/images/jquery-ui/ui-bg_flat_55_eeeeee_40x100.png +0 -0
  66. data/app/assets/images/jquery-ui/ui-bg_flat_55_fafafa_40x100.png +0 -0
  67. data/app/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  68. data/app/assets/images/jquery-ui/ui-bg_flat_55_ffffff_40x100.png +0 -0
  69. data/app/assets/images/jquery-ui/ui-bg_flat_65_ffffff_40x100.png +0 -0
  70. data/app/assets/images/jquery-ui/ui-bg_flat_75_aaaaaa_40x100.png +0 -0
  71. data/app/assets/images/jquery-ui/ui-bg_flat_75_ba9217_40x100.png +0 -0
  72. data/app/assets/images/jquery-ui/ui-bg_flat_75_ddd4b0_40x100.png +0 -0
  73. data/app/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png +0 -0
  74. data/app/assets/images/jquery-ui/ui-bg_glass_100_e4f1fb_1x400.png +0 -0
  75. data/app/assets/images/jquery-ui/ui-bg_glass_100_f5f0e5_1x400.png +0 -0
  76. data/app/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  77. data/app/assets/images/jquery-ui/ui-bg_glass_100_f8f8f8_1x400.png +0 -0
  78. data/app/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  79. data/app/assets/images/jquery-ui/ui-bg_glass_15_5f391b_1x400.png +0 -0
  80. data/app/assets/images/jquery-ui/ui-bg_glass_20_555555_1x400.png +0 -0
  81. data/app/assets/images/jquery-ui/ui-bg_glass_25_cb842e_1x400.png +0 -0
  82. data/app/assets/images/jquery-ui/ui-bg_glass_35_dddddd_1x400.png +0 -0
  83. data/app/assets/images/jquery-ui/ui-bg_glass_40_0078a3_1x400.png +0 -0
  84. data/app/assets/images/jquery-ui/ui-bg_glass_40_0a0a0a_1x400.png +0 -0
  85. data/app/assets/images/jquery-ui/ui-bg_glass_40_111111_1x400.png +0 -0
  86. data/app/assets/images/jquery-ui/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  87. data/app/assets/images/jquery-ui/ui-bg_glass_45_0078ae_1x400.png +0 -0
  88. data/app/assets/images/jquery-ui/ui-bg_glass_50_3baae3_1x400.png +0 -0
  89. data/app/assets/images/jquery-ui/ui-bg_glass_55_1c1c1c_1x400.png +0 -0
  90. data/app/assets/images/jquery-ui/ui-bg_glass_55_f1fbe5_1x400.png +0 -0
  91. data/app/assets/images/jquery-ui/ui-bg_glass_55_f8da4e_1x400.png +0 -0
  92. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
  93. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
  94. data/app/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  95. data/app/assets/images/jquery-ui/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  96. data/app/assets/images/jquery-ui/ui-bg_glass_60_000000_1x400.png +0 -0
  97. data/app/assets/images/jquery-ui/ui-bg_glass_60_eeeeee_1x400.png +0 -0
  98. data/app/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  99. data/app/assets/images/jquery-ui/ui-bg_glass_70_ede4d4_1x400.png +0 -0
  100. data/app/assets/images/jquery-ui/ui-bg_glass_75_79c9ec_1x400.png +0 -0
  101. data/app/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  102. data/app/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png +0 -0
  103. data/app/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  104. data/app/assets/images/jquery-ui/ui-bg_glass_80_d7ebf9_1x400.png +0 -0
  105. data/app/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  106. data/app/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  107. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_100_ece8da_500x100.png +0 -0
  108. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_16_121212_500x100.png +0 -0
  109. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_111111_500x100.png +0 -0
  110. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_20_1c160d_500x100.png +0 -0
  111. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  112. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_25_453326_500x100.png +0 -0
  113. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_3d3644_500x100.png +0 -0
  114. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_30_44372c_500x100.png +0 -0
  115. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  116. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_817865_500x100.png +0 -0
  117. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_45_e14f1c_500x100.png +0 -0
  118. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_50_6eac2c_500x100.png +0 -0
  119. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_000000_500x100.png +0 -0
  120. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  121. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_60_fece2f_500x100.png +0 -0
  122. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_70_ffdd57_500x100.png +0 -0
  123. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_75_2191c0_500x100.png +0 -0
  124. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_85_9fda58_500x100.png +0 -0
  125. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_90_fff9e5_500x100.png +0 -0
  126. data/app/assets/images/jquery-ui/ui-bg_gloss-wave_95_f6ecd5_500x100.png +0 -0
  127. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
  128. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f2f5f7_1x100.png +0 -0
  129. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f4f0ec_1x100.png +0 -0
  130. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f5f3e5_1x100.png +0 -0
  131. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
  132. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
  133. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_100_fafaf4_1x100.png +0 -0
  134. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_459e00_1x100.png +0 -0
  135. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_15_888888_1x100.png +0 -0
  136. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_20_0972a5_1x100.png +0 -0
  137. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_30_285c00_1x100.png +0 -0
  138. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png +0 -0
  139. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_55_555555_1x100.png +0 -0
  140. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_65_fee4bd_1x100.png +0 -0
  141. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_70_000000_1x100.png +0 -0
  142. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_75_f5f5b5_1x100.png +0 -0
  143. data/app/assets/images/jquery-ui/ui-bg_highlight-hard_95_cccccc_1x100.png +0 -0
  144. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_dcd9de_1x100.png +0 -0
  145. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_deedf7_1x100.png +0 -0
  146. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eae6ea_1x100.png +0 -0
  147. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  148. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  149. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_f9f9f9_1x100.png +0 -0
  150. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_100_feeebd_1x100.png +0 -0
  151. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
  152. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_201913_1x100.png +0 -0
  153. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_20_619226_1x100.png +0 -0
  154. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  155. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_30273a_1x100.png +0 -0
  156. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_67b021_1x100.png +0 -0
  157. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_25_ffef8f_1x100.png +0 -0
  158. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_003147_1x100.png +0 -0
  159. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_33_3a8104_1x100.png +0 -0
  160. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_222222_1x100.png +0 -0
  161. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_35_adadad_1x100.png +0 -0
  162. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_44_444444_1x100.png +0 -0
  163. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_45_5f5964_1x100.png +0 -0
  164. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_4eb305_1x100.png +0 -0
  165. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png +0 -0
  166. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  167. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_4ca20b_1x100.png +0 -0
  168. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_60_dddddd_1x100.png +0 -0
  169. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  170. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  171. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  172. data/app/assets/images/jquery-ui/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  173. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_eeeeee_1x100.png +0 -0
  174. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  175. data/app/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  176. data/app/assets/images/jquery-ui/ui-bg_inset-hard_45_cd0a0a_1x100.png +0 -0
  177. data/app/assets/images/jquery-ui/ui-bg_inset-hard_55_ffeb80_1x100.png +0 -0
  178. data/app/assets/images/jquery-ui/ui-bg_inset-hard_75_999999_1x100.png +0 -0
  179. data/app/assets/images/jquery-ui/ui-bg_inset-soft_100_f4f0ec_1x100.png +0 -0
  180. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_201913_1x100.png +0 -0
  181. data/app/assets/images/jquery-ui/ui-bg_inset-soft_10_285c00_1x100.png +0 -0
  182. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_121212_1x100.png +0 -0
  183. data/app/assets/images/jquery-ui/ui-bg_inset-soft_15_2b2922_1x100.png +0 -0
  184. data/app/assets/images/jquery-ui/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  185. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  186. data/app/assets/images/jquery-ui/ui-bg_inset-soft_30_ffffff_1x100.png +0 -0
  187. data/app/assets/images/jquery-ui/ui-bg_inset-soft_50_c9c9c9_1x100.png +0 -0
  188. data/app/assets/images/jquery-ui/ui-bg_loop_25_000000_21x21.png +0 -0
  189. data/app/assets/images/jquery-ui/ui-bg_white-lines_85_f7f7ba_40x100.png +0 -0
  190. data/app/assets/images/jquery-ui/ui-icons_000000_256x240.png +0 -0
  191. data/app/assets/images/jquery-ui/ui-icons_004276_256x240.png +0 -0
  192. data/app/assets/images/jquery-ui/ui-icons_00498f_256x240.png +0 -0
  193. data/app/assets/images/jquery-ui/ui-icons_0073ea_256x240.png +0 -0
  194. data/app/assets/images/jquery-ui/ui-icons_0078ae_256x240.png +0 -0
  195. data/app/assets/images/jquery-ui/ui-icons_056b93_256x240.png +0 -0
  196. data/app/assets/images/jquery-ui/ui-icons_070603_256x240.png +0 -0
  197. data/app/assets/images/jquery-ui/ui-icons_0a82eb_256x240.png +0 -0
  198. data/app/assets/images/jquery-ui/ui-icons_0b54d5_256x240.png +0 -0
  199. data/app/assets/images/jquery-ui/ui-icons_1f1f1f_256x240.png +0 -0
  200. data/app/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  201. data/app/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  202. data/app/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  203. data/app/assets/images/jquery-ui/ui-icons_2694e8_256x240.png +0 -0
  204. data/app/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  205. data/app/assets/images/jquery-ui/ui-icons_3383bb_256x240.png +0 -0
  206. data/app/assets/images/jquery-ui/ui-icons_3572ac_256x240.png +0 -0
  207. data/app/assets/images/jquery-ui/ui-icons_3d3d3d_256x240.png +0 -0
  208. data/app/assets/images/jquery-ui/ui-icons_3d80b3_256x240.png +0 -0
  209. data/app/assets/images/jquery-ui/ui-icons_454545_256x240.png +0 -0
  210. data/app/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  211. data/app/assets/images/jquery-ui/ui-icons_4b8e0b_256x240.png +0 -0
  212. data/app/assets/images/jquery-ui/ui-icons_4ca300_256x240.png +0 -0
  213. data/app/assets/images/jquery-ui/ui-icons_4eb305_256x240.png +0 -0
  214. data/app/assets/images/jquery-ui/ui-icons_5fa5e3_256x240.png +0 -0
  215. data/app/assets/images/jquery-ui/ui-icons_666666_256x240.png +0 -0
  216. data/app/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  217. data/app/assets/images/jquery-ui/ui-icons_70b2e1_256x240.png +0 -0
  218. data/app/assets/images/jquery-ui/ui-icons_72a7cf_256x240.png +0 -0
  219. data/app/assets/images/jquery-ui/ui-icons_72b42d_256x240.png +0 -0
  220. data/app/assets/images/jquery-ui/ui-icons_734d99_256x240.png +0 -0
  221. data/app/assets/images/jquery-ui/ui-icons_808080_256x240.png +0 -0
  222. data/app/assets/images/jquery-ui/ui-icons_847e71_256x240.png +0 -0
  223. data/app/assets/images/jquery-ui/ui-icons_888888_256x240.png +0 -0
  224. data/app/assets/images/jquery-ui/ui-icons_88a206_256x240.png +0 -0
  225. data/app/assets/images/jquery-ui/ui-icons_8DC262_256x240.png +0 -0
  226. data/app/assets/images/jquery-ui/ui-icons_8c291d_256x240.png +0 -0
  227. data/app/assets/images/jquery-ui/ui-icons_8d78a5_256x240.png +0 -0
  228. data/app/assets/images/jquery-ui/ui-icons_98d2fb_256x240.png +0 -0
  229. data/app/assets/images/jquery-ui/ui-icons_999999_256x240.png +0 -0
  230. data/app/assets/images/jquery-ui/ui-icons_9bcc60_256x240.png +0 -0
  231. data/app/assets/images/jquery-ui/ui-icons_9ccdfc_256x240.png +0 -0
  232. data/app/assets/images/jquery-ui/ui-icons_9fda58_256x240.png +0 -0
  233. data/app/assets/images/jquery-ui/ui-icons_a83300_256x240.png +0 -0
  234. data/app/assets/images/jquery-ui/ui-icons_a8a3ae_256x240.png +0 -0
  235. data/app/assets/images/jquery-ui/ui-icons_aaaaaa_256x240.png +0 -0
  236. data/app/assets/images/jquery-ui/ui-icons_add978_256x240.png +0 -0
  237. data/app/assets/images/jquery-ui/ui-icons_b83400_256x240.png +0 -0
  238. data/app/assets/images/jquery-ui/ui-icons_b8ec79_256x240.png +0 -0
  239. data/app/assets/images/jquery-ui/ui-icons_bbbbbb_256x240.png +0 -0
  240. data/app/assets/images/jquery-ui/ui-icons_bd7b00_256x240.png +0 -0
  241. data/app/assets/images/jquery-ui/ui-icons_c02669_256x240.png +0 -0
  242. data/app/assets/images/jquery-ui/ui-icons_c47a23_256x240.png +0 -0
  243. data/app/assets/images/jquery-ui/ui-icons_c98000_256x240.png +0 -0
  244. data/app/assets/images/jquery-ui/ui-icons_cb672b_256x240.png +0 -0
  245. data/app/assets/images/jquery-ui/ui-icons_cc0000_256x240.png +0 -0
  246. data/app/assets/images/jquery-ui/ui-icons_cccccc_256x240.png +0 -0
  247. data/app/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  248. data/app/assets/images/jquery-ui/ui-icons_d19405_256x240.png +0 -0
  249. data/app/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  250. data/app/assets/images/jquery-ui/ui-icons_e0fdff_256x240.png +0 -0
  251. data/app/assets/images/jquery-ui/ui-icons_e1e463_256x240.png +0 -0
  252. data/app/assets/images/jquery-ui/ui-icons_e3ddc9_256x240.png +0 -0
  253. data/app/assets/images/jquery-ui/ui-icons_e8e2b5_256x240.png +0 -0
  254. data/app/assets/images/jquery-ui/ui-icons_e9cd86_256x240.png +0 -0
  255. data/app/assets/images/jquery-ui/ui-icons_eb990f_256x240.png +0 -0
  256. data/app/assets/images/jquery-ui/ui-icons_ebccce_256x240.png +0 -0
  257. data/app/assets/images/jquery-ui/ui-icons_ed9f26_256x240.png +0 -0
  258. data/app/assets/images/jquery-ui/ui-icons_ededed_256x240.png +0 -0
  259. data/app/assets/images/jquery-ui/ui-icons_eeeeee_256x240.png +0 -0
  260. data/app/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  261. data/app/assets/images/jquery-ui/ui-icons_efec9f_256x240.png +0 -0
  262. data/app/assets/images/jquery-ui/ui-icons_f08000_256x240.png +0 -0
  263. data/app/assets/images/jquery-ui/ui-icons_f1fd86_256x240.png +0 -0
  264. data/app/assets/images/jquery-ui/ui-icons_f29a00_256x240.png +0 -0
  265. data/app/assets/images/jquery-ui/ui-icons_f2ec64_256x240.png +0 -0
  266. data/app/assets/images/jquery-ui/ui-icons_f35f07_256x240.png +0 -0
  267. data/app/assets/images/jquery-ui/ui-icons_f5e175_256x240.png +0 -0
  268. data/app/assets/images/jquery-ui/ui-icons_f7a50d_256x240.png +0 -0
  269. data/app/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  270. data/app/assets/images/jquery-ui/ui-icons_f9f2bd_256x240.png +0 -0
  271. data/app/assets/images/jquery-ui/ui-icons_fadc7a_256x240.png +0 -0
  272. data/app/assets/images/jquery-ui/ui-icons_fbc856_256x240.png +0 -0
  273. data/app/assets/images/jquery-ui/ui-icons_fbdb93_256x240.png +0 -0
  274. data/app/assets/images/jquery-ui/ui-icons_fcd113_256x240.png +0 -0
  275. data/app/assets/images/jquery-ui/ui-icons_fcdd4a_256x240.png +0 -0
  276. data/app/assets/images/jquery-ui/ui-icons_ff0084_256x240.png +0 -0
  277. data/app/assets/images/jquery-ui/ui-icons_ff7519_256x240.png +0 -0
  278. data/app/assets/images/jquery-ui/ui-icons_ffcf29_256x240.png +0 -0
  279. data/app/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  280. data/app/assets/images/jquery-ui/ui-icons_ffe180_256x240.png +0 -0
  281. data/app/assets/images/jquery-ui/ui-icons_ffeb33_256x240.png +0 -0
  282. data/app/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  283. data/app/assets/javascripts/inline_forms/inline_forms.js +14 -0
  284. data/app/assets/stylesheets/inline_forms/_foundation_icons.scss +596 -0
  285. data/app/assets/stylesheets/inline_forms/devise.scss +34 -3
  286. data/app/assets/stylesheets/inline_forms/foundation_and_overrides.scss +62 -4
  287. data/app/assets/stylesheets/inline_forms/inline_forms.scss +196 -44
  288. data/app/assets/stylesheets/jquery_ui/jquery.ui.accordion.css.scss +39 -0
  289. data/app/assets/stylesheets/jquery_ui/jquery.ui.all.css.scss +14 -0
  290. data/app/assets/stylesheets/jquery_ui/jquery.ui.autocomplete.css.scss +17 -0
  291. data/app/assets/stylesheets/jquery_ui/jquery.ui.base.css.scss +27 -0
  292. data/app/assets/stylesheets/jquery_ui/jquery.ui.button.css.scss +115 -0
  293. data/app/assets/stylesheets/jquery_ui/jquery.ui.core.css.scss +92 -0
  294. data/app/assets/stylesheets/jquery_ui/jquery.ui.datepicker.css.scss +179 -0
  295. data/app/assets/stylesheets/jquery_ui/jquery.ui.dialog.css.scss +70 -0
  296. data/app/assets/stylesheets/jquery_ui/jquery.ui.menu.css.scss +80 -0
  297. data/app/assets/stylesheets/jquery_ui/jquery.ui.progressbar.css.scss +29 -0
  298. data/app/assets/stylesheets/jquery_ui/jquery.ui.resizable.css.scss +79 -0
  299. data/app/assets/stylesheets/jquery_ui/jquery.ui.selectable.css.scss +16 -0
  300. data/app/assets/stylesheets/jquery_ui/jquery.ui.slider.css.scss +74 -0
  301. data/app/assets/stylesheets/jquery_ui/jquery.ui.spinner.css.scss +66 -0
  302. data/app/assets/stylesheets/jquery_ui/jquery.ui.tabs.css.scss +53 -0
  303. data/app/assets/stylesheets/jquery_ui/jquery.ui.theme.css.scss +408 -0
  304. data/app/assets/stylesheets/jquery_ui/jquery.ui.tooltip.css.scss +20 -0
  305. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.base.css.scss +78 -0
  306. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.black-tie.css.scss +80 -0
  307. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.blitzer.css.scss +80 -0
  308. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.cupertino.css.scss +80 -0
  309. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dark-hive.css.scss +80 -0
  310. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.dot-luv.css.scss +80 -0
  311. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.eggplant.css.scss +80 -0
  312. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.excite-bike.css.scss +80 -0
  313. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.flick.css.scss +80 -0
  314. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.hot-sneaks.css.scss +80 -0
  315. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.humanity.css.scss +80 -0
  316. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.le-frog.css.scss +80 -0
  317. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.mint-choc.css.scss +80 -0
  318. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.overcast.css.scss +80 -0
  319. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.pepper-grinder.css.scss +80 -0
  320. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.redmond.css.scss +80 -0
  321. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.smoothness.css.scss +80 -0
  322. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.south-street.css.scss +80 -0
  323. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.start.css.scss +80 -0
  324. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.sunny.css.scss +80 -0
  325. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.swanky-purse.css.scss +80 -0
  326. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.trontastic.css.scss +80 -0
  327. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-darkness.css.scss +80 -0
  328. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.ui-lightness.css.scss +80 -0
  329. data/app/assets/stylesheets/jquery_ui/themes/_jquery.ui.vader.css.scss +80 -0
  330. data/app/controllers/inline_forms_controller.rb +29 -1
  331. data/app/helpers/form_elements/rich_text.rb +36 -0
  332. data/app/helpers/inline_forms_helper.rb +40 -0
  333. data/app/views/devise/passwords/_top-bar-and-flash.html.erb +8 -9
  334. data/app/views/devise/passwords/edit.html.erb +1 -1
  335. data/app/views/devise/passwords/new.html.erb +1 -1
  336. data/app/views/devise/sessions/_top-bar.html.erb +8 -9
  337. data/app/views/devise/sessions/new.html.erb +1 -1
  338. data/app/views/inline_forms/_edit.html.erb +1 -1
  339. data/app/views/inline_forms/_header.html.erb +18 -25
  340. data/app/views/inline_forms/_list.html.erb +64 -4
  341. data/app/views/inline_forms/_versions_list.html.erb +75 -50
  342. data/app/views/layouts/application.html.erb +13 -2
  343. data/app/views/layouts/inline_forms.html.erb +14 -2
  344. data/bin/inline_forms +1 -1
  345. data/bin/inline_forms_app_template.rb +3 -1
  346. data/bin/inline_forms_installer_core.rb +203 -36
  347. data/docs/prompt/.gitignore +5 -0
  348. data/docs/prompt/test-the-example-app.md +32 -0
  349. data/inline_forms.gemspec +1 -1
  350. data/lib/generators/assets/stylesheets/inline_forms.scss +215 -76
  351. data/lib/generators/inline_forms_generator.rb +30 -0
  352. data/lib/generators/templates/_inline_forms_tabs.html.erb +38 -39
  353. data/lib/generators/templates/migration.erb +1 -1
  354. data/lib/generators/templates/model.erb +1 -0
  355. data/lib/inline_forms/version.rb +1 -1
  356. data/lib/inline_forms.rb +10 -0
  357. data/lib/installer_templates/dartsass/devise_main.scss +2 -0
  358. data/lib/installer_templates/dartsass/inline_forms_dartsass_builds.rb +14 -0
  359. data/lib/installer_templates/dartsass/inline_forms_main.scss +2 -0
  360. data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_photos_pagination_test.rb +228 -0
  361. data/lib/installer_templates/example_app_tests/test/integration/example_app_turbo_layout_test.rb +28 -0
  362. data/lib/installer_templates/example_app_tests/test/models/example_app_paper_trail_changeset_test.rb +78 -0
  363. data/test/inline_forms_generator_test.rb +155 -0
  364. metadata +336 -5
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../example_app/example_integration_test_case"
4
+
5
+ # Smoke test for rollout step 2 of stuff/ujs-to-turbo.md (gem-side):
6
+ # the nested has_many list (apartments -> photos) is now wrapped in a
7
+ # <turbo-frame> and pagination is no longer remote: true. Relies on
8
+ # the SeedKonferenshaPhotos migration that the inline_forms installer
9
+ # generates when invoked with --example: it creates a "Konferensha"
10
+ # Apartment with one Photo per file in db/seed_images/, and the gem
11
+ # ships 12 sample jpgs in pics/, so combined with `Photo.per_page = 5`
12
+ # (also set by the installer) this gallery paginates 5 / 5 / 2.
13
+ class ExampleAppApartmentPhotosPaginationTest < ExampleAppIntegrationTestCase
14
+ # `bundle exec rails test` loads the test DB from db/schema.rb, which is
15
+ # DDL-only -- the SeedKonferenshaPhotos migration's row inserts never
16
+ # land in db/test.sqlite3. We re-seed here from the same db/seed_images/
17
+ # the installer copied into the app so the test asserts against real
18
+ # records (and real CarrierWave file mounts) without depending on
19
+ # development-DB state.
20
+ setup do
21
+ @apartment = Apartment.find_or_create_by!(name: "Konferensha") do |a|
22
+ a.title = "Konferensha sobre Papiamentu"
23
+ end
24
+ seed_dir = Rails.root.join("db", "seed_images")
25
+ if seed_dir.directory?
26
+ Dir.glob(seed_dir.join("*.{jpg,jpeg,png,gif}"), File::FNM_CASEFOLD).sort.each do |abs|
27
+ base = File.basename(abs)
28
+ next if Photo.exists?(name: base, apartment_id: @apartment.id)
29
+ File.open(abs, "rb") do |io|
30
+ Photo.create!(
31
+ name: base,
32
+ caption: "Konferensha foto #{base}",
33
+ apartment: @apartment,
34
+ image: io
35
+ )
36
+ end
37
+ end
38
+ end
39
+ @update_span = "apartment_#{@apartment.id}_photos_list"
40
+ end
41
+
42
+ test "seed migration left at least 6 photos under Konferensha so pagination triggers" do
43
+ assert @apartment.photos.count >= 6,
44
+ "expected SeedKonferenshaPhotos to seed >= 6 photos for Konferensha; " \
45
+ "got #{@apartment.photos.count}. Check db/seed_images/ and the migration."
46
+ end
47
+
48
+ test "Photo.per_page is overridden so will_paginate splits the gallery" do
49
+ assert_equal 5, Photo.per_page,
50
+ "expected the installer to set `self.per_page = 5` on Photo so the seeded gallery paginates"
51
+ end
52
+
53
+ test "nested photos index without Turbo-Frame header renders full inline_forms layout (bookmark / full navigation)" do
54
+ get photos_path(
55
+ parent_class: "Apartment",
56
+ parent_id: @apartment.id,
57
+ update: @update_span,
58
+ ul_needed: true
59
+ )
60
+ assert_response :success
61
+
62
+ assert_match(
63
+ /id="outer_container"/,
64
+ @response.body,
65
+ "direct or full-page GET /photos?... must use the inline_forms layout " \
66
+ "so the page is styled; `layout: false` used to emit only a bare <turbo-frame> " \
67
+ "which looks broken in the address bar."
68
+ )
69
+ assert_match(
70
+ %r{<turbo-frame\s+id="#{Regexp.escape(@update_span)}"},
71
+ @response.body,
72
+ "expected the gallery frame inside the layout body"
73
+ )
74
+ end
75
+
76
+ test "nested photos index with Turbo-Frame header uses minimal layout without app chrome" do
77
+ get photos_path(
78
+ parent_class: "Apartment",
79
+ parent_id: @apartment.id,
80
+ update: @update_span,
81
+ ul_needed: true
82
+ ),
83
+ headers: { "Turbo-Frame" => @update_span }
84
+ assert_response :success
85
+
86
+ assert_match(
87
+ %r{<turbo-frame\s+id="#{Regexp.escape(@update_span)}"},
88
+ @response.body,
89
+ "expected Turbo frame navigation to receive a matching <turbo-frame id=\"#{@update_span}\">"
90
+ )
91
+ refute_match(
92
+ /id="outer_container"/,
93
+ @response.body,
94
+ "frame requests should not pay for the full inline_forms chrome; use turbo_rails/frame layout"
95
+ )
96
+ end
97
+
98
+ test "nested photos index is wrapped in a <turbo-frame> instead of remote-UJS <div>" do
99
+ get photos_path(
100
+ parent_class: "Apartment",
101
+ parent_id: @apartment.id,
102
+ update: @update_span,
103
+ ul_needed: true
104
+ )
105
+ assert_response :success
106
+
107
+ assert_match(
108
+ %r{<turbo-frame\s+id="#{Regexp.escape(@update_span)}"},
109
+ @response.body,
110
+ "expected the nested photos list to render as <turbo-frame id=\"#{@update_span}\">"
111
+ )
112
+
113
+ refute_match(
114
+ %r{<div[^>]+class="list_container"[^>]+id="#{Regexp.escape(@update_span)}"},
115
+ @response.body,
116
+ "nested photos list should no longer use the legacy <div class=\"list_container\"> wrapper"
117
+ )
118
+ end
119
+
120
+ test "nested photos pagination renders will_paginate links inside the frame" do
121
+ get photos_path(
122
+ parent_class: "Apartment",
123
+ parent_id: @apartment.id,
124
+ update: @update_span,
125
+ ul_needed: true
126
+ )
127
+ assert_response :success
128
+
129
+ assert_match(
130
+ /<(?:div|nav)[^>]+class="[^"]*\bpagination\b[^"]*"/,
131
+ @response.body,
132
+ "expected will_paginate to render a .pagination element (gallery has more rows than Photo.per_page)"
133
+ )
134
+
135
+ refute_match(
136
+ /class="next_page"[^>]*data-remote="true"/,
137
+ @response.body,
138
+ "pagination links should no longer carry data-remote=\"true\" (Turbo Frame handles in-frame nav)"
139
+ )
140
+ end
141
+
142
+ test "pagination links carry the same update= as the surrounding turbo-frame id" do
143
+ # This is the regression class that broke "Next" in 7.2.1: the
144
+ # legacy UJS pagination passed `update=apartment_<id>_photos`
145
+ # (the OUTER wrapper id from _show.html.erb, which list.js.erb
146
+ # used as the swap target). Turbo Frames swaps by id-match between
147
+ # the frame in the DOM and a frame in the response, so when a Next
148
+ # click re-rendered _list with update_span derived from the URL,
149
+ # the response contained `<turbo-frame id="apartment_<id>_photos">`
150
+ # while the page held `<turbo-frame id="apartment_<id>_photos_list">`,
151
+ # and Turbo logged "the response did not contain the expected
152
+ # <turbo-frame>" and dropped the swap. The `update=` param on every
153
+ # pagination link must be the same id as the surrounding frame.
154
+ get photos_path(
155
+ parent_class: "Apartment",
156
+ parent_id: @apartment.id,
157
+ update: @update_span,
158
+ ul_needed: true
159
+ )
160
+ assert_response :success
161
+
162
+ page_link_updates =
163
+ @response.body.scan(/href="[^"]*\?[^"]*update=([^&"]+)[^"]*"/).flatten
164
+
165
+ assert page_link_updates.any? { |u| u == @update_span },
166
+ "expected at least one pagination link to carry update=#{@update_span} " \
167
+ "(matching the <turbo-frame id=\"#{@update_span}\">), got updates=#{page_link_updates.inspect}"
168
+
169
+ refute page_link_updates.any? { |u| u == @update_span.sub(/_list\z/, "") },
170
+ "no pagination link should still carry the legacy outer-wrapper id " \
171
+ "(#{@update_span.sub(/_list\z/, "")}) -- Turbo Frame can't swap on that id"
172
+ end
173
+
174
+ test "top-level apartment rows do NOT carry data-turbo=\"false\" (would poison nested frames)" do
175
+ # 7.2.2 broke pagination of the inner photos <turbo-frame> because
176
+ # the top-level apartment row was emitting data-turbo="false" too.
177
+ # When show.js.erb swaps the inline edit (containing the nested
178
+ # <turbo-frame>) into that row, every link inside the nested frame
179
+ # -- including pagination links -- has the row as an ancestor.
180
+ # Turbo's Session.elementIsNavigatable does
181
+ # `findClosestRecursively(link, "[data-turbo]")` and does NOT stop
182
+ # at the intervening <turbo-frame>; it picks up the row's
183
+ # data-turbo="false" and refuses to intercept the click, so the
184
+ # browser does a full-page navigation to /photos?page=N&... and
185
+ # the user sees the bare partial without a layout. The attribute
186
+ # must stay scoped to NESTED rows (which need the opt-out for
187
+ # their swapped-in inline-edit forms); top-level rows must NOT
188
+ # carry it.
189
+ get apartments_path
190
+ assert_response :success
191
+
192
+ refute_match(
193
+ /<div[^>]+class="[^"]*\btop-level\b[^"]*"[^>]*data-turbo="false"|<div[^>]+data-turbo="false"[^>]*class="[^"]*\btop-level\b[^"]*"/,
194
+ @response.body,
195
+ "top-level list rows must not carry data-turbo=\"false\"; that attribute would " \
196
+ "be inherited by every link inside any nested <turbo-frame> swapped into the row"
197
+ )
198
+ end
199
+
200
+ test "row container opts out of Turbo so swapped-in UJS forms (replace photo etc.) keep working" do
201
+ get photos_path(
202
+ parent_class: "Apartment",
203
+ parent_id: @apartment.id,
204
+ update: @update_span,
205
+ ul_needed: true
206
+ )
207
+ assert_response :success
208
+
209
+ # The container-level opt-out is what protects the inline-edit /
210
+ # replace-photo flow: when a user replaces a photo, show.js.erb /
211
+ # edit.js.erb does $('#<row_id>').html(<form>), so the multipart
212
+ # form that submits the upload is a descendant of this row. With
213
+ # data-turbo="false" on the row, Turbo doesn't intercept that
214
+ # submission -- jquery-ujs + remotipart do, the request goes out
215
+ # with Accept: text/javascript, and the controller's format.js
216
+ # branch handles it. Without this, Turbo Frames would send
217
+ # Accept: text/html and the update action (no format.html for
218
+ # not_accessible_through_html? models like Photo) raises
219
+ # UnknownFormat AFTER the DB write -- a 406 with a corrupted UI.
220
+ sample_row_id = "apartment_#{@apartment.id}_photo_#{@apartment.photos.first.id}"
221
+ assert_match(
222
+ %r{<div[^>]+id="#{Regexp.escape(sample_row_id)}"[^>]*data-turbo="false"|<div[^>]+data-turbo="false"[^>]*id="#{Regexp.escape(sample_row_id)}"},
223
+ @response.body,
224
+ "expected the per-row container (id=\"#{sample_row_id}\") to carry data-turbo=\"false\" " \
225
+ "so swapped-in UJS forms inherit the Turbo opt-out"
226
+ )
227
+ end
228
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../example_app/example_integration_test_case"
4
+
5
+ # Smoke test for rollout step 1 of stuff/ujs-to-turbo.md (gem-side):
6
+ # the layout loads Turbo as an ES module and disables Drive so existing
7
+ # UJS-driven links/forms keep working unchanged. If this asserts ever
8
+ # fails, frame/stream conversions in later slices will silently fall
9
+ # back to full-page navigation (Turbo not loaded) instead of using the
10
+ # `<turbo-frame>` fast path.
11
+ class ExampleAppTurboLayoutTest < ExampleAppIntegrationTestCase
12
+ test "inline_forms layout loads turbo.min.js as an ES module with drive disabled" do
13
+ get apartments_path
14
+ assert_response :success
15
+
16
+ assert_match(
17
+ %r{<script\s+type="module">\s*import\s+\{\s*Turbo\s*\}\s+from\s+"[^"]*turbo\.min(?:-[a-f0-9]+)?\.js"}m,
18
+ @response.body,
19
+ "expected the inline_forms layout to import turbo.min.js as a module"
20
+ )
21
+
22
+ assert_match(
23
+ /Turbo\.session\.drive\s*=\s*false/,
24
+ @response.body,
25
+ "expected Turbo.session.drive = false so existing UJS keeps working"
26
+ )
27
+ end
28
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ # Regression: PaperTrail (>= 13) deserializes `versions.object_changes` via
6
+ # `YAML.safe_load`, using `ActiveRecord.yaml_column_permitted_classes` as the
7
+ # allow-list. Rails 7's default is `[Symbol]`, so any update that touches
8
+ # `updated_at` (an `ActiveSupport::TimeWithZone`) raises `Psych::DisallowedClass`
9
+ # inside `version.changeset`, and PaperTrail rescues that into `{}`. The
10
+ # inline_forms versions list then renders every changeset as `empty`.
11
+ #
12
+ # The installer ships `config/initializers/paper_trail_yaml_safe_load.rb`,
13
+ # which extends the allow-list. This test fails if that initializer is
14
+ # missing or insufficient.
15
+ class ExampleAppPaperTrailChangesetTest < ActiveSupport::TestCase
16
+ test "version.changeset round-trips a normal update" do
17
+ PaperTrail.request.whodunnit = "test"
18
+
19
+ apartment = Apartment.create!(name: "Original", title: "Old Title")
20
+ apartment.update!(name: "Renamed", title: "New Title")
21
+
22
+ version = apartment.versions.last
23
+ assert_equal "update", version.event,
24
+ "expected an update version to be recorded by paper_trail"
25
+
26
+ changeset = version.changeset
27
+ assert_kind_of Hash, changeset
28
+ refute_empty changeset,
29
+ "version.changeset is empty; PaperTrail's YAML.safe_load probably hit a " \
30
+ "DisallowedClass and returned {}. Check " \
31
+ "config/initializers/paper_trail_yaml_safe_load.rb and the Rails " \
32
+ "ActiveRecord.yaml_column_permitted_classes setting."
33
+
34
+ assert_equal ["Original", "Renamed"], changeset["name"]
35
+ assert_equal ["Old Title", "New Title"], changeset["title"]
36
+ end
37
+
38
+ # `has_rich_text :description` lives in the `action_text_rich_texts` table,
39
+ # so `has_paper_trail` on Apartment cannot see body edits. The installer adds
40
+ # `config/initializers/rich_text_paper_trail.rb` (which declares
41
+ # `has_paper_trail` on `ActionText::RichText`), and `inline_forms_versions_for`
42
+ # merges rich-text versions into the parent's history. This test fails if
43
+ # either piece regresses.
44
+ test "rich_text edits surface in the merged versions list for the parent" do
45
+ PaperTrail.request.whodunnit = "test"
46
+
47
+ apartment = Apartment.create!(name: "RT", title: "RT", description: "v1 body")
48
+ apartment.update!(description: "v2 body")
49
+
50
+ rich_text = ActionText::RichText.find_by!(
51
+ record_type: Apartment.name, record_id: apartment.id, name: "description"
52
+ )
53
+ assert rich_text.respond_to?(:versions),
54
+ "ActionText::RichText is missing has_paper_trail; check " \
55
+ "config/initializers/rich_text_paper_trail.rb"
56
+ refute_empty rich_text.versions,
57
+ "no PaperTrail versions on ActionText::RichText; the on_load hook " \
58
+ "in config/initializers/rich_text_paper_trail.rb did not fire or " \
59
+ "has_paper_trail was not applied"
60
+
61
+ helper = Class.new { include InlineFormsHelper }.new
62
+ entries = helper.inline_forms_versions_for(apartment)
63
+
64
+ rich_text_entries = entries.select { |e| e[:kind] == :rich_text }
65
+ refute_empty rich_text_entries,
66
+ "inline_forms_versions_for did not return any rich_text entries"
67
+
68
+ body_changes = rich_text_entries
69
+ .map { |e| e[:version].changeset }
70
+ .select { |cs| cs && cs["body"].is_a?(Array) }
71
+ .map { |cs| cs["body"] }
72
+
73
+ refute_empty body_changes,
74
+ "no body changesets recorded for ActionText::RichText"
75
+ assert body_changes.any? { |old, new_| old.to_s.include?("v1 body") && new_.to_s.include?("v2 body") },
76
+ "expected an entry whose body change moves from 'v1 body' to 'v2 body'; got #{body_changes.inspect}"
77
+ end
78
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+ require "tmpdir"
5
+ require "fileutils"
6
+ require "logger"
7
+ require "rails"
8
+ require "rails/generators"
9
+ require "inline_forms"
10
+ require_relative "../lib/generators/inline_forms_generator"
11
+
12
+ class InlineFormsGeneratorTest < Minitest::Test
13
+ def setup
14
+ @destination_root = Dir.mktmpdir("inline_forms_generator_test")
15
+ build_destination_skeleton!
16
+ end
17
+
18
+ def teardown
19
+ FileUtils.remove_entry(@destination_root) if @destination_root && Dir.exist?(@destination_root)
20
+ end
21
+
22
+ def test_generates_model_controller_route_migration_and_tab_injection
23
+ run_generator(
24
+ "Thing",
25
+ "name:string",
26
+ "category:dropdown",
27
+ "photos:has_many",
28
+ "_enabled:yes",
29
+ "_presentation:\\#{name}"
30
+ )
31
+
32
+ model = read("app/models/thing.rb")
33
+ controller = read("app/controllers/things_controller.rb")
34
+ routes = read("config/routes.rb")
35
+ application_controller = read("app/controllers/application_controller.rb")
36
+ migration = read_single_migration_for("things")
37
+
38
+ assert_includes(model, "class Thing < ApplicationRecord")
39
+ assert_includes(model, "belongs_to :category")
40
+ assert_includes(model, "has_many :photos")
41
+ assert_includes(model, "[ :name , \"name\", :text_field ]")
42
+ assert_includes(model, "[ :category , \"category\", :dropdown ]")
43
+
44
+ assert_includes(controller, "class ThingsController < InlineFormsController")
45
+ assert_includes(controller, "set_tab :thing")
46
+
47
+ assert_includes(routes, "resources :things do")
48
+ assert_includes(routes, "post 'revert', :on => :member")
49
+ assert_includes(routes, "get 'list_versions', :on => :member")
50
+
51
+ assert_includes(application_controller, "MODEL_TABS = %w(things ")
52
+
53
+ assert_includes(migration, "class InlineFormsCreateThings < ActiveRecord::Migration[7.0]")
54
+ assert_includes(migration, "create_table :things do |t|")
55
+ assert_includes(migration, "t.string :name")
56
+ assert_includes(migration, "t.belongs_to :category")
57
+ refute_includes(migration, "photos")
58
+ end
59
+
60
+ def test_skips_model_controller_and_routes_when_no_model_flag_is_present
61
+ run_generator("AuditLog", "message:string", "_no_model:yes")
62
+
63
+ refute_exist("app/models/audit_log.rb")
64
+ refute_exist("app/controllers/audit_logs_controller.rb")
65
+
66
+ routes = read("config/routes.rb")
67
+ refute_includes(routes, "resources :audit_logs")
68
+ end
69
+
70
+ def test_fails_fast_for_unknown_types_by_default
71
+ stdout, stderr = capture_io do
72
+ run_generator("Mystery", "payload:not_a_real_type", "--no-allow-unknown")
73
+ end
74
+ output = "#{stdout}#{stderr}"
75
+
76
+ assert_includes(output, "Unknown field type(s): payload:not_a_real_type")
77
+ assert_includes(output, "--allow-unknown")
78
+ refute_exist("app/models/mystery.rb")
79
+ assert_equal([], Dir.glob(File.join(@destination_root, "db/migrate/*_inline_forms_create_mysteries.rb")))
80
+ end
81
+
82
+ def test_allow_unknown_keeps_legacy_commented_output
83
+ run_generator("Mystery", "payload:not_a_real_type", "--allow-unknown")
84
+
85
+ model = read("app/models/mystery.rb")
86
+ migration = read_single_migration_for("mysteries")
87
+
88
+ assert_includes(model, "# [ :payload , \"payload\", :unknown ]")
89
+ assert_includes(migration, "# t.unknown :payload")
90
+ end
91
+
92
+ def test_rich_text_adds_has_rich_text_without_migration_column
93
+ run_generator("Article", "title:string", "content:rich_text")
94
+
95
+ model = read("app/models/article.rb")
96
+ migration = read_single_migration_for("articles")
97
+
98
+ assert_includes(model, "has_rich_text :content")
99
+ refute_includes(migration, "t.no_migration :content")
100
+ refute_includes(migration, "t.text :content")
101
+ end
102
+
103
+ private
104
+
105
+ def build_destination_skeleton!
106
+ mkdir_p("config")
107
+ mkdir_p("app/controllers")
108
+ mkdir_p("app/models")
109
+ mkdir_p("db/migrate")
110
+ mkdir_p("test/unit")
111
+
112
+ write(
113
+ "config/routes.rb",
114
+ <<~RUBY
115
+ Rails.application.routes.draw do
116
+ end
117
+ RUBY
118
+ )
119
+
120
+ write(
121
+ "app/controllers/application_controller.rb",
122
+ <<~RUBY
123
+ class ApplicationController < ActionController::Base
124
+ ActionView::CompiledTemplates::MODEL_TABS = %w()
125
+ end
126
+ RUBY
127
+ )
128
+ end
129
+
130
+ def run_generator(*args)
131
+ InlineForms::InlineFormsGenerator.start(args, destination_root: @destination_root)
132
+ end
133
+
134
+ def read(relative_path)
135
+ File.read(File.join(@destination_root, relative_path))
136
+ end
137
+
138
+ def read_single_migration_for(table_name)
139
+ migration_files = Dir.glob(File.join(@destination_root, "db/migrate/*_inline_forms_create_#{table_name}.rb"))
140
+ assert_equal(1, migration_files.size, "Expected one migration for #{table_name}, got #{migration_files.inspect}")
141
+ File.read(migration_files.first)
142
+ end
143
+
144
+ def refute_exist(relative_path)
145
+ refute(File.exist?(File.join(@destination_root, relative_path)), "Expected #{relative_path} to not exist")
146
+ end
147
+
148
+ def mkdir_p(relative_path)
149
+ FileUtils.mkdir_p(File.join(@destination_root, relative_path))
150
+ end
151
+
152
+ def write(relative_path, content)
153
+ File.write(File.join(@destination_root, relative_path), content)
154
+ end
155
+ end