avo 2.45.0 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (371) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +26 -25
  3. data/Gemfile.lock +179 -147
  4. data/README.md +1 -1
  5. data/app/assets/stylesheets/avo.base.css +0 -1
  6. data/app/assets/svgs/font.svg +1 -0
  7. data/app/assets/svgs/triangle-up.svg +1 -0
  8. data/app/components/avo/actions_component.html.erb +19 -5
  9. data/app/components/avo/actions_component.rb +37 -17
  10. data/app/components/avo/asset_manager/javascript_component.html.erb +3 -0
  11. data/app/components/avo/asset_manager/javascript_component.rb +13 -0
  12. data/app/components/avo/asset_manager/stylesheet_component.html.erb +3 -0
  13. data/app/components/avo/asset_manager/stylesheet_component.rb +13 -0
  14. data/app/components/avo/base_component.rb +15 -12
  15. data/app/components/avo/button_component.rb +20 -3
  16. data/app/components/avo/empty_state_component.rb +1 -1
  17. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  18. data/app/components/avo/field_wrapper_component.rb +8 -8
  19. data/app/components/avo/fields/area_field/edit_component.html.erb +2 -2
  20. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +96 -118
  21. data/app/components/avo/fields/belongs_to_field/edit_component.rb +6 -17
  22. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  23. data/app/components/avo/fields/belongs_to_field/show_component.rb +2 -2
  24. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  25. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +3 -3
  26. data/app/components/avo/fields/common/badge_viewer_component.html.erb +24 -1
  27. data/app/components/avo/fields/common/badge_viewer_component.rb +0 -24
  28. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  29. data/app/components/avo/fields/common/files/list_viewer_component.rb +3 -3
  30. data/app/components/avo/fields/common/files/view_type/{grid_item_component.html.erb → grid_component.html.erb} +2 -2
  31. data/app/components/avo/fields/common/files/view_type/{grid_item_component.rb → grid_component.rb} +4 -5
  32. data/app/components/avo/fields/common/files/view_type/{list_item_component.rb → list_component.rb} +1 -1
  33. data/app/components/avo/fields/edit_component.rb +1 -1
  34. data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
  35. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  36. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  37. data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -2
  38. data/app/components/avo/fields/has_one_field/show_component.rb +2 -2
  39. data/app/components/avo/fields/index_component.rb +5 -5
  40. data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
  41. data/app/components/avo/fields/preview_field/index_component.rb +4 -0
  42. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  43. data/app/components/avo/fields/show_component.rb +4 -1
  44. data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
  45. data/app/components/avo/filters_component.html.erb +9 -3
  46. data/app/components/avo/filters_component.rb +4 -4
  47. data/app/components/avo/index/field_wrapper_component.rb +0 -12
  48. data/app/components/avo/index/grid_item_component.html.erb +13 -36
  49. data/app/components/avo/index/grid_item_component.rb +43 -16
  50. data/app/components/avo/index/resource_controls_component.html.erb +3 -81
  51. data/app/components/avo/index/resource_controls_component.rb +124 -17
  52. data/app/components/avo/index/resource_grid_component.html.erb +5 -3
  53. data/app/components/avo/index/resource_grid_component.rb +5 -2
  54. data/app/components/avo/index/resource_map_component.html.erb +1 -1
  55. data/app/components/avo/index/resource_map_component.rb +3 -3
  56. data/app/components/avo/index/resource_table_component.html.erb +5 -4
  57. data/app/components/avo/index/resource_table_component.rb +14 -20
  58. data/app/components/avo/index/table_row_component.html.erb +8 -4
  59. data/app/components/avo/index/table_row_component.rb +3 -2
  60. data/app/components/avo/item_switcher_component.rb +2 -2
  61. data/app/components/avo/modal_component.html.erb +7 -12
  62. data/app/components/avo/modal_component.rb +0 -21
  63. data/app/components/avo/paginator_component.html.erb +40 -29
  64. data/app/components/avo/paginator_component.rb +5 -23
  65. data/app/components/avo/panel_component.html.erb +8 -6
  66. data/app/components/avo/referrer_params_component.html.erb +1 -2
  67. data/app/components/avo/resource_component.rb +189 -14
  68. data/app/components/avo/resource_sidebar_component.html.erb +6 -2
  69. data/app/components/avo/resource_sidebar_component.rb +1 -1
  70. data/app/components/avo/sidebar/link_component.rb +1 -1
  71. data/app/components/avo/sidebar_component.html.erb +10 -3
  72. data/app/components/avo/sidebar_component.rb +5 -3
  73. data/app/components/avo/sidebar_profile_component.html.erb +15 -8
  74. data/app/components/avo/tab_group_component.html.erb +13 -7
  75. data/app/components/avo/tab_group_component.rb +1 -6
  76. data/app/components/avo/tab_switcher_component.html.erb +17 -40
  77. data/app/components/avo/tab_switcher_component.rb +4 -39
  78. data/app/components/avo/views/resource_edit_component.html.erb +12 -48
  79. data/app/components/avo/views/resource_edit_component.rb +7 -18
  80. data/app/components/avo/views/resource_index_component.html.erb +41 -47
  81. data/app/components/avo/views/resource_index_component.rb +62 -12
  82. data/app/components/avo/views/resource_show_component.html.erb +6 -149
  83. data/app/components/avo/views/resource_show_component.rb +6 -11
  84. data/app/controllers/avo/actions_controller.rb +27 -24
  85. data/app/controllers/avo/application_controller.rb +105 -151
  86. data/app/controllers/avo/associations_controller.rb +34 -43
  87. data/app/controllers/avo/attachments_controller.rb +4 -4
  88. data/app/controllers/avo/base_controller.rb +102 -102
  89. data/app/controllers/avo/debug_controller.rb +17 -5
  90. data/app/controllers/avo/home_controller.rb +1 -1
  91. data/app/controllers/avo/search_controller.rb +30 -51
  92. data/app/controllers/avo/team_users_controller.rb +4 -0
  93. data/app/controllers/concerns/avo/initializes_avo.rb +21 -0
  94. data/app/helpers/avo/application_helper.rb +15 -9
  95. data/app/helpers/avo/resources_helper.rb +1 -1
  96. data/app/helpers/avo/url_helpers.rb +27 -11
  97. data/app/javascript/avo.base.js +1 -0
  98. data/app/javascript/js/application.js +0 -3
  99. data/app/javascript/js/controllers/action_controller.js +5 -3
  100. data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
  101. data/app/javascript/js/controllers/filter_controller.js +1 -1
  102. data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
  103. data/app/javascript/js/controllers/preview_controller.js +24 -0
  104. data/app/javascript/js/controllers/search_controller.js +2 -2
  105. data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
  106. data/app/javascript/js/controllers/toggle_controller.js +48 -0
  107. data/app/javascript/js/controllers.js +10 -6
  108. data/app/javascript/js/custom-stream-actions.js +15 -0
  109. data/app/views/avo/actions/keep_modal_open.turbo_stream.erb +5 -0
  110. data/app/views/avo/actions/show.html.erb +9 -6
  111. data/app/views/avo/associations/new.html.erb +2 -2
  112. data/app/views/avo/base/index.html.erb +3 -2
  113. data/app/views/avo/base/new.html.erb +2 -1
  114. data/app/views/avo/base/preview.html.erb +19 -0
  115. data/app/views/avo/base/show.html.erb +1 -1
  116. data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
  117. data/app/views/avo/debug/report.html.erb +32 -17
  118. data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
  119. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  120. data/app/views/avo/partials/_footer.html.erb +1 -1
  121. data/app/views/avo/partials/_javascript.html.erb +5 -0
  122. data/app/views/avo/partials/_logo.html.erb +1 -1
  123. data/app/views/avo/partials/_navbar.html.erb +3 -5
  124. data/app/views/avo/partials/_table_header.html.erb +5 -11
  125. data/app/views/layouts/avo/application.html.erb +4 -2
  126. data/avo.gemspec +7 -7
  127. data/bin/dev +1 -1
  128. data/bin/prod +0 -0
  129. data/config/i18n-tasks.yml +1 -1
  130. data/config/initializers/pagy.rb +0 -2
  131. data/config/master.key +1 -0
  132. data/config/routes.rb +6 -10
  133. data/db/factories.rb +7 -1
  134. data/lib/avo/action_model.rb +20 -0
  135. data/lib/avo/asset_manager.rb +30 -0
  136. data/lib/avo/base_action.rb +57 -41
  137. data/lib/avo/base_resource.rb +263 -226
  138. data/lib/avo/base_resource_tool.rb +9 -16
  139. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  140. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  141. data/lib/avo/concerns/filters_session_handler.rb +5 -3
  142. data/lib/avo/concerns/has_controls.rb +37 -0
  143. data/lib/avo/concerns/has_description.rb +23 -0
  144. data/lib/avo/concerns/has_item_type.rb +42 -0
  145. data/lib/avo/concerns/has_items.rb +325 -0
  146. data/lib/avo/concerns/is_resource_item.rb +24 -36
  147. data/lib/avo/concerns/is_visible.rb +15 -0
  148. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  149. data/lib/avo/concerns/visible_in_different_views.rb +126 -0
  150. data/lib/avo/configuration/branding.rb +0 -12
  151. data/lib/avo/configuration.rb +1 -37
  152. data/lib/avo/current.rb +39 -0
  153. data/lib/avo/dsl/field_parser.rb +1 -1
  154. data/lib/avo/dynamic_router.rb +18 -3
  155. data/lib/avo/engine.rb +35 -30
  156. data/lib/avo/error_manager.rb +25 -0
  157. data/lib/avo/execution_context.rb +10 -14
  158. data/lib/avo/fields/badge_field.rb +1 -1
  159. data/lib/avo/fields/base_field.rb +91 -105
  160. data/lib/avo/fields/belongs_to_field.rb +18 -22
  161. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  162. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  163. data/lib/avo/fields/concerns/has_default.rb +1 -5
  164. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  165. data/lib/avo/fields/concerns/has_html_attributes.rb +110 -0
  166. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  167. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  168. data/lib/avo/fields/concerns/is_required.rb +5 -7
  169. data/lib/avo/fields/concerns/is_searchable.rb +13 -0
  170. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  171. data/lib/avo/fields/country_field.rb +4 -0
  172. data/lib/avo/fields/date_time_field.rb +1 -5
  173. data/lib/avo/fields/field_manager.rb +55 -0
  174. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  175. data/lib/avo/fields/has_base_field.rb +12 -15
  176. data/lib/avo/fields/has_many_field.rb +5 -2
  177. data/lib/avo/fields/has_one_field.rb +6 -10
  178. data/lib/avo/fields/heading_field.rb +4 -1
  179. data/lib/avo/fields/hidden_field.rb +1 -1
  180. data/lib/avo/fields/id_field.rb +1 -1
  181. data/lib/avo/fields/location_field.rb +8 -8
  182. data/lib/avo/fields/password_field.rb +1 -1
  183. data/lib/avo/fields/preview_field.rb +14 -0
  184. data/lib/avo/fields/select_field.rb +12 -8
  185. data/lib/avo/fields/status_field.rb +4 -0
  186. data/lib/avo/filters/base_filter.rb +8 -4
  187. data/lib/avo/html/builder.rb +7 -8
  188. data/lib/avo/item_grapher.rb +78 -0
  189. data/lib/avo/licensing/h_q.rb +7 -66
  190. data/lib/avo/licensing/license.rb +1 -1
  191. data/lib/avo/licensing/pro_license.rb +1 -7
  192. data/lib/avo/loaders/fields_loader.rb +7 -1
  193. data/lib/avo/plugin.rb +16 -0
  194. data/lib/avo/plugin_manager.rb +56 -0
  195. data/lib/avo/prefixed_test_helpers.rb +20 -0
  196. data/lib/avo/reloader.rb +3 -0
  197. data/lib/avo/resources/controls/actions_list.rb +7 -12
  198. data/lib/avo/resources/controls/attach_button.rb +15 -0
  199. data/lib/avo/resources/controls/back_button.rb +1 -1
  200. data/lib/avo/resources/controls/base_control.rb +15 -49
  201. data/lib/avo/resources/controls/create_button.rb +15 -0
  202. data/lib/avo/resources/controls/delete_button.rb +5 -1
  203. data/lib/avo/resources/controls/detach_button.rb +4 -1
  204. data/lib/avo/resources/controls/edit_button.rb +4 -1
  205. data/lib/avo/resources/controls/order_controls.rb +8 -0
  206. data/lib/avo/resources/controls/save_button.rb +13 -0
  207. data/lib/avo/resources/controls/show_button.rb +15 -0
  208. data/lib/avo/resources/items/holder.rb +84 -0
  209. data/lib/avo/resources/items/item_group.rb +49 -0
  210. data/lib/avo/resources/items/main_panel.rb +2 -0
  211. data/lib/avo/resources/items/panel.rb +2 -0
  212. data/lib/avo/resources/items/row.rb +54 -0
  213. data/lib/avo/resources/items/sidebar.rb +47 -0
  214. data/lib/avo/resources/items/tab.rb +60 -0
  215. data/lib/avo/resources/items/tab_group.rb +68 -0
  216. data/lib/avo/resources/resource_manager.rb +174 -0
  217. data/lib/avo/services/authorization_service.rb +11 -110
  218. data/lib/avo/services/debug_service.rb +93 -0
  219. data/lib/avo/services/telemetry_service.rb +85 -0
  220. data/lib/avo/test_helpers.rb +362 -0
  221. data/lib/avo/tools/tool_manager.rb +30 -0
  222. data/lib/avo/version.rb +1 -1
  223. data/lib/avo.rb +115 -24
  224. data/lib/generators/avo/action_generator.rb +8 -8
  225. data/lib/generators/avo/card_generator.rb +27 -0
  226. data/lib/generators/avo/filter_generator.rb +8 -8
  227. data/lib/generators/avo/resource_generator.rb +4 -4
  228. data/lib/generators/avo/scope_generator.rb +15 -0
  229. data/lib/generators/avo/tailwindcss/install_generator.rb +1 -15
  230. data/lib/generators/avo/templates/action.tt +8 -6
  231. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  232. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  233. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  234. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  235. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  236. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  237. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  238. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  239. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  240. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  241. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  242. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  243. data/lib/generators/avo/templates/initializer/avo.tt +1 -9
  244. data/lib/generators/avo/templates/locales/avo.ar.yml +5 -5
  245. data/lib/generators/avo/templates/locales/avo.en.yml +4 -5
  246. data/lib/generators/avo/templates/locales/avo.fr.yml +1 -2
  247. data/lib/generators/avo/templates/locales/avo.nb.yml +1 -2
  248. data/lib/generators/avo/templates/locales/avo.nn.yml +1 -2
  249. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -2
  250. data/lib/generators/avo/templates/locales/avo.pt.yml +1 -2
  251. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -7
  252. data/lib/generators/avo/templates/locales/avo.tr.yml +1 -2
  253. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  254. data/lib/generators/avo/templates/resource_tools/partial.tt +4 -4
  255. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  256. data/lib/generators/avo/templates/scope.tt +6 -0
  257. data/lib/generators/avo/templates/tool/view.tt +2 -2
  258. data/lib/tasks/avo_tasks.rake +27 -0
  259. data/public/avo-assets/avo.base.css +1810 -1189
  260. data/public/avo-assets/avo.base.js +217 -305
  261. data/public/avo-assets/avo.base.js.map +3 -3
  262. data/public/avo-assets/avo.css +9744 -0
  263. data/public/avo-assets/avo.js +513 -0
  264. data/public/avo-assets/avo.js.map +7 -0
  265. metadata +96 -137
  266. data/app/assets/stylesheets/css/tags.css +0 -32
  267. data/app/components/avo/card_component.html.erb +0 -46
  268. data/app/components/avo/card_component.rb +0 -25
  269. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  270. data/app/components/avo/dashboards/divider_component.rb +0 -19
  271. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  272. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  273. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  274. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  275. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  276. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  277. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  278. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  279. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  280. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  281. data/app/components/avo/index/ordering/base_component.rb +0 -9
  282. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  283. data/app/components/avo/index/ordering/button_component.rb +0 -23
  284. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  285. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  286. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  287. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  288. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  289. data/app/controllers/avo/dashboards_controller.rb +0 -22
  290. data/app/controllers/avo/reorder_controller.rb +0 -25
  291. data/app/javascript/js/controllers/base_controller.js +0 -22
  292. data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +0 -51
  293. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  294. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  295. data/app/views/avo/base/_new_via_belongs_to.html.erb +0 -12
  296. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +0 -8
  297. data/app/views/avo/base/create_fail_action.turbo_stream.erb +0 -13
  298. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  299. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  300. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  301. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  302. data/app/views/avo/dashboards/show.html.erb +0 -38
  303. data/app/views/avo/partials/_flash_alerts.turbo_stream.erb +0 -3
  304. data/app/views/avo/partials/_global_search.html.erb +0 -19
  305. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  306. data/lib/avo/app.rb +0 -237
  307. data/lib/avo/base_card.rb +0 -161
  308. data/lib/avo/concerns/fetches_things.rb +0 -150
  309. data/lib/avo/concerns/handles_field_args.rb +0 -47
  310. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  311. data/lib/avo/concerns/has_fields.rb +0 -334
  312. data/lib/avo/concerns/has_html_attributes.rb +0 -108
  313. data/lib/avo/concerns/pagination.rb +0 -53
  314. data/lib/avo/concerns/policy_helpers.rb +0 -31
  315. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  316. data/lib/avo/concerns/visible_items.rb +0 -51
  317. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  318. data/lib/avo/dashboards/base_divider.rb +0 -35
  319. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  320. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  321. data/lib/avo/dashboards/metric_card.rb +0 -9
  322. data/lib/avo/dashboards/partial_card.rb +0 -7
  323. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  324. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  325. data/lib/avo/fields/tags_field.rb +0 -102
  326. data/lib/avo/grid_collector.rb +0 -42
  327. data/lib/avo/hosts/association_scope_host.rb +0 -8
  328. data/lib/avo/hosts/base_host.rb +0 -25
  329. data/lib/avo/hosts/card_visibility.rb +0 -20
  330. data/lib/avo/hosts/dashboard_card.rb +0 -22
  331. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  332. data/lib/avo/hosts/ordering.rb +0 -22
  333. data/lib/avo/hosts/record_host.rb +0 -7
  334. data/lib/avo/hosts/resource_record_host.rb +0 -7
  335. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  336. data/lib/avo/hosts/search_scope_host.rb +0 -7
  337. data/lib/avo/hosts/view_record_host.rb +0 -7
  338. data/lib/avo/hosts/visibility_host.rb +0 -12
  339. data/lib/avo/items_holder.rb +0 -96
  340. data/lib/avo/main_panel.rb +0 -3
  341. data/lib/avo/menu/base_item.rb +0 -25
  342. data/lib/avo/menu/builder.rb +0 -82
  343. data/lib/avo/menu/dashboard.rb +0 -22
  344. data/lib/avo/menu/group.rb +0 -2
  345. data/lib/avo/menu/link.rb +0 -6
  346. data/lib/avo/menu/menu.rb +0 -2
  347. data/lib/avo/menu/resource.rb +0 -22
  348. data/lib/avo/menu/section.rb +0 -2
  349. data/lib/avo/panel.rb +0 -24
  350. data/lib/avo/panel_builder.rb +0 -25
  351. data/lib/avo/resources/controls/action.rb +0 -38
  352. data/lib/avo/resources/controls/execution_context.rb +0 -58
  353. data/lib/avo/resources/controls/items_holder.rb +0 -19
  354. data/lib/avo/resources/controls/link_to.rb +0 -27
  355. data/lib/avo/row.rb +0 -26
  356. data/lib/avo/row_builder.rb +0 -24
  357. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  358. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  359. data/lib/avo/sidebar.rb +0 -30
  360. data/lib/avo/sidebar_builder.rb +0 -24
  361. data/lib/avo/tab.rb +0 -72
  362. data/lib/avo/tab_builder.rb +0 -25
  363. data/lib/avo/tab_group.rb +0 -42
  364. data/lib/avo/tab_group_builder.rb +0 -43
  365. data/lib/avo/tools_manager.rb +0 -11
  366. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  367. data/lib/generators/avo/card/metric_generator.rb +0 -18
  368. data/lib/generators/avo/card/partial_generator.rb +0 -19
  369. data/lib/generators/avo/templates/locales/avo.es.yml +0 -126
  370. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  371. /data/app/components/avo/fields/common/files/view_type/{list_item_component.html.erb → list_component.html.erb} +0 -0
@@ -3,53 +3,61 @@ module Avo
3
3
  extend ActiveSupport::DescendantsTracker
4
4
 
5
5
  include ActionView::Helpers::UrlHelper
6
- include Avo::Concerns::HasFields
7
- include Avo::Concerns::CanReplaceFields
8
- include Avo::Concerns::HasEditableControls
6
+ include Avo::Concerns::HasItems
7
+ include Avo::Concerns::CanReplaceItems
8
+ include Avo::Concerns::HasControls
9
9
  include Avo::Concerns::HasStimulusControllers
10
10
  include Avo::Concerns::ModelClassConstantized
11
- include Avo::Concerns::Pagination
11
+ include Avo::Concerns::HasDescription
12
12
 
13
- delegate :view_context, to: ::Avo::App
14
- delegate :current_user, to: ::Avo::App
15
- delegate :params, to: ::Avo::App
13
+ # Avo::Current methods
14
+ delegate :context, to: Avo::Current
15
+ def curent_user
16
+ Avo::Current.user
17
+ end
18
+ delegate :params, to: Avo::Current
19
+ delegate :request, to: Avo::Current
20
+ delegate :view_context, to: Avo::Current
21
+
22
+ # view_context methods
16
23
  delegate :simple_format, :content_tag, to: :view_context
17
24
  delegate :main_app, to: :view_context
18
25
  delegate :avo, to: :view_context
19
26
  delegate :resource_path, to: :view_context
20
27
  delegate :resources_path, to: :view_context
28
+
29
+ # I18n methods
21
30
  delegate :t, to: ::I18n
22
- delegate :context, to: ::Avo::App
31
+
32
+ # class methods
33
+ delegate :class_name, to: :class
34
+ delegate :route_key, to: :class
35
+ delegate :singular_route_key, to: :class
23
36
 
24
37
  attr_accessor :view
25
38
  attr_accessor :reflection
26
39
  attr_accessor :user
27
- attr_accessor :params
40
+ attr_accessor :record
28
41
 
29
42
  class_attribute :id, default: :id
30
- class_attribute :title, default: :id
31
- class_attribute :description, default: :id
32
- class_attribute :search_query, default: nil
33
- class_attribute :search_query_help, default: ""
34
- class_attribute :search_result_path
43
+ class_attribute :title
44
+ class_attribute :search, default: {}
35
45
  class_attribute :includes, default: []
36
46
  class_attribute :authorization_policy
37
47
  class_attribute :translation_key
38
48
  class_attribute :default_view_type, default: :table
39
49
  class_attribute :devise_password_optional, default: false
40
- class_attribute :actions_loader
50
+ class_attribute :scopes_loader
41
51
  class_attribute :filters_loader
42
- class_attribute :grid_loader
52
+ class_attribute :view_types
53
+ class_attribute :grid_view
43
54
  class_attribute :visible_on_sidebar, default: true
44
- class_attribute :unscoped_queries_on_index, default: false
45
- class_attribute :resolve_query_scope
46
- class_attribute :resolve_find_scope
47
- # TODO: refactor this into a Host without args
48
- class_attribute :find_record_method, default: ->(model_class:, id:, params:) {
49
- model_class.find id
55
+ class_attribute :index_query, default: -> {
56
+ query
57
+ }
58
+ class_attribute :find_record_method, default: -> {
59
+ query.find id
50
60
  }
51
- class_attribute :ordering
52
- class_attribute :hide_from_global_search, default: false
53
61
  class_attribute :after_create_path, default: :show
54
62
  class_attribute :after_update_path, default: :show
55
63
  class_attribute :record_selector, default: true
@@ -58,59 +66,44 @@ module Avo
58
66
  class_attribute :link_to_child_resource, default: false
59
67
  class_attribute :map_view
60
68
 
69
+ # EXTRACT:
70
+ class_attribute :ordering
71
+
61
72
  class << self
62
73
  delegate :t, to: ::I18n
63
- delegate :context, to: ::Avo::App
64
-
65
- def grid(&block)
66
- grid_collector = GridCollector.new
67
- grid_collector.instance_eval(&block)
68
-
69
- self.grid_loader = grid_collector
70
- end
74
+ delegate :context, to: ::Avo::Current
71
75
 
72
76
  def action(action_class, arguments: {})
73
- self.actions_loader ||= Avo::Loaders::Loader.new
74
-
75
- action = { class: action_class, arguments: arguments }
76
- self.actions_loader.use action
77
+ deprecated_dsl_api __method__, "actions"
77
78
  end
78
79
 
79
80
  def filter(filter_class, arguments: {})
80
- self.filters_loader ||= Avo::Loaders::Loader.new
81
-
82
- filter = { class: filter_class , arguments: arguments }
83
- self.filters_loader.use filter
81
+ deprecated_dsl_api __method__, "filters"
84
82
  end
85
83
 
86
- # This is the search_query scope
87
- # This should be removed and passed to the search block
88
- def scope
89
- query_scope
84
+ def scope(scope_class)
85
+ deprecated_dsl_api __method__, "scopes"
90
86
  end
91
87
 
92
88
  # This resolves the scope when doing "where" queries (not find queries)
89
+ #
90
+ # It's used to apply the authorization feature.
93
91
  def query_scope
94
- final_scope = resolve_query_scope.present? ? resolve_query_scope.call(model_class: model_class) : model_class
95
-
96
- authorization.apply_policy final_scope
92
+ authorization.apply_policy Avo::ExecutionContext.new(
93
+ target: index_query,
94
+ query: model_class
95
+ ).handle
97
96
  end
98
97
 
99
98
  # This resolves the scope when finding records (not "where" queries)
99
+ #
100
+ # It's used to apply the authorization feature.
100
101
  def find_scope
101
- final_scope = resolve_find_scope.present? ? resolve_find_scope.call(model_class: model_class) : model_class
102
-
103
- authorization.apply_policy final_scope
102
+ authorization.apply_policy model_class
104
103
  end
105
104
 
106
105
  def authorization
107
- Avo::Services::AuthorizationService.new Avo::App.current_user, model_class, policy_class: authorization_policy
108
- end
109
-
110
- def order_actions
111
- return {} if ordering.blank?
112
-
113
- ordering.dig(:actions) || {}
106
+ Avo::Services::AuthorizationService.new Avo::Current.user, model_class, policy_class: authorization_policy
114
107
  end
115
108
 
116
109
  def get_record_associations(record)
@@ -134,170 +127,242 @@ module Avo
134
127
  ApplicationRecord.descendants
135
128
  end
136
129
 
137
- def valid_model_class(model_class)
130
+ def get_model_by_name(model_name)
138
131
  get_available_models.find do |m|
139
- m.to_s == model_class.to_s
132
+ m.to_s == model_name.to_s
140
133
  end
141
134
  end
142
- end
143
135
 
144
- def initialize
145
- unless self.class.model_class.present?
146
- if model_class.present? && model_class.respond_to?(:base_class)
147
- self.class.model_class = model_class.base_class
148
- end
136
+ # Returns the model class being used for this resource.
137
+ #
138
+ # The Resource instance has a model_class method too so it can support the STI use cases
139
+ # where we figure out the model class from the record
140
+ def model_class(record_class: nil)
141
+ # get the model class off of the static property
142
+ return @model_class if @model_class.present?
143
+
144
+ # get the model class off of the record for STI models
145
+ return record_class if record_class.present?
146
+
147
+ # generate a model class
148
+ class_name.safe_constantize
149
149
  end
150
- end
151
150
 
152
- def record
153
- @model
154
- end
155
- alias_method :model, :record
151
+ # This is used as the model class ID
152
+ # We use this instead of the route_key to maintain compatibility with uncountable models
153
+ # With uncountable models route key appends an _index suffix (Fish->fish_index)
154
+ # Example: User->users, MediaItem->media_items, Fish->fish
155
+ def model_key
156
+ model_class.model_name.plural
157
+ end
156
158
 
159
+ def class_name
160
+ to_s.demodulize
161
+ end
157
162
 
158
- def hydrate(model: nil, view: nil, user: nil, params: nil)
159
- @view = view if view.present?
160
- @user = user if user.present?
161
- @params = params if params.present?
163
+ def route_key
164
+ class_name.underscore.pluralize
165
+ end
162
166
 
163
- if model.present?
164
- @model = model
167
+ def singular_route_key
168
+ route_key.singularize
169
+ end
165
170
 
166
- hydrate_model_with_default_values if @view == :new
171
+ def translation_key
172
+ @translation_key || "avo.resource_translations.#{class_name.underscore}"
167
173
  end
168
174
 
169
- self
170
- end
175
+ def name
176
+ default = class_name.underscore.humanize
171
177
 
172
- def get_grid_fields
173
- return if self.class.grid_loader.blank?
178
+ if translation_key
179
+ t(translation_key, count: 1, default: default).humanize
180
+ else
181
+ default
182
+ end
183
+ end
184
+ alias_method :singular_name, :name
174
185
 
175
- self.class.grid_loader.hydrate(model: @model, view: @view, resource: self)
176
- end
186
+ def plural_name
187
+ default = name.pluralize
177
188
 
178
- def get_filters
179
- return [] if self.class.filters_loader.blank?
189
+ if translation_key
190
+ t(translation_key, count: 2, default: default).humanize
191
+ else
192
+ default
193
+ end
194
+ end
180
195
 
181
- self.class.filters_loader.bag
182
- end
196
+ def underscore_name
197
+ return @name if @name.present?
183
198
 
184
- def get_filter_arguments(filter_class)
185
- filter = get_filters.find { |filter| filter[:class] == filter_class.constantize }
199
+ name.demodulize.underscore
200
+ end
186
201
 
187
- filter[:arguments]
188
- end
202
+ def navigation_label
203
+ plural_name.humanize
204
+ end
189
205
 
190
- def get_actions
191
- return [] if self.class.actions_loader.blank?
206
+ def find_record(id, query: nil, params: nil)
207
+ Avo::ExecutionContext.new(
208
+ target: find_record_method,
209
+ query: query || find_scope, # If no record is given we'll use the default
210
+ id: id,
211
+ params: params
212
+ ).handle
213
+ end
214
+
215
+ def search_query
216
+ search.dig(:query)
217
+ end
192
218
 
193
- self.class.actions_loader.bag
219
+ def fetch_search(key, record: nil)
220
+ # self.class.fetch_search
221
+ Avo::ExecutionContext.new(target: search[key], resource: self, record: record).handle
222
+ end
194
223
  end
195
224
 
196
- def get_action_arguments(action_class)
197
- action = get_actions.find { |action| action[:class].to_s == action_class.to_s }
225
+ delegate :context, to: ::Avo::Current
226
+ delegate :name, to: :class
227
+ delegate :singular_name, to: :class
228
+ delegate :plural_name, to: :class
229
+ delegate :underscore_name, to: :class
230
+ delegate :underscore_name, to: :class
231
+ delegate :find_record, to: :class
232
+ delegate :model_key, to: :class
198
233
 
199
- action[:arguments]
200
- end
234
+ def initialize(record: nil, view: nil, user: nil, params: nil)
235
+ @view = view if view.present?
236
+ @user = user if user.present?
237
+ @params = params if params.present?
201
238
 
202
- def default_panel_name
203
- return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
239
+ if record.present?
240
+ @record = record
204
241
 
205
- case @view
206
- when :show
207
- model_title
208
- when :edit
209
- model_title
210
- when :new
211
- t("avo.create_new_item", item: name.downcase).upcase_first
242
+ hydrate_model_with_default_values if @view == :new
212
243
  end
213
- end
214
244
 
215
- def class_name_without_resource
216
- self.class.name.demodulize.delete_suffix("Resource")
245
+ detect_fields
246
+
247
+ unless self.class.model_class.present?
248
+ if model_class.present? && model_class.respond_to?(:base_class)
249
+ self.class.model_class = model_class.base_class
250
+ end
251
+ end
217
252
  end
218
253
 
219
- def model_class
220
- # get the model class off of the static property
221
- return self.class.model_class if self.class.model_class.present?
254
+ def detect_fields
255
+ self.items_holder = Avo::Resources::Items::Holder.new
222
256
 
223
- # get the model class off of the model for STI models
224
- return @model.base_class if @model.present?
257
+ # Used in testing to replace items
258
+ if temporary_items.present?
259
+ instance_eval(&temporary_items)
260
+ else
261
+ fields
262
+ end
225
263
 
226
- # generate a model class
227
- class_name_without_resource.safe_constantize
264
+ self
228
265
  end
229
266
 
230
- def model_id
231
- @model.send id
267
+ def fields
268
+ # blank fields method
232
269
  end
233
270
 
234
- def model_title
235
- return name if @model.nil?
271
+ [:action, :filter, :scope].each do |entity|
272
+ plural_entity = entity.to_s.pluralize
236
273
 
237
- the_title = @model.send title
238
- return the_title if the_title.present?
274
+ # def actions / def filters / def scopes
275
+ define_method plural_entity do
276
+ # blank entity method
277
+ end
239
278
 
240
- model_id
241
- rescue
242
- name
243
- end
279
+ # def action / def filter / def scope
280
+ define_method entity do |entity_class, arguments: {}|
281
+ entity_loader(entity).use({class: entity_class, arguments: arguments})
282
+ end
244
283
 
245
- def resource_description
246
- return instance_exec(&self.class.description) if self.class.description.respond_to? :call
284
+ # def get_actions / def get_filters / def get_scopes
285
+ define_method "get_#{plural_entity}" do
286
+ return entity_loader(entity).bag if entity_loader(entity).present?
247
287
 
248
- # Show the description only on the resource index view.
249
- # If the user wants to conditionally it on all pages, they should use a block.
250
- if view == :index
251
- return self.class.description if self.class.description.is_a? String
252
- end
253
- end
288
+ instance_variable_set("@#{plural_entity}_loader", Avo::Loaders::Loader.new)
289
+ send plural_entity
254
290
 
255
- def translation_key
256
- return "avo.resource_translations.#{class_name_without_resource.underscore}" if ::Avo::App.translation_enabled
291
+ entity_loader(entity).bag
292
+ end
257
293
 
258
- self.class.translation_key
294
+ # def get_action_arguments / def get_filter_arguments / def get_scope_arguments
295
+ define_method "get_#{entity}_arguments" do |entity_class|
296
+ send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
297
+ end
259
298
  end
260
299
 
261
- def name
262
- default = class_name_without_resource.to_s.gsub('::', ' ').underscore.humanize
300
+ def hydrate(record: nil, view: nil, user: nil, params: nil)
301
+ @view = view if view.present?
302
+ @user = user if user.present?
303
+ @params = params if params.present?
263
304
 
264
- return @name if @name.present?
305
+ if record.present?
306
+ @record = record
265
307
 
266
- if translation_key && ::Avo::App.translation_enabled
267
- t(translation_key, count: 1, default: default).humanize
268
- else
269
- default
308
+ hydrate_model_with_default_values if @view == :new
270
309
  end
271
- end
272
310
 
273
- def singular_name
274
- name
311
+ self
275
312
  end
276
313
 
277
- def plural_name
278
- default = name.pluralize
314
+ def default_panel_name
315
+ return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
279
316
 
280
- if translation_key && ::Avo::App.translation_enabled
281
- t(translation_key, count: 2, default: default).humanize
282
- else
283
- default
317
+ case @view
318
+ when :show
319
+ record_title
320
+ when :edit
321
+ record_title
322
+ when :new
323
+ t("avo.create_new_item", item: name.humanize(capitalize: false)).upcase_first
284
324
  end
285
325
  end
286
326
 
287
- def underscore_name
288
- return @name if @name.present?
327
+ # Returns the model class being used for this resource.
328
+ #
329
+ # We use the class method as a fallback but we pass it the record too so it can support the STI use cases
330
+ # where we figure out the model class from that record.
331
+ def model_class
332
+ record_class = @record&.class
289
333
 
290
- self.class.name.demodulize.underscore
334
+ self.class.model_class record_class: record_class
291
335
  end
292
336
 
293
- def navigation_label
294
- plural_name.humanize
337
+ def record_title
338
+ return name if @record.nil?
339
+
340
+ # Get the title from the record if title is not set, try to get the name, title or label, or fallback to the id
341
+ return @record.try(:name) || @record.try(:title) || @record.try(:label) || @record.id if title.nil?
342
+
343
+ # If the title is a symbol, get the value from the record else execute the block/string
344
+ case title
345
+ when Symbol
346
+ @record.send title
347
+ when Proc
348
+ Avo::ExecutionContext.new(target: title, resource: self, record: @record).handle
349
+ end
295
350
  end
296
351
 
297
352
  def available_view_types
353
+ if self.class.view_types.present?
354
+ return Array(
355
+ Avo::ExecutionContext.new(
356
+ target: self.class.view_types,
357
+ resource: self,
358
+ record: record
359
+ ).handle
360
+ )
361
+ end
362
+
298
363
  view_types = [:table]
299
364
 
300
- view_types << :grid if get_grid_fields.present?
365
+ view_types << :grid if self.class.grid_view.present?
301
366
  view_types << :map if map_view.present?
302
367
 
303
368
  view_types
@@ -309,7 +374,7 @@ module Avo
309
374
  end
310
375
  end
311
376
 
312
- # Map the received params to their actual fields.
377
+ # Map the received params to their actual fields
313
378
  def fields_by_database_id
314
379
  get_field_definitions
315
380
  .reject do |field|
@@ -321,28 +386,28 @@ module Avo
321
386
  .to_h
322
387
  end
323
388
 
324
- def fill_model(model, params, extra_params: [])
389
+ def fill_record(record, params, extra_params: [])
325
390
  # Write the field values
326
391
  params.each do |key, value|
327
392
  field = fields_by_database_id[key]
328
393
 
329
394
  next unless field.present?
330
395
 
331
- model = field.fill_field model, key, value, params
396
+ record = field.fill_field record, key, value, params
332
397
  end
333
398
 
334
- # Write the user configured extra params to the model
399
+ # Write the user configured extra params to the record
335
400
  if extra_params.present?
336
401
  # Let Rails fill in the rest of the params
337
- model.assign_attributes params.permit(extra_params)
402
+ record.assign_attributes params.permit(extra_params)
338
403
  end
339
404
 
340
- model
405
+ record
341
406
  end
342
407
 
343
408
  def authorization(user: nil)
344
- current_user = user || Avo::App.current_user
345
- Avo::Services::AuthorizationService.new(current_user, model || model_class, policy_class: authorization_policy)
409
+ current_user = user || Avo::Current.user
410
+ Avo::Services::AuthorizationService.new(current_user, record || model_class, policy_class: authorization_policy)
346
411
  end
347
412
 
348
413
  def file_hash
@@ -363,15 +428,15 @@ module Avo
363
428
  Digest::MD5.hexdigest(content_to_be_hashed)
364
429
  end
365
430
 
366
- def cache_hash(parent_model)
367
- if parent_model.present?
368
- [model, file_hash, parent_model]
431
+ def cache_hash(parent_record)
432
+ if parent_record.present?
433
+ [record, file_hash, parent_record]
369
434
  else
370
- [model, file_hash]
435
+ [record, file_hash]
371
436
  end
372
437
  end
373
438
 
374
- # We will not overwrite any attributes that come pre-filled in the model.
439
+ # We will not overwrite any attributes that come pre-filled in the record.
375
440
  def hydrate_model_with_default_values
376
441
  default_values = get_fields
377
442
  .select do |field|
@@ -382,18 +447,18 @@ module Avo
382
447
 
383
448
  if field.type == "belongs_to"
384
449
 
385
- reflection = @model._reflections[@params[:via_relation]]
450
+ reflection = @record._reflections[@params[:via_relation]]
386
451
 
387
452
  if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
388
453
  # set the value to the actual record
389
- via_resource = ::Avo::App.get_resource_by_model_name(@params[:via_relation_class])
390
- value = via_resource.find_record(@params[:via_resource_id])
454
+ via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
455
+ value = via_resource.find_record(@params[:via_record_id])
391
456
  elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
392
- resource = Avo::App.get_resource_by_model_name params[:via_relation_class]
393
- model = resource.find_record @params[:via_resource_id], params: params
457
+ resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
458
+ record = resource.find_record @params[:via_record_id], params: params
394
459
  id_param = reflection.options[:primary_key] || :id
395
460
 
396
- value = model.send(id_param)
461
+ value = record.send(id_param)
397
462
  end
398
463
  end
399
464
 
@@ -405,26 +470,10 @@ module Avo
405
470
  end
406
471
 
407
472
  default_values.each do |field, value|
408
- field.assign_value record: @model, value: value
473
+ field.assign_value record: @record, value: value
409
474
  end
410
475
  end
411
476
 
412
- def route_key
413
- class_name_without_resource.underscore.pluralize
414
- end
415
-
416
- def singular_route_key
417
- route_key.singularize
418
- end
419
-
420
- # This is used as the model class ID
421
- # We use this instead of the route_key to maintain compatibility with uncountable models
422
- # With uncountable models route key appends an _index suffix (Fish->fish_index)
423
- # Example: User->users, MediaItem->media_items, Fish->fish
424
- def model_key
425
- model_class.model_name.plural
426
- end
427
-
428
477
  def model_name
429
478
  model_class.model_name
430
479
  end
@@ -434,25 +483,13 @@ module Avo
434
483
  end
435
484
 
436
485
  def record_path
437
- resource_path(model: model, resource: self)
486
+ resource_path(record: record, resource: self)
438
487
  end
439
488
 
440
489
  def records_path
441
490
  resources_path(resource: self)
442
491
  end
443
492
 
444
- def label_field
445
- get_field_definitions.find do |field|
446
- field.as_label.present?
447
- end
448
- rescue
449
- nil
450
- end
451
-
452
- def label
453
- label_field&.value || model_title
454
- end
455
-
456
493
  def avatar_field
457
494
  get_field_definitions.find do |field|
458
495
  field.as_avatar.present?
@@ -477,34 +514,34 @@ module Avo
477
514
  nil
478
515
  end
479
516
 
480
- def description_field
481
- get_field_definitions.find do |field|
482
- field.as_description.present?
483
- end
484
- rescue
485
- nil
517
+ def form_scope
518
+ model_class.base_class.to_s.underscore.downcase
486
519
  end
487
520
 
488
- def description
489
- description_field&.value
521
+ def has_record_id?
522
+ record.present? && record_id.present?
490
523
  end
491
524
 
492
- def form_scope
493
- model_class.base_class.to_s.underscore.downcase
525
+ def id_attribute
526
+ :id
494
527
  end
495
528
 
496
- def ordering_host(**args)
497
- Avo::Hosts::Ordering.new resource: self, options: self.class.ordering, **args
529
+ def record_id
530
+ record.send(id_attribute)
498
531
  end
499
532
 
500
- def has_model_id?
501
- model.present? && model.id.present?
533
+ def description_attributes
534
+ {
535
+ view: view,
536
+ resource: self,
537
+ record: record
538
+ }
502
539
  end
503
540
 
504
- def find_record(id, query: nil, params: nil)
505
- query ||= self.class.find_scope
541
+ private
506
542
 
507
- self.class.find_record_method.call(model_class: query, id: id, params: params)
543
+ def entity_loader(entity)
544
+ instance_variable_get("@#{entity.to_s.pluralize}_loader")
508
545
  end
509
546
  end
510
547
  end