avo 2.48.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 (376) 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 +15 -26
  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/hidden_field/edit_component.html.erb +1 -2
  40. data/app/components/avo/fields/index_component.rb +5 -5
  41. data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
  42. data/app/components/avo/fields/preview_field/index_component.rb +4 -0
  43. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  44. data/app/components/avo/fields/show_component.rb +4 -1
  45. data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
  46. data/app/components/avo/filters_component.html.erb +9 -3
  47. data/app/components/avo/filters_component.rb +4 -4
  48. data/app/components/avo/index/field_wrapper_component.rb +0 -12
  49. data/app/components/avo/index/grid_item_component.html.erb +13 -36
  50. data/app/components/avo/index/grid_item_component.rb +43 -16
  51. data/app/components/avo/index/resource_controls_component.html.erb +3 -81
  52. data/app/components/avo/index/resource_controls_component.rb +124 -17
  53. data/app/components/avo/index/resource_grid_component.html.erb +5 -3
  54. data/app/components/avo/index/resource_grid_component.rb +5 -2
  55. data/app/components/avo/index/resource_map_component.html.erb +1 -1
  56. data/app/components/avo/index/resource_map_component.rb +3 -3
  57. data/app/components/avo/index/resource_table_component.html.erb +5 -4
  58. data/app/components/avo/index/resource_table_component.rb +14 -20
  59. data/app/components/avo/index/table_row_component.html.erb +8 -4
  60. data/app/components/avo/index/table_row_component.rb +3 -2
  61. data/app/components/avo/item_switcher_component.rb +2 -2
  62. data/app/components/avo/modal_component.html.erb +7 -12
  63. data/app/components/avo/modal_component.rb +0 -21
  64. data/app/components/avo/paginator_component.html.erb +40 -29
  65. data/app/components/avo/paginator_component.rb +5 -23
  66. data/app/components/avo/panel_component.html.erb +8 -6
  67. data/app/components/avo/referrer_params_component.html.erb +1 -2
  68. data/app/components/avo/resource_component.rb +189 -14
  69. data/app/components/avo/resource_sidebar_component.html.erb +6 -2
  70. data/app/components/avo/resource_sidebar_component.rb +1 -1
  71. data/app/components/avo/sidebar/link_component.rb +1 -1
  72. data/app/components/avo/sidebar_component.html.erb +10 -3
  73. data/app/components/avo/sidebar_component.rb +5 -3
  74. data/app/components/avo/sidebar_profile_component.html.erb +15 -8
  75. data/app/components/avo/tab_group_component.html.erb +13 -7
  76. data/app/components/avo/tab_group_component.rb +1 -6
  77. data/app/components/avo/tab_switcher_component.html.erb +17 -40
  78. data/app/components/avo/tab_switcher_component.rb +4 -39
  79. data/app/components/avo/views/resource_edit_component.html.erb +12 -48
  80. data/app/components/avo/views/resource_edit_component.rb +7 -18
  81. data/app/components/avo/views/resource_index_component.html.erb +41 -47
  82. data/app/components/avo/views/resource_index_component.rb +62 -12
  83. data/app/components/avo/views/resource_show_component.html.erb +6 -149
  84. data/app/components/avo/views/resource_show_component.rb +6 -11
  85. data/app/controllers/avo/actions_controller.rb +27 -24
  86. data/app/controllers/avo/application_controller.rb +105 -151
  87. data/app/controllers/avo/associations_controller.rb +34 -43
  88. data/app/controllers/avo/attachments_controller.rb +4 -4
  89. data/app/controllers/avo/base_controller.rb +102 -102
  90. data/app/controllers/avo/debug_controller.rb +17 -5
  91. data/app/controllers/avo/home_controller.rb +1 -1
  92. data/app/controllers/avo/search_controller.rb +30 -51
  93. data/app/controllers/avo/team_users_controller.rb +4 -0
  94. data/app/controllers/concerns/avo/initializes_avo.rb +21 -0
  95. data/app/helpers/avo/application_helper.rb +15 -9
  96. data/app/helpers/avo/resources_helper.rb +1 -1
  97. data/app/helpers/avo/url_helpers.rb +27 -11
  98. data/app/javascript/avo.base.js +1 -0
  99. data/app/javascript/js/application.js +0 -3
  100. data/app/javascript/js/controllers/action_controller.js +5 -3
  101. data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
  102. data/app/javascript/js/controllers/fields/key_value_controller.js +1 -2
  103. data/app/javascript/js/controllers/filter_controller.js +1 -1
  104. data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
  105. data/app/javascript/js/controllers/preview_controller.js +24 -0
  106. data/app/javascript/js/controllers/search_controller.js +2 -2
  107. data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
  108. data/app/javascript/js/controllers/toggle_controller.js +48 -0
  109. data/app/javascript/js/controllers.js +10 -6
  110. data/app/javascript/js/custom-stream-actions.js +15 -0
  111. data/app/views/avo/actions/keep_modal_open.turbo_stream.erb +5 -0
  112. data/app/views/avo/actions/show.html.erb +10 -7
  113. data/app/views/avo/associations/new.html.erb +2 -2
  114. data/app/views/avo/base/index.html.erb +3 -2
  115. data/app/views/avo/base/new.html.erb +2 -1
  116. data/app/views/avo/base/preview.html.erb +19 -0
  117. data/app/views/avo/base/show.html.erb +1 -1
  118. data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
  119. data/app/views/avo/debug/report.html.erb +32 -17
  120. data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
  121. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  122. data/app/views/avo/partials/_footer.html.erb +1 -1
  123. data/app/views/avo/partials/_javascript.html.erb +5 -0
  124. data/app/views/avo/partials/_logo.html.erb +1 -1
  125. data/app/views/avo/partials/_navbar.html.erb +3 -5
  126. data/app/views/avo/partials/_table_header.html.erb +5 -11
  127. data/app/views/layouts/avo/application.html.erb +4 -2
  128. data/avo.gemspec +7 -7
  129. data/bin/dev +1 -1
  130. data/bin/prod +0 -0
  131. data/config/i18n-tasks.yml +1 -1
  132. data/config/initializers/pagy.rb +0 -2
  133. data/config/master.key +1 -0
  134. data/config/routes.rb +6 -10
  135. data/db/factories.rb +7 -1
  136. data/lib/avo/action_model.rb +20 -0
  137. data/lib/avo/asset_manager.rb +30 -0
  138. data/lib/avo/base_action.rb +57 -42
  139. data/lib/avo/base_resource.rb +264 -227
  140. data/lib/avo/base_resource_tool.rb +9 -16
  141. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  142. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  143. data/lib/avo/concerns/filters_session_handler.rb +5 -3
  144. data/lib/avo/concerns/has_controls.rb +37 -0
  145. data/lib/avo/concerns/has_description.rb +23 -0
  146. data/lib/avo/concerns/has_item_type.rb +42 -0
  147. data/lib/avo/concerns/has_items.rb +325 -0
  148. data/lib/avo/concerns/{has_resource_stimulus_controllers.rb → has_stimulus_controllers.rb} +1 -1
  149. data/lib/avo/concerns/is_resource_item.rb +24 -36
  150. data/lib/avo/concerns/is_visible.rb +15 -0
  151. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  152. data/lib/avo/concerns/visible_in_different_views.rb +126 -0
  153. data/lib/avo/configuration/branding.rb +0 -12
  154. data/lib/avo/configuration.rb +1 -37
  155. data/lib/avo/current.rb +39 -0
  156. data/lib/avo/dsl/field_parser.rb +1 -1
  157. data/lib/avo/dynamic_router.rb +18 -3
  158. data/lib/avo/engine.rb +35 -30
  159. data/lib/avo/error_manager.rb +25 -0
  160. data/lib/avo/execution_context.rb +10 -14
  161. data/lib/avo/fields/badge_field.rb +1 -1
  162. data/lib/avo/fields/base_field.rb +91 -106
  163. data/lib/avo/fields/belongs_to_field.rb +18 -22
  164. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  165. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  166. data/lib/avo/fields/concerns/has_default.rb +1 -5
  167. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  168. data/lib/avo/fields/concerns/has_html_attributes.rb +110 -0
  169. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  170. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  171. data/lib/avo/fields/concerns/is_required.rb +5 -7
  172. data/lib/avo/fields/concerns/is_searchable.rb +13 -0
  173. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  174. data/lib/avo/fields/country_field.rb +4 -0
  175. data/lib/avo/fields/date_time_field.rb +1 -5
  176. data/lib/avo/fields/field_manager.rb +55 -0
  177. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  178. data/lib/avo/fields/has_base_field.rb +12 -15
  179. data/lib/avo/fields/has_many_field.rb +5 -2
  180. data/lib/avo/fields/has_one_field.rb +6 -10
  181. data/lib/avo/fields/heading_field.rb +4 -1
  182. data/lib/avo/fields/hidden_field.rb +1 -1
  183. data/lib/avo/fields/id_field.rb +1 -1
  184. data/lib/avo/fields/location_field.rb +8 -8
  185. data/lib/avo/fields/password_field.rb +1 -1
  186. data/lib/avo/fields/preview_field.rb +14 -0
  187. data/lib/avo/fields/select_field.rb +12 -8
  188. data/lib/avo/fields/status_field.rb +4 -0
  189. data/lib/avo/filters/base_filter.rb +8 -4
  190. data/lib/avo/html/builder.rb +7 -8
  191. data/lib/avo/item_grapher.rb +78 -0
  192. data/lib/avo/licensing/h_q.rb +8 -67
  193. data/lib/avo/licensing/license.rb +1 -1
  194. data/lib/avo/licensing/pro_license.rb +1 -7
  195. data/lib/avo/loaders/fields_loader.rb +7 -1
  196. data/lib/avo/plugin.rb +16 -0
  197. data/lib/avo/plugin_manager.rb +56 -0
  198. data/lib/avo/prefixed_test_helpers.rb +20 -0
  199. data/lib/avo/reloader.rb +3 -0
  200. data/lib/avo/resources/controls/actions_list.rb +7 -12
  201. data/lib/avo/resources/controls/attach_button.rb +15 -0
  202. data/lib/avo/resources/controls/back_button.rb +1 -1
  203. data/lib/avo/resources/controls/base_control.rb +15 -49
  204. data/lib/avo/resources/controls/create_button.rb +15 -0
  205. data/lib/avo/resources/controls/delete_button.rb +5 -1
  206. data/lib/avo/resources/controls/detach_button.rb +4 -1
  207. data/lib/avo/resources/controls/edit_button.rb +4 -1
  208. data/lib/avo/resources/controls/order_controls.rb +8 -0
  209. data/lib/avo/resources/controls/save_button.rb +13 -0
  210. data/lib/avo/resources/controls/show_button.rb +15 -0
  211. data/lib/avo/resources/items/holder.rb +84 -0
  212. data/lib/avo/resources/items/item_group.rb +49 -0
  213. data/lib/avo/resources/items/main_panel.rb +2 -0
  214. data/lib/avo/resources/items/panel.rb +2 -0
  215. data/lib/avo/resources/items/row.rb +54 -0
  216. data/lib/avo/resources/items/sidebar.rb +47 -0
  217. data/lib/avo/resources/items/tab.rb +60 -0
  218. data/lib/avo/resources/items/tab_group.rb +68 -0
  219. data/lib/avo/resources/resource_manager.rb +174 -0
  220. data/lib/avo/services/authorization_service.rb +11 -110
  221. data/lib/avo/services/debug_service.rb +93 -0
  222. data/lib/avo/services/encryption_service.rb +5 -1
  223. data/lib/avo/services/telemetry_service.rb +85 -0
  224. data/lib/avo/test_helpers.rb +362 -0
  225. data/lib/avo/tools/tool_manager.rb +30 -0
  226. data/lib/avo/version.rb +1 -1
  227. data/lib/avo.rb +115 -24
  228. data/lib/generators/avo/action_generator.rb +8 -8
  229. data/lib/generators/avo/card_generator.rb +27 -0
  230. data/lib/generators/avo/filter_generator.rb +8 -8
  231. data/lib/generators/avo/resource_generator.rb +4 -4
  232. data/lib/generators/avo/scope_generator.rb +15 -0
  233. data/lib/generators/avo/tailwindcss/install_generator.rb +1 -15
  234. data/lib/generators/avo/templates/action.tt +8 -6
  235. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  236. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  237. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  238. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  239. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  240. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  241. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  242. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  243. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  244. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  245. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  246. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  247. data/lib/generators/avo/templates/initializer/avo.tt +1 -9
  248. data/lib/generators/avo/templates/locales/avo.ar.yml +6 -6
  249. data/lib/generators/avo/templates/locales/avo.en.yml +4 -5
  250. data/lib/generators/avo/templates/locales/avo.fr.yml +1 -2
  251. data/lib/generators/avo/templates/locales/avo.nb.yml +1 -2
  252. data/lib/generators/avo/templates/locales/avo.nn.yml +1 -2
  253. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -2
  254. data/lib/generators/avo/templates/locales/avo.pt.yml +1 -2
  255. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -7
  256. data/lib/generators/avo/templates/locales/avo.tr.yml +1 -2
  257. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  258. data/lib/generators/avo/templates/resource_tools/partial.tt +4 -4
  259. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  260. data/lib/generators/avo/templates/scope.tt +6 -0
  261. data/lib/generators/avo/templates/tool/view.tt +2 -2
  262. data/lib/tasks/avo_tasks.rake +27 -0
  263. data/public/avo-assets/avo.base.css +1810 -1189
  264. data/public/avo-assets/avo.base.js +217 -307
  265. data/public/avo-assets/avo.base.js.map +3 -3
  266. data/public/avo-assets/avo.css +9744 -0
  267. data/public/avo-assets/avo.js +513 -0
  268. data/public/avo-assets/avo.js.map +7 -0
  269. metadata +97 -139
  270. data/app/assets/stylesheets/css/tags.css +0 -32
  271. data/app/components/avo/card_component.html.erb +0 -46
  272. data/app/components/avo/card_component.rb +0 -25
  273. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  274. data/app/components/avo/dashboards/divider_component.rb +0 -19
  275. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  276. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  277. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  278. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  279. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  280. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  281. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  282. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  283. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  284. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  285. data/app/components/avo/index/ordering/base_component.rb +0 -9
  286. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  287. data/app/components/avo/index/ordering/button_component.rb +0 -23
  288. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  289. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  290. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  291. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  292. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  293. data/app/controllers/avo/dashboards_controller.rb +0 -22
  294. data/app/controllers/avo/reorder_controller.rb +0 -25
  295. data/app/javascript/js/controllers/base_controller.js +0 -22
  296. data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +0 -51
  297. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  298. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  299. data/app/views/avo/base/_new_via_belongs_to.html.erb +0 -12
  300. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +0 -8
  301. data/app/views/avo/base/create_fail_action.turbo_stream.erb +0 -13
  302. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  303. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  304. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  305. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  306. data/app/views/avo/dashboards/show.html.erb +0 -38
  307. data/app/views/avo/partials/_flash_alerts.turbo_stream.erb +0 -3
  308. data/app/views/avo/partials/_global_search.html.erb +0 -19
  309. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  310. data/lib/avo/app.rb +0 -237
  311. data/lib/avo/base_card.rb +0 -161
  312. data/lib/avo/concerns/fetches_things.rb +0 -150
  313. data/lib/avo/concerns/handles_field_args.rb +0 -47
  314. data/lib/avo/concerns/has_action_stimulus_controllers.rb +0 -15
  315. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  316. data/lib/avo/concerns/has_fields.rb +0 -334
  317. data/lib/avo/concerns/has_html_attributes.rb +0 -123
  318. data/lib/avo/concerns/pagination.rb +0 -53
  319. data/lib/avo/concerns/policy_helpers.rb +0 -31
  320. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  321. data/lib/avo/concerns/visible_items.rb +0 -51
  322. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  323. data/lib/avo/dashboards/base_divider.rb +0 -35
  324. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  325. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  326. data/lib/avo/dashboards/metric_card.rb +0 -9
  327. data/lib/avo/dashboards/partial_card.rb +0 -7
  328. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  329. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  330. data/lib/avo/fields/tags_field.rb +0 -102
  331. data/lib/avo/grid_collector.rb +0 -42
  332. data/lib/avo/hosts/association_scope_host.rb +0 -8
  333. data/lib/avo/hosts/base_host.rb +0 -25
  334. data/lib/avo/hosts/card_visibility.rb +0 -20
  335. data/lib/avo/hosts/dashboard_card.rb +0 -22
  336. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  337. data/lib/avo/hosts/ordering.rb +0 -22
  338. data/lib/avo/hosts/record_host.rb +0 -7
  339. data/lib/avo/hosts/resource_record_host.rb +0 -7
  340. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  341. data/lib/avo/hosts/search_scope_host.rb +0 -7
  342. data/lib/avo/hosts/view_record_host.rb +0 -7
  343. data/lib/avo/hosts/visibility_host.rb +0 -12
  344. data/lib/avo/items_holder.rb +0 -96
  345. data/lib/avo/main_panel.rb +0 -3
  346. data/lib/avo/menu/base_item.rb +0 -25
  347. data/lib/avo/menu/builder.rb +0 -82
  348. data/lib/avo/menu/dashboard.rb +0 -22
  349. data/lib/avo/menu/group.rb +0 -2
  350. data/lib/avo/menu/link.rb +0 -6
  351. data/lib/avo/menu/menu.rb +0 -2
  352. data/lib/avo/menu/resource.rb +0 -22
  353. data/lib/avo/menu/section.rb +0 -2
  354. data/lib/avo/panel.rb +0 -24
  355. data/lib/avo/panel_builder.rb +0 -25
  356. data/lib/avo/resources/controls/action.rb +0 -38
  357. data/lib/avo/resources/controls/execution_context.rb +0 -58
  358. data/lib/avo/resources/controls/items_holder.rb +0 -19
  359. data/lib/avo/resources/controls/link_to.rb +0 -27
  360. data/lib/avo/row.rb +0 -26
  361. data/lib/avo/row_builder.rb +0 -24
  362. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  363. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  364. data/lib/avo/sidebar.rb +0 -30
  365. data/lib/avo/sidebar_builder.rb +0 -24
  366. data/lib/avo/tab.rb +0 -72
  367. data/lib/avo/tab_builder.rb +0 -25
  368. data/lib/avo/tab_group.rb +0 -42
  369. data/lib/avo/tab_group_builder.rb +0 -43
  370. data/lib/avo/tools_manager.rb +0 -11
  371. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  372. data/lib/generators/avo/card/metric_generator.rb +0 -18
  373. data/lib/generators/avo/card/partial_generator.rb +0 -19
  374. data/lib/generators/avo/templates/locales/avo.es.yml +0 -126
  375. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  376. /data/app/components/avo/fields/common/files/view_type/{list_item_component.html.erb → list_component.html.erb} +0 -0
@@ -0,0 +1,68 @@
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 = 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
+ class << self
28
+ def parse_block(**args, &block)
29
+ Docile.dsl_eval(new(**args), &block).build
30
+ end
31
+ end
32
+
33
+ attr_reader :items_holder
34
+
35
+ delegate :tab, to: :items_holder
36
+
37
+ def initialize(style: nil)
38
+ @group = Avo::Resources::Items::TabGroup.new(style: style)
39
+ @items_holder = Avo::Resources::Items::Holder.new
40
+ end
41
+
42
+ def field(field_name, **args, &block)
43
+ parsed = Avo::Dsl::FieldParser.new(id: field_name, order_index: @items_index, **args, &block).parse
44
+ field_instance = parsed.instance
45
+
46
+ name = field_instance.name
47
+ tab = Avo::Resources::Items::Tab.new name: name
48
+
49
+ if field_instance.has_own_panel?
50
+ tab.items_holder.add_item parsed.instance
51
+ else
52
+ # If the field is not in a panel, create one and add it
53
+ panel = Avo::Resources::Items::Panel.new name: name
54
+ panel.items_holder.add_item parsed.instance
55
+ # Add that panel to the items_holder
56
+ tab.items_holder.add_item panel
57
+ end
58
+
59
+ @items_holder.tabs tab
60
+ end
61
+
62
+ # Fetch the tab
63
+ def build
64
+ @group.items_holder = @items_holder
65
+ @group
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,174 @@
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
+ Services::AuthorizationService.authorize user, resource.model_class, Avo.configuration.authorization_methods.stringify_keys["index"], raise_exception: false
156
+ end
157
+ .sort_by { |r| r.name }
158
+ end
159
+
160
+ def resources_for_navigation(user = nil)
161
+ get_available_resources(user)
162
+ .select do |resource|
163
+ resource.visible_on_sidebar
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ def get_mapping_for_model(klass)
170
+ (Avo.configuration.model_resource_mapping || {}).stringify_keys.transform_values(&:to_s)[klass.to_s]
171
+ end
172
+ end
173
+ end
174
+ end
@@ -6,109 +6,19 @@ module Avo
6
6
  attr_accessor :policy_class
7
7
 
8
8
  class << self
9
- def client
10
- client = Avo.configuration.authorization_client
11
-
12
- client = nil if Avo::App.license.lacks(:authorization)
13
-
14
- klass = case client
15
- when nil
16
- nil_client
17
- when :pundit
18
- pundit_client
19
- else
20
- if client.is_a?(String)
21
- client.safe_constantize
22
- else
23
- client
24
- end
25
- end
26
-
27
- klass.new
28
- end
29
-
30
- def authorize(user, record, action, policy_class: nil, **args)
31
- return true if skip_authorization
32
-
33
- client.authorize user, record, action, policy_class: policy_class
34
-
9
+ def authorize(*args, **kwargs)
35
10
  true
36
- rescue NoPolicyError => error
37
- # By default, Avo allows anything if you don't have a policy present.
38
- return true unless Avo.configuration.raise_error_on_missing_policy
39
-
40
- raise error
41
- rescue => error
42
- if args[:raise_exception] == false
43
- false
44
- else
45
- raise error
46
- end
47
11
  end
48
12
 
49
- def authorize_action(user, record, action, policy_class: nil, **args)
50
- action = Avo.configuration.authorization_methods.stringify_keys[action.to_s] || action
51
-
52
- # If no action passed we should raise error if the user wants that.
53
- # If not, just allow it.
54
- if action.nil?
55
- raise NoPolicyError.new "Policy method is missing" if Avo.configuration.raise_error_on_missing_policy
56
-
57
- return true
58
- end
59
-
60
- # Add the question mark if it's missing
61
- action = "#{action}?" unless action.end_with? "?"
62
- authorize(user, record, action, policy_class: policy_class, **args)
63
- end
64
-
65
- def apply_policy(user, model, policy_class: nil)
66
- return model if skip_authorization
67
-
68
- client.apply_policy(user, model, policy_class: policy_class)
69
- rescue NoPolicyError => error
70
- return model unless Avo.configuration.raise_error_on_missing_policy
71
-
72
- raise error
73
- end
74
-
75
- def skip_authorization
76
- Avo::App.license.lacks_with_trial :authorization
77
- end
78
-
79
- def defined_methods(user, record, policy_class: nil, **args)
80
- return client.policy!(user, record).methods if policy_class.nil?
81
-
82
- # I'm aware this will not raise a Pundit error.
83
- # Should the policy not exist, it will however raise an uninitialized constant error, which is probably what we want when specifying a custom policy
84
- policy_class.new(user, record).methods
85
- rescue NoPolicyError => error
86
- return [] unless Avo.configuration.raise_error_on_missing_policy
87
-
88
- raise error
89
- rescue => error
90
- if args[:raise_exception] == false
91
- []
92
- else
93
- raise error
94
- end
95
- end
96
-
97
- def pundit_client
98
- raise Avo::MissingGemError.new("Please add `gem 'pundit'` to your Gemfile.") unless defined?(Pundit)
99
-
100
- Avo::Services::AuthorizationClients::PunditClient
101
- end
102
-
103
- def nil_client
104
- Avo::Services::AuthorizationClients::NilClient
13
+ def apply_policy(user, query)
14
+ query
105
15
  end
106
16
  end
107
17
 
108
18
  def initialize(user = nil, record = nil, policy_class: nil)
109
19
  @user = user
110
20
  @record = record
111
- @policy_class = policy_class || self.class.client.policy(user, record)&.class
21
+ @policy_class = NilPolicy
112
22
  end
113
23
 
114
24
  def set_record(record)
@@ -117,28 +27,19 @@ module Avo
117
27
  self
118
28
  end
119
29
 
120
- def authorize_action(action, **args)
121
- self.class.authorize_action(user, args[:record] || record, action, policy_class: policy_class, **args)
30
+ def apply_policy(query)
31
+ query
122
32
  end
123
33
 
124
- def apply_policy(model)
125
- self.class.apply_policy(user, model, policy_class: policy_class)
34
+ def authorize_action(*args)
35
+ true
126
36
  end
127
37
 
128
- def defined_methods(model, **args)
129
- self.class.defined_methods(user, model, policy_class: policy_class, **args)
38
+ def has_method?(*args, **kwargs)
39
+ false
130
40
  end
131
41
 
132
- def has_method?(method, **args)
133
- method = "#{method}?" unless method.to_s.end_with? "?"
134
- defined_methods(args[:record] || record, **args).include? method.to_sym
135
- end
136
-
137
- # Check the received method to see if the user overrode it in their config and then checks if it's present on the policy.
138
- def has_action_method?(method, **args)
139
- method = Avo.configuration.authorization_methods.stringify_keys[method.to_s] || method
140
-
141
- has_method? method, **args
42
+ class NilPolicy
142
43
  end
143
44
  end
144
45
  end
@@ -0,0 +1,93 @@
1
+ class Avo::Services::DebugService
2
+ class << self
3
+ def debug_report(request = nil)
4
+ payload = {}
5
+
6
+ hq = Avo::Licensing::HQ.new(request)
7
+
8
+ payload[:license_id] = Avo::Current&.license&.id
9
+ payload[:license_valid] = Avo::Current&.license&.valid?
10
+ payload[:license_payload] = Avo::Current&.license&.payload
11
+ payload[:license_response] = Avo::Current&.license&.response
12
+ payload[:hq_payload] = hq&.payload
13
+ payload[:thread_count] = get_thread_count
14
+ payload[:license_abilities] = Avo::Current&.license&.abilities
15
+ payload[:cache_store] = Avo.cache_store&.class&.to_s
16
+ payload[:avo_metadata] = avo_metadata
17
+ payload[:app_timezone] = Time.current.zone
18
+ payload[:cache_key] = Avo::Licensing::HQ.cache_key
19
+ payload[:cache_key_contents] = hq&.cached_response
20
+ payload[:plugins] = Avo.plugin_manager
21
+
22
+ payload
23
+ rescue => e
24
+ e
25
+ end
26
+
27
+ def get_thread_count
28
+ Thread.list.count { |thread| thread.status == "run" }
29
+ rescue => e
30
+ e
31
+ end
32
+
33
+ def avo_metadata
34
+ resources = Avo.resource_manager.all
35
+ dashboards = defined?(Avo::Dashboards) ? Avo::Dashboards.dashboard_manager.all : []
36
+ field_definitions = resources.map(&:get_field_definitions)
37
+ fields_count = field_definitions.map(&:count).sum
38
+ fields_per_resource = sprintf("%0.01f", fields_count / (resources.count + 0.0))
39
+
40
+ field_types = {}
41
+ custom_fields_count = 0
42
+ field_definitions.each do |fields|
43
+ fields.each do |field|
44
+ field_types[field.type] ||= 0
45
+ field_types[field.type] += 1
46
+
47
+ custom_fields_count += 1 if field.custom?
48
+ end
49
+ end
50
+
51
+ {
52
+ resources_count: resources.count,
53
+ dashboards_count: dashboards.count,
54
+ fields_count: fields_count,
55
+ fields_per_resource: fields_per_resource,
56
+ custom_fields_count: custom_fields_count,
57
+ field_types: field_types,
58
+ # **other_metadata(:actions), # TODO: this is fetching actions without hydration
59
+ **other_metadata(:filters),
60
+ main_menu_present: Avo.configuration.main_menu.present?,
61
+ profile_menu_present: Avo.configuration.profile_menu.present?,
62
+ cache_store: Avo.cache_store&.class&.to_s,
63
+ **config_metadata
64
+ }
65
+ # rescue => error
66
+ # {
67
+ # error: error.message
68
+ # }
69
+ end
70
+
71
+ def other_metadata(type = :actions)
72
+ resources = Avo.resource_manager.all
73
+
74
+ types = resources.map(&:"get_#{type}")
75
+ type_count = types.flatten.uniq.count
76
+ type_per_resource = sprintf("%0.01f", types.map(&:count).sum / (resources.count + 0.0))
77
+
78
+ {
79
+ "#{type}_count": type_count,
80
+ "#{type}_per_resource": type_per_resource
81
+ }
82
+ end
83
+
84
+ def config_metadata
85
+ {
86
+ config: {
87
+ root_path: Avo.configuration.root_path,
88
+ app_name: Avo.configuration.app_name
89
+ }
90
+ }
91
+ end
92
+ end
93
+ end
@@ -32,12 +32,16 @@ module Avo
32
32
  private
33
33
 
34
34
  def encryption_key
35
- Rails.application.secret_key_base[0..31]
35
+ secret_key_base[0..31]
36
36
  rescue
37
37
  # This will fail the decryption process.
38
38
  # It's here only to keep Avo from crashing
39
39
  SecureRandom.random_bytes(32)
40
40
  end
41
+
42
+ def secret_key_base
43
+ ENV["SECRET_KEY_BASE"] || Rails.application.credentials.secret_key_base || Rails.application.secrets.secret_key_base
44
+ end
41
45
  end
42
46
  end
43
47
  end
@@ -0,0 +1,85 @@
1
+ class Avo::Services::TelemetryService
2
+ class << self
3
+ def telemetry_info
4
+ {
5
+ # license: Avo.configuration.license,
6
+ # license_key: Avo.configuration.license_key,
7
+ avo_version: Avo::VERSION,
8
+ rails_version: Rails::VERSION::STRING,
9
+ ruby_version: RUBY_VERSION,
10
+ environment: Rails.env,
11
+ # ip: current_request&.ip,
12
+ # host: current_request&.host,
13
+ # port: current_request&.port,
14
+ app_name: app_name,
15
+ avo_metadata: avo_metadata,
16
+ }
17
+ end
18
+
19
+ def app_name
20
+ Rails.application.class.to_s.split("::").first
21
+ rescue
22
+ nil
23
+ end
24
+
25
+ def avo_metadata
26
+ resources = Avo.resource_manager.all
27
+ dashboards = Avo::Current.app.dashboard_manager.all
28
+ field_definitions = resources.map(&:get_field_definitions)
29
+ fields_count = field_definitions.map(&:count).sum
30
+ fields_per_resource = sprintf("%0.01f", fields_count / (resources.count + 0.0))
31
+
32
+ field_types = {}
33
+ custom_fields_count = 0
34
+ field_definitions.each do |fields|
35
+ fields.each do |field|
36
+ field_types[field.type] ||= 0
37
+ field_types[field.type] += 1
38
+
39
+ custom_fields_count += 1 if field.custom?
40
+ end
41
+ end
42
+
43
+ {
44
+ resources_count: resources.count,
45
+ dashboards_count: dashboards.count,
46
+ fields_count: fields_count,
47
+ fields_per_resource: fields_per_resource,
48
+ custom_fields_count: custom_fields_count,
49
+ field_types: field_types,
50
+ **other_metadata(:actions),
51
+ **other_metadata(:filters),
52
+ main_menu_present: Avo.configuration.main_menu.present?,
53
+ profile_menu_present: Avo.configuration.profile_menu.present?,
54
+ cache_store: Avo.cache_store&.class&.to_s,
55
+ **config_metadata
56
+ }
57
+ # rescue => error
58
+ # {
59
+ # error: error.message
60
+ # }
61
+ end
62
+
63
+ def other_metadata(type = :actions)
64
+ resources = Avo.resource_manager.all
65
+
66
+ types = resources.map(&:"get_#{type}")
67
+ type_count = types.flatten.uniq.count
68
+ type_per_resource = sprintf("%0.01f", types.map(&:count).sum / (resources.count + 0.0))
69
+
70
+ {
71
+ "#{type}_count": type_count,
72
+ "#{type}_per_resource": type_per_resource
73
+ }
74
+ end
75
+
76
+ def config_metadata
77
+ {
78
+ config: {
79
+ root_path: Avo.configuration.root_path,
80
+ app_name: Avo.configuration.app_name
81
+ }
82
+ }
83
+ end
84
+ end
85
+ end