avo 2.44.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) 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 +9 -15
  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 +5 -4
  73. data/app/components/avo/index/resource_table_component.rb +24 -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 +29 -40
  84. data/app/components/avo/paginator_component.rb +23 -5
  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 -84
  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 -181
  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 +145 -98
  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 +3 -1
  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 +9 -5
  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/_flash_alerts.turbo_stream.erb +1 -1
  143. data/app/views/avo/partials/_footer.html.erb +1 -1
  144. data/app/views/avo/partials/_javascript.html.erb +5 -0
  145. data/app/views/avo/partials/_logo.html.erb +1 -1
  146. data/app/views/avo/partials/_navbar.html.erb +3 -5
  147. data/app/views/avo/partials/_resource_search.html.erb +1 -0
  148. data/app/views/avo/partials/_table_header.html.erb +5 -11
  149. data/app/views/layouts/avo/application.html.erb +5 -4
  150. data/avo.gemspec +10 -8
  151. data/bin/dev +3 -1
  152. data/bin/prod +0 -0
  153. data/config/i18n-tasks.yml +1 -1
  154. data/config/initializers/pagy.rb +2 -0
  155. data/config/master.key +1 -0
  156. data/config/routes.rb +7 -10
  157. data/db/factories.rb +6 -0
  158. data/lib/avo/asset_manager.rb +30 -0
  159. data/lib/avo/base_action.rb +78 -60
  160. data/lib/avo/base_resource.rb +286 -225
  161. data/lib/avo/base_resource_tool.rb +9 -16
  162. data/lib/avo/concerns/borrow_items_holder.rb +35 -0
  163. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  164. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  165. data/lib/avo/concerns/filters_session_handler.rb +7 -5
  166. data/lib/avo/concerns/has_controls.rb +37 -0
  167. data/lib/avo/concerns/has_description.rb +23 -0
  168. data/lib/avo/concerns/has_helpers.rb +18 -0
  169. data/lib/avo/concerns/has_item_type.rb +42 -0
  170. data/lib/avo/concerns/has_items.rb +339 -0
  171. data/lib/avo/concerns/hydration.rb +17 -0
  172. data/lib/avo/concerns/is_resource_item.rb +16 -36
  173. data/lib/avo/concerns/is_visible.rb +15 -0
  174. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  175. data/lib/avo/concerns/pagination.rb +53 -0
  176. data/lib/avo/concerns/visible_in_different_views.rb +132 -0
  177. data/lib/avo/concerns/visible_items.rb +7 -38
  178. data/lib/avo/configuration/branding.rb +0 -12
  179. data/lib/avo/configuration.rb +28 -11
  180. data/lib/avo/current.rb +39 -0
  181. data/lib/avo/dsl/field_parser.rb +3 -3
  182. data/lib/avo/dynamic_router.rb +18 -3
  183. data/lib/avo/engine.rb +35 -30
  184. data/lib/avo/error_manager.rb +25 -0
  185. data/lib/avo/execution_context.rb +14 -15
  186. data/lib/avo/fields/base_field.rb +84 -121
  187. data/lib/avo/fields/belongs_to_field.rb +19 -23
  188. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  189. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  190. data/lib/avo/fields/concerns/has_default.rb +1 -5
  191. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  192. data/lib/avo/fields/concerns/has_html_attributes.rb +112 -0
  193. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  194. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  195. data/lib/avo/fields/concerns/is_required.rb +5 -7
  196. data/lib/avo/fields/concerns/is_searchable.rb +15 -0
  197. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  198. data/lib/avo/fields/concerns/use_view_components.rb +45 -0
  199. data/lib/avo/fields/country_field.rb +4 -0
  200. data/lib/avo/fields/date_time_field.rb +1 -5
  201. data/lib/avo/fields/external_image_field.rb +2 -2
  202. data/lib/avo/fields/field_manager.rb +55 -0
  203. data/lib/avo/fields/file_field.rb +2 -2
  204. data/lib/avo/fields/gravatar_field.rb +2 -2
  205. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  206. data/lib/avo/fields/has_base_field.rb +21 -17
  207. data/lib/avo/fields/has_many_field.rb +5 -2
  208. data/lib/avo/fields/has_one_field.rb +8 -12
  209. data/lib/avo/fields/heading_field.rb +9 -14
  210. data/lib/avo/fields/hidden_field.rb +1 -1
  211. data/lib/avo/fields/id_field.rb +3 -3
  212. data/lib/avo/fields/location_field.rb +10 -10
  213. data/lib/avo/fields/password_field.rb +1 -1
  214. data/lib/avo/fields/preview_field.rb +14 -0
  215. data/lib/avo/fields/select_field.rb +12 -8
  216. data/lib/avo/fields/status_field.rb +7 -1
  217. data/lib/avo/fields/text_field.rb +2 -2
  218. data/lib/avo/filters/base_filter.rb +9 -4
  219. data/lib/avo/html/builder.rb +8 -8
  220. data/lib/avo/item_grapher.rb +78 -0
  221. data/lib/avo/licensing/h_q.rb +11 -73
  222. data/lib/avo/licensing/license.rb +5 -1
  223. data/lib/avo/licensing/license_manager.rb +1 -1
  224. data/lib/avo/licensing/pro_license.rb +1 -7
  225. data/lib/avo/loaders/fields_loader.rb +7 -1
  226. data/lib/avo/plugin.rb +36 -0
  227. data/lib/avo/plugin_manager.rb +56 -0
  228. data/lib/avo/prefixed_test_helpers.rb +20 -0
  229. data/lib/avo/reloader.rb +3 -0
  230. data/lib/avo/resources/controls/actions_list.rb +7 -12
  231. data/lib/avo/resources/controls/attach_button.rb +15 -0
  232. data/lib/avo/resources/controls/back_button.rb +1 -1
  233. data/lib/avo/resources/controls/base_control.rb +15 -49
  234. data/lib/avo/resources/controls/create_button.rb +15 -0
  235. data/lib/avo/resources/controls/delete_button.rb +5 -1
  236. data/lib/avo/resources/controls/detach_button.rb +4 -1
  237. data/lib/avo/resources/controls/edit_button.rb +4 -1
  238. data/lib/avo/resources/controls/order_controls.rb +8 -0
  239. data/lib/avo/resources/controls/save_button.rb +13 -0
  240. data/lib/avo/resources/controls/show_button.rb +15 -0
  241. data/lib/avo/resources/items/holder.rb +96 -0
  242. data/lib/avo/resources/items/item_group.rb +44 -0
  243. data/lib/avo/resources/items/main_panel.rb +12 -0
  244. data/lib/avo/resources/items/panel.rb +2 -0
  245. data/lib/avo/resources/items/row.rb +42 -0
  246. data/lib/avo/resources/items/sidebar.rb +46 -0
  247. data/lib/avo/resources/items/tab.rb +54 -0
  248. data/lib/avo/resources/items/tab_group.rb +62 -0
  249. data/lib/avo/resources/resource_manager.rb +179 -0
  250. data/lib/avo/services/authorization_service.rb +11 -110
  251. data/lib/avo/services/debug_service.rb +93 -0
  252. data/lib/avo/services/encryption_service.rb +8 -12
  253. data/lib/avo/services/telemetry_service.rb +85 -0
  254. data/lib/avo/test_helpers.rb +362 -0
  255. data/lib/avo/tools/tool_manager.rb +30 -0
  256. data/lib/avo/version.rb +1 -1
  257. data/lib/avo/view_inquirer.rb +36 -0
  258. data/lib/avo.rb +109 -24
  259. data/lib/generators/avo/action_generator.rb +8 -8
  260. data/lib/generators/avo/card_generator.rb +27 -0
  261. data/lib/generators/avo/concerns/parent_controller.rb +20 -0
  262. data/lib/generators/avo/controller_generator.rb +3 -0
  263. data/lib/generators/avo/eject_generator.rb +180 -15
  264. data/lib/generators/avo/field_generator.rb +49 -2
  265. data/lib/generators/avo/filter_generator.rb +8 -8
  266. data/lib/generators/avo/js/install_generator.rb +2 -2
  267. data/lib/generators/avo/resource_generator.rb +12 -9
  268. data/lib/generators/avo/scope_generator.rb +15 -0
  269. data/lib/generators/avo/tailwindcss/install_generator.rb +70 -26
  270. data/lib/generators/avo/templates/action.tt +8 -6
  271. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  272. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  273. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  274. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  275. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  276. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  277. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  278. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  279. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  280. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  281. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  282. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  283. data/lib/generators/avo/templates/initializer/avo.tt +7 -3
  284. data/lib/generators/avo/templates/locales/avo.ar.yml +7 -6
  285. data/lib/generators/avo/templates/locales/avo.en.yml +6 -3
  286. data/lib/generators/avo/templates/locales/avo.es.yml +127 -0
  287. data/lib/generators/avo/templates/locales/avo.fr.yml +3 -0
  288. data/lib/generators/avo/templates/locales/avo.nb.yml +3 -0
  289. data/lib/generators/avo/templates/locales/avo.nn.yml +3 -0
  290. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +3 -0
  291. data/lib/generators/avo/templates/locales/avo.pt.yml +3 -0
  292. data/lib/generators/avo/templates/locales/avo.ro.yml +8 -5
  293. data/lib/generators/avo/templates/locales/avo.tr.yml +3 -0
  294. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  295. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  296. data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
  297. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  298. data/lib/generators/avo/templates/scope.tt +6 -0
  299. data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
  300. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
  301. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
  302. data/lib/tasks/avo_tasks.rake +72 -4
  303. data/public/avo-assets/avo.base.css +1893 -1187
  304. data/public/avo-assets/avo.base.js +217 -305
  305. data/public/avo-assets/avo.base.js.map +3 -3
  306. data/public/avo-assets/avo.css +9744 -0
  307. data/public/avo-assets/avo.js +513 -0
  308. data/public/avo-assets/avo.js.map +7 -0
  309. data/tailwind.custom.js +47 -0
  310. data/tailwind.preset.js +152 -0
  311. metadata +107 -114
  312. data/app/components/avo/card_component.html.erb +0 -46
  313. data/app/components/avo/card_component.rb +0 -25
  314. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  315. data/app/components/avo/dashboards/divider_component.rb +0 -19
  316. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  317. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  318. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  319. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  320. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  321. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  322. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  323. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  324. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  325. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  326. data/app/components/avo/index/ordering/base_component.rb +0 -9
  327. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  328. data/app/components/avo/index/ordering/button_component.rb +0 -23
  329. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  330. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  331. data/app/components/avo/item_switcher_component.html.erb +0 -27
  332. data/app/components/avo/item_switcher_component.rb +0 -48
  333. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  334. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  335. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  336. data/app/controllers/avo/dashboards_controller.rb +0 -22
  337. data/app/controllers/avo/reorder_controller.rb +0 -25
  338. data/app/javascript/js/controllers/base_controller.js +0 -22
  339. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  340. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  341. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  342. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  343. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  344. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  345. data/app/views/avo/dashboards/show.html.erb +0 -38
  346. data/app/views/avo/partials/_global_search.html.erb +0 -19
  347. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  348. data/lib/avo/app.rb +0 -237
  349. data/lib/avo/base_card.rb +0 -161
  350. data/lib/avo/concerns/fetches_things.rb +0 -150
  351. data/lib/avo/concerns/handles_field_args.rb +0 -47
  352. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  353. data/lib/avo/concerns/has_fields.rb +0 -334
  354. data/lib/avo/concerns/has_html_attributes.rb +0 -108
  355. data/lib/avo/concerns/policy_helpers.rb +0 -31
  356. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  357. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  358. data/lib/avo/dashboards/base_divider.rb +0 -35
  359. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  360. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  361. data/lib/avo/dashboards/metric_card.rb +0 -9
  362. data/lib/avo/dashboards/partial_card.rb +0 -7
  363. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  364. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  365. data/lib/avo/fields/tags_field.rb +0 -102
  366. data/lib/avo/grid_collector.rb +0 -42
  367. data/lib/avo/hosts/association_scope_host.rb +0 -8
  368. data/lib/avo/hosts/base_host.rb +0 -25
  369. data/lib/avo/hosts/card_visibility.rb +0 -20
  370. data/lib/avo/hosts/dashboard_card.rb +0 -22
  371. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  372. data/lib/avo/hosts/ordering.rb +0 -22
  373. data/lib/avo/hosts/record_host.rb +0 -7
  374. data/lib/avo/hosts/resource_record_host.rb +0 -7
  375. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  376. data/lib/avo/hosts/search_scope_host.rb +0 -7
  377. data/lib/avo/hosts/view_record_host.rb +0 -7
  378. data/lib/avo/hosts/visibility_host.rb +0 -12
  379. data/lib/avo/items_holder.rb +0 -96
  380. data/lib/avo/main_panel.rb +0 -3
  381. data/lib/avo/menu/base_item.rb +0 -25
  382. data/lib/avo/menu/builder.rb +0 -82
  383. data/lib/avo/menu/dashboard.rb +0 -22
  384. data/lib/avo/menu/group.rb +0 -2
  385. data/lib/avo/menu/link.rb +0 -6
  386. data/lib/avo/menu/menu.rb +0 -2
  387. data/lib/avo/menu/resource.rb +0 -22
  388. data/lib/avo/menu/section.rb +0 -2
  389. data/lib/avo/panel.rb +0 -24
  390. data/lib/avo/panel_builder.rb +0 -25
  391. data/lib/avo/resources/controls/action.rb +0 -38
  392. data/lib/avo/resources/controls/execution_context.rb +0 -58
  393. data/lib/avo/resources/controls/items_holder.rb +0 -19
  394. data/lib/avo/resources/controls/link_to.rb +0 -27
  395. data/lib/avo/row.rb +0 -26
  396. data/lib/avo/row_builder.rb +0 -24
  397. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  398. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  399. data/lib/avo/sidebar.rb +0 -30
  400. data/lib/avo/sidebar_builder.rb +0 -24
  401. data/lib/avo/tab.rb +0 -72
  402. data/lib/avo/tab_builder.rb +0 -25
  403. data/lib/avo/tab_group.rb +0 -42
  404. data/lib/avo/tab_group_builder.rb +0 -43
  405. data/lib/avo/tools_manager.rb +0 -11
  406. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  407. data/lib/generators/avo/card/metric_generator.rb +0 -18
  408. data/lib/generators/avo/card/partial_generator.rb +0 -19
  409. data/lib/generators/avo/templates/js/avo.custom.js +0 -2
  410. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  411. /data/app/assets/stylesheets/css/{tags.css → fields/tags.css} +0 -0
@@ -4,35 +4,39 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
4
4
  include Avo::ResourcesHelper
5
5
  include Avo::ApplicationHelper
6
6
 
7
+ attr_reader :scopes, :query, :turbo_frame, :parent_record, :parent_resource, :resource, :actions
8
+
7
9
  def initialize(
8
10
  resource: nil,
9
11
  resources: nil,
10
- models: [],
12
+ records: [],
11
13
  pagy: nil,
12
14
  index_params: {},
13
15
  filters: [],
14
16
  actions: [],
15
17
  reflection: nil,
16
18
  turbo_frame: "",
17
- parent_model: nil,
19
+ parent_record: nil,
18
20
  parent_resource: nil,
19
21
  applied_filters: [],
20
- query: nil
22
+ query: nil,
23
+ scopes: nil
21
24
  )
22
25
  @resource = resource
23
26
  @resources = resources
24
- @models = models
27
+ @records = records
25
28
  @pagy = pagy
26
29
  @index_params = index_params
27
30
  @filters = filters
28
31
  @actions = actions
29
32
  @reflection = reflection
30
33
  @turbo_frame = turbo_frame
31
- @parent_model = parent_model
34
+ @parent_record = parent_record
32
35
  @parent_resource = parent_resource
33
36
  @applied_filters = applied_filters
34
- @view = :index
37
+ @view = Avo::ViewInquirer.new("index")
35
38
  @query = query
39
+ @scopes = scopes
36
40
  end
37
41
 
38
42
  def title
@@ -73,8 +77,9 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
73
77
 
74
78
  if @reflection.present?
75
79
  args = {
80
+ via_resource_class: @parent_resource.class,
76
81
  via_relation_class: reflection_model_class,
77
- via_resource_id: @parent_model.to_param
82
+ via_record_id: @parent_record.to_param
78
83
  }
79
84
 
80
85
  if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
@@ -96,7 +101,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
96
101
  def attach_path
97
102
  current_path = CGI.unescape(request.env["PATH_INFO"]).split("/").select(&:present?)
98
103
 
99
- Avo::App.root_path(paths: [*current_path, "new"])
104
+ Avo.root_path(paths: [*current_path, "new"])
100
105
  end
101
106
 
102
107
  def singular_resource_name
@@ -117,12 +122,12 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
117
122
  return
118
123
  end
119
124
 
120
- @resource.resource_description
125
+ @resource.description
121
126
  end
122
127
 
123
128
  def show_search_input
124
129
  return false unless authorized_to_search?
125
- return false unless @resource.search_query.present?
130
+ return false unless resource.class.search_query.present?
126
131
  return false if field&.hide_search_input
127
132
 
128
133
  true
@@ -130,9 +135,40 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
130
135
 
131
136
  def authorized_to_search?
132
137
  # Hide the search if the authorization prevents it
133
- return true unless @resource.authorization.has_action_method?("search")
138
+ return true unless resource.authorization.respond_to?(:has_action_method?)
139
+ return true unless resource.authorization.has_action_method?("search")
140
+
141
+ resource.authorization.authorize_action("search", raise_exception: false)
142
+ end
143
+
144
+ def render_dynamic_filters_button
145
+ return unless Avo.avo_dynamic_filters_installed?
146
+ return unless resource.has_filters?
147
+ return if Avo::DynamicFilters.configuration.always_expanded
148
+
149
+ a_button size: :sm,
150
+ color: :primary,
151
+ icon: "filter",
152
+ data: {
153
+ controller: "avo-filters",
154
+ action: "click->avo-filters#toggleFiltersArea",
155
+ avo_filters_dynamic_filters_component_id_value: dynamic_filters_component_id
156
+ } do
157
+ Avo::DynamicFilters.configuration.button_label
158
+ end
159
+ end
160
+
161
+ def scopes_list
162
+ Avo::Pro::Scopes::ListComponent.new(
163
+ scopes: scopes,
164
+ resource: resource,
165
+ turbo_frame: turbo_frame,
166
+ parent_record: parent_record
167
+ )
168
+ end
134
169
 
135
- @resource.authorization.authorize_action("search", raise_exception: false)
170
+ def can_render_scopes?
171
+ defined?(Avo::Pro)
136
172
  end
137
173
 
138
174
  private
@@ -152,7 +188,34 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
152
188
  association: "has_many",
153
189
  association_id: @reflection.name,
154
190
  class: reflection_model_class,
155
- id: @parent_model.to_param
191
+ id: @parent_record.to_param,
192
+ view: @parent_resource.view
156
193
  }
157
194
  end
195
+
196
+ def header_visible?
197
+ search_query_present? || filters_present? || has_many_view_types? || has_dynamic_filters?
198
+ end
199
+
200
+ def has_dynamic_filters?
201
+ Avo.avo_dynamic_filters_installed? && resource.has_filters?
202
+ end
203
+
204
+ def search_query_present?
205
+ @resource.class.search_query.present?
206
+ end
207
+
208
+ def filters_present?
209
+ @filters.present?
210
+ end
211
+
212
+ def has_many_view_types?
213
+ available_view_types.count > 1
214
+ end
215
+
216
+ # Generate a unique component id for the current component.
217
+ # This is used to identify the component in the DOM.
218
+ def dynamic_filters_component_id
219
+ @dynamic_filters_component_id ||= "dynamic_filters_component_id_#{SecureRandom.hex(3)}"
220
+ end
158
221
  end
@@ -2,186 +2,25 @@
2
2
  data: {
3
3
  model_name: @resource.model_name.to_s,
4
4
  resource_name: @resource.class.to_s,
5
- model_id: @resource.model.id,
5
+ record_id: @resource.record.id,
6
6
  selected_resources_name: @resource.model_key,
7
- selected_resources: [@resource.model.id],
7
+ selected_resources: [@resource.record.to_param],
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
- <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
11
- <% c.with_tools do %>
12
- <% if @resource.has_show_controls? %>
13
- <% @resource.render_show_controls.each do |control| %>
14
- <% if control.back_button? %>
15
- <%= a_link back_path,
16
- style: :text,
17
- title: control.title,
18
- data: {
19
- tippy: control.title ? :tooltip : nil,
20
- },
21
- icon: 'arrow-left' do %>
22
- <%= control.label %>
23
- <% end %>
24
- <% elsif control.delete_button? %>
25
- <% if can_see_the_destroy_button? %>
26
- <%= a_link helpers.resource_path(model: @resource.model, resource: @resource),
27
- style: :text,
28
- color: :red,
29
- icon: 'trash',
30
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
31
- title: control.title,
32
- data: {
33
- turbo_confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
34
- turbo_method: :delete,
35
- control: :destroy,
36
- tippy: control.title ? :tooltip : nil,
37
- 'resource-id': @resource.model.id,
38
- } do %>
39
- <%= control.label %>
40
- <% end %>
41
- <% end %>
42
- <% elsif can_act_on? && control.actions_list? %>
43
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view, exclude: control.exclude, include: control.include, style: control.style, color: control.color, label: control.label %>
44
- <% elsif control.edit_button? %>
45
- <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
46
- <%= a_link edit_path,
47
- color: :primary,
48
- style: :primary,
49
- title: control.title,
50
- data: {
51
- tippy: control.title ? :tooltip : nil,
52
- },
53
- icon: 'edit' do %>
54
- <%= control.label %>
55
- <% end %>
56
- <% end %>
57
- <% elsif control.action? %>
58
- <% if render_action_control?(control.action) %>
59
- <%= a_link control.path,
60
- color: control.color,
61
- style: control.style,
62
- icon: control.icon,
63
- title: control.title,
64
- data: {
65
- tippy: control.title ? :tooltip : nil,
66
- 'turbo-frame': 'actions_show',
67
- 'action': 'click->actions-picker#visitAction',
68
- } do %>
69
- <%= control.label %>
70
- <% end %>
71
- <% end %>
72
- <% elsif control.link_to? %>
73
- <%= a_link control.path,
74
- color: control.color,
75
- style: control.style,
76
- icon: control.icon,
77
- title: control.title,
78
- target: control.target,
79
- class: control.class,
80
- data: {
81
- **control.data,
82
- tippy: control.title ? :tooltip : nil,
83
- } do %>
84
- <%= control.label %>
85
- <% end %>
86
- <% elsif control.detach_button? %>
87
- <% if @reflection.present? && @resource.model.present? && can_detach? %>
88
- <%= a_button url: detach_path,
89
- icon: 'detach',
90
- method: :delete,
91
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
92
- style: :text,
93
- data: {
94
- confirm: "Are you sure you want to detach this #{title}."
95
- } do %>
96
- <%= control.label %>
97
- <% end %>
98
- <% end %>
99
- <% end %>
100
- <% end %>
101
- <% else %>
102
- <% if @reflection.present? && @resource.model.present? %>
103
- <% if can_detach? %>
104
- <%= a_button url: detach_path,
105
- icon: 'detach',
106
- method: :delete,
107
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
108
- style: :text,
109
- data: {
110
- confirm: "Are you sure you want to detach this #{title}."
111
- } do %>
112
- <%= t('avo.detach_item', item: title).humanize %>
113
- <% end %>
114
- <% end %>
115
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
116
- <% if can_see_the_edit_button? %>
117
- <%= a_link edit_path,
118
- color: :primary,
119
- style: :primary,
120
- icon: 'edit' do %>
121
- <%= t('avo.edit').capitalize %>
122
- <% end %>
123
- <% end %>
124
- <% else %>
125
- <%= a_link back_path,
126
- style: :text,
127
- icon: 'arrow-left' do %>
128
- <%= t('avo.go_back') %>
129
- <% end %>
130
- <% if can_see_the_destroy_button? %>
131
- <%= a_link destroy_path,
132
- style: :text,
133
- color: :red,
134
- icon: 'trash',
135
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
136
- data: {
137
- turbo_confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
138
- turbo_method: :delete,
139
- control: :destroy,
140
- 'resource-id': @resource.model.id,
141
- } do %>
142
- <%= t('avo.delete').capitalize %>
143
- <% end %>
144
- <% end %>
145
- <% if can_act_on? %>
146
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
147
- <% end %>
148
- <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
149
- <%= a_link edit_path,
150
- color: :primary,
151
- style: :primary,
152
- icon: 'edit' do %>
153
- <%= t('avo.edit').capitalize %>
154
- <% end %>
155
- <% end %>
156
- <% end %>
157
- <% end %>
158
- <% end %>
159
- <% if main_panel.present? %>
160
- <% c.with_body do %>
161
- <%# the overflow helps with long values %>
162
- <div class="divide-y overflow-auto">
163
- <% main_panel.items.each_with_index do |field, index| %>
164
- <%= render field
165
- .hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: view)
166
- .component_for_view(view)
167
- .new(field: field, resource: @resource, index: index, compact: sidebar.present?)
168
- %>
169
- <% end %>
170
- </div>
171
- <% end %>
172
- <% end %>
173
- <% if sidebar.present? %>
174
- <% c.with_sidebar do %>
175
- <%= render sidebar_component %>
176
- <% end %>
177
- <% end %>
178
- <% end %>
179
- <% if @reflection.blank? %>
180
- <%= content_tag :div, class: 'space-y-12 mt-12' do %>
181
- <% @resource.get_items.each_with_index do |item, index| %>
182
- <% next if item.nil? %>
183
- <%= render Avo::ItemSwitcherComponent.new resource: @resource, reflection: @reflection, item: item, index: index + 1, view: @view %>
184
- <% end %>
10
+ <%= content_tag :div, class: 'space-y-12' do %>
11
+ <%= render_cards_component %>
12
+ <% @resource.get_items.each_with_index do |item, index| %>
13
+ <%= render Avo::Items::SwitcherComponent.new(
14
+ resource: @resource,
15
+ reflection: @reflection,
16
+ item: item,
17
+ index: index + 1,
18
+ view: @view,
19
+ parent_resource: @parent_resource,
20
+ parent_record: @parent_record,
21
+ parent_component: self,
22
+ actions: @actions
23
+ )%>
185
24
  <% end %>
186
25
  <% end %>
187
26
  <% if should_display_invalid_fields_errors? %>
@@ -1,17 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
4
- include Avo::ResourcesHelper
5
4
  include Avo::ApplicationHelper
6
5
 
7
- def initialize(resource: nil, reflection: nil, parent_resource: nil, parent_model: nil, resource_panel: nil, actions: [])
6
+ attr_reader :actions, :display_breadcrumbs
7
+
8
+ def initialize(resource: nil, reflection: nil, parent_resource: nil, parent_record: nil, resource_panel: nil, actions: [])
8
9
  @resource = resource
9
10
  @reflection = reflection
10
11
  @resource_panel = resource_panel
11
12
  @actions = actions
12
- @parent_model = parent_model
13
+ @parent_record = parent_record
13
14
  @parent_resource = parent_resource
14
- @view = :show
15
+ @view = Avo::ViewInquirer.new("show")
16
+ @display_breadcrumbs = reflection.blank?
15
17
  end
16
18
 
17
19
  def title
@@ -26,7 +28,7 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
26
28
 
27
29
  def back_path
28
30
  if via_resource?
29
- helpers.resource_path(model: association_resource.model_class, resource: association_resource, resource_id: params[:via_resource_id])
31
+ helpers.resource_path(record: association_resource.model_class, resource: association_resource, resource_id: params[:via_record_id])
30
32
  else
31
33
  helpers.resources_path(resource: @resource)
32
34
  end
@@ -38,20 +40,24 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
38
40
  if via_resource?
39
41
  args = {
40
42
  via_resource_class: params[:via_resource_class],
41
- via_resource_id: params[:via_resource_id]
43
+ via_record_id: params[:via_record_id]
42
44
  }
43
45
  end
44
46
 
45
- helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
47
+ helpers.edit_resource_path(record: @resource.record, resource: @resource, **args)
48
+ end
49
+
50
+ def controls
51
+ @resource.render_show_controls
46
52
  end
47
53
 
48
- def render_action_control?(action)
49
- can_act_on? && action.visible_in_view(parent_resource: @parent_resource)
54
+ def view_for(field)
55
+ @view
50
56
  end
51
57
 
52
58
  private
53
59
 
54
- # In development and test environments we shoudl show the invalid field errors
60
+ # In development and test environments we should show the invalid field errors
55
61
  def should_display_invalid_fields_errors?
56
62
  (Rails.env.development? || Rails.env.test?) && @resource.invalid_fields.present?
57
63
  end
@@ -4,41 +4,30 @@ module Avo
4
4
  class ActionsController < ApplicationController
5
5
  before_action :set_resource_name
6
6
  before_action :set_resource
7
- before_action :set_model, only: :show, if: ->(request) do
8
- # Try to se the model only if the user is on the record page.
9
- # set_model will fail if it's tried to be used from the Index page.
7
+ before_action :set_record, only: :show, if: ->(request) do
8
+ # Try to se the record only if the user is on the record page.
9
+ # set_record will fail if it's tried to be used from the Index page.
10
10
  request.params[:id].present?
11
11
  end
12
12
  before_action :set_action, only: [:show, :handle]
13
+ before_action :verify_authorization, only: [:show, :handle]
13
14
 
14
15
  def show
15
16
  # Se the view to :new so the default value gets prefilled
16
- @view = :new
17
+ @view = Avo::ViewInquirer.new("new")
17
18
 
18
- @resource.hydrate(model: @model, view: @view, user: _current_user, params: params)
19
+ @resource.hydrate(record: @record, view: @view, user: _current_user, params: params)
19
20
  end
20
21
 
21
22
  def handle
22
23
  resource_ids = action_params[:fields][:avo_resource_ids].split(",")
23
- @selected_query = action_params[:fields][:avo_selected_query]
24
24
 
25
- fields = action_params[:fields].except(:avo_resource_ids, :avo_selected_query)
26
-
27
- args = {
28
- fields: fields,
25
+ performed_action = @action.handle_action(
26
+ fields: action_params[:fields].except(:avo_resource_ids, :avo_selected_query),
29
27
  current_user: _current_user,
30
- resource: resource
31
- }
32
-
33
- unless @action.standalone
34
- args[:models] = if @selected_query.present?
35
- @resource.model_class.find_by_sql decrypted_query
36
- else
37
- @resource.find_record resource_ids, params: params
38
- end
39
- end
40
-
41
- performed_action = @action.handle_action(**args)
28
+ resource: resource,
29
+ query: decrypted_query || @resource.find_record(resource_ids, params: params)
30
+ )
42
31
 
43
32
  respond performed_action.response
44
33
  end
@@ -51,19 +40,17 @@ module Avo
51
40
 
52
41
  def set_action
53
42
  @action = action_class.new(
54
- model: @model,
43
+ record: @record,
55
44
  resource: @resource,
56
45
  user: _current_user,
57
46
  view: :new, # force the action view to in order to render new-related fields (hidden field)
58
- arguments: @resource.get_action_arguments(action_class)
47
+ arguments: decrypted_arguments || {}
59
48
  )
60
49
  end
61
50
 
62
51
  def action_class
63
- klass_name = params[:action_id].gsub("avo_actions_", "").camelize
64
-
65
52
  Avo::BaseAction.descendants.find do |action|
66
- action.to_s == klass_name
53
+ action.to_s == params[:action_id]
67
54
  end
68
55
  end
69
56
 
@@ -96,8 +83,6 @@ module Avo
96
83
  end
97
84
  end
98
85
 
99
- private
100
-
101
86
  def get_messages(response)
102
87
  default_message = {
103
88
  type: :info,
@@ -113,9 +98,18 @@ module Avo
113
98
  end
114
99
 
115
100
  def decrypted_query
101
+ return if (encrypted_query = action_params[:fields][:avo_selected_query]).blank?
102
+
103
+ Avo::Services::EncryptionService.decrypt(message: encrypted_query, purpose: :select_all, serializer: Marshal)
104
+ end
105
+
106
+ def decrypted_arguments
107
+ arguments = params[:arguments] || params.dig(:fields, :arguments)
108
+ return if arguments.blank?
109
+
116
110
  Avo::Services::EncryptionService.decrypt(
117
- message: @selected_query,
118
- purpose: :select_all
111
+ message: Base64.decode64(arguments),
112
+ purpose: :action_arguments
119
113
  )
120
114
  end
121
115
 
@@ -134,5 +128,9 @@ module Avo
134
128
  end
135
129
  end
136
130
  end
131
+
132
+ def verify_authorization
133
+ raise Avo::NotAuthorizedError.new unless @action.authorized?
134
+ end
137
135
  end
138
136
  end