avo 2.46.0 → 3.0.2

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 (409) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +28 -26
  3. data/Gemfile.lock +231 -161
  4. data/README.md +19 -27
  5. data/Rakefile +2 -0
  6. data/app/assets/stylesheets/avo.base.css +1 -1
  7. data/app/assets/svgs/font.svg +1 -0
  8. data/app/assets/svgs/triangle-up.svg +1 -0
  9. data/app/components/avo/actions_component.html.erb +19 -5
  10. data/app/components/avo/actions_component.rb +39 -19
  11. data/app/components/avo/asset_manager/javascript_component.html.erb +3 -0
  12. data/app/components/avo/asset_manager/javascript_component.rb +13 -0
  13. data/app/components/avo/asset_manager/stylesheet_component.html.erb +3 -0
  14. data/app/components/avo/asset_manager/stylesheet_component.rb +13 -0
  15. data/app/components/avo/base_component.rb +15 -12
  16. data/app/components/avo/button_component.rb +20 -3
  17. data/app/components/avo/empty_state_component.rb +1 -1
  18. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  19. data/app/components/avo/field_wrapper_component.rb +12 -29
  20. data/app/components/avo/fields/area_field/edit_component.html.erb +2 -2
  21. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +75 -79
  22. data/app/components/avo/fields/belongs_to_field/edit_component.rb +7 -7
  23. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  24. data/app/components/avo/fields/belongs_to_field/show_component.rb +2 -2
  25. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  26. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  27. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +3 -3
  28. data/app/components/avo/fields/common/badge_viewer_component.rb +1 -1
  29. data/app/components/avo/fields/common/boolean_check_component.html.erb +1 -12
  30. data/app/components/avo/fields/common/boolean_check_component.rb +2 -1
  31. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  32. data/app/components/avo/fields/common/files/view_type/grid_item_component.rb +2 -2
  33. data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
  34. data/app/components/avo/fields/common/gravatar_viewer_component.rb +2 -2
  35. data/app/components/avo/fields/common/heading_component.html.erb +3 -8
  36. data/app/components/avo/fields/common/heading_component.rb +1 -3
  37. data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
  38. data/app/components/avo/fields/common/key_value_component.rb +2 -2
  39. data/app/components/avo/fields/common/progress_bar_component.rb +3 -9
  40. data/app/components/avo/fields/common/status_viewer_component.html.erb +3 -0
  41. data/app/components/avo/fields/edit_component.rb +2 -2
  42. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
  43. data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
  44. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  45. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  46. data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -2
  47. data/app/components/avo/fields/has_one_field/show_component.rb +2 -2
  48. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  49. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  50. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  51. data/app/components/avo/fields/index_component.rb +6 -6
  52. data/app/components/avo/fields/location_field/edit_component.html.erb +12 -10
  53. data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
  54. data/app/components/avo/fields/preview_field/index_component.rb +4 -0
  55. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  56. data/app/components/avo/fields/show_component.rb +5 -2
  57. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  58. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
  59. data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
  60. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  61. data/app/components/avo/filters_component.html.erb +9 -3
  62. data/app/components/avo/filters_component.rb +4 -4
  63. data/app/components/avo/index/field_wrapper_component.rb +1 -13
  64. data/app/components/avo/index/grid_item_component.html.erb +13 -36
  65. data/app/components/avo/index/grid_item_component.rb +43 -16
  66. data/app/components/avo/index/resource_controls_component.html.erb +3 -81
  67. data/app/components/avo/index/resource_controls_component.rb +125 -18
  68. data/app/components/avo/index/resource_grid_component.html.erb +5 -3
  69. data/app/components/avo/index/resource_grid_component.rb +5 -2
  70. data/app/components/avo/index/resource_map_component.html.erb +1 -1
  71. data/app/components/avo/index/resource_map_component.rb +3 -3
  72. data/app/components/avo/index/resource_table_component.html.erb +3 -2
  73. data/app/components/avo/index/resource_table_component.rb +8 -7
  74. data/app/components/avo/index/table_row_component.html.erb +9 -5
  75. data/app/components/avo/index/table_row_component.rb +3 -2
  76. data/app/components/avo/items/panel_component.html.erb +25 -0
  77. data/app/components/avo/items/panel_component.rb +43 -0
  78. data/app/components/avo/items/switcher_component.html.erb +17 -0
  79. data/app/components/avo/items/switcher_component.rb +79 -0
  80. data/app/components/avo/items/visible_items_component.html.erb +10 -0
  81. data/app/components/avo/items/visible_items_component.rb +11 -0
  82. data/app/components/avo/modal_component.html.erb +3 -4
  83. data/app/components/avo/paginator_component.html.erb +1 -1
  84. data/app/components/avo/paginator_component.rb +6 -6
  85. data/app/components/avo/panel_component.html.erb +7 -5
  86. data/app/components/avo/referrer_params_component.html.erb +1 -1
  87. data/app/components/avo/resource_component.rb +205 -26
  88. data/app/components/avo/resource_sidebar_component.html.erb +15 -18
  89. data/app/components/avo/resource_sidebar_component.rb +5 -3
  90. data/app/components/avo/sidebar/link_component.rb +1 -1
  91. data/app/components/avo/sidebar_component.html.erb +10 -3
  92. data/app/components/avo/sidebar_component.rb +5 -3
  93. data/app/components/avo/sidebar_profile_component.html.erb +18 -12
  94. data/app/components/avo/tab_group_component.html.erb +14 -8
  95. data/app/components/avo/tab_group_component.rb +1 -6
  96. data/app/components/avo/tab_switcher_component.html.erb +17 -40
  97. data/app/components/avo/tab_switcher_component.rb +6 -41
  98. data/app/components/avo/views/resource_edit_component.html.erb +23 -86
  99. data/app/components/avo/views/resource_edit_component.rb +20 -19
  100. data/app/components/avo/views/resource_index_component.html.erb +42 -47
  101. data/app/components/avo/views/resource_index_component.rb +76 -13
  102. data/app/components/avo/views/resource_show_component.html.erb +16 -177
  103. data/app/components/avo/views/resource_show_component.rb +16 -10
  104. data/app/controllers/avo/actions_controller.rb +29 -31
  105. data/app/controllers/avo/application_controller.rb +119 -180
  106. data/app/controllers/avo/associations_controller.rb +34 -43
  107. data/app/controllers/avo/attachments_controller.rb +4 -4
  108. data/app/controllers/avo/base_controller.rb +139 -91
  109. data/app/controllers/avo/debug_controller.rb +17 -5
  110. data/app/controllers/avo/home_controller.rb +1 -1
  111. data/app/controllers/avo/search_controller.rb +56 -50
  112. data/app/controllers/concerns/avo/initializes_avo.rb +22 -0
  113. data/app/helpers/avo/application_helper.rb +18 -8
  114. data/app/helpers/avo/resources_helper.rb +1 -1
  115. data/app/helpers/avo/url_helpers.rb +28 -12
  116. data/app/javascript/avo.base.js +1 -0
  117. data/app/javascript/js/controllers/action_controller.js +5 -3
  118. data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
  119. data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +7 -7
  120. data/app/javascript/js/controllers/filter_controller.js +1 -1
  121. data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
  122. data/app/javascript/js/controllers/preview_controller.js +24 -0
  123. data/app/javascript/js/controllers/search_controller.js +4 -2
  124. data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
  125. data/app/javascript/js/controllers/toggle_controller.js +48 -0
  126. data/app/javascript/js/controllers.js +11 -5
  127. data/app/javascript/js/custom-stream-actions.js +15 -0
  128. data/app/views/avo/actions/show.html.erb +10 -6
  129. data/app/views/avo/associations/new.html.erb +2 -2
  130. data/app/views/avo/base/_new_via_belongs_to.html.erb +1 -1
  131. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +3 -3
  132. data/app/views/avo/base/create_fail_action.turbo_stream.erb +2 -2
  133. data/app/views/avo/base/edit.html.erb +1 -1
  134. data/app/views/avo/base/index.html.erb +4 -3
  135. data/app/views/avo/base/new.html.erb +2 -1
  136. data/app/views/avo/base/preview.html.erb +19 -0
  137. data/app/views/avo/base/show.html.erb +2 -2
  138. data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
  139. data/app/views/avo/debug/report.html.erb +32 -17
  140. data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
  141. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  142. data/app/views/avo/partials/_footer.html.erb +1 -1
  143. data/app/views/avo/partials/_javascript.html.erb +5 -0
  144. data/app/views/avo/partials/_logo.html.erb +1 -1
  145. data/app/views/avo/partials/_navbar.html.erb +3 -5
  146. data/app/views/avo/partials/_resource_search.html.erb +1 -0
  147. data/app/views/avo/partials/_table_header.html.erb +5 -11
  148. data/app/views/layouts/avo/application.html.erb +5 -4
  149. data/avo.gemspec +10 -8
  150. data/bin/dev +3 -1
  151. data/bin/prod +0 -0
  152. data/config/master.key +1 -0
  153. data/config/routes.rb +7 -10
  154. data/db/factories.rb +6 -0
  155. data/lib/avo/asset_manager.rb +30 -0
  156. data/lib/avo/base_action.rb +82 -67
  157. data/lib/avo/base_resource.rb +286 -226
  158. data/lib/avo/base_resource_tool.rb +9 -16
  159. data/lib/avo/concerns/borrow_items_holder.rb +35 -0
  160. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  161. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  162. data/lib/avo/concerns/filters_session_handler.rb +7 -5
  163. data/lib/avo/concerns/has_controls.rb +37 -0
  164. data/lib/avo/concerns/has_description.rb +23 -0
  165. data/lib/avo/concerns/has_helpers.rb +18 -0
  166. data/lib/avo/concerns/has_item_type.rb +42 -0
  167. data/lib/avo/concerns/has_items.rb +339 -0
  168. data/lib/avo/concerns/{has_resource_stimulus_controllers.rb → has_stimulus_controllers.rb} +1 -1
  169. data/lib/avo/concerns/hydration.rb +17 -0
  170. data/lib/avo/concerns/is_resource_item.rb +16 -36
  171. data/lib/avo/concerns/is_visible.rb +15 -0
  172. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  173. data/lib/avo/concerns/visible_in_different_views.rb +132 -0
  174. data/lib/avo/concerns/visible_items.rb +7 -38
  175. data/lib/avo/configuration/branding.rb +0 -12
  176. data/lib/avo/configuration.rb +28 -11
  177. data/lib/avo/current.rb +39 -0
  178. data/lib/avo/dsl/field_parser.rb +3 -3
  179. data/lib/avo/dynamic_router.rb +18 -3
  180. data/lib/avo/engine.rb +35 -30
  181. data/lib/avo/error_manager.rb +25 -0
  182. data/lib/avo/execution_context.rb +14 -15
  183. data/lib/avo/fields/base_field.rb +84 -122
  184. data/lib/avo/fields/belongs_to_field.rb +19 -23
  185. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  186. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  187. data/lib/avo/fields/concerns/has_default.rb +1 -5
  188. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  189. data/lib/avo/fields/concerns/has_html_attributes.rb +112 -0
  190. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  191. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  192. data/lib/avo/fields/concerns/is_required.rb +5 -7
  193. data/lib/avo/fields/concerns/is_searchable.rb +15 -0
  194. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  195. data/lib/avo/fields/concerns/use_view_components.rb +45 -0
  196. data/lib/avo/fields/country_field.rb +4 -0
  197. data/lib/avo/fields/date_time_field.rb +1 -5
  198. data/lib/avo/fields/external_image_field.rb +2 -2
  199. data/lib/avo/fields/field_manager.rb +55 -0
  200. data/lib/avo/fields/file_field.rb +2 -2
  201. data/lib/avo/fields/gravatar_field.rb +2 -2
  202. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  203. data/lib/avo/fields/has_base_field.rb +21 -17
  204. data/lib/avo/fields/has_many_field.rb +5 -2
  205. data/lib/avo/fields/has_one_field.rb +8 -12
  206. data/lib/avo/fields/heading_field.rb +9 -14
  207. data/lib/avo/fields/hidden_field.rb +1 -1
  208. data/lib/avo/fields/id_field.rb +3 -3
  209. data/lib/avo/fields/location_field.rb +10 -10
  210. data/lib/avo/fields/password_field.rb +1 -1
  211. data/lib/avo/fields/preview_field.rb +14 -0
  212. data/lib/avo/fields/select_field.rb +12 -8
  213. data/lib/avo/fields/status_field.rb +7 -1
  214. data/lib/avo/fields/text_field.rb +2 -2
  215. data/lib/avo/filters/base_filter.rb +9 -4
  216. data/lib/avo/html/builder.rb +8 -8
  217. data/lib/avo/item_grapher.rb +78 -0
  218. data/lib/avo/licensing/h_q.rb +11 -73
  219. data/lib/avo/licensing/license.rb +5 -1
  220. data/lib/avo/licensing/license_manager.rb +1 -1
  221. data/lib/avo/licensing/pro_license.rb +1 -7
  222. data/lib/avo/loaders/fields_loader.rb +7 -1
  223. data/lib/avo/plugin.rb +36 -0
  224. data/lib/avo/plugin_manager.rb +56 -0
  225. data/lib/avo/prefixed_test_helpers.rb +20 -0
  226. data/lib/avo/reloader.rb +3 -0
  227. data/lib/avo/resources/controls/actions_list.rb +7 -12
  228. data/lib/avo/resources/controls/attach_button.rb +15 -0
  229. data/lib/avo/resources/controls/back_button.rb +1 -1
  230. data/lib/avo/resources/controls/base_control.rb +15 -49
  231. data/lib/avo/resources/controls/create_button.rb +15 -0
  232. data/lib/avo/resources/controls/delete_button.rb +5 -1
  233. data/lib/avo/resources/controls/detach_button.rb +4 -1
  234. data/lib/avo/resources/controls/edit_button.rb +4 -1
  235. data/lib/avo/resources/controls/order_controls.rb +8 -0
  236. data/lib/avo/resources/controls/save_button.rb +13 -0
  237. data/lib/avo/resources/controls/show_button.rb +15 -0
  238. data/lib/avo/resources/items/holder.rb +96 -0
  239. data/lib/avo/resources/items/item_group.rb +44 -0
  240. data/lib/avo/resources/items/main_panel.rb +12 -0
  241. data/lib/avo/resources/items/panel.rb +2 -0
  242. data/lib/avo/resources/items/row.rb +42 -0
  243. data/lib/avo/resources/items/sidebar.rb +46 -0
  244. data/lib/avo/resources/items/tab.rb +54 -0
  245. data/lib/avo/resources/items/tab_group.rb +62 -0
  246. data/lib/avo/resources/resource_manager.rb +179 -0
  247. data/lib/avo/services/authorization_service.rb +11 -110
  248. data/lib/avo/services/debug_service.rb +93 -0
  249. data/lib/avo/services/encryption_service.rb +8 -12
  250. data/lib/avo/services/telemetry_service.rb +85 -0
  251. data/lib/avo/test_helpers.rb +362 -0
  252. data/lib/avo/tools/tool_manager.rb +30 -0
  253. data/lib/avo/version.rb +1 -1
  254. data/lib/avo/view_inquirer.rb +36 -0
  255. data/lib/avo.rb +109 -24
  256. data/lib/generators/avo/action_generator.rb +8 -8
  257. data/lib/generators/avo/card_generator.rb +27 -0
  258. data/lib/generators/avo/concerns/parent_controller.rb +20 -0
  259. data/lib/generators/avo/controller_generator.rb +3 -0
  260. data/lib/generators/avo/eject_generator.rb +180 -15
  261. data/lib/generators/avo/field_generator.rb +49 -2
  262. data/lib/generators/avo/filter_generator.rb +8 -8
  263. data/lib/generators/avo/js/install_generator.rb +2 -2
  264. data/lib/generators/avo/resource_generator.rb +12 -9
  265. data/lib/generators/avo/scope_generator.rb +15 -0
  266. data/lib/generators/avo/tailwindcss/install_generator.rb +70 -26
  267. data/lib/generators/avo/templates/action.tt +8 -6
  268. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  269. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  270. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  271. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  272. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  273. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  274. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  275. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  276. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  277. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  278. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  279. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  280. data/lib/generators/avo/templates/initializer/avo.tt +7 -3
  281. data/lib/generators/avo/templates/locales/avo.ar.yml +1 -0
  282. data/lib/generators/avo/templates/locales/avo.en.yml +4 -3
  283. data/lib/generators/avo/templates/locales/avo.es.yml +1 -0
  284. data/lib/generators/avo/templates/locales/avo.fr.yml +1 -0
  285. data/lib/generators/avo/templates/locales/avo.nb.yml +1 -0
  286. data/lib/generators/avo/templates/locales/avo.nn.yml +1 -0
  287. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -0
  288. data/lib/generators/avo/templates/locales/avo.pt.yml +1 -0
  289. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -5
  290. data/lib/generators/avo/templates/locales/avo.tr.yml +1 -0
  291. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  292. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  293. data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
  294. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  295. data/lib/generators/avo/templates/scope.tt +6 -0
  296. data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
  297. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
  298. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
  299. data/lib/tasks/avo_tasks.rake +72 -4
  300. data/public/avo-assets/avo.base.css +1893 -1187
  301. data/public/avo-assets/avo.base.js +217 -305
  302. data/public/avo-assets/avo.base.js.map +3 -3
  303. data/public/avo-assets/avo.css +9744 -0
  304. data/public/avo-assets/avo.js +513 -0
  305. data/public/avo-assets/avo.js.map +7 -0
  306. data/tailwind.custom.js +47 -0
  307. data/tailwind.preset.js +152 -0
  308. metadata +106 -116
  309. data/app/components/avo/card_component.html.erb +0 -46
  310. data/app/components/avo/card_component.rb +0 -25
  311. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  312. data/app/components/avo/dashboards/divider_component.rb +0 -19
  313. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  314. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  315. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  316. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  317. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  318. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  319. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  320. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  321. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  322. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  323. data/app/components/avo/index/ordering/base_component.rb +0 -9
  324. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  325. data/app/components/avo/index/ordering/button_component.rb +0 -23
  326. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  327. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  328. data/app/components/avo/item_switcher_component.html.erb +0 -27
  329. data/app/components/avo/item_switcher_component.rb +0 -48
  330. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  331. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  332. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  333. data/app/controllers/avo/dashboards_controller.rb +0 -22
  334. data/app/controllers/avo/reorder_controller.rb +0 -25
  335. data/app/javascript/js/controllers/base_controller.js +0 -22
  336. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  337. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  338. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  339. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  340. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  341. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  342. data/app/views/avo/dashboards/show.html.erb +0 -38
  343. data/app/views/avo/partials/_global_search.html.erb +0 -19
  344. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  345. data/lib/avo/app.rb +0 -237
  346. data/lib/avo/base_card.rb +0 -161
  347. data/lib/avo/concerns/fetches_things.rb +0 -150
  348. data/lib/avo/concerns/handles_field_args.rb +0 -47
  349. data/lib/avo/concerns/has_action_stimulus_controllers.rb +0 -15
  350. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  351. data/lib/avo/concerns/has_fields.rb +0 -334
  352. data/lib/avo/concerns/has_html_attributes.rb +0 -123
  353. data/lib/avo/concerns/policy_helpers.rb +0 -31
  354. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  355. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  356. data/lib/avo/dashboards/base_divider.rb +0 -35
  357. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  358. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  359. data/lib/avo/dashboards/metric_card.rb +0 -9
  360. data/lib/avo/dashboards/partial_card.rb +0 -7
  361. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  362. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  363. data/lib/avo/fields/tags_field.rb +0 -102
  364. data/lib/avo/grid_collector.rb +0 -42
  365. data/lib/avo/hosts/association_scope_host.rb +0 -8
  366. data/lib/avo/hosts/base_host.rb +0 -25
  367. data/lib/avo/hosts/card_visibility.rb +0 -20
  368. data/lib/avo/hosts/dashboard_card.rb +0 -22
  369. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  370. data/lib/avo/hosts/ordering.rb +0 -22
  371. data/lib/avo/hosts/record_host.rb +0 -7
  372. data/lib/avo/hosts/resource_record_host.rb +0 -7
  373. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  374. data/lib/avo/hosts/search_scope_host.rb +0 -7
  375. data/lib/avo/hosts/view_record_host.rb +0 -7
  376. data/lib/avo/hosts/visibility_host.rb +0 -12
  377. data/lib/avo/items_holder.rb +0 -96
  378. data/lib/avo/main_panel.rb +0 -3
  379. data/lib/avo/menu/base_item.rb +0 -25
  380. data/lib/avo/menu/builder.rb +0 -82
  381. data/lib/avo/menu/dashboard.rb +0 -22
  382. data/lib/avo/menu/group.rb +0 -2
  383. data/lib/avo/menu/link.rb +0 -6
  384. data/lib/avo/menu/menu.rb +0 -2
  385. data/lib/avo/menu/resource.rb +0 -22
  386. data/lib/avo/menu/section.rb +0 -2
  387. data/lib/avo/panel.rb +0 -24
  388. data/lib/avo/panel_builder.rb +0 -25
  389. data/lib/avo/resources/controls/action.rb +0 -38
  390. data/lib/avo/resources/controls/execution_context.rb +0 -58
  391. data/lib/avo/resources/controls/items_holder.rb +0 -19
  392. data/lib/avo/resources/controls/link_to.rb +0 -27
  393. data/lib/avo/row.rb +0 -26
  394. data/lib/avo/row_builder.rb +0 -24
  395. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  396. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  397. data/lib/avo/sidebar.rb +0 -30
  398. data/lib/avo/sidebar_builder.rb +0 -24
  399. data/lib/avo/tab.rb +0 -72
  400. data/lib/avo/tab_builder.rb +0 -25
  401. data/lib/avo/tab_group.rb +0 -42
  402. data/lib/avo/tab_group_builder.rb +0 -43
  403. data/lib/avo/tools_manager.rb +0 -11
  404. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  405. data/lib/generators/avo/card/metric_generator.rb +0 -18
  406. data/lib/generators/avo/card/partial_generator.rb +0 -19
  407. data/lib/generators/avo/templates/js/avo.custom.js +0 -2
  408. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  409. /data/app/assets/stylesheets/css/{tags.css → fields/tags.css} +0 -0
@@ -0,0 +1,15 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class ShowButton < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+
8
+ if args[:item].present?
9
+ @title = I18n.t("avo.view_item", item: args[:item]).humanize if title.nil?
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,96 @@
1
+ class Avo::Resources::Items::Holder
2
+ attr_reader :tools, :from
3
+ attr_accessor :items
4
+ attr_accessor :invalid_fields
5
+
6
+ def initialize(from: nil, parent: nil)
7
+ @items = []
8
+ @items_index = 0
9
+ @invalid_fields = []
10
+ @from = from
11
+ @parent = parent
12
+ end
13
+
14
+ # Adds a field to the items_holder
15
+ def field(field_name, **args, &block)
16
+ # If the field is paresed inside a tab group, add it to the tab
17
+ # This will happen when the field is parsed inside a tab group from a resource method
18
+ if from.present? && from.class == Avo::Resources::Items::TabGroup::Builder
19
+ return from.field(field_name, holder: self, **args, &block)
20
+ end
21
+
22
+ field_parser = Avo::Dsl::FieldParser.new(id: field_name, order_index: @items_index, **args, &block).parse
23
+
24
+ if field_parser.invalid?
25
+ as = args.fetch(:as, nil)
26
+
27
+ # End execution ehre and add the field to the invalid_fileds payload so we know to wanr the developer about that.
28
+ # @todo: Make sure this warning is still active
29
+ return add_invalid_field({
30
+ name: field_name,
31
+ as: as,
32
+ # resource: resource_class.name,
33
+ message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: :#{as}</code>"
34
+ })
35
+ end
36
+
37
+ add_item field_parser.instance
38
+ end
39
+
40
+ def tabs(tab = nil, **kwargs, &block)
41
+ if tab.present?
42
+ add_item tab
43
+ else
44
+ add_item Avo::Resources::Items::TabGroup::Builder.parse_block(parent: @parent, **kwargs, &block)
45
+ end
46
+ end
47
+
48
+ def tab(name, **args, &block)
49
+ add_item Avo::Resources::Items::Tab::Builder.parse_block(name: name, parent: @parent, **args, &block)
50
+ end
51
+
52
+ def row(**args, &block)
53
+ add_item Avo::Resources::Items::Row::Builder.parse_block(parent: @parent, **args, &block)
54
+ end
55
+
56
+ def tool(klass, **args)
57
+ add_item klass.new(**args)
58
+ end
59
+
60
+ def panel(panel_name = nil, **args, &block)
61
+ add_item Avo::Resources::Items::ItemGroup::Builder.parse_block(name: panel_name, parent: @parent, **args, &block)
62
+ end
63
+
64
+ # The main panel is the one that also render the header of the resource with the breadcrumbs, the title and the controls.
65
+ def main_panel(**args, &block)
66
+ add_item Avo::Resources::Items::MainPanel::Builder.parse_block(name: "main_panel", parent: @parent, **args, &block)
67
+ end
68
+
69
+ def sidebar(**args, &block)
70
+ check_sidebar_is_inside_a_panel
71
+
72
+ add_item Avo::Resources::Items::Sidebar::Builder.parse_block(parent: @parent, **args, &block)
73
+ end
74
+
75
+ def add_item(instance)
76
+ @items << instance
77
+
78
+ increment_order_index
79
+ end
80
+
81
+ private
82
+
83
+ def add_invalid_field(payload)
84
+ invalid_fields << payload
85
+ end
86
+
87
+ def increment_order_index
88
+ @items_index += 1
89
+ end
90
+
91
+ def check_sidebar_is_inside_a_panel
92
+ unless @from.eql?(Avo::Resources::Items::Panel::Builder) || @from.eql?(Avo::Resources::Items::MainPanel::Builder)
93
+ raise "The sidebar must be inside a panel."
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,44 @@
1
+ class Avo::Resources::Items::ItemGroup
2
+ prepend Avo::Concerns::IsResourceItem
3
+
4
+ include Avo::Concerns::HasItems
5
+ include Avo::Concerns::HasItemType
6
+ include Avo::Concerns::VisibleItems
7
+ include Avo::Concerns::VisibleInDifferentViews
8
+
9
+ attr_reader :name
10
+ attr_reader :description
11
+
12
+ delegate :items, :add_item, to: :items_holder
13
+
14
+ def initialize(name: nil, description: nil, view: nil, **args)
15
+ @name = name
16
+ @view = Avo::ViewInquirer.new view
17
+ @description = description
18
+ @items_holder = Avo::Resources::Items::Holder.new
19
+ @args = args
20
+
21
+ post_initialize if respond_to?(:post_initialize)
22
+ end
23
+
24
+ class Builder
25
+ include Avo::Concerns::BorrowItemsHolder
26
+
27
+ delegate :heading, to: :items_holder
28
+ delegate :field, to: :items_holder
29
+ delegate :row, to: :items_holder
30
+ delegate :items, to: :items_holder
31
+ delegate :sidebar, to: :items_holder
32
+
33
+ def initialize(parent:, name: nil, **args)
34
+ @panel = Avo::Resources::Items::Panel.new(name: name, **args)
35
+ @items_holder = Avo::Resources::Items::Holder.new(from: self.class, parent: parent)
36
+ end
37
+
38
+ # Fetch the tab
39
+ def build
40
+ @panel.items_holder = @items_holder
41
+ @panel
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ class Avo::Resources::Items::MainPanel < Avo::Resources::Items::Panel
2
+ class Builder < Avo::Resources::Items::ItemGroup::Builder
3
+ def initialize(parent: ,**args)
4
+ @panel = Avo::Resources::Items::MainPanel.new(**args)
5
+ @items_holder = Avo::Resources::Items::Holder.new(from: self.class, parent: parent)
6
+ end
7
+ end
8
+
9
+ def visible?
10
+ true
11
+ end
12
+ end
@@ -0,0 +1,2 @@
1
+ class Avo::Resources::Items::Panel < Avo::Resources::Items::ItemGroup
2
+ end
@@ -0,0 +1,42 @@
1
+ class Avo::Resources::Items::Row
2
+ include Avo::Concerns::IsResourceItem
3
+ include Avo::Concerns::HasItems
4
+ include Avo::Concerns::HasItemType
5
+ include Avo::Concerns::VisibleItems
6
+ include Avo::Concerns::Hydration
7
+
8
+ class_attribute :item_type, default: :row
9
+
10
+ attr_reader :view
11
+ attr_accessor :items_holder
12
+
13
+ delegate :items, :add_item, to: :items_holder
14
+
15
+ def initialize(view: nil)
16
+ @view = Avo::ViewInquirer.new view
17
+ @items_holder = Avo::Resources::Items::Holder.new
18
+ end
19
+
20
+ def has_items?
21
+ @items.present?
22
+ end
23
+
24
+ class Builder
25
+ include Avo::Concerns::BorrowItemsHolder
26
+
27
+ delegate :field, to: :items_holder
28
+ delegate :tool, to: :items_holder
29
+ delegate :items, to: :items_holder
30
+
31
+ def initialize(parent:, **args)
32
+ @row = Avo::Resources::Items::Row.new(**args)
33
+ @items_holder = Avo::Resources::Items::Holder.new(parent: @parent)
34
+ end
35
+
36
+ # Fetch the tab
37
+ def build
38
+ @row.items_holder = @items_holder
39
+ @row
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ class Avo::Resources::Items::Sidebar
2
+ prepend Avo::Concerns::IsResourceItem
3
+
4
+ include Avo::Concerns::HasItems
5
+ include Avo::Concerns::HasItemType
6
+ include Avo::Concerns::IsVisible
7
+ include Avo::Concerns::VisibleInDifferentViews
8
+
9
+ delegate :items, :add_item, to: :items_holder
10
+
11
+ attr_reader :name
12
+
13
+ def initialize(name: nil, view: nil, **args)
14
+ @name = name
15
+ @items_holder = Avo::Resources::Items::Holder.new
16
+ @view = Avo::ViewInquirer.new view
17
+ @panel_wrapper = args[:panel_wrapper].nil? ? true : args[:panel_wrapper]
18
+ @args = args
19
+
20
+ post_initialize if respond_to?(:post_initialize)
21
+ end
22
+
23
+ def panel_wrapper?
24
+ @panel_wrapper
25
+ end
26
+
27
+ class Builder
28
+ include Avo::Concerns::BorrowItemsHolder
29
+
30
+ delegate :field, to: :items_holder
31
+ delegate :tool, to: :items_holder
32
+ delegate :items, to: :items_holder
33
+ delegate :heading, to: :items_holder
34
+
35
+ def initialize(parent: , name: nil, **args)
36
+ @sidebar = Avo::Resources::Items::Sidebar.new(**args)
37
+ @items_holder = Avo::Resources::Items::Holder.new(parent: parent)
38
+ end
39
+
40
+ # Fetch the sidebar
41
+ def build
42
+ @sidebar.items_holder = @items_holder
43
+ @sidebar
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ class Avo::Resources::Items::Tab
2
+ prepend Avo::Concerns::IsResourceItem
3
+
4
+ include Avo::Concerns::HasItems
5
+ include Avo::Concerns::HasItemType
6
+ include Avo::Concerns::VisibleItems
7
+ include Avo::Concerns::VisibleInDifferentViews
8
+
9
+ delegate :items, :add_item, to: :items_holder
10
+
11
+ attr_accessor :description
12
+
13
+ def initialize(name: nil, description: nil, view: nil, **args)
14
+ @name = name
15
+ @description = description
16
+ @items_holder = Avo::Resources::Items::Holder.new
17
+ @view = Avo::ViewInquirer.new view
18
+ @args = args
19
+
20
+ post_initialize if respond_to?(:post_initialize)
21
+ end
22
+
23
+ def name
24
+ Avo::ExecutionContext.new(target: @name).handle
25
+ end
26
+
27
+ def turbo_frame_id(parent: nil)
28
+ id = "#{Avo::Resources::Items::Tab.to_s.parameterize} #{name}".parameterize
29
+
30
+ return id if parent.nil?
31
+
32
+ "#{parent.turbo_frame_id} #{id}".parameterize
33
+ end
34
+
35
+ class Builder
36
+ include Avo::Concerns::BorrowItemsHolder
37
+
38
+ delegate :field, to: :items_holder
39
+ delegate :tool, to: :items_holder
40
+ delegate :panel, to: :items_holder
41
+ delegate :items, to: :items_holder
42
+
43
+ def initialize(parent:, name: nil, **args)
44
+ @tab = Avo::Resources::Items::Tab.new(name: name, **args)
45
+ @items_holder = Avo::Resources::Items::Holder.new(parent: parent)
46
+ end
47
+
48
+ # Fetch the tab
49
+ def build
50
+ @tab.items_holder = @items_holder
51
+ @tab
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,62 @@
1
+ class Avo::Resources::Items::TabGroup
2
+ prepend Avo::Concerns::IsResourceItem
3
+
4
+ include Avo::Concerns::HasItems
5
+ include Avo::Concerns::HasItemType
6
+ include Avo::Concerns::IsVisible
7
+ include Avo::Concerns::VisibleInDifferentViews
8
+
9
+ attr_accessor :index
10
+ attr_accessor :style
11
+
12
+ def initialize(index: 0, view: nil, style: nil, **args)
13
+ @index = index
14
+ @items_holder = Avo::Resources::Items::Holder.new
15
+ @view = Avo::ViewInquirer.new view
16
+ @style = style
17
+ @args = args
18
+
19
+ post_initialize if respond_to?(:post_initialize)
20
+ end
21
+
22
+ def turbo_frame_id
23
+ "#{Avo::Resources::Items::TabGroup.to_s.parameterize} #{index}".parameterize
24
+ end
25
+
26
+ class Builder
27
+ include Avo::Concerns::BorrowItemsHolder
28
+
29
+ delegate :tab, to: :items_holder
30
+
31
+ def field(field_name, **args, &block)
32
+ parsed = Avo::Dsl::FieldParser.new(id: field_name, order_index: @items_index, **args, &block).parse
33
+ field_instance = parsed.instance
34
+
35
+ name = field_instance.name
36
+ tab = Avo::Resources::Items::Tab.new name: name
37
+
38
+ if field_instance.has_own_panel?
39
+ tab.items_holder.add_item parsed.instance
40
+ else
41
+ # If the field is not in a panel, create one and add it
42
+ panel = Avo::Resources::Items::Panel.new name: name
43
+ panel.items_holder.add_item parsed.instance
44
+ # Add that panel to the items_holder
45
+ tab.items_holder.add_item panel
46
+ end
47
+
48
+ @items_holder.tabs tab
49
+ end
50
+
51
+ def initialize(parent: ,style: nil)
52
+ @group = Avo::Resources::Items::TabGroup.new(style: style)
53
+ @items_holder = Avo::Resources::Items::Holder.new(parent: parent, from: self)
54
+ end
55
+
56
+ # Fetch the tab
57
+ def build
58
+ @group.items_holder = @items_holder
59
+ @group
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,179 @@
1
+ module Avo
2
+ module Resources
3
+ class ResourceManager
4
+ attr_accessor :resources
5
+
6
+ alias_method :all, :resources
7
+
8
+ class << self
9
+ def build
10
+ instance = new
11
+ instance.init_resources
12
+ instance.check_bad_resources
13
+ instance
14
+ end
15
+
16
+ # Fetches the resources available to the application.
17
+ # We have two ways of doing that.
18
+ #
19
+ # 1. Through eager loading.
20
+ # We automatically eager load the resources directory and fetch the descendants from the scanned files.
21
+ # This is the simple way to get started.
22
+ #
23
+ # 2. Manually, declared by the user.
24
+ # We have this option to load the resources because when they are loaded automatically through eager loading,
25
+ # those Resource classes and their methods may trigger loading other classes. And that may disrupt Rails booting process.
26
+ # Ex: AdminResource may use self.model_class = User. That will trigger Ruby to load the User class and itself load
27
+ # other classes in a chain reaction.
28
+ # The scenario that comes up most often is when Rails boots, the routes are being computed which eager loads the resource files.
29
+ # At that boot time some migration might have not been run yet, but Rails tries to access them through model associations,
30
+ # and they are not available.
31
+ #
32
+ # To enable this feature add a `resources` array config in your Avo initializer.
33
+ # config.resources = [
34
+ # "UserResource",
35
+ # "FishResource",
36
+ # ]
37
+ def fetch_resources
38
+ resources = if Avo.configuration.resources.nil?
39
+ BaseResource.descendants
40
+ else
41
+ Avo.configuration.resources
42
+ end
43
+
44
+ resources.map do |resource|
45
+ if resource.is_a?(Class)
46
+ resource
47
+ else
48
+ resource.to_s.safe_constantize
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def initialize
55
+ @resources = []
56
+ end
57
+
58
+ def init_resources
59
+ self.resources = self.class.fetch_resources
60
+ .reject do |resource|
61
+ # Remove the BaseResource. We only need the descendants
62
+ resource == Avo::BaseResource
63
+ end
64
+ .uniq do |klass|
65
+ # On invalid resource configuration the resource classes get duplicated in `ObjectSpace`
66
+ # We need to de-duplicate them
67
+ klass.name
68
+ end
69
+ end
70
+
71
+ def check_bad_resources
72
+ resources.each do |resource|
73
+ has_model = resource.model_class.present?
74
+
75
+ unless has_model
76
+ possible_model = resource.to_s.gsub "Avo::Resources::", ""
77
+ possible_model = possible_model.gsub "Resource", ""
78
+
79
+ Avo.error_manager.add({
80
+ url: "https://docs.avohq.io/2.0/resources.html#custom-model-class",
81
+ target: "_blank",
82
+ message: "#{resource} does not have a valid model assigned. It failed to find the #{possible_model} model. \n\r Please create that model or assign one using self.model_class = YOUR_MODEL"
83
+ })
84
+ end
85
+ end
86
+ end
87
+
88
+ # Filters out the resources that are missing the model_class
89
+ def valid_resources
90
+ resources.select { |resource| resource.model_class.present? }.sort_by(&:name)
91
+ end
92
+
93
+ # Returns the Avo resource by camelized name
94
+ #
95
+ # get_resource_by_name('User') => instance of Avo::Resources::User
96
+ def get_resource(resource)
97
+ resource = "Avo::Resources::#{resource}" unless resource.to_s.starts_with?("Avo::Resources::")
98
+
99
+ resources.find do |available_resource|
100
+ resource.to_s == available_resource.to_s
101
+ end
102
+ end
103
+
104
+ # Returns the Avo resource by singular snake_cased name
105
+ #
106
+ # get_resource_by_name('user') => instance of Avo::Resources::User
107
+ def get_resource_by_name(name)
108
+ get_resource name.singularize.camelize
109
+ end
110
+
111
+ # Returns the Avo resource by singular snake_cased name
112
+ # From all the resources that use the same model_class, it will fetch the first one in alphabetical order
113
+ #
114
+ # get_resource_by_name('User') => instance of Avo::Resources::User
115
+ # get_resource_by_name(User) => instance of Avo::Resources::User
116
+
117
+ def get_resource_by_model_class(klass)
118
+ # Fetch the mappings imposed by the user.
119
+ # If they are present, use those ones.
120
+ mapping = get_mapping_for_model klass
121
+ return get_resource(mapping) if mapping.present?
122
+
123
+ valid_resources
124
+ .find do |resource|
125
+ resource.model_class.model_name.name == klass.to_s
126
+ end
127
+ end
128
+
129
+ # Returns the Avo resource by singular snake_cased name
130
+ #
131
+ # get_resource_by_controller_name('delayed_backend_active_record_jobs') => instance of Avo::Resources::DelayedJob
132
+ # get_resource_by_controller_name('users') => instance of Avo::Resources::User
133
+ def get_resource_by_controller_name(name)
134
+ valid_resources
135
+ .find do |resource|
136
+ resource.model_class.to_s.pluralize.underscore.tr("/", "_") == name.to_s
137
+ end
138
+ end
139
+
140
+ # Returns the Avo resource by some name
141
+ def guess_resource(name)
142
+ get_resource_by_name(name.to_s) || get_resource_by_model_class(name)
143
+ end
144
+
145
+ # Returns the Rails model class by singular snake_cased name
146
+ #
147
+ # get_model_class_by_name('user') => User
148
+ def get_model_class_by_name(name)
149
+ name.to_s.camelize.singularize
150
+ end
151
+
152
+ def get_available_resources(user = nil)
153
+ valid_resources
154
+ .select do |resource|
155
+ resource.authorization.class.authorize(
156
+ user,
157
+ resource.model_class,
158
+ Avo.configuration.authorization_methods.stringify_keys["index"],
159
+ raise_exception: false
160
+ )
161
+ end
162
+ .sort_by { |r| r.name }
163
+ end
164
+
165
+ def resources_for_navigation(user = nil)
166
+ get_available_resources(user)
167
+ .select do |resource|
168
+ resource.visible_on_sidebar
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def get_mapping_for_model(klass)
175
+ (Avo.configuration.model_resource_mapping || {}).stringify_keys.transform_values(&:to_s)[klass.to_s]
176
+ end
177
+ end
178
+ end
179
+ end