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
@@ -2,7 +2,19 @@ require_dependency "avo/application_controller"
2
2
 
3
3
  module Avo
4
4
  class DebugController < ApplicationController
5
- def index
5
+ def status
6
+ end
7
+
8
+ def send_to_hq
9
+ url = "#{ENV["HQ_URL"]}/api/v3/debug_requests"
10
+ timeout = 10 # seconds
11
+ license_key = Avo::Services::DebugService.debug_report(request)[:hq_payload][:license_key]
12
+ body = params[:body]
13
+ body = {license_key: license_key, body: body, payload: Avo::Services::DebugService.debug_report(request).to_json}.to_json
14
+
15
+ HTTParty.post url, body: body, headers: {"Content-Type": "application/json"}, timeout: timeout
16
+
17
+ render turbo_stream: turbo_stream.replace(:send_to_hq, plain: "Payload sent to Avo HQ.")
6
18
  end
7
19
 
8
20
  def report
@@ -13,13 +25,13 @@ module Avo
13
25
 
14
26
  if license.valid?
15
27
  flash[:notice] = "avohq.io responded: \"#{license.id.humanize} license is valid\"."
16
- elsif license.response['reason'].present?
17
- flash[:error] = "avohq.io responded: \"#{license.response['reason']}\"."
28
+ elsif license.response["reason"].present?
29
+ flash[:error] = "avohq.io responded: \"#{license.response["reason"]}\"."
18
30
  else
19
- flash[:error] = license.response['error']
31
+ flash[:error] = license.response["error"]
20
32
  end
21
33
 
22
- redirect_back fallback_location: avo.avo_private_debug_index_path
34
+ redirect_back fallback_location: avo.avo_private_status_path
23
35
  end
24
36
  end
25
37
  end
@@ -14,7 +14,7 @@ module Avo
14
14
  redirect_to computed_path
15
15
  elsif !Rails.env.development?
16
16
  @page_title = "Get started"
17
- resource = Avo::App.resources.min_by { |resource| resource.model_key }
17
+ resource = Avo.resource_manager.all.min_by { |resource| resource.model_key }
18
18
  redirect_to resources_path(resource: resource)
19
19
  end
20
20
  end
@@ -4,18 +4,8 @@ module Avo
4
4
  class SearchController < ApplicationController
5
5
  include Rails.application.routes.url_helpers
6
6
 
7
- before_action :set_resource_name, only: [:show]
8
- before_action :set_resource, only: [:show]
9
-
10
- def index
11
- raise ActionController::BadRequest.new("This feature requires the pro license https://avohq.io/purchase/pro") if App.license.lacks_with_trial(:global_search)
12
-
13
- resources = Avo::App.resources.reject do |resource|
14
- resource.class.hide_from_global_search
15
- end
16
-
17
- render json: search_resources(resources)
18
- end
7
+ before_action :set_resource_name, only: :show
8
+ before_action :set_resource, only: :show
19
9
 
20
10
  def show
21
11
  render json: search_resources([resource])
@@ -28,7 +18,6 @@ module Avo
28
18
  .map do |resource|
29
19
  # Apply authorization
30
20
  next unless @authorization.set_record(resource.model_class).authorize_action(:search, raise_exception: false)
31
-
32
21
  # Filter out the models without a search_query
33
22
  next if resource.search_query.nil?
34
23
 
@@ -45,20 +34,20 @@ module Avo
45
34
  end
46
35
 
47
36
  def search_resource(resource)
48
- query = Avo::Hosts::SearchScopeHost.new(
49
- block: resource.search_query,
37
+ query = Avo::ExecutionContext.new(
38
+ target: resource.search_query,
50
39
  params: params,
51
- scope: resource.class.scope
40
+ query: resource.query_scope
52
41
  ).handle
53
42
 
54
- query = apply_scope(query) if should_apply_any_scope?
55
-
56
43
  # Get the count
57
44
  results_count = query.reselect(resource.model_class.primary_key).count
58
45
 
59
46
  # Get the results
60
47
  query = query.limit(8)
61
48
 
49
+ query = apply_scope(query) if should_apply_any_scope?
50
+
62
51
  results = apply_search_metadata(query, resource)
63
52
 
64
53
  header = resource.plural_name
@@ -69,9 +58,9 @@ module Avo
69
58
 
70
59
  result_object = {
71
60
  header: header,
72
- help: resource.class.search_query_help,
61
+ help: resource.fetch_search(:help) || "",
73
62
  results: results,
74
- count: results_count
63
+ count: results.count
75
64
  }
76
65
 
77
66
  [resource.name.pluralize.downcase, result_object]
@@ -96,9 +85,9 @@ module Avo
96
85
  # to scope the query.
97
86
  # Example usage: Got to a project, create a new review, and search for a user.
98
87
  if parent.blank? && params[:via_parent_resource_id].present? && params[:via_parent_resource_class].present? && params[:via_relation].present?
99
- parent_resource_class = BaseResource.valid_model_class params[:via_parent_resource_class]
88
+ parent_resource_class = BaseResource.get_model_by_name params[:via_parent_resource_class]
100
89
 
101
- reflection_class = BaseResource.valid_model_class params[:via_reflection_class]
90
+ reflection_class = BaseResource.get_model_by_name params[:via_reflection_class]
102
91
 
103
92
  grandparent = parent_resource_class.find params[:via_parent_resource_id]
104
93
  parent = reflection_class.new(
@@ -106,7 +95,7 @@ module Avo
106
95
  )
107
96
  end
108
97
 
109
- Avo::Hosts::AssociationScopeHost.new(block: attach_scope, query: query, parent: parent).handle
98
+ Avo::ExecutionContext.new(target: attach_scope, query: query, parent: parent).handle
110
99
  end
111
100
 
112
101
  # This scope is applied if the search is being performed on a has_many association
@@ -114,44 +103,34 @@ module Avo
114
103
  association_name = BaseResource.valid_association_name(parent, params[:via_association_id])
115
104
 
116
105
  # Get association records
117
- scope = parent.send(association_name)
106
+ query = parent.send(association_name)
118
107
 
119
108
  # Apply policy scope if authorization is present
120
- scope = resource.authorization&.apply_policy scope
109
+ query = resource.authorization&.apply_policy query
121
110
 
122
- Avo::Hosts::SearchScopeHost.new(block: @resource.search_query, params: params, scope: scope).handle
111
+ Avo::ExecutionContext.new(target: @resource.class.search_query, params: params, query: query).handle
123
112
  end
124
113
 
125
- def apply_search_metadata(models, avo_resource)
126
- models.map do |model|
127
- resource = avo_resource.dup.hydrate(model: model).hydrate_fields(model: model)
128
-
129
- record_path = if resource.search_result_path.present?
130
- Avo::Hosts::ResourceRecordHost.new(block: resource.search_result_path, resource: resource, record: model).handle
131
- else
132
- resource.record_path
133
- end
114
+ def apply_search_metadata(records, avo_resource)
115
+ records.map do |record|
116
+ resource = avo_resource.new(record: record)
134
117
 
135
- result = {
136
- _id: model.id,
137
- _label: resource.label,
138
- _url: record_path
139
- }
140
-
141
- if App.license.has_with_trial(:enhanced_search_results)
142
- result[:_description] = resource.description
143
- result[:_avatar] = resource.avatar.present? ? main_app.url_for(resource.avatar) : nil
144
- result[:_avatar_type] = resource.avatar_type
145
- end
146
-
147
- result
118
+ fetch_result_information record, resource, resource.class.fetch_search(:item, record: record)
148
119
  end
149
120
  end
150
121
 
151
122
  private
152
123
 
124
+ def fetch_result_information(record, resource, item)
125
+ {
126
+ _id: record.id,
127
+ _label: item&.dig(:title) || resource.record_title,
128
+ _url: resource.class.fetch_search(:result_path, record: resource.record) || resource.record_path
129
+ }
130
+ end
131
+
153
132
  def should_apply_has_many_scope?
154
- params[:via_association] == "has_many" && @resource.search_query.present?
133
+ params[:via_association] == "has_many" && @resource.class.search_query.present?
155
134
  end
156
135
 
157
136
  def should_apply_attach_scope?
@@ -175,14 +154,14 @@ module Avo
175
154
  end
176
155
 
177
156
  def fetch_field
178
- fields = ::Avo::App.get_resource_by_model_name(params[:via_reflection_class]).get_field_definitions
157
+ fields = Avo.resource_manager.get_resource_by_model_class(params[:via_reflection_class]).new.get_field_definitions
179
158
  fields.find { |f| f.id.to_s == params[:via_association_id] }
180
159
  end
181
160
 
182
161
  def fetch_parent
183
162
  return unless params[:via_reflection_id].present?
184
163
 
185
- parent_resource = ::Avo::App.get_resource_by_model_name params[:via_reflection_class]
164
+ parent_resource = Avo.resource_manager.get_resource_by_model_class params[:via_reflection_class]
186
165
  parent_resource.find_record params[:via_reflection_id], params: params
187
166
  end
188
167
  end
@@ -0,0 +1,4 @@
1
+ # This controller has been generated to enable Rails' resource routes.
2
+ # You shouldn't need to modify it in order to use Avo.
3
+ class Avo::TeamUsersController < Avo::ResourcesController
4
+ end
@@ -0,0 +1,21 @@
1
+ module Avo
2
+ module InitializesAvo
3
+ def init_app
4
+ Avo::Current.license = Avo::Licensing::NilLicense.new
5
+ Avo::Current.context = context
6
+ Avo::Current.user = _current_user
7
+ Avo::Current.view_context = view_context
8
+ Avo.init
9
+ Avo::Current.license = Licensing::LicenseManager.new(Licensing::HQ.new(request).response).license
10
+ Avo.plugin_manager.init_plugins
11
+ end
12
+
13
+ def _current_user
14
+ instance_eval(&Avo.configuration.current_user)
15
+ end
16
+
17
+ def context
18
+ instance_eval(&Avo.configuration.context)
19
+ end
20
+ end
21
+ end
@@ -1,12 +1,7 @@
1
1
  module Avo
2
2
  module ApplicationHelper
3
3
  include ::Pagy::Frontend
4
-
5
- def render_license_warnings
6
- render partial: "avo/sidebar/license_warnings", locals: {
7
- license: Avo::App.license.properties
8
- }
9
- end
4
+ include Avo::ResourcesHelper
10
5
 
11
6
  def render_license_warning(title: "", message: "", icon: "exclamation")
12
7
  render partial: "avo/sidebar/license_warning", locals: {
@@ -119,8 +114,19 @@ module Avo
119
114
  Avo::Filters::BaseFilter.encode_filters(filter_params)
120
115
  end
121
116
 
122
- def frame_id(resource)
123
- ["frame", resource.model_name.singular, resource.model.id].compact.join("-")
117
+ def number_to_social(number, start_at: 10_000)
118
+ return number_with_delimiter(number) if number < start_at
119
+
120
+ number_to_human(number,
121
+ precision: 1,
122
+ significant: false,
123
+ round_mode: :down,
124
+ format: "%n%u",
125
+ units: {
126
+ thousand: "K",
127
+ million: "M",
128
+ billion: "B"
129
+ })
124
130
  end
125
131
 
126
132
  private
@@ -144,7 +150,7 @@ module Avo
144
150
  field = field_klass.new id, form: form, view: view, **args, &block
145
151
 
146
152
  # Add the form record to the field so all fields have access to it.
147
- field.hydrate(model: form.object) if form.present?
153
+ field.hydrate(record: form.object) if form.present?
148
154
 
149
155
  render field.component_for_view(view).new field: field, form: form, **component_options
150
156
  end
@@ -38,7 +38,7 @@ module Avo
38
38
  end
39
39
 
40
40
  def item_selector_init(resource)
41
- "data-resource-name='#{resource.model_key}' data-resource-id='#{resource.model.id}' data-controller='item-selector'"
41
+ "data-resource-name='#{resource.model_key}' data-resource-id='#{resource.record.id}' data-controller='item-selector'"
42
42
  end
43
43
 
44
44
  def item_selector_input(floating: false, size: :md)
@@ -20,14 +20,14 @@ module Avo
20
20
  end
21
21
 
22
22
  def resource_path(
23
- model:,
23
+ record:,
24
24
  resource:,
25
25
  resource_id: nil,
26
26
  keep_query_params: false,
27
27
  **args
28
28
  )
29
- if model.respond_to? :id
30
- id = model
29
+ if record.respond_to? :id
30
+ id = record
31
31
  elsif resource_id.present?
32
32
  id = resource_id
33
33
  end
@@ -35,29 +35,45 @@ module Avo
35
35
  avo.send :"resources_#{resource.singular_route_key}_path", id, **args
36
36
  end
37
37
 
38
+ def preview_resource_path(
39
+ record:,
40
+ resource:,
41
+ resource_id: nil,
42
+ keep_query_params: false,
43
+ **args
44
+ )
45
+ if record.respond_to? resource.id_attribute
46
+ id = record
47
+ elsif resource_id.present?
48
+ id = resource_id
49
+ end
50
+
51
+ avo.send :"preview_resources_#{resource.singular_route_key}_path", id, **args
52
+ end
53
+
38
54
  def new_resource_path(resource:, **args)
39
55
  avo.send :"new_resources_#{resource.singular_route_key}_path", **args
40
56
  end
41
57
 
42
- def edit_resource_path(model:, resource:, **args)
43
- avo.send :"edit_resources_#{resource.singular_route_key}_path", model, **args
58
+ def edit_resource_path(record:, resource:, **args)
59
+ avo.send :"edit_resources_#{resource.singular_route_key}_path", record, **args
44
60
  end
45
61
 
46
- def resource_attach_path(resource, model_id, related_name, related_id = nil)
47
- helpers.avo.resources_associations_new_path(resource.singular_route_key, model_id, related_name)
62
+ def resource_attach_path(resource, record_id, related_name, related_id = nil)
63
+ helpers.avo.resources_associations_new_path(resource.singular_route_key, record_id, related_name)
48
64
  end
49
65
 
50
66
  def resource_detach_path(
51
67
  model_name, # teams
52
- model_id, # 1
68
+ record_id, # 1
53
69
  related_name, # admin
54
70
  related_id = nil
55
71
  )
56
- avo.resources_associations_destroy_path(model_name, model_id, related_name, related_id)
72
+ avo.resources_associations_destroy_path(model_name, record_id, related_name, related_id)
57
73
  end
58
74
 
59
75
  def related_resources_path(
60
- parent_model,
76
+ parent_record,
61
77
  record,
62
78
  keep_query_params: false,
63
79
  **args
@@ -74,7 +90,7 @@ module Avo
74
90
  rescue
75
91
  end
76
92
 
77
- avo.resources_associations_index_path(parent_model.model_name.route_key, record.id, **existing_params, **args)
93
+ avo.resources_associations_index_path(parent_record.model_name.route_key, record.id, **existing_params, **args)
78
94
  end
79
95
 
80
96
  def resource_view_path(**args)
@@ -12,6 +12,7 @@ import 'chartkick/chart.js/chart.esm'
12
12
 
13
13
  import './js/active-storage'
14
14
  import './js/controllers'
15
+ import './js/custom-stream-actions'
15
16
 
16
17
  Rails.start()
17
18
 
@@ -2,9 +2,6 @@ import 'mapkick/bundle'
2
2
 
3
3
  import { Alert, Popover } from 'tailwindcss-stimulus-components'
4
4
  import { Application } from '@hotwired/stimulus'
5
- import TurboPower from 'turbo_power'
6
-
7
- TurboPower.initialize(Turbo.StreamActions)
8
5
 
9
6
  const application = Application.start()
10
7
 
@@ -2,10 +2,12 @@ import { Controller } from '@hotwired/stimulus'
2
2
  import { castBoolean } from '../helpers/cast_boolean'
3
3
 
4
4
  export default class extends Controller {
5
- static targets = ['controllerDiv', 'resourceIds', 'submit', 'selectedAllQuery']
5
+ static targets = ['controllerDiv', 'resourceIds', 'form', 'selectedAllQuery']
6
6
 
7
7
  connect() {
8
- this.resourceIdsTarget.value = this.resourceIds
8
+ if (this.resourceIdsTarget.value === '') {
9
+ this.resourceIdsTarget.value = this.resourceIds
10
+ }
9
11
 
10
12
  // This value is picked up from the DOM so we check true/false as strings
11
13
  if (this.selectionOptions.itemSelectAllSelectedAllValue === 'true') {
@@ -13,7 +15,7 @@ export default class extends Controller {
13
15
  }
14
16
 
15
17
  if (this.noConfirmation) {
16
- this.submitTarget.click()
18
+ this.formTarget.submit()
17
19
  } else {
18
20
  this.controllerDivTarget.classList.remove('hidden')
19
21
  }
@@ -0,0 +1,62 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ['content']
5
+
6
+ static values = {
7
+ panelList: Boolean,
8
+ }
9
+
10
+ // get the table or grid component, if both null, get the panel body (for show page for example)
11
+ get parentTarget() {
12
+ return document.querySelector('[data-component-name="avo/index/resource_table_component"]')
13
+ || document.querySelector('[data-component-name="avo/index/resource_grid_component"]')
14
+ || document.querySelector('[data-target="panel-body"]')
15
+ }
16
+
17
+ childDimensions = null
18
+
19
+ parentDimensions = null
20
+
21
+ connect() {
22
+ // We need to make the element visible in order to get it's position
23
+ this.element.style.display = 'block'
24
+ this.childDimensions = this.contentTarget.getBoundingClientRect()
25
+ this.element.style.display = ''
26
+ this.parentDimensions = this.parentTarget.getBoundingClientRect()
27
+
28
+ this.adjustOverflow()
29
+ }
30
+
31
+ adjustOverflow() {
32
+ this.adjustVerticalOverflow()
33
+ this.adjustHorizontalOverflow()
34
+ }
35
+
36
+ adjustVerticalOverflow() {
37
+ if (this.contentBottomOverflow) {
38
+ this.contentTarget.classList.remove('top-full', 'mt-2')
39
+ this.contentTarget.classList.add('bottom-full', 'mb-2')
40
+ }
41
+ }
42
+
43
+ adjustHorizontalOverflow() {
44
+ if (this.contentLeftOverflow) {
45
+ this.contentTarget.classList.remove('xl:right-0', 'sm:right-0')
46
+ this.contentTarget.classList.add('xl:left-0', 'sm:left-0')
47
+ }
48
+ }
49
+
50
+ get contentBottomOverflow() {
51
+ // If the list is on panel header, we don't want to adjust the vertical overflow
52
+ if (this.panelListValue === true) {
53
+ return false
54
+ }
55
+
56
+ return this.parentDimensions.bottom < this.childDimensions.bottom
57
+ }
58
+
59
+ get contentLeftOverflow() {
60
+ return this.parentDimensions.left > this.childDimensions.left
61
+ }
62
+ }
@@ -98,7 +98,7 @@ export default class extends Controller {
98
98
 
99
99
  url.query(query)
100
100
 
101
- this.urlRedirectTarget.href = url
101
+ this.urlRedirectTarget.href = url.readable().toString()
102
102
  this.urlRedirectTarget.click()
103
103
  }
104
104
  }
@@ -0,0 +1,12 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ['element'];
5
+
6
+ focus({ params }) {
7
+ const element = this.context.element.querySelector(params.selector)
8
+ if (this.element) {
9
+ element.focus()
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,24 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import tippy from 'tippy.js'
3
+
4
+ export default class extends Controller {
5
+ static values = {
6
+ url: String,
7
+ }
8
+
9
+ connect() {
10
+ const vm = this;
11
+
12
+ tippy(vm.context.element, {
13
+ content: "loading...",
14
+ allowHTML: true,
15
+ theme: 'light',
16
+ maxWidth: 550,
17
+ async onShow(instance) {
18
+ const response = await fetch(vm.urlValue)
19
+ const content = await response.text()
20
+ instance.setContent(content)
21
+ },
22
+ })
23
+ }
24
+ }
@@ -212,8 +212,8 @@ export default class extends Controller {
212
212
  const url = URI()
213
213
 
214
214
  return url.segment([window.Avo.configuration.root_path, ...this.searchSegments()])
215
- .search(this.searchParams(encodeURIComponent(query)))
216
- .readable().toString()
215
+ .search(this.searchParams(encodeURIComponent(query)))
216
+ .readable().toString()
217
217
  }
218
218
 
219
219
  searchSegments() {
@@ -0,0 +1,7 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ destroy() {
5
+ this.context.element.remove()
6
+ }
7
+ }
@@ -0,0 +1,48 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import { leave, toggle } from 'el-transition'
3
+ import { useClickOutside } from 'stimulus-use'
4
+
5
+ export default class extends Controller {
6
+ static targets = ['panel']
7
+
8
+ static values = {
9
+ // One may want to have an element that is exempt from triggerring the click outside event
10
+ exemptionContainer: String,
11
+ }
12
+
13
+ get exemptionContainerTarget() {
14
+ return document.querySelector(this.exemptionContainerValue)
15
+ }
16
+
17
+ connect() {
18
+ useClickOutside(this)
19
+ }
20
+
21
+ clickOutside(e) {
22
+ if (this.hasPanelTarget) {
23
+ if (this.hasExemptionContainerValue) {
24
+ const inExemptionContainer = this.exemptionContainerTarget.contains(e.target)
25
+
26
+ if (!inExemptionContainer) {
27
+ leave(this.panelTarget)
28
+ }
29
+ } else {
30
+ leave(this.panelTarget)
31
+ }
32
+ }
33
+ }
34
+
35
+ togglePanel() {
36
+ if (this.hasPanelTarget) {
37
+ toggle(this.panelTarget)
38
+ }
39
+ }
40
+
41
+ outlet({ params }) {
42
+ const { outlet } = params
43
+
44
+ if (outlet && document.querySelector(outlet)) {
45
+ document.querySelector(outlet).classList.toggle('hidden')
46
+ }
47
+ }
48
+ }