rails_admin 2.0.2 → 3.1.2

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 (522) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +15 -16
  3. data/README.md +44 -44
  4. data/Rakefile +15 -2
  5. data/app/assets/javascripts/rails_admin/application.js.erb +29 -0
  6. data/app/assets/stylesheets/rails_admin/application.scss.erb +35 -0
  7. data/app/assets/stylesheets/rails_admin/custom/mixins.scss +1 -1
  8. data/app/assets/stylesheets/rails_admin/custom/variables.scss +1 -1
  9. data/app/controllers/rails_admin/application_controller.rb +6 -3
  10. data/app/controllers/rails_admin/main_controller.rb +55 -50
  11. data/app/helpers/rails_admin/application_helper.rb +129 -63
  12. data/app/helpers/rails_admin/form_builder.rb +25 -13
  13. data/app/helpers/rails_admin/main_helper.rb +18 -41
  14. data/app/views/kaminari/ra-twitter-bootstrap/_gap.html.erb +5 -0
  15. data/app/views/kaminari/ra-twitter-bootstrap/_next_page.html.erb +9 -0
  16. data/app/views/kaminari/ra-twitter-bootstrap/_page.html.erb +9 -0
  17. data/app/views/kaminari/ra-twitter-bootstrap/_paginator.html.erb +15 -0
  18. data/app/views/kaminari/ra-twitter-bootstrap/_prev_page.html.erb +9 -0
  19. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_next_page.html.erb +9 -0
  20. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_paginator.html.erb +8 -0
  21. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_prev_page.html.erb +9 -0
  22. data/app/views/layouts/rails_admin/_head.html.erb +29 -0
  23. data/app/views/layouts/rails_admin/_navigation.html.erb +17 -0
  24. data/app/views/layouts/rails_admin/_secondary_navigation.html.erb +26 -0
  25. data/app/views/layouts/rails_admin/_sidebar_navigation.html.erb +5 -0
  26. data/app/views/layouts/rails_admin/application.html.erb +27 -0
  27. data/app/views/layouts/rails_admin/content.html.erb +22 -0
  28. data/app/views/layouts/rails_admin/modal.js.erb +7 -0
  29. data/app/views/rails_admin/main/_dashboard_history.html.erb +45 -0
  30. data/app/views/rails_admin/main/_delete_notice.html.erb +35 -0
  31. data/app/views/rails_admin/main/_form_action_text.html.erb +8 -0
  32. data/app/views/rails_admin/main/_form_boolean.html.erb +14 -0
  33. data/app/views/rails_admin/main/{_form_ck_editor.html.haml → _form_ck_editor.html.erb} +3 -3
  34. data/app/views/rails_admin/main/_form_code_mirror.html.erb +9 -0
  35. data/app/views/rails_admin/main/_form_colorpicker.html.erb +5 -0
  36. data/app/views/rails_admin/main/_form_datetime.html.erb +10 -0
  37. data/app/views/rails_admin/main/_form_enumeration.html.erb +25 -0
  38. data/app/views/rails_admin/main/_form_field.html.erb +1 -0
  39. data/app/views/rails_admin/main/_form_file_upload.html.erb +17 -0
  40. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +49 -0
  41. data/app/views/rails_admin/main/_form_filtering_select.html.erb +33 -0
  42. data/app/views/rails_admin/main/_form_froala.html.erb +8 -0
  43. data/app/views/rails_admin/main/_form_multiple_file_upload.html.erb +20 -0
  44. data/app/views/rails_admin/main/_form_nested_many.html.erb +21 -0
  45. data/app/views/rails_admin/main/_form_nested_one.html.erb +21 -0
  46. data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +32 -0
  47. data/app/views/rails_admin/main/_form_simple_mde.html.erb +8 -0
  48. data/app/views/rails_admin/main/_form_text.html.erb +1 -0
  49. data/app/views/rails_admin/main/_form_wysihtml5.html.erb +8 -0
  50. data/app/views/rails_admin/main/_submit_buttons.html.erb +25 -0
  51. data/app/views/rails_admin/main/bulk_delete.html.erb +19 -0
  52. data/app/views/rails_admin/main/dashboard.html.erb +64 -0
  53. data/app/views/rails_admin/main/delete.html.erb +21 -0
  54. data/app/views/rails_admin/main/edit.html.erb +3 -0
  55. data/app/views/rails_admin/main/export.html.erb +149 -0
  56. data/app/views/rails_admin/main/history.html.erb +80 -0
  57. data/app/views/rails_admin/main/index.html.erb +184 -0
  58. data/app/views/rails_admin/main/new.html.erb +3 -0
  59. data/app/views/rails_admin/main/show.html.erb +30 -0
  60. data/config/initializers/active_record_extensions.rb +25 -0
  61. data/config/initializers/mongoid_extensions.rb +3 -1
  62. data/config/locales/rails_admin.en.yml +8 -4
  63. data/config/routes.rb +2 -0
  64. data/lib/generators/rails_admin/importmap_formatter.rb +28 -0
  65. data/lib/generators/rails_admin/install_generator.rb +117 -5
  66. data/lib/generators/rails_admin/templates/initializer.erb +2 -1
  67. data/lib/generators/rails_admin/templates/rails_admin.js +1 -0
  68. data/lib/generators/rails_admin/templates/rails_admin.scss.erb +1 -0
  69. data/lib/generators/rails_admin/templates/rails_admin.webpacker.js +2 -0
  70. data/lib/generators/rails_admin/utils.rb +2 -0
  71. data/lib/rails_admin/abstract_model.rb +35 -15
  72. data/lib/rails_admin/adapters/active_record/association.rb +31 -2
  73. data/lib/rails_admin/adapters/active_record/object_extension.rb +31 -0
  74. data/lib/rails_admin/adapters/active_record/property.rb +4 -2
  75. data/lib/rails_admin/adapters/active_record.rb +67 -29
  76. data/lib/rails_admin/adapters/composite_primary_keys/association.rb +45 -0
  77. data/lib/rails_admin/adapters/composite_primary_keys.rb +40 -0
  78. data/lib/rails_admin/adapters/mongoid/association.rb +52 -13
  79. data/lib/rails_admin/adapters/mongoid/bson.rb +6 -5
  80. data/lib/rails_admin/adapters/mongoid/extension.rb +2 -0
  81. data/lib/rails_admin/adapters/mongoid/object_extension.rb +34 -0
  82. data/lib/rails_admin/adapters/mongoid/property.rb +7 -5
  83. data/lib/rails_admin/adapters/mongoid.rb +33 -23
  84. data/lib/rails_admin/config/actions/base.rb +11 -4
  85. data/lib/rails_admin/config/actions/bulk_delete.rb +4 -2
  86. data/lib/rails_admin/config/actions/dashboard.rb +16 -9
  87. data/lib/rails_admin/config/actions/delete.rb +11 -9
  88. data/lib/rails_admin/config/actions/edit.rb +13 -7
  89. data/lib/rails_admin/config/actions/export.rb +6 -3
  90. data/lib/rails_admin/config/actions/history_index.rb +4 -2
  91. data/lib/rails_admin/config/actions/history_show.rb +4 -2
  92. data/lib/rails_admin/config/actions/index.rb +9 -8
  93. data/lib/rails_admin/config/actions/new.rb +18 -10
  94. data/lib/rails_admin/config/actions/show.rb +3 -1
  95. data/lib/rails_admin/config/actions/show_in_app.rb +9 -3
  96. data/lib/rails_admin/config/actions.rb +6 -4
  97. data/lib/rails_admin/config/configurable.rb +4 -2
  98. data/lib/rails_admin/config/const_load_suppressor.rb +78 -0
  99. data/lib/rails_admin/config/fields/association.rb +21 -11
  100. data/lib/rails_admin/config/fields/base.rb +86 -32
  101. data/lib/rails_admin/config/fields/factories/action_text.rb +2 -0
  102. data/lib/rails_admin/config/fields/factories/active_storage.rb +5 -1
  103. data/lib/rails_admin/config/fields/factories/association.rb +12 -13
  104. data/lib/rails_admin/config/fields/factories/carrierwave.rb +6 -2
  105. data/lib/rails_admin/config/fields/factories/devise.rb +6 -2
  106. data/lib/rails_admin/config/fields/factories/dragonfly.rb +6 -2
  107. data/lib/rails_admin/config/fields/factories/enum.rb +2 -0
  108. data/lib/rails_admin/config/fields/factories/paperclip.rb +6 -2
  109. data/lib/rails_admin/config/fields/factories/password.rb +2 -0
  110. data/lib/rails_admin/config/fields/factories/shrine.rb +3 -1
  111. data/lib/rails_admin/config/fields/group.rb +3 -2
  112. data/lib/rails_admin/config/fields/types/action_text.rb +7 -1
  113. data/lib/rails_admin/config/fields/types/active_record_enum.rb +4 -0
  114. data/lib/rails_admin/config/fields/types/active_storage.rb +23 -3
  115. data/lib/rails_admin/config/fields/types/all.rb +4 -0
  116. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +9 -15
  117. data/lib/rails_admin/config/fields/types/boolean.rb +38 -8
  118. data/lib/rails_admin/config/fields/types/bson_object_id.rb +2 -0
  119. data/lib/rails_admin/config/fields/types/carrierwave.rb +3 -0
  120. data/lib/rails_admin/config/fields/types/citext.rb +15 -0
  121. data/lib/rails_admin/config/fields/types/ck_editor.rb +2 -0
  122. data/lib/rails_admin/config/fields/types/code_mirror.rb +2 -0
  123. data/lib/rails_admin/config/fields/types/color.rb +8 -2
  124. data/lib/rails_admin/config/fields/types/composite_keys_belongs_to_association.rb +31 -0
  125. data/lib/rails_admin/config/fields/types/date.rb +12 -6
  126. data/lib/rails_admin/config/fields/types/datetime.rb +36 -21
  127. data/lib/rails_admin/config/fields/types/decimal.rb +11 -2
  128. data/lib/rails_admin/config/fields/types/dragonfly.rb +5 -1
  129. data/lib/rails_admin/config/fields/types/enum.rb +16 -3
  130. data/lib/rails_admin/config/fields/types/file_upload.rb +11 -4
  131. data/lib/rails_admin/config/fields/types/float.rb +11 -2
  132. data/lib/rails_admin/config/fields/types/froala.rb +2 -0
  133. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -0
  134. data/lib/rails_admin/config/fields/types/has_many_association.rb +7 -5
  135. data/lib/rails_admin/config/fields/types/has_one_association.rb +12 -14
  136. data/lib/rails_admin/config/fields/types/hidden.rb +2 -0
  137. data/lib/rails_admin/config/fields/types/inet.rb +2 -0
  138. data/lib/rails_admin/config/fields/types/integer.rb +4 -6
  139. data/lib/rails_admin/config/fields/types/json.rb +2 -0
  140. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +30 -2
  141. data/lib/rails_admin/config/fields/types/multiple_carrierwave.rb +3 -0
  142. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +8 -4
  143. data/lib/rails_admin/config/fields/types/numeric.rb +24 -0
  144. data/lib/rails_admin/config/fields/types/paperclip.rb +2 -0
  145. data/lib/rails_admin/config/fields/types/password.rb +2 -0
  146. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +5 -2
  147. data/lib/rails_admin/config/fields/types/serialized.rb +2 -0
  148. data/lib/rails_admin/config/fields/types/shrine.rb +15 -11
  149. data/lib/rails_admin/config/fields/types/simple_mde.rb +2 -0
  150. data/lib/rails_admin/config/fields/types/string.rb +3 -1
  151. data/lib/rails_admin/config/fields/types/string_like.rb +6 -0
  152. data/lib/rails_admin/config/fields/types/text.rb +2 -0
  153. data/lib/rails_admin/config/fields/types/time.rb +16 -4
  154. data/lib/rails_admin/config/fields/types/timestamp.rb +2 -4
  155. data/lib/rails_admin/config/fields/types/uuid.rb +2 -0
  156. data/lib/rails_admin/config/fields/types/wysihtml5.rb +2 -0
  157. data/lib/rails_admin/config/fields/types.rb +3 -1
  158. data/lib/rails_admin/config/fields.rb +6 -2
  159. data/lib/rails_admin/config/groupable.rb +2 -0
  160. data/lib/rails_admin/config/has_description.rb +2 -0
  161. data/lib/rails_admin/config/has_fields.rb +12 -7
  162. data/lib/rails_admin/config/has_groups.rb +2 -0
  163. data/lib/rails_admin/config/hideable.rb +3 -1
  164. data/lib/rails_admin/config/inspectable.rb +3 -3
  165. data/lib/rails_admin/config/lazy_model.rb +13 -7
  166. data/lib/rails_admin/config/model.rb +22 -10
  167. data/lib/rails_admin/config/proxyable/proxy.rb +2 -0
  168. data/lib/rails_admin/config/proxyable.rb +2 -0
  169. data/lib/rails_admin/config/sections/base.rb +4 -3
  170. data/lib/rails_admin/config/sections/create.rb +2 -0
  171. data/lib/rails_admin/config/sections/edit.rb +2 -0
  172. data/lib/rails_admin/config/sections/export.rb +2 -0
  173. data/lib/rails_admin/config/sections/list.rb +14 -19
  174. data/lib/rails_admin/config/sections/modal.rb +2 -0
  175. data/lib/rails_admin/config/sections/nested.rb +2 -0
  176. data/lib/rails_admin/config/sections/show.rb +2 -0
  177. data/lib/rails_admin/config/sections/update.rb +2 -0
  178. data/lib/rails_admin/config/sections.rb +3 -1
  179. data/lib/rails_admin/config.rb +80 -47
  180. data/lib/rails_admin/engine.rb +43 -32
  181. data/lib/rails_admin/extension.rb +8 -14
  182. data/lib/rails_admin/extensions/cancancan/authorization_adapter.rb +25 -6
  183. data/lib/rails_admin/extensions/cancancan.rb +2 -0
  184. data/lib/rails_admin/extensions/controller_extension.rb +2 -0
  185. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +62 -35
  186. data/lib/rails_admin/extensions/paper_trail.rb +2 -0
  187. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +8 -7
  188. data/lib/rails_admin/extensions/pundit.rb +2 -0
  189. data/lib/rails_admin/support/csv_converter.rb +14 -15
  190. data/lib/rails_admin/support/datetime.rb +50 -85
  191. data/lib/rails_admin/support/es_module_processor.rb +23 -0
  192. data/lib/rails_admin/support/hash_helper.rb +8 -5
  193. data/lib/rails_admin/version.rb +41 -2
  194. data/lib/rails_admin.rb +7 -5
  195. data/lib/tasks/rails_admin.rake +19 -8
  196. data/package.json +30 -0
  197. data/src/rails_admin/base.js +29 -0
  198. data/src/rails_admin/filter-box.js +360 -0
  199. data/src/rails_admin/filtering-multiselect.js +389 -0
  200. data/src/rails_admin/filtering-select.js +308 -0
  201. data/src/rails_admin/i18n.js +18 -0
  202. data/src/rails_admin/jquery.js +3 -0
  203. data/src/rails_admin/nested-form-hooks.js +110 -0
  204. data/src/rails_admin/remote-form.js +193 -0
  205. data/src/rails_admin/sidescroll.js +20 -0
  206. data/src/rails_admin/styles/base/theming.scss +342 -0
  207. data/src/rails_admin/styles/base/variables.scss +3 -0
  208. data/src/rails_admin/styles/base.scss +27 -0
  209. data/src/rails_admin/styles/filtering-multiselect.scss +53 -0
  210. data/src/rails_admin/styles/filtering-select.scss +70 -0
  211. data/src/rails_admin/styles/widgets.scss +26 -0
  212. data/src/rails_admin/ui.js +176 -0
  213. data/src/rails_admin/vendor/jquery_nested_form.js +122 -0
  214. data/src/rails_admin/widgets.js +507 -0
  215. data/vendor/assets/fonts/rails_admin/fa-solid-900.ttf +0 -0
  216. data/vendor/assets/fonts/rails_admin/fa-solid-900.woff2 +0 -0
  217. data/vendor/assets/javascripts/rails_admin/bootstrap.js +5046 -0
  218. data/vendor/assets/javascripts/rails_admin/flatpickr-with-locales.js +11246 -0
  219. data/vendor/assets/javascripts/rails_admin/jquery-ui/data.js +41 -0
  220. data/vendor/assets/javascripts/rails_admin/jquery-ui/effect.js +1637 -0
  221. data/vendor/assets/javascripts/rails_admin/jquery-ui/ie.js +17 -0
  222. data/vendor/assets/javascripts/rails_admin/jquery-ui/keycode.js +47 -0
  223. data/vendor/assets/javascripts/rails_admin/jquery-ui/position.js +500 -0
  224. data/vendor/assets/javascripts/rails_admin/jquery-ui/safe-active-element.js +42 -0
  225. data/vendor/assets/javascripts/rails_admin/jquery-ui/scroll-parent.js +47 -0
  226. data/vendor/assets/javascripts/rails_admin/jquery-ui/unique-id.js +51 -0
  227. data/vendor/assets/javascripts/rails_admin/jquery-ui/version.js +17 -0
  228. data/vendor/assets/javascripts/rails_admin/jquery-ui/widget.js +735 -0
  229. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/autocomplete.js +689 -0
  230. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/menu.js +680 -0
  231. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/mouse.js +230 -0
  232. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/sortable.js +1561 -0
  233. data/vendor/assets/javascripts/rails_admin/jquery3.js +10881 -0
  234. data/vendor/assets/javascripts/rails_admin/popper.js +1974 -0
  235. data/vendor/assets/stylesheets/rails_admin/bootstrap/_accordion.scss +118 -0
  236. data/vendor/assets/stylesheets/rails_admin/bootstrap/_alert.scss +57 -0
  237. data/vendor/assets/stylesheets/rails_admin/bootstrap/_badge.scss +29 -0
  238. data/vendor/assets/stylesheets/rails_admin/bootstrap/_breadcrumb.scss +28 -0
  239. data/vendor/assets/stylesheets/rails_admin/bootstrap/_button-group.scss +139 -0
  240. data/vendor/assets/stylesheets/rails_admin/bootstrap/_buttons.scss +64 -110
  241. data/vendor/assets/stylesheets/rails_admin/bootstrap/_card.scss +216 -0
  242. data/vendor/assets/stylesheets/rails_admin/bootstrap/_carousel.scss +162 -176
  243. data/vendor/assets/stylesheets/rails_admin/bootstrap/_close.scss +31 -26
  244. data/vendor/assets/stylesheets/rails_admin/bootstrap/_containers.scss +41 -0
  245. data/vendor/assets/stylesheets/rails_admin/bootstrap/_dropdown.scss +240 -0
  246. data/vendor/assets/stylesheets/rails_admin/bootstrap/_forms.scss +9 -538
  247. data/vendor/assets/stylesheets/rails_admin/bootstrap/_functions.scss +302 -0
  248. data/vendor/assets/stylesheets/rails_admin/bootstrap/_grid.scss +18 -69
  249. data/vendor/assets/stylesheets/rails_admin/bootstrap/_helpers.scss +9 -0
  250. data/vendor/assets/stylesheets/rails_admin/bootstrap/_images.scss +42 -0
  251. data/vendor/assets/stylesheets/rails_admin/bootstrap/_list-group.scss +127 -84
  252. data/vendor/assets/stylesheets/rails_admin/bootstrap/_mixins.scss +26 -22
  253. data/vendor/assets/stylesheets/rails_admin/bootstrap/_modal.scss +209 -0
  254. data/vendor/assets/stylesheets/rails_admin/bootstrap/_nav.scss +139 -0
  255. data/vendor/assets/stylesheets/rails_admin/bootstrap/_navbar.scss +218 -542
  256. data/vendor/assets/stylesheets/rails_admin/bootstrap/_offcanvas.scss +83 -0
  257. data/vendor/assets/stylesheets/rails_admin/bootstrap/_pagination.scss +46 -70
  258. data/vendor/assets/stylesheets/rails_admin/bootstrap/_placeholders.scss +51 -0
  259. data/vendor/assets/stylesheets/rails_admin/bootstrap/_popover.scss +158 -0
  260. data/vendor/assets/stylesheets/rails_admin/bootstrap/_progress.scss +48 -0
  261. data/vendor/assets/stylesheets/rails_admin/bootstrap/_reboot.scss +625 -0
  262. data/vendor/assets/stylesheets/rails_admin/bootstrap/_root.scss +54 -0
  263. data/vendor/assets/stylesheets/rails_admin/bootstrap/_spinners.scss +69 -0
  264. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tables.scss +100 -178
  265. data/vendor/assets/stylesheets/rails_admin/bootstrap/_toasts.scss +51 -0
  266. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tooltip.scss +97 -77
  267. data/vendor/assets/stylesheets/rails_admin/bootstrap/_transitions.scss +27 -0
  268. data/vendor/assets/stylesheets/rails_admin/bootstrap/_type.scss +54 -254
  269. data/vendor/assets/stylesheets/rails_admin/bootstrap/_utilities.scss +628 -55
  270. data/vendor/assets/stylesheets/rails_admin/bootstrap/_variables.scss +1572 -781
  271. data/vendor/assets/stylesheets/rails_admin/bootstrap/bootstrap.scss +38 -35
  272. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_floating-labels.scss +63 -0
  273. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-check.scss +152 -0
  274. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-control.scss +219 -0
  275. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-range.scss +91 -0
  276. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-select.scss +72 -0
  277. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-text.scss +11 -0
  278. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_input-group.scss +121 -0
  279. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_labels.scss +36 -0
  280. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_validation.scss +12 -0
  281. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_clearfix.scss +3 -0
  282. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_colored-links.scss +12 -0
  283. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_position.scss +30 -0
  284. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_ratio.scss +26 -0
  285. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stacks.scss +15 -0
  286. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stretched-link.scss +15 -0
  287. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_text-truncation.scss +7 -0
  288. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_visually-hidden.scss +8 -0
  289. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_vr.scss +8 -0
  290. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_alert.scss +11 -0
  291. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_backdrop.scss +14 -0
  292. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_border-radius.scss +72 -12
  293. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_box-shadow.scss +18 -0
  294. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_breakpoints.scss +127 -0
  295. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_buttons.scss +113 -30
  296. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_caret.scss +64 -0
  297. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_clearfix.scss +5 -18
  298. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_color-scheme.scss +7 -0
  299. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_container.scss +9 -0
  300. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_deprecate.scss +10 -0
  301. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_forms.scss +130 -70
  302. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_gradients.scss +27 -38
  303. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_grid.scss +127 -98
  304. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_image.scss +6 -24
  305. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_list-group.scss +13 -20
  306. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_lists.scss +7 -0
  307. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_pagination.scss +24 -16
  308. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_reset-text.scss +17 -0
  309. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_resize.scss +1 -1
  310. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_table-variants.scss +21 -0
  311. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/{_text-overflow.scss → _text-truncate.scss} +2 -2
  312. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_transition.scss +26 -0
  313. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_utilities.scss +89 -0
  314. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_visually-hidden.scss +29 -0
  315. data/vendor/assets/stylesheets/rails_admin/bootstrap/utilities/_api.scss +47 -0
  316. data/vendor/assets/stylesheets/rails_admin/bootstrap/vendor/_rfs.scss +354 -0
  317. data/vendor/assets/stylesheets/rails_admin/flatpickr.css +791 -0
  318. data/vendor/assets/stylesheets/rails_admin/font-awesome.scss +6291 -2282
  319. metadata +182 -330
  320. data/app/assets/images/rails_admin/aristo/images/bg_fallback.png +0 -0
  321. data/app/assets/images/rails_admin/aristo/images/icon_sprite.png +0 -0
  322. data/app/assets/images/rails_admin/aristo/images/progress_bar.gif +0 -0
  323. data/app/assets/images/rails_admin/aristo/images/slider_handles.png +0 -0
  324. data/app/assets/images/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  325. data/app/assets/images/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  326. data/app/assets/images/rails_admin/bullet_black.png +0 -0
  327. data/app/assets/images/rails_admin/bullet_white.png +0 -0
  328. data/app/assets/images/rails_admin/calendar.png +0 -0
  329. data/app/assets/images/rails_admin/clock.png +0 -0
  330. data/app/assets/images/rails_admin/logo.png +0 -0
  331. data/app/assets/images/rails_admin/magnifier.png +0 -0
  332. data/app/assets/images/rails_admin/multiselect/icon_sprite.png +0 -0
  333. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-dark.png +0 -0
  334. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-light.png +0 -0
  335. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-dark.png +0 -0
  336. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-light.png +0 -0
  337. data/app/assets/javascripts/rails_admin/jquery-ui.js.erb +0 -8
  338. data/app/assets/javascripts/rails_admin/ra.filter-box.js +0 -226
  339. data/app/assets/javascripts/rails_admin/ra.filtering-multiselect.js +0 -331
  340. data/app/assets/javascripts/rails_admin/ra.filtering-select.js +0 -294
  341. data/app/assets/javascripts/rails_admin/ra.i18n.js +0 -28
  342. data/app/assets/javascripts/rails_admin/ra.nested-form-hooks.js +0 -59
  343. data/app/assets/javascripts/rails_admin/ra.remote-form.js +0 -155
  344. data/app/assets/javascripts/rails_admin/ra.sidescroll.js +0 -31
  345. data/app/assets/javascripts/rails_admin/ra.widgets.js +0 -379
  346. data/app/assets/javascripts/rails_admin/rails_admin.js +0 -20
  347. data/app/assets/javascripts/rails_admin/ui.js +0 -135
  348. data/app/assets/stylesheets/rails_admin/aristo/images/bg_fallback.png +0 -0
  349. data/app/assets/stylesheets/rails_admin/aristo/images/icon_sprite.png +0 -0
  350. data/app/assets/stylesheets/rails_admin/aristo/images/progress_bar.gif +0 -0
  351. data/app/assets/stylesheets/rails_admin/aristo/images/slider_handles.png +0 -0
  352. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  353. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  354. data/app/assets/stylesheets/rails_admin/aristo/jquery-ui-1.8.7.custom.scss +0 -733
  355. data/app/assets/stylesheets/rails_admin/base/font-awesome-4-compability.scss +0 -153
  356. data/app/assets/stylesheets/rails_admin/base/theming.scss +0 -341
  357. data/app/assets/stylesheets/rails_admin/base/variables.scss +0 -1
  358. data/app/assets/stylesheets/rails_admin/ra.filtering-multiselect.scss +0 -88
  359. data/app/assets/stylesheets/rails_admin/ra.sidescroll.scss +0 -29
  360. data/app/assets/stylesheets/rails_admin/ra.widgets.scss +0 -17
  361. data/app/assets/stylesheets/rails_admin/rails_admin.scss.erb +0 -110
  362. data/app/assets/stylesheets/rails_admin/themes/cerulean/mixins.scss +0 -0
  363. data/app/assets/stylesheets/rails_admin/themes/cerulean/theming.scss +0 -133
  364. data/app/assets/stylesheets/rails_admin/themes/cerulean/variables.scss +0 -857
  365. data/app/assets/stylesheets/rails_admin/themes/default/mixins.scss +0 -8
  366. data/app/assets/stylesheets/rails_admin/themes/default/theming.scss +0 -11
  367. data/app/assets/stylesheets/rails_admin/themes/default/variables.scss +0 -12
  368. data/app/views/kaminari/ra-twitter-bootstrap/_gap.html.haml +0 -2
  369. data/app/views/kaminari/ra-twitter-bootstrap/_next_page.html.haml +0 -4
  370. data/app/views/kaminari/ra-twitter-bootstrap/_page.html.haml +0 -4
  371. data/app/views/kaminari/ra-twitter-bootstrap/_paginator.html.haml +0 -9
  372. data/app/views/kaminari/ra-twitter-bootstrap/_prev_page.html.haml +0 -4
  373. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_next_page.html.haml +0 -4
  374. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_paginator.html.haml +0 -4
  375. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_prev_page.html.haml +0 -4
  376. data/app/views/layouts/rails_admin/_head.html.haml +0 -7
  377. data/app/views/layouts/rails_admin/_navigation.html.haml +0 -12
  378. data/app/views/layouts/rails_admin/_secondary_navigation.html.haml +0 -10
  379. data/app/views/layouts/rails_admin/_sidebar_navigation.html.haml +0 -3
  380. data/app/views/layouts/rails_admin/application.html.haml +0 -16
  381. data/app/views/layouts/rails_admin/pjax.html.haml +0 -12
  382. data/app/views/rails_admin/main/_dashboard_history.html.haml +0 -21
  383. data/app/views/rails_admin/main/_delete_notice.html.haml +0 -24
  384. data/app/views/rails_admin/main/_form_action_text.html.haml +0 -7
  385. data/app/views/rails_admin/main/_form_boolean.html.haml +0 -3
  386. data/app/views/rails_admin/main/_form_code_mirror.html.haml +0 -9
  387. data/app/views/rails_admin/main/_form_colorpicker.html.haml +0 -1
  388. data/app/views/rails_admin/main/_form_datetime.html.haml +0 -5
  389. data/app/views/rails_admin/main/_form_enumeration.html.haml +0 -18
  390. data/app/views/rails_admin/main/_form_field.html.haml +0 -1
  391. data/app/views/rails_admin/main/_form_file_upload.html.haml +0 -17
  392. data/app/views/rails_admin/main/_form_filtering_multiselect.html.haml +0 -48
  393. data/app/views/rails_admin/main/_form_filtering_select.html.haml +0 -37
  394. data/app/views/rails_admin/main/_form_froala.html.haml +0 -8
  395. data/app/views/rails_admin/main/_form_multiple_file_upload.html.haml +0 -16
  396. data/app/views/rails_admin/main/_form_nested_many.html.haml +0 -15
  397. data/app/views/rails_admin/main/_form_nested_one.html.haml +0 -17
  398. data/app/views/rails_admin/main/_form_polymorphic_association.html.haml +0 -26
  399. data/app/views/rails_admin/main/_form_simple_mde.haml +0 -8
  400. data/app/views/rails_admin/main/_form_text.html.haml +0 -1
  401. data/app/views/rails_admin/main/_form_wysihtml5.html.haml +0 -8
  402. data/app/views/rails_admin/main/_submit_buttons.html.haml +0 -16
  403. data/app/views/rails_admin/main/bulk_delete.html.haml +0 -11
  404. data/app/views/rails_admin/main/dashboard.html.haml +0 -34
  405. data/app/views/rails_admin/main/delete.html.haml +0 -18
  406. data/app/views/rails_admin/main/edit.html.haml +0 -2
  407. data/app/views/rails_admin/main/export.html.haml +0 -92
  408. data/app/views/rails_admin/main/history.html.haml +0 -51
  409. data/app/views/rails_admin/main/index.html.haml +0 -126
  410. data/app/views/rails_admin/main/new.html.haml +0 -2
  411. data/app/views/rails_admin/main/show.html.haml +0 -15
  412. data/config/initializers/devise_patch.rb +0 -9
  413. data/config/initializers/haml.rb +0 -5
  414. data/lib/rails_admin/adapters/active_record/abstract_object.rb +0 -32
  415. data/lib/rails_admin/adapters/mongoid/abstract_object.rb +0 -42
  416. data/lib/rails_admin/bootstrap-sass/compass_functions.rb +0 -28
  417. data/lib/rails_admin/bootstrap-sass/sass_functions.rb +0 -16
  418. data/lib/rails_admin/bootstrap-sass.rb +0 -49
  419. data/lib/rails_admin/extensions/history/auditing_adapter.rb +0 -37
  420. data/lib/rails_admin/extensions/history/history.rb +0 -44
  421. data/lib/rails_admin/extensions/history.rb +0 -3
  422. data/lib/rails_admin/support/i18n.rb +0 -43
  423. data/vendor/assets/fonts/rails_admin/FontAwesome.otf +0 -0
  424. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.eot +0 -0
  425. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.svg +0 -2671
  426. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.ttf +0 -0
  427. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.woff +0 -0
  428. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.woff2 +0 -0
  429. data/vendor/assets/images/rails_admin/bootstrap/glyphicons-halflings-white.png +0 -0
  430. data/vendor/assets/images/rails_admin/bootstrap/glyphicons-halflings.png +0 -0
  431. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_background.png +0 -0
  432. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_hex.png +0 -0
  433. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_hsb_b.png +0 -0
  434. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_hsb_h.png +0 -0
  435. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_hsb_s.png +0 -0
  436. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_indic.gif +0 -0
  437. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_overlay.png +0 -0
  438. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_rgb_b.png +0 -0
  439. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_rgb_g.png +0 -0
  440. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_rgb_r.png +0 -0
  441. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_select.gif +0 -0
  442. data/vendor/assets/images/rails_admin/colorpicker/colorpicker_submit.png +0 -0
  443. data/vendor/assets/images/rails_admin/colorpicker/custom_background.png +0 -0
  444. data/vendor/assets/images/rails_admin/colorpicker/custom_hex.png +0 -0
  445. data/vendor/assets/images/rails_admin/colorpicker/custom_hsb_b.png +0 -0
  446. data/vendor/assets/images/rails_admin/colorpicker/custom_hsb_h.png +0 -0
  447. data/vendor/assets/images/rails_admin/colorpicker/custom_hsb_s.png +0 -0
  448. data/vendor/assets/images/rails_admin/colorpicker/custom_indic.gif +0 -0
  449. data/vendor/assets/images/rails_admin/colorpicker/custom_rgb_b.png +0 -0
  450. data/vendor/assets/images/rails_admin/colorpicker/custom_rgb_g.png +0 -0
  451. data/vendor/assets/images/rails_admin/colorpicker/custom_rgb_r.png +0 -0
  452. data/vendor/assets/images/rails_admin/colorpicker/custom_submit.png +0 -0
  453. data/vendor/assets/images/rails_admin/colorpicker/select.png +0 -0
  454. data/vendor/assets/images/rails_admin/colorpicker/select2.png +0 -0
  455. data/vendor/assets/images/rails_admin/colorpicker/slider.png +0 -0
  456. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-affix.js +0 -142
  457. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-alert.js +0 -92
  458. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-button.js +0 -110
  459. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-carousel.js +0 -223
  460. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-collapse.js +0 -170
  461. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-dropdown.js +0 -151
  462. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-modal.js +0 -280
  463. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-popover.js +0 -113
  464. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-scrollspy.js +0 -170
  465. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-tab.js +0 -128
  466. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-tooltip.js +0 -457
  467. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-transition.js +0 -59
  468. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-typeahead.js +0 -1782
  469. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap.js +0 -13
  470. data/vendor/assets/javascripts/rails_admin/bootstrap-datetimepicker.js +0 -2444
  471. data/vendor/assets/javascripts/rails_admin/jquery.colorpicker.js +0 -484
  472. data/vendor/assets/javascripts/rails_admin/jquery.pjax.js +0 -741
  473. data/vendor/assets/javascripts/rails_admin/moment-with-locales.js +0 -16165
  474. data/vendor/assets/stylesheets/rails_admin/_bootstrap-datetimepicker.scss +0 -343
  475. data/vendor/assets/stylesheets/rails_admin/bootstrap/_alerts.scss +0 -68
  476. data/vendor/assets/stylesheets/rails_admin/bootstrap/_badges.scss +0 -57
  477. data/vendor/assets/stylesheets/rails_admin/bootstrap/_breadcrumbs.scss +0 -26
  478. data/vendor/assets/stylesheets/rails_admin/bootstrap/_button-groups.scss +0 -240
  479. data/vendor/assets/stylesheets/rails_admin/bootstrap/_code.scss +0 -68
  480. data/vendor/assets/stylesheets/rails_admin/bootstrap/_component-animations.scss +0 -35
  481. data/vendor/assets/stylesheets/rails_admin/bootstrap/_dropdowns.scss +0 -215
  482. data/vendor/assets/stylesheets/rails_admin/bootstrap/_glyphicons.scss +0 -237
  483. data/vendor/assets/stylesheets/rails_admin/bootstrap/_input-groups.scss +0 -166
  484. data/vendor/assets/stylesheets/rails_admin/bootstrap/_jumbotron.scss +0 -48
  485. data/vendor/assets/stylesheets/rails_admin/bootstrap/_labels.scss +0 -66
  486. data/vendor/assets/stylesheets/rails_admin/bootstrap/_media.scss +0 -56
  487. data/vendor/assets/stylesheets/rails_admin/bootstrap/_modals.scss +0 -150
  488. data/vendor/assets/stylesheets/rails_admin/bootstrap/_navs.scss +0 -242
  489. data/vendor/assets/stylesheets/rails_admin/bootstrap/_normalize.scss +0 -425
  490. data/vendor/assets/stylesheets/rails_admin/bootstrap/_pager.scss +0 -55
  491. data/vendor/assets/stylesheets/rails_admin/bootstrap/_panels.scss +0 -243
  492. data/vendor/assets/stylesheets/rails_admin/bootstrap/_popovers.scss +0 -133
  493. data/vendor/assets/stylesheets/rails_admin/bootstrap/_print.scss +0 -101
  494. data/vendor/assets/stylesheets/rails_admin/bootstrap/_progress-bars.scss +0 -105
  495. data/vendor/assets/stylesheets/rails_admin/bootstrap/_responsive-embed.scss +0 -34
  496. data/vendor/assets/stylesheets/rails_admin/bootstrap/_responsive-utilities.scss +0 -174
  497. data/vendor/assets/stylesheets/rails_admin/bootstrap/_scaffolding.scss +0 -150
  498. data/vendor/assets/stylesheets/rails_admin/bootstrap/_theme.scss +0 -258
  499. data/vendor/assets/stylesheets/rails_admin/bootstrap/_thumbnails.scss +0 -38
  500. data/vendor/assets/stylesheets/rails_admin/bootstrap/_wells.scss +0 -29
  501. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_alerts.scss +0 -14
  502. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_background-variant.scss +0 -11
  503. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_center-block.scss +0 -7
  504. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_grid-framework.scss +0 -81
  505. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_hide-text.scss +0 -21
  506. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_labels.scss +0 -12
  507. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_nav-divider.scss +0 -10
  508. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_nav-vertical-align.scss +0 -9
  509. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_opacity.scss +0 -8
  510. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_panels.scss +0 -24
  511. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_progress-bar.scss +0 -10
  512. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_reset-filter.scss +0 -8
  513. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_responsive-visibility.scss +0 -21
  514. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_size.scss +0 -10
  515. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_tab-focus.scss +0 -9
  516. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_table-row.scss +0 -28
  517. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_text-emphasis.scss +0 -11
  518. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_vendor-prefixes.scss +0 -219
  519. data/vendor/assets/stylesheets/rails_admin/bootstrap-datetimepicker-build.scss +0 -16
  520. data/vendor/assets/stylesheets/rails_admin/jquery.colorpicker.scss +0 -182
  521. /data/{app/assets/stylesheets/rails_admin → src/rails_admin/styles}/base/README.txt +0 -0
  522. /data/{app/assets/stylesheets/rails_admin → src/rails_admin/styles}/base/mixins.scss +0 -0
@@ -1,18 +1,130 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators'
2
- require File.expand_path('../utils', __FILE__)
4
+ require 'rails_admin/version'
5
+ require File.expand_path('utils', __dir__)
3
6
 
4
7
  module RailsAdmin
5
8
  class InstallGenerator < Rails::Generators::Base
6
- source_root File.expand_path('../templates', __FILE__)
9
+ source_root File.expand_path('templates', __dir__)
7
10
  include Generators::Utils::InstanceMethods
8
11
 
9
12
  argument :_namespace, type: :string, required: false, desc: 'RailsAdmin url namespace'
13
+ class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, webpack, sprockets, importmap]'
10
14
  desc 'RailsAdmin installation generator'
11
15
 
12
16
  def install
13
- namespace = ask_for('Where do you want to mount rails_admin?', 'admin', _namespace)
14
- route("mount RailsAdmin::Engine => '/#{namespace}', as: 'rails_admin'")
15
- template 'initializer.erb', 'config/initializers/rails_admin.rb'
17
+ if File.read(File.join(destination_root, 'config/routes.rb')).include?('mount RailsAdmin::Engine')
18
+ display "Skipped route addition, since it's already there"
19
+ else
20
+ namespace = ask_for('Where do you want to mount rails_admin?', 'admin', _namespace)
21
+ route("mount RailsAdmin::Engine => '/#{namespace}', as: 'rails_admin'")
22
+ end
23
+ if File.exist? File.join(destination_root, 'config/initializers/rails_admin.rb')
24
+ insert_into_file 'config/initializers/rails_admin.rb', " config.asset_source = :#{asset}\n", after: "RailsAdmin.config do |config|\n"
25
+ else
26
+ template 'initializer.erb', 'config/initializers/rails_admin.rb'
27
+ end
28
+ display "Using [#{asset}] for asset delivery method"
29
+ case asset
30
+ when 'webpack'
31
+ configure_for_webpack
32
+ when 'importmap'
33
+ configure_for_importmap
34
+ when 'webpacker'
35
+ configure_for_webpacker5
36
+ when 'sprockets'
37
+ configure_for_sprockets
38
+ else
39
+ raise "Unknown asset source: #{asset}"
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def asset
46
+ return options['asset'] if options['asset']
47
+
48
+ if defined?(Webpacker)
49
+ 'webpacker'
50
+ elsif Rails.root.join('webpack.config.js').exist?
51
+ 'webpack'
52
+ elsif Rails.root.join('config/importmap.rb').exist?
53
+ 'importmap'
54
+ else
55
+ 'sprockets'
56
+ end
57
+ end
58
+
59
+ def configure_for_sprockets
60
+ gem 'sassc-rails'
61
+ end
62
+
63
+ def configure_for_webpacker5
64
+ run "yarn add rails_admin@#{RailsAdmin::Version.js}"
65
+ template 'rails_admin.webpacker.js', 'app/javascript/packs/rails_admin.js'
66
+ template 'rails_admin.scss.erb', 'app/javascript/stylesheets/rails_admin.scss'
67
+ # To work around https://github.com/railsadminteam/rails_admin/issues/3565
68
+ add_package_json_field('resolutions', {'rails_admin/@fortawesome/fontawesome-free' => '^5.15.0'})
69
+ end
70
+
71
+ def configure_for_webpack
72
+ run "yarn add rails_admin@#{RailsAdmin::Version.js}"
73
+ template 'rails_admin.js', 'app/javascript/rails_admin.js'
74
+ webpack_config = File.join(destination_root, 'webpack.config.js')
75
+ marker = %r{application: ["']./app/javascript/application.js["']}
76
+ if File.exist?(webpack_config) && File.read(webpack_config) =~ marker
77
+ insert_into_file 'webpack.config.js', %(,\n rails_admin: "./app/javascript/rails_admin.js"), after: marker
78
+ else
79
+ say 'Add `rails_admin: "./app/javascript/rails_admin.js"` to the entry section in your webpack.config.js.', :red
80
+ end
81
+ setup_css({'build' => 'webpack --config webpack.config.js'})
82
+ end
83
+
84
+ def configure_for_importmap
85
+ run "yarn add rails_admin@#{RailsAdmin::Version.js}"
86
+ template 'rails_admin.js', 'app/javascript/rails_admin.js'
87
+ require_relative 'importmap_formatter'
88
+ add_file 'config/importmap.rails_admin.rb', ImportmapFormatter.new.format
89
+ setup_css
90
+ end
91
+
92
+ def setup_css(additional_script_entries = {})
93
+ gem 'cssbundling-rails'
94
+ rake 'css:install:sass'
95
+
96
+ @fa_font_path = '.'
97
+ template 'rails_admin.scss.erb', 'app/assets/stylesheets/rails_admin.scss'
98
+ asset_config = %{Rails.application.config.assets.paths << Rails.root.join("node_modules/@fortawesome/fontawesome-free/webfonts")\n}
99
+ if File.exist? File.join(destination_root, 'config/initializers/assets.rb')
100
+ append_to_file 'config/initializers/assets.rb', asset_config
101
+ else
102
+ add_file 'config/initializers/assets.rb', asset_config
103
+ end
104
+ add_package_json_field('scripts', additional_script_entries.merge({'build:css' => 'sass ./app/assets/stylesheets/rails_admin.scss:./app/assets/builds/rails_admin.css --no-source-map --load-path=node_modules'}), <<~INSTRUCTION)
105
+ Taking 'build:css' as an example, if you're already have application.sass.css for the sass build, the resulting script would look like:
106
+ sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css ./app/assets/stylesheets/rails_admin.scss:./app/assets/builds/rails_admin.css --no-source-map --load-path=node_modules
107
+ INSTRUCTION
108
+ end
109
+
110
+ def add_package_json_field(name, entries, instruction = nil)
111
+ display "Add #{name} to package.json"
112
+ package = begin
113
+ JSON.parse(File.read(File.join(destination_root, 'package.json')))
114
+ rescue Errno::ENOENT, JSON::ParserError
115
+ {}
116
+ end
117
+ if package[name] && (package[name].keys & entries.keys).any?
118
+ say <<~MESSAGE, :red
119
+ You need to merge "#{name}": #{JSON.pretty_generate(entries)} into the existing #{name} in your package.json.#{instruction && "\n#{instruction}"}
120
+ MESSAGE
121
+ else
122
+ package[name] ||= {}
123
+ entries.each do |entry, value|
124
+ package[name][entry] = value
125
+ end
126
+ add_file 'package.json', "#{JSON.pretty_generate(package)}\n"
127
+ end
16
128
  end
17
129
  end
18
130
  end
@@ -1,4 +1,5 @@
1
1
  RailsAdmin.config do |config|
2
+ config.asset_source = :<%= asset %>
2
3
 
3
4
  ### Popular gems integration
4
5
 
@@ -17,7 +18,7 @@ RailsAdmin.config do |config|
17
18
  ## == PaperTrail ==
18
19
  # config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0
19
20
 
20
- ### More at https://github.com/sferik/rails_admin/wiki/Base-configuration
21
+ ### More at https://github.com/railsadminteam/rails_admin/wiki/Base-configuration
21
22
 
22
23
  ## == Gravatar integration ==
23
24
  ## To disable Gravatar integration in Navigation Bar set to false
@@ -0,0 +1 @@
1
+ import "rails_admin/src/rails_admin/base";
@@ -0,0 +1 @@
1
+ <%= @fa_font_path ? %{$fa-font-path: "#{@fa_font_path}";\n} : '' %>@import "rails_admin/src/rails_admin/styles/base";
@@ -0,0 +1,2 @@
1
+ import "rails_admin/src/rails_admin/base";
2
+ import "../stylesheets/rails_admin.scss";
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  module Generators
3
5
  module Utils
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails_admin/support/datetime'
2
4
 
3
5
  module RailsAdmin
@@ -19,7 +21,7 @@ module RailsAdmin
19
21
  def new(m)
20
22
  m = m.constantize unless m.is_a?(Class)
21
23
  (am = old_new(m)).model && am.adapter ? am : nil
22
- rescue LoadError, NameError
24
+ rescue *([LoadError, NameError] + (defined?(ActiveRecord) ? ['ActiveRecord::NoDatabaseError'.constantize, 'ActiveRecord::ConnectionNotEstablished'.constantize] : []))
23
25
  puts "[RailsAdmin] Could not load model #{m}, assuming model is non existing. (#{$ERROR_INFO})" unless Rails.env.test?
24
26
  nil
25
27
  end
@@ -86,9 +88,8 @@ module RailsAdmin
86
88
  associations.each do |association|
87
89
  case association.type
88
90
  when :has_one
89
- if child = object.send(association.name)
90
- yield(association, [child])
91
- end
91
+ child = object.send(association.name)
92
+ yield(association, [child]) if child
92
93
  when :has_many
93
94
  children = object.send(association.name)
94
95
  yield(association, Array.new(children))
@@ -100,8 +101,13 @@ module RailsAdmin
100
101
 
101
102
  def initialize_active_record
102
103
  @adapter = :active_record
103
- require 'rails_admin/adapters/active_record'
104
- extend Adapters::ActiveRecord
104
+ if defined?(::CompositePrimaryKeys)
105
+ require 'rails_admin/adapters/composite_primary_keys'
106
+ extend Adapters::CompositePrimaryKeys
107
+ else
108
+ require 'rails_admin/adapters/active_record'
109
+ extend Adapters::ActiveRecord
110
+ end
105
111
  end
106
112
 
107
113
  def initialize_mongoid
@@ -124,6 +130,7 @@ module RailsAdmin
124
130
 
125
131
  def to_statement
126
132
  return if [@operator, @value].any? { |v| v == '_discard' }
133
+
127
134
  unary_operators[@operator] || unary_operators[@value] ||
128
135
  build_statement_for_type_generic
129
136
  end
@@ -139,21 +146,22 @@ module RailsAdmin
139
146
  case @type
140
147
  when :date
141
148
  build_statement_for_date
142
- when :datetime, :timestamp
149
+ when :datetime, :timestamp, :time
143
150
  build_statement_for_datetime_or_timestamp
144
151
  end
145
152
  end
146
153
  end
147
154
 
148
155
  def build_statement_for_type
149
- raise('You must override build_statement_for_type in your StatementBuilder')
156
+ raise 'You must override build_statement_for_type in your StatementBuilder'
150
157
  end
151
158
 
152
159
  def build_statement_for_integer_decimal_or_float
153
160
  case @value
154
- when Array then
161
+ when Array
155
162
  val, range_begin, range_end = *@value.collect do |v|
156
163
  next unless v.to_i.to_s == v || v.to_f.to_s == v
164
+
157
165
  @type == :integer ? v.to_i : v.to_f
158
166
  end
159
167
  case @operator
@@ -171,24 +179,36 @@ module RailsAdmin
171
179
 
172
180
  def build_statement_for_date
173
181
  start_date, end_date = get_filtering_duration
174
- start_date = (start_date.to_date rescue nil) if start_date
175
- end_date = (end_date.to_date rescue nil) if end_date
182
+ if start_date
183
+ start_date = begin
184
+ start_date.to_date
185
+ rescue StandardError
186
+ nil
187
+ end
188
+ end
189
+ if end_date
190
+ end_date = begin
191
+ end_date.to_date
192
+ rescue StandardError
193
+ nil
194
+ end
195
+ end
176
196
  range_filter(start_date, end_date)
177
197
  end
178
198
 
179
199
  def build_statement_for_datetime_or_timestamp
180
200
  start_date, end_date = get_filtering_duration
181
- start_date = start_date.try(:beginning_of_day) if start_date
182
- end_date = end_date.try(:end_of_day) if end_date
201
+ start_date = start_date.beginning_of_day if start_date.is_a?(Date)
202
+ end_date = end_date.end_of_day if end_date.is_a?(Date)
183
203
  range_filter(start_date, end_date)
184
204
  end
185
205
 
186
206
  def unary_operators
187
- raise('You must override unary_operators in your StatementBuilder')
207
+ raise 'You must override unary_operators in your StatementBuilder'
188
208
  end
189
209
 
190
210
  def range_filter(_min, _max)
191
- raise('You must override range_filter in your StatementBuilder')
211
+ raise 'You must override range_filter in your StatementBuilder'
192
212
  end
193
213
 
194
214
  class FilteringDuration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  module Adapters
3
5
  module ActiveRecord
@@ -21,6 +23,14 @@ module RailsAdmin
21
23
  association.macro
22
24
  end
23
25
 
26
+ def field_type
27
+ if polymorphic?
28
+ :polymorphic_association
29
+ else
30
+ :"#{association.macro}_association"
31
+ end
32
+ end
33
+
24
34
  def klass
25
35
  if options[:polymorphic]
26
36
  polymorphic_parents(:active_record, model.name.to_s, name) || []
@@ -30,7 +40,14 @@ module RailsAdmin
30
40
  end
31
41
 
32
42
  def primary_key
33
- (options[:primary_key] || association.klass.primary_key).try(:to_sym) unless polymorphic?
43
+ return nil if polymorphic?
44
+
45
+ case type
46
+ when :has_one
47
+ association.klass.primary_key
48
+ else
49
+ association.association_primary_key
50
+ end.try(:to_sym)
34
51
  end
35
52
 
36
53
  def foreign_key
@@ -39,6 +56,7 @@ module RailsAdmin
39
56
 
40
57
  def foreign_key_nullable?
41
58
  return true if foreign_key.nil? || type != :has_many
59
+
42
60
  (column = klass.columns_hash[foreign_key.to_s]).nil? || column.null
43
61
  end
44
62
 
@@ -50,6 +68,17 @@ module RailsAdmin
50
68
  nil
51
69
  end
52
70
 
71
+ def key_accessor
72
+ case type
73
+ when :has_many, :has_and_belongs_to_many
74
+ "#{name.to_s.singularize}_ids".to_sym
75
+ when :has_one
76
+ "#{name}_id".to_sym
77
+ else
78
+ foreign_key
79
+ end
80
+ end
81
+
53
82
  def as
54
83
  options[:as].try :to_sym
55
84
  end
@@ -63,7 +92,7 @@ module RailsAdmin
63
92
  end
64
93
 
65
94
  def read_only?
66
- (klass.all.instance_eval(&scope).readonly_value if scope.is_a? Proc) ||
95
+ (klass.all.instance_exec(&scope).readonly_value if scope.is_a?(Proc) && scope.arity == 0) ||
67
96
  association.nested? ||
68
97
  false
69
98
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdmin
4
+ module Adapters
5
+ module ActiveRecord
6
+ module ObjectExtension
7
+ def self.extended(object)
8
+ object.class.reflect_on_all_associations.each do |association|
9
+ association = Association.new(association, object.class)
10
+ case association.type
11
+ when :has_one
12
+ object.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
13
+ def #{association.name}_id
14
+ self.#{association.name}&.id
15
+ end
16
+
17
+ def #{association.name}_id=(item_id)
18
+ self.#{association.name} = (#{association.klass}.find(item_id) rescue nil)
19
+ end
20
+ RUBY
21
+ end
22
+ end
23
+ end
24
+
25
+ def assign_attributes(attributes)
26
+ super if attributes
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  module Adapters
3
5
  module ActiveRecord
@@ -42,13 +44,13 @@ module RailsAdmin
42
44
  end
43
45
 
44
46
  def read_only?
45
- false
47
+ model.readonly_attributes.include? property.name.to_s
46
48
  end
47
49
 
48
50
  private
49
51
 
50
52
  def serialized?
51
- model.type_for_attribute(property.name).class == ::ActiveRecord::Type::Serialized
53
+ model.type_for_attribute(property.name).instance_of?(::ActiveRecord::Type::Serialized)
52
54
  end
53
55
  end
54
56
  end
@@ -1,20 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
- require 'rails_admin/adapters/active_record/abstract_object'
3
4
  require 'rails_admin/adapters/active_record/association'
5
+ require 'rails_admin/adapters/active_record/object_extension'
4
6
  require 'rails_admin/adapters/active_record/property'
5
7
 
6
8
  module RailsAdmin
7
9
  module Adapters
8
10
  module ActiveRecord
9
- DISABLED_COLUMN_TYPES = [:tsvector, :blob, :binary, :spatial, :hstore, :geometry].freeze
11
+ DISABLED_COLUMN_TYPES = %i[tsvector blob binary spatial hstore geometry].freeze
10
12
 
11
13
  def new(params = {})
12
- AbstractObject.new(model.new(params))
14
+ model.new(params).extend(ObjectExtension)
13
15
  end
14
16
 
15
- def get(id)
16
- return unless object = model.where(primary_key => id).first
17
- AbstractObject.new object
17
+ def get(id, scope = scoped)
18
+ object = scope.where(primary_key => id).first
19
+ return unless object
20
+
21
+ object.extend(ObjectExtension)
18
22
  end
19
23
 
20
24
  def scoped
@@ -29,13 +33,11 @@ module RailsAdmin
29
33
  scope ||= scoped
30
34
  scope = scope.includes(options[:include]) if options[:include]
31
35
  scope = scope.limit(options[:limit]) if options[:limit]
32
- scope = scope.where(primary_key => options[:bulk_ids]) if options[:bulk_ids]
36
+ scope = bulk_scope(scope, options) if options[:bulk_ids]
33
37
  scope = query_scope(scope, options[:query]) if options[:query]
34
38
  scope = filter_scope(scope, options[:filters]) if options[:filters]
35
- if options[:page] && options[:per]
36
- scope = scope.send(Kaminari.config.page_method_name, options[:page]).per(options[:per])
37
- end
38
- scope = scope.reorder("#{options[:sort]} #{options[:sort_reverse] ? 'asc' : 'desc'}") if options[:sort]
39
+ scope = scope.send(Kaminari.config.page_method_name, options[:page]).per(options[:per]) if options[:page] && options[:per]
40
+ scope = sort_scope(scope, options) if options[:sort]
39
41
  scope
40
42
  end
41
43
 
@@ -71,13 +73,23 @@ module RailsAdmin
71
73
  delegate :primary_key, :table_name, to: :model, prefix: false
72
74
 
73
75
  def encoding
74
- case ::ActiveRecord::Base.connection_config[:adapter]
76
+ adapter =
77
+ if ::ActiveRecord::Base.respond_to?(:connection_db_config)
78
+ ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter]
79
+ else
80
+ ::ActiveRecord::Base.connection_config[:adapter]
81
+ end
82
+ case adapter
75
83
  when 'postgresql'
76
84
  ::ActiveRecord::Base.connection.select_one("SELECT ''::text AS str;").values.first.encoding
77
85
  when 'mysql2'
78
- ::ActiveRecord::Base.connection.instance_variable_get(:@connection).encoding
86
+ if RUBY_ENGINE == 'jruby'
87
+ ::ActiveRecord::Base.connection.select_one("SELECT '' AS str;").values.first.encoding
88
+ else
89
+ ::ActiveRecord::Base.connection.raw_connection.encoding
90
+ end
79
91
  when 'oracle_enhanced'
80
- ::ActiveRecord::Base.connection.select_one("SELECT dummy FROM DUAL").values.first.encoding
92
+ ::ActiveRecord::Base.connection.select_one('SELECT dummy FROM DUAL').values.first.encoding
81
93
  else
82
94
  ::ActiveRecord::Base.connection.select_one("SELECT '' AS str;").values.first.encoding
83
95
  end
@@ -95,6 +107,27 @@ module RailsAdmin
95
107
  true
96
108
  end
97
109
 
110
+ private
111
+
112
+ def bulk_scope(scope, options)
113
+ scope.where(primary_key => options[:bulk_ids])
114
+ end
115
+
116
+ def sort_scope(scope, options)
117
+ direction = options[:sort_reverse] ? :asc : :desc
118
+ case options[:sort]
119
+ when String, Symbol
120
+ scope.reorder("#{options[:sort]} #{direction}")
121
+ when Array
122
+ scope.reorder(options[:sort].zip(Array.new(options[:sort].size) { direction }).to_h)
123
+ when Hash
124
+ scope.reorder(options[:sort].map { |table_name, column| "#{table_name}.#{column}" }.
125
+ zip(Array.new(options[:sort].size) { direction }).to_h)
126
+ else
127
+ raise ArgumentError.new("Unsupported sort value: #{options[:sort]}")
128
+ end
129
+ end
130
+
98
131
  class WhereBuilder
99
132
  def initialize(scope)
100
133
  @statements = []
@@ -199,7 +232,9 @@ module RailsAdmin
199
232
  alias_method :numeric_unary_operators, :boolean_unary_operators
200
233
 
201
234
  def range_filter(min, max)
202
- if min && max
235
+ if min && max && min == max
236
+ ["(#{@column} = ?)", min]
237
+ elsif min && max
203
238
  ["(#{@column} BETWEEN ? AND ?)", min, max]
204
239
  elsif min
205
240
  ["(#{@column} >= ?)", min]
@@ -212,7 +247,7 @@ module RailsAdmin
212
247
  case @type
213
248
  when :boolean then build_statement_for_boolean
214
249
  when :integer, :decimal, :float then build_statement_for_integer_decimal_or_float
215
- when :string, :text then build_statement_for_string_or_text
250
+ when :string, :text, :citext then build_statement_for_string_or_text
216
251
  when :enum then build_statement_for_enum
217
252
  when :belongs_to_association then build_statement_for_belongs_to_association
218
253
  when :uuid then build_statement_for_uuid
@@ -220,8 +255,8 @@ module RailsAdmin
220
255
  end
221
256
 
222
257
  def build_statement_for_boolean
223
- return ["(#{@column} IS NULL OR #{@column} = ?)", false] if %w(false f 0).include?(@value)
224
- return ["(#{@column} = ?)", true] if %w(true t 1).include?(@value)
258
+ return ["(#{@column} IS NULL OR #{@column} = ?)", false] if %w[false f 0].include?(@value)
259
+ return ["(#{@column} = ?)", true] if %w[true t 1].include?(@value)
225
260
  end
226
261
 
227
262
  def column_for_value(value)
@@ -230,6 +265,7 @@ module RailsAdmin
230
265
 
231
266
  def build_statement_for_belongs_to_association
232
267
  return if @value.blank?
268
+
233
269
  ["(#{@column} = ?)", @value.to_i] if @value.to_i.to_s == @value
234
270
  end
235
271
 
@@ -238,13 +274,11 @@ module RailsAdmin
238
274
 
239
275
  return ["(#{@column} = ?)", @value] if ['is', '='].include?(@operator)
240
276
 
241
- unless ['postgresql', 'postgis'].include? ar_adapter
242
- @value = @value.mb_chars.downcase
243
- end
277
+ @value = @value.mb_chars.downcase unless %w[postgresql postgis].include? ar_adapter
244
278
 
245
- @value = begin
279
+ @value =
246
280
  case @operator
247
- when 'default', 'like'
281
+ when 'default', 'like', 'not_like'
248
282
  "%#{@value}%"
249
283
  when 'starts_with'
250
284
  "#{@value}%"
@@ -253,10 +287,15 @@ module RailsAdmin
253
287
  else
254
288
  return
255
289
  end
256
- end
257
290
 
258
- if ['postgresql', 'postgis'].include? ar_adapter
259
- ["(#{@column} ILIKE ?)", @value]
291
+ if %w[postgresql postgis].include? ar_adapter
292
+ if @operator == 'not_like'
293
+ ["(#{@column} NOT ILIKE ?)", @value]
294
+ else
295
+ ["(#{@column} ILIKE ?)", @value]
296
+ end
297
+ elsif @operator == 'not_like'
298
+ ["(LOWER(#{@column}) NOT LIKE ?)", @value]
260
299
  else
261
300
  ["(LOWER(#{@column}) LIKE ?)", @value]
262
301
  end
@@ -264,13 +303,12 @@ module RailsAdmin
264
303
 
265
304
  def build_statement_for_enum
266
305
  return if @value.blank?
306
+
267
307
  ["(#{@column} IN (?))", Array.wrap(@value)]
268
308
  end
269
309
 
270
310
  def build_statement_for_uuid
271
- if @value.to_s =~ /\A[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\z/
272
- column_for_value(@value)
273
- end
311
+ column_for_value(@value) if /\A[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\z/.match?(@value.to_s)
274
312
  end
275
313
 
276
314
  def ar_adapter
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdmin
4
+ module Adapters
5
+ module CompositePrimaryKeys
6
+ class Association < RailsAdmin::Adapters::ActiveRecord::Association
7
+ def field_type
8
+ if type == :belongs_to && association.foreign_key.is_a?(Array)
9
+ :composite_keys_belongs_to_association
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def primary_key
16
+ return nil if polymorphic?
17
+
18
+ value = association.association_primary_key
19
+
20
+ if value.is_a? Array
21
+ :id
22
+ else
23
+ value.to_sym
24
+ end
25
+ end
26
+
27
+ def foreign_key
28
+ if association.foreign_key.is_a? Array
29
+ association.foreign_key.map(&:to_sym)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def key_accessor
36
+ if type == :belongs_to && foreign_key.is_a?(Array)
37
+ :"#{name}_id"
38
+ else
39
+ super
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end