avo 2.46.0 → 3.0.2

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

Potentially problematic release.


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

Files changed (409) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +28 -26
  3. data/Gemfile.lock +231 -161
  4. data/README.md +19 -27
  5. data/Rakefile +2 -0
  6. data/app/assets/stylesheets/avo.base.css +1 -1
  7. data/app/assets/svgs/font.svg +1 -0
  8. data/app/assets/svgs/triangle-up.svg +1 -0
  9. data/app/components/avo/actions_component.html.erb +19 -5
  10. data/app/components/avo/actions_component.rb +39 -19
  11. data/app/components/avo/asset_manager/javascript_component.html.erb +3 -0
  12. data/app/components/avo/asset_manager/javascript_component.rb +13 -0
  13. data/app/components/avo/asset_manager/stylesheet_component.html.erb +3 -0
  14. data/app/components/avo/asset_manager/stylesheet_component.rb +13 -0
  15. data/app/components/avo/base_component.rb +15 -12
  16. data/app/components/avo/button_component.rb +20 -3
  17. data/app/components/avo/empty_state_component.rb +1 -1
  18. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  19. data/app/components/avo/field_wrapper_component.rb +12 -29
  20. data/app/components/avo/fields/area_field/edit_component.html.erb +2 -2
  21. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +75 -79
  22. data/app/components/avo/fields/belongs_to_field/edit_component.rb +7 -7
  23. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  24. data/app/components/avo/fields/belongs_to_field/show_component.rb +2 -2
  25. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  26. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  27. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +3 -3
  28. data/app/components/avo/fields/common/badge_viewer_component.rb +1 -1
  29. data/app/components/avo/fields/common/boolean_check_component.html.erb +1 -12
  30. data/app/components/avo/fields/common/boolean_check_component.rb +2 -1
  31. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  32. data/app/components/avo/fields/common/files/view_type/grid_item_component.rb +2 -2
  33. data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
  34. data/app/components/avo/fields/common/gravatar_viewer_component.rb +2 -2
  35. data/app/components/avo/fields/common/heading_component.html.erb +3 -8
  36. data/app/components/avo/fields/common/heading_component.rb +1 -3
  37. data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
  38. data/app/components/avo/fields/common/key_value_component.rb +2 -2
  39. data/app/components/avo/fields/common/progress_bar_component.rb +3 -9
  40. data/app/components/avo/fields/common/status_viewer_component.html.erb +3 -0
  41. data/app/components/avo/fields/edit_component.rb +2 -2
  42. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
  43. data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
  44. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  45. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  46. data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -2
  47. data/app/components/avo/fields/has_one_field/show_component.rb +2 -2
  48. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  49. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  50. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  51. data/app/components/avo/fields/index_component.rb +6 -6
  52. data/app/components/avo/fields/location_field/edit_component.html.erb +12 -10
  53. data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
  54. data/app/components/avo/fields/preview_field/index_component.rb +4 -0
  55. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  56. data/app/components/avo/fields/show_component.rb +5 -2
  57. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  58. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
  59. data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
  60. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  61. data/app/components/avo/filters_component.html.erb +9 -3
  62. data/app/components/avo/filters_component.rb +4 -4
  63. data/app/components/avo/index/field_wrapper_component.rb +1 -13
  64. data/app/components/avo/index/grid_item_component.html.erb +13 -36
  65. data/app/components/avo/index/grid_item_component.rb +43 -16
  66. data/app/components/avo/index/resource_controls_component.html.erb +3 -81
  67. data/app/components/avo/index/resource_controls_component.rb +125 -18
  68. data/app/components/avo/index/resource_grid_component.html.erb +5 -3
  69. data/app/components/avo/index/resource_grid_component.rb +5 -2
  70. data/app/components/avo/index/resource_map_component.html.erb +1 -1
  71. data/app/components/avo/index/resource_map_component.rb +3 -3
  72. data/app/components/avo/index/resource_table_component.html.erb +3 -2
  73. data/app/components/avo/index/resource_table_component.rb +8 -7
  74. data/app/components/avo/index/table_row_component.html.erb +9 -5
  75. data/app/components/avo/index/table_row_component.rb +3 -2
  76. data/app/components/avo/items/panel_component.html.erb +25 -0
  77. data/app/components/avo/items/panel_component.rb +43 -0
  78. data/app/components/avo/items/switcher_component.html.erb +17 -0
  79. data/app/components/avo/items/switcher_component.rb +79 -0
  80. data/app/components/avo/items/visible_items_component.html.erb +10 -0
  81. data/app/components/avo/items/visible_items_component.rb +11 -0
  82. data/app/components/avo/modal_component.html.erb +3 -4
  83. data/app/components/avo/paginator_component.html.erb +1 -1
  84. data/app/components/avo/paginator_component.rb +6 -6
  85. data/app/components/avo/panel_component.html.erb +7 -5
  86. data/app/components/avo/referrer_params_component.html.erb +1 -1
  87. data/app/components/avo/resource_component.rb +205 -26
  88. data/app/components/avo/resource_sidebar_component.html.erb +15 -18
  89. data/app/components/avo/resource_sidebar_component.rb +5 -3
  90. data/app/components/avo/sidebar/link_component.rb +1 -1
  91. data/app/components/avo/sidebar_component.html.erb +10 -3
  92. data/app/components/avo/sidebar_component.rb +5 -3
  93. data/app/components/avo/sidebar_profile_component.html.erb +18 -12
  94. data/app/components/avo/tab_group_component.html.erb +14 -8
  95. data/app/components/avo/tab_group_component.rb +1 -6
  96. data/app/components/avo/tab_switcher_component.html.erb +17 -40
  97. data/app/components/avo/tab_switcher_component.rb +6 -41
  98. data/app/components/avo/views/resource_edit_component.html.erb +23 -86
  99. data/app/components/avo/views/resource_edit_component.rb +20 -19
  100. data/app/components/avo/views/resource_index_component.html.erb +42 -47
  101. data/app/components/avo/views/resource_index_component.rb +76 -13
  102. data/app/components/avo/views/resource_show_component.html.erb +16 -177
  103. data/app/components/avo/views/resource_show_component.rb +16 -10
  104. data/app/controllers/avo/actions_controller.rb +29 -31
  105. data/app/controllers/avo/application_controller.rb +119 -180
  106. data/app/controllers/avo/associations_controller.rb +34 -43
  107. data/app/controllers/avo/attachments_controller.rb +4 -4
  108. data/app/controllers/avo/base_controller.rb +139 -91
  109. data/app/controllers/avo/debug_controller.rb +17 -5
  110. data/app/controllers/avo/home_controller.rb +1 -1
  111. data/app/controllers/avo/search_controller.rb +56 -50
  112. data/app/controllers/concerns/avo/initializes_avo.rb +22 -0
  113. data/app/helpers/avo/application_helper.rb +18 -8
  114. data/app/helpers/avo/resources_helper.rb +1 -1
  115. data/app/helpers/avo/url_helpers.rb +28 -12
  116. data/app/javascript/avo.base.js +1 -0
  117. data/app/javascript/js/controllers/action_controller.js +5 -3
  118. data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
  119. data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +7 -7
  120. data/app/javascript/js/controllers/filter_controller.js +1 -1
  121. data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
  122. data/app/javascript/js/controllers/preview_controller.js +24 -0
  123. data/app/javascript/js/controllers/search_controller.js +4 -2
  124. data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
  125. data/app/javascript/js/controllers/toggle_controller.js +48 -0
  126. data/app/javascript/js/controllers.js +11 -5
  127. data/app/javascript/js/custom-stream-actions.js +15 -0
  128. data/app/views/avo/actions/show.html.erb +10 -6
  129. data/app/views/avo/associations/new.html.erb +2 -2
  130. data/app/views/avo/base/_new_via_belongs_to.html.erb +1 -1
  131. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +3 -3
  132. data/app/views/avo/base/create_fail_action.turbo_stream.erb +2 -2
  133. data/app/views/avo/base/edit.html.erb +1 -1
  134. data/app/views/avo/base/index.html.erb +4 -3
  135. data/app/views/avo/base/new.html.erb +2 -1
  136. data/app/views/avo/base/preview.html.erb +19 -0
  137. data/app/views/avo/base/show.html.erb +2 -2
  138. data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
  139. data/app/views/avo/debug/report.html.erb +32 -17
  140. data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
  141. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  142. data/app/views/avo/partials/_footer.html.erb +1 -1
  143. data/app/views/avo/partials/_javascript.html.erb +5 -0
  144. data/app/views/avo/partials/_logo.html.erb +1 -1
  145. data/app/views/avo/partials/_navbar.html.erb +3 -5
  146. data/app/views/avo/partials/_resource_search.html.erb +1 -0
  147. data/app/views/avo/partials/_table_header.html.erb +5 -11
  148. data/app/views/layouts/avo/application.html.erb +5 -4
  149. data/avo.gemspec +10 -8
  150. data/bin/dev +3 -1
  151. data/bin/prod +0 -0
  152. data/config/master.key +1 -0
  153. data/config/routes.rb +7 -10
  154. data/db/factories.rb +6 -0
  155. data/lib/avo/asset_manager.rb +30 -0
  156. data/lib/avo/base_action.rb +82 -67
  157. data/lib/avo/base_resource.rb +286 -226
  158. data/lib/avo/base_resource_tool.rb +9 -16
  159. data/lib/avo/concerns/borrow_items_holder.rb +35 -0
  160. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  161. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  162. data/lib/avo/concerns/filters_session_handler.rb +7 -5
  163. data/lib/avo/concerns/has_controls.rb +37 -0
  164. data/lib/avo/concerns/has_description.rb +23 -0
  165. data/lib/avo/concerns/has_helpers.rb +18 -0
  166. data/lib/avo/concerns/has_item_type.rb +42 -0
  167. data/lib/avo/concerns/has_items.rb +339 -0
  168. data/lib/avo/concerns/{has_resource_stimulus_controllers.rb → has_stimulus_controllers.rb} +1 -1
  169. data/lib/avo/concerns/hydration.rb +17 -0
  170. data/lib/avo/concerns/is_resource_item.rb +16 -36
  171. data/lib/avo/concerns/is_visible.rb +15 -0
  172. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  173. data/lib/avo/concerns/visible_in_different_views.rb +132 -0
  174. data/lib/avo/concerns/visible_items.rb +7 -38
  175. data/lib/avo/configuration/branding.rb +0 -12
  176. data/lib/avo/configuration.rb +28 -11
  177. data/lib/avo/current.rb +39 -0
  178. data/lib/avo/dsl/field_parser.rb +3 -3
  179. data/lib/avo/dynamic_router.rb +18 -3
  180. data/lib/avo/engine.rb +35 -30
  181. data/lib/avo/error_manager.rb +25 -0
  182. data/lib/avo/execution_context.rb +14 -15
  183. data/lib/avo/fields/base_field.rb +84 -122
  184. data/lib/avo/fields/belongs_to_field.rb +19 -23
  185. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  186. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  187. data/lib/avo/fields/concerns/has_default.rb +1 -5
  188. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  189. data/lib/avo/fields/concerns/has_html_attributes.rb +112 -0
  190. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  191. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  192. data/lib/avo/fields/concerns/is_required.rb +5 -7
  193. data/lib/avo/fields/concerns/is_searchable.rb +15 -0
  194. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  195. data/lib/avo/fields/concerns/use_view_components.rb +45 -0
  196. data/lib/avo/fields/country_field.rb +4 -0
  197. data/lib/avo/fields/date_time_field.rb +1 -5
  198. data/lib/avo/fields/external_image_field.rb +2 -2
  199. data/lib/avo/fields/field_manager.rb +55 -0
  200. data/lib/avo/fields/file_field.rb +2 -2
  201. data/lib/avo/fields/gravatar_field.rb +2 -2
  202. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  203. data/lib/avo/fields/has_base_field.rb +21 -17
  204. data/lib/avo/fields/has_many_field.rb +5 -2
  205. data/lib/avo/fields/has_one_field.rb +8 -12
  206. data/lib/avo/fields/heading_field.rb +9 -14
  207. data/lib/avo/fields/hidden_field.rb +1 -1
  208. data/lib/avo/fields/id_field.rb +3 -3
  209. data/lib/avo/fields/location_field.rb +10 -10
  210. data/lib/avo/fields/password_field.rb +1 -1
  211. data/lib/avo/fields/preview_field.rb +14 -0
  212. data/lib/avo/fields/select_field.rb +12 -8
  213. data/lib/avo/fields/status_field.rb +7 -1
  214. data/lib/avo/fields/text_field.rb +2 -2
  215. data/lib/avo/filters/base_filter.rb +9 -4
  216. data/lib/avo/html/builder.rb +8 -8
  217. data/lib/avo/item_grapher.rb +78 -0
  218. data/lib/avo/licensing/h_q.rb +11 -73
  219. data/lib/avo/licensing/license.rb +5 -1
  220. data/lib/avo/licensing/license_manager.rb +1 -1
  221. data/lib/avo/licensing/pro_license.rb +1 -7
  222. data/lib/avo/loaders/fields_loader.rb +7 -1
  223. data/lib/avo/plugin.rb +36 -0
  224. data/lib/avo/plugin_manager.rb +56 -0
  225. data/lib/avo/prefixed_test_helpers.rb +20 -0
  226. data/lib/avo/reloader.rb +3 -0
  227. data/lib/avo/resources/controls/actions_list.rb +7 -12
  228. data/lib/avo/resources/controls/attach_button.rb +15 -0
  229. data/lib/avo/resources/controls/back_button.rb +1 -1
  230. data/lib/avo/resources/controls/base_control.rb +15 -49
  231. data/lib/avo/resources/controls/create_button.rb +15 -0
  232. data/lib/avo/resources/controls/delete_button.rb +5 -1
  233. data/lib/avo/resources/controls/detach_button.rb +4 -1
  234. data/lib/avo/resources/controls/edit_button.rb +4 -1
  235. data/lib/avo/resources/controls/order_controls.rb +8 -0
  236. data/lib/avo/resources/controls/save_button.rb +13 -0
  237. data/lib/avo/resources/controls/show_button.rb +15 -0
  238. data/lib/avo/resources/items/holder.rb +96 -0
  239. data/lib/avo/resources/items/item_group.rb +44 -0
  240. data/lib/avo/resources/items/main_panel.rb +12 -0
  241. data/lib/avo/resources/items/panel.rb +2 -0
  242. data/lib/avo/resources/items/row.rb +42 -0
  243. data/lib/avo/resources/items/sidebar.rb +46 -0
  244. data/lib/avo/resources/items/tab.rb +54 -0
  245. data/lib/avo/resources/items/tab_group.rb +62 -0
  246. data/lib/avo/resources/resource_manager.rb +179 -0
  247. data/lib/avo/services/authorization_service.rb +11 -110
  248. data/lib/avo/services/debug_service.rb +93 -0
  249. data/lib/avo/services/encryption_service.rb +8 -12
  250. data/lib/avo/services/telemetry_service.rb +85 -0
  251. data/lib/avo/test_helpers.rb +362 -0
  252. data/lib/avo/tools/tool_manager.rb +30 -0
  253. data/lib/avo/version.rb +1 -1
  254. data/lib/avo/view_inquirer.rb +36 -0
  255. data/lib/avo.rb +109 -24
  256. data/lib/generators/avo/action_generator.rb +8 -8
  257. data/lib/generators/avo/card_generator.rb +27 -0
  258. data/lib/generators/avo/concerns/parent_controller.rb +20 -0
  259. data/lib/generators/avo/controller_generator.rb +3 -0
  260. data/lib/generators/avo/eject_generator.rb +180 -15
  261. data/lib/generators/avo/field_generator.rb +49 -2
  262. data/lib/generators/avo/filter_generator.rb +8 -8
  263. data/lib/generators/avo/js/install_generator.rb +2 -2
  264. data/lib/generators/avo/resource_generator.rb +12 -9
  265. data/lib/generators/avo/scope_generator.rb +15 -0
  266. data/lib/generators/avo/tailwindcss/install_generator.rb +70 -26
  267. data/lib/generators/avo/templates/action.tt +8 -6
  268. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  269. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  270. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  271. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  272. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  273. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  274. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  275. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  276. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  277. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  278. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  279. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  280. data/lib/generators/avo/templates/initializer/avo.tt +7 -3
  281. data/lib/generators/avo/templates/locales/avo.ar.yml +1 -0
  282. data/lib/generators/avo/templates/locales/avo.en.yml +4 -3
  283. data/lib/generators/avo/templates/locales/avo.es.yml +1 -0
  284. data/lib/generators/avo/templates/locales/avo.fr.yml +1 -0
  285. data/lib/generators/avo/templates/locales/avo.nb.yml +1 -0
  286. data/lib/generators/avo/templates/locales/avo.nn.yml +1 -0
  287. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -0
  288. data/lib/generators/avo/templates/locales/avo.pt.yml +1 -0
  289. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -5
  290. data/lib/generators/avo/templates/locales/avo.tr.yml +1 -0
  291. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  292. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  293. data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
  294. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  295. data/lib/generators/avo/templates/scope.tt +6 -0
  296. data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
  297. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
  298. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
  299. data/lib/tasks/avo_tasks.rake +72 -4
  300. data/public/avo-assets/avo.base.css +1893 -1187
  301. data/public/avo-assets/avo.base.js +217 -305
  302. data/public/avo-assets/avo.base.js.map +3 -3
  303. data/public/avo-assets/avo.css +9744 -0
  304. data/public/avo-assets/avo.js +513 -0
  305. data/public/avo-assets/avo.js.map +7 -0
  306. data/tailwind.custom.js +47 -0
  307. data/tailwind.preset.js +152 -0
  308. metadata +106 -116
  309. data/app/components/avo/card_component.html.erb +0 -46
  310. data/app/components/avo/card_component.rb +0 -25
  311. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  312. data/app/components/avo/dashboards/divider_component.rb +0 -19
  313. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  314. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  315. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  316. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  317. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  318. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  319. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  320. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  321. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  322. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  323. data/app/components/avo/index/ordering/base_component.rb +0 -9
  324. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  325. data/app/components/avo/index/ordering/button_component.rb +0 -23
  326. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  327. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  328. data/app/components/avo/item_switcher_component.html.erb +0 -27
  329. data/app/components/avo/item_switcher_component.rb +0 -48
  330. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  331. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  332. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  333. data/app/controllers/avo/dashboards_controller.rb +0 -22
  334. data/app/controllers/avo/reorder_controller.rb +0 -25
  335. data/app/javascript/js/controllers/base_controller.js +0 -22
  336. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  337. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  338. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  339. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  340. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  341. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  342. data/app/views/avo/dashboards/show.html.erb +0 -38
  343. data/app/views/avo/partials/_global_search.html.erb +0 -19
  344. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  345. data/lib/avo/app.rb +0 -237
  346. data/lib/avo/base_card.rb +0 -161
  347. data/lib/avo/concerns/fetches_things.rb +0 -150
  348. data/lib/avo/concerns/handles_field_args.rb +0 -47
  349. data/lib/avo/concerns/has_action_stimulus_controllers.rb +0 -15
  350. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  351. data/lib/avo/concerns/has_fields.rb +0 -334
  352. data/lib/avo/concerns/has_html_attributes.rb +0 -123
  353. data/lib/avo/concerns/policy_helpers.rb +0 -31
  354. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  355. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  356. data/lib/avo/dashboards/base_divider.rb +0 -35
  357. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  358. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  359. data/lib/avo/dashboards/metric_card.rb +0 -9
  360. data/lib/avo/dashboards/partial_card.rb +0 -7
  361. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  362. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  363. data/lib/avo/fields/tags_field.rb +0 -102
  364. data/lib/avo/grid_collector.rb +0 -42
  365. data/lib/avo/hosts/association_scope_host.rb +0 -8
  366. data/lib/avo/hosts/base_host.rb +0 -25
  367. data/lib/avo/hosts/card_visibility.rb +0 -20
  368. data/lib/avo/hosts/dashboard_card.rb +0 -22
  369. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  370. data/lib/avo/hosts/ordering.rb +0 -22
  371. data/lib/avo/hosts/record_host.rb +0 -7
  372. data/lib/avo/hosts/resource_record_host.rb +0 -7
  373. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  374. data/lib/avo/hosts/search_scope_host.rb +0 -7
  375. data/lib/avo/hosts/view_record_host.rb +0 -7
  376. data/lib/avo/hosts/visibility_host.rb +0 -12
  377. data/lib/avo/items_holder.rb +0 -96
  378. data/lib/avo/main_panel.rb +0 -3
  379. data/lib/avo/menu/base_item.rb +0 -25
  380. data/lib/avo/menu/builder.rb +0 -82
  381. data/lib/avo/menu/dashboard.rb +0 -22
  382. data/lib/avo/menu/group.rb +0 -2
  383. data/lib/avo/menu/link.rb +0 -6
  384. data/lib/avo/menu/menu.rb +0 -2
  385. data/lib/avo/menu/resource.rb +0 -22
  386. data/lib/avo/menu/section.rb +0 -2
  387. data/lib/avo/panel.rb +0 -24
  388. data/lib/avo/panel_builder.rb +0 -25
  389. data/lib/avo/resources/controls/action.rb +0 -38
  390. data/lib/avo/resources/controls/execution_context.rb +0 -58
  391. data/lib/avo/resources/controls/items_holder.rb +0 -19
  392. data/lib/avo/resources/controls/link_to.rb +0 -27
  393. data/lib/avo/row.rb +0 -26
  394. data/lib/avo/row_builder.rb +0 -24
  395. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  396. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  397. data/lib/avo/sidebar.rb +0 -30
  398. data/lib/avo/sidebar_builder.rb +0 -24
  399. data/lib/avo/tab.rb +0 -72
  400. data/lib/avo/tab_builder.rb +0 -25
  401. data/lib/avo/tab_group.rb +0 -42
  402. data/lib/avo/tab_group_builder.rb +0 -43
  403. data/lib/avo/tools_manager.rb +0 -11
  404. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  405. data/lib/generators/avo/card/metric_generator.rb +0 -18
  406. data/lib/generators/avo/card/partial_generator.rb +0 -19
  407. data/lib/generators/avo/templates/js/avo.custom.js +0 -2
  408. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  409. /data/app/assets/stylesheets/css/{tags.css → fields/tags.css} +0 -0
@@ -0,0 +1,362 @@
1
+ module Avo
2
+ module TestHelpers
3
+ # Finds the wrapper element on the index view for the given field id and type, and associated with the given record id
4
+ # Example usage:
5
+ # index_field_wrapper(id: "name", type: "text", record_id: 2)
6
+ # index_field_wrapper(id: "name", record_id: 2)
7
+ def index_field_wrapper(id:, record_id:, type: nil)
8
+ base_data = "#{row(record_id)} [data-field-id='#{id}']"
9
+
10
+ if type.present?
11
+ find("#{base_data}[data-resource-index-target='#{wrapper_name_for(id: id, type: type)}']")
12
+ else
13
+ find(base_data)
14
+ end
15
+ end
16
+
17
+ # Finds the wrapper element on the index grid view type for the given record id
18
+ # Example usage:
19
+ # grid_field_wrapper(record_id: 5)
20
+ def grid_field_wrapper(record_id:)
21
+ find("[data-component-name='avo/index/grid_item_component'][data-resource-id='#{record_id}']")
22
+ end
23
+
24
+ # Finds the wrapper element on the show view for the given field id and type
25
+ # Example usage:
26
+ # show_field_wrapper(id: "name", type: "text")
27
+ # show_field_wrapper(id: "name")
28
+ def show_field_wrapper(id:, type: nil)
29
+ base_data = "[data-panel-id='main'] [data-field-id='#{id}']"
30
+
31
+ if type.present?
32
+ find("#{base_data}[data-resource-show-target='#{wrapper_name_for(id: id, type: type)}']")
33
+ else
34
+ find(base_data)
35
+ end
36
+ end
37
+
38
+ # Finds the table on the show view for the given has_many field id and view
39
+ # Example usage:
40
+ # has_many_field_wrapper(id: :users)
41
+ # has_many_field_wrapper(id: :users, view: :edit)
42
+ def has_many_field_wrapper(id:, view: :show)
43
+ related_field_context(id: id, relation: :has_many, view: view)
44
+ end
45
+
46
+ # Finds the table on the show view for the given has_and_belongs_to_many field id and view
47
+ # Example usage:
48
+ # has_and_belongs_to_many_field_wrapper(id: :users)
49
+ # has_and_belongs_to_many_field_wrapper(id: :users, view: :edit)
50
+ def has_and_belongs_to_many_field_wrapper(id:, view: :show)
51
+ related_field_context(id: id, relation: :has_and_belongs_to_many, view: view)
52
+ end
53
+
54
+ # Finds the table on the show view for the given has_one field id and view
55
+ # Example usage:
56
+ # has_one_field_wrapper(id: :users)
57
+ # has_one_field_wrapper(id: :users, view: :edit)
58
+ def has_one_field_wrapper(id:, view: :show)
59
+ related_field_context(id: id, relation: :has_one, view: view)
60
+ end
61
+
62
+ # Finds the label element on the index view for the given field id
63
+ # Example usage:
64
+ # index_field_label(id: "name")
65
+ def index_field_label(id:)
66
+ find("[data-component-name='avo/partials/table_header'] [data-table-header-field-id='#{id}']").text
67
+ end
68
+
69
+ # Finds the label element on the show view for the given field id
70
+ # Example usage:
71
+ # show_field_label(id: "name")
72
+ def show_field_label(id:)
73
+ within(show_field_wrapper(id: id)) { find("[data-slot='label']").text }
74
+ end
75
+
76
+ # Finds the value element on the index view for the given field id
77
+ # Example usage:
78
+ # index_field_value(id: "name", record_id: 2)
79
+ def index_field_value(id:, record_id:, type: nil)
80
+ index_field_wrapper(id: id, record_id: record_id, type: type).text
81
+ end
82
+
83
+ # Finds the value element on the show view for the given field id
84
+ # Example usage:
85
+ # show_field_value(id: "name")
86
+ def show_field_value(id:, type: nil)
87
+ within(show_field_wrapper(id: id, type: type)) { find("[data-slot='value']").text }
88
+ end
89
+
90
+ def empty_dash
91
+ "—"
92
+ end
93
+
94
+ def confirm_alert
95
+ Capybara.using_wait_time(1) do
96
+ page.driver.browser.switch_to.alert.accept
97
+ rescue Selenium::WebDriver::Error::NoSuchAlertError
98
+ retry
99
+ end
100
+ end
101
+
102
+ # Example usage:
103
+ # click_resource_search_input # opens the first search box on the given page
104
+ # opens the search box for the "users" resource
105
+ # within(has_and_belongs_to_many_field_wrapper(id: :users)) {
106
+ # click_resource_search_input
107
+ # write_in_search("Bob")
108
+ # }
109
+ def click_resource_search_input
110
+ first("[data-search-resource]:not([data-search-resource='global'])").click
111
+ wait_for_search_loaded
112
+ end
113
+
114
+ def click_global_search_input
115
+ page.find(:xpath, "//*[contains(@class, 'global-search')]").click
116
+ wait_for_search_loaded
117
+ end
118
+
119
+ # Should use the click_global_search_input or click_resource_search_input method to open the search box first.
120
+ # Example usage:
121
+ # open_search_box(:users)
122
+ # within(has_and_belongs_to_many_field_wrapper(id: :users)) {
123
+ # click_resource_search_input # opens the search box for the "users" resource
124
+ # write_in_search("Bob")
125
+ # }
126
+ def write_in_search(input)
127
+ # Use xpath to find outside of within context if any
128
+ find(:xpath, "//input[@class='aa-Input']").set(input)
129
+ wait_for_search_loaded
130
+ end
131
+
132
+ # Should use the click_global_search_input or click_resource_search_input method to open the search box first and optionaly write_in_search.
133
+ # Example usage:
134
+ # open_search_box(:users) # opens the search box for the "users" resource
135
+ # write_in_search("John Doe")
136
+ # select_first_result_in_search
137
+ def select_first_result_in_search
138
+ find(".aa-Input").send_keys :arrow_down
139
+ find(".aa-Input").send_keys :enter
140
+ wait_for_search_loaded
141
+ end
142
+
143
+ # Save a record and wait for the page to load
144
+ def save
145
+ click_on "Save"
146
+ wait_for_loaded
147
+ end
148
+
149
+ def click_tab(tab_name = "", within_target: nil, **args)
150
+ if within_target.present?
151
+ within within_target do
152
+ within find('[data-controller="tabs"] turbo-frame:not(.hidden) [data-target="tab-switcher"]') do
153
+ find_link(tab_name).click
154
+ end
155
+ end
156
+ else
157
+ within find('[data-controller="tabs"] turbo-frame:not(.hidden) [data-target="tab-switcher"]') do
158
+ find_link(tab_name).click
159
+ end
160
+ end
161
+ end
162
+
163
+ def tab_group(index = 0)
164
+ find_all('[data-controller="tabs"]')[index]
165
+ end
166
+
167
+ def first_tab_group
168
+ tab_group 0
169
+ end
170
+
171
+ def second_tab_group
172
+ tab_group 1
173
+ end
174
+
175
+ def third_tab_group
176
+ tab_group 3
177
+ end
178
+
179
+ def click_on_sidebar_item(label)
180
+ within main_sidebar do
181
+ click_on label
182
+ end
183
+ end
184
+
185
+ def set_picker_day(date)
186
+ find(".flatpickr-day[aria-label=\"#{date}\"]").click
187
+ sleep 0.2
188
+ end
189
+
190
+ def set_picker_hour(value)
191
+ find(".flatpickr-hour").set(value)
192
+ end
193
+
194
+ def set_picker_minute(value)
195
+ find(".flatpickr-minute").set(value)
196
+ end
197
+
198
+ def set_picker_second(value)
199
+ find(".flatpickr-second").set(value)
200
+ end
201
+
202
+ def open_picker
203
+ text_input.click
204
+ end
205
+
206
+ def close_picker
207
+ find('[data-target="title"]').click
208
+ sleep 0.3
209
+ end
210
+
211
+ # Click on the action from the panel (index and show above the table)
212
+ # Pass list: nil to run an action outside of the list
213
+ # Pass list: "List name" if list is not the default "Actions"
214
+ # Example usage:
215
+ # open_panel_action(action_name: "Dummy action")
216
+ # open_panel_action(list: nil, action_name: "Release fish")
217
+ # open_panel_action(list: "Runnables", action_name: "Release fish")
218
+ def open_panel_action(action_name:, list: "Actions")
219
+ open_action(action_name: action_name, list: list, context: first("[data-target='panel-tools']"))
220
+ end
221
+
222
+ # Open the action from the record_id row
223
+ # Pass list: nil to run an action outside of the list
224
+ # Pass list: "List name" if list is not the default "Actions"
225
+ # Example usage:
226
+ # open_row_action(action_name: "Dummy action")
227
+ # open_row_action(list: nil, action_name: "Release fish")
228
+ # open_row_action(list: "Runnables", action_name: "Release fish")
229
+ def open_row_action(record_id:, action_name:, list: "Actions")
230
+ open_action(action_name: action_name, list: list, context: row(record_id))
231
+ end
232
+
233
+ # Click on submit action button if dialog is open
234
+ def run_action
235
+ within(find("[role='dialog']")) do
236
+ find("[data-target='submit_action']").click
237
+ end
238
+
239
+ wait_for_action_dialog_to_disappear
240
+ end
241
+
242
+ def check_select_all
243
+ find("input[type='checkbox'][name='Select all'][data-action='input->item-select-all#toggle']").set(true)
244
+ end
245
+
246
+ def toggle_collapsable(section)
247
+ find("[data-action='click->menu#triggerCollapse'][data-menu-key-param*='main_menu.#{section.underscore}'] svg").click
248
+ end
249
+
250
+ # Example usage:
251
+ # expect(add_tag(field: :tags, tag: "one")).to eq ["one"]
252
+ # add_tag(field: :tags, tag: "two")
253
+ def add_tag(field:, tag:)
254
+ # Find the input field for the specified field
255
+ input = find("[data-field-id='#{field}'] [data-slot='value'] [role='textbox']")
256
+
257
+ # Enter the specified tag into the input field
258
+ input.set(tag)
259
+ sleep 0.1
260
+
261
+ input.send_keys :return
262
+ wait_for_tag_to_appear(tag)
263
+
264
+ # Return an array of the current tags
265
+ tags(field: field)
266
+ end
267
+
268
+ # Example usage:
269
+ # expect(remove_tag(field: :tags, tag: "one")).to eq ["three"]
270
+ # remove_tag(field: :tags, tag: "one")
271
+ def remove_tag(field:, tag:)
272
+ # Within the specified field
273
+ within("[data-field-id='#{field}'] [data-slot='value']") do
274
+ # Find the tag with the specified text and click the remove button for the tag
275
+ page.find(".tagify__tag", text: tag).find(".tagify__tag__removeBtn").click
276
+
277
+ wait_for_tag_to_disappear(tag)
278
+ end
279
+
280
+ # Return an array of the current tags
281
+ tags(field: field)
282
+ end
283
+
284
+ # Example usage:
285
+ # expect(tags(field: :tags)).to eq ["one", "two", "three"]
286
+ # expect(tags(field: :tags)).to eq []
287
+ def tags(field:)
288
+ # Find all elements with class 'tagify__tag'
289
+ # Map the elements to their 'label' attribute values and return the array of labels
290
+ page.all(".tagify__tag").map { |element| element[:label] }
291
+ end
292
+
293
+ # Example usage:
294
+ # expect(tag_suggestions(field: :tags, input: "")).to eq ["one", "two", "three"]
295
+ # expect(tag_suggestions(field: :tags, input: "t")).to eq ["two", "three"]
296
+ def tag_suggestions(field:, input:)
297
+ # Find the input field for the specified tag field
298
+ input_area = find("[data-field-id='#{field}'] [data-slot='value'] [role='textbox']")
299
+
300
+ # If the input argument is present, enter it into the input field
301
+ # Else, just click on the middle of the input field to display the dropdown
302
+ if input.present?
303
+ input_area.set(input)
304
+ else
305
+ input_area.click(x: input_area.native.size.width / 2, y: input_area.native.size.height / 2)
306
+ end
307
+ wait_for_tag_suggestions_to_appear
308
+
309
+ # Find all elements with class 'tagify_dropdown_item' within the dropdown
310
+ # Map the elements to their 'label' attribute values and return the array of labels
311
+ page.all(".tagify__dropdown__item").map { |element| element[:label] }
312
+ end
313
+
314
+ private
315
+
316
+ # Returns the name of the wrapper element for the given field id and type
317
+ def wrapper_name_for(id:, type:)
318
+ "#{id.camelize(:lower)}#{type.camelize}Wrapper"
319
+ end
320
+
321
+ # Finds the context element for the related field with the given id, relation, and view
322
+ # ex: has_and_belongs_to_many_users = related_field_context(id: :users, relation: :has_and_belongs_to_many)
323
+ # Now on the returend element you can do:
324
+ # first_name_wrapper = within has_and_belongs_to_many_users do
325
+ # index_field_wrapper(id: "first_name", type: "text", record_id: 7)
326
+ # end
327
+ def related_field_context(id:, relation:, view: :show)
328
+ turbo_frame = "#{relation}_field_#{view}_#{id}"
329
+ find("[id='#{turbo_frame}']")
330
+ end
331
+
332
+ def main_sidebar
333
+ find('[data-sidebar-target="sidebar"]')
334
+ end
335
+
336
+ # Opens an action. If a list is provided, it will click on the list first
337
+ # and then find the specified action name within the panel.
338
+ # If no list is present, it will directly click on the action link.
339
+ def open_action(action_name:, list:, context:, &block)
340
+ within(context) do
341
+ if list.present?
342
+ sleep 0.1
343
+ click_on list
344
+ within("[data-toggle-target='panel']") do
345
+ find("a[data-action-name='#{action_name}']").click
346
+ end
347
+ else
348
+ click_link(action_name)
349
+ end
350
+ end
351
+
352
+ # Within the dialog, ensure that the action name is present
353
+ within(find("[role='dialog']")) do
354
+ expect(page).to have_content(action_name)
355
+ end
356
+ end
357
+
358
+ def row(id)
359
+ "[data-component-name='avo/index/table_row_component'][data-resource-id='#{id}']"
360
+ end
361
+ end
362
+ end
@@ -0,0 +1,30 @@
1
+ module Avo
2
+ module Tools
3
+ class ToolManager
4
+ class << self
5
+ def build
6
+ new
7
+ end
8
+ end
9
+
10
+ # Insert any partials that we find in app/views/avo/sidebar/items.
11
+ def get_sidebar_partials
12
+ Dir.glob(Rails.root.join("app", "views", "avo", "sidebar", "items", "*.html.erb"))
13
+ .map do |path|
14
+ File.basename path
15
+ end
16
+ .map do |filename|
17
+ # remove the leading underscore (_)
18
+ filename[0] = ""
19
+ # remove the extension
20
+ filename.gsub!(".html.erb", "")
21
+ filename
22
+ end
23
+ end
24
+
25
+ def tools_for_navigation
26
+ get_sidebar_partials
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.46.0" unless const_defined?(:VERSION)
2
+ VERSION = "3.0.2" unless const_defined?(:VERSION)
3
3
  end
@@ -0,0 +1,36 @@
1
+ # Allows to check the the view type by using `view.index?` or `view.edit?` etc...
2
+ # It also allows to check if the view is a form or a display view by using `view.form?` or `view.display?`
3
+ module Avo
4
+ class ViewInquirer < ActiveSupport::StringInquirer
5
+ DISPLAY_VIEWS = %w[index show].freeze unless defined? DISPLAY_VIEWS
6
+ FORM_VIEWS = %w[new edit].freeze unless defined? FORM_VIEWS
7
+
8
+ def initialize(view)
9
+ super(view.to_s)
10
+
11
+ @display = in? DISPLAY_VIEWS
12
+ @form = in? FORM_VIEWS
13
+ end
14
+
15
+ def display?
16
+ @display
17
+ end
18
+
19
+ def form?
20
+ @form
21
+ end
22
+
23
+ # To avoid breaking changes we allow the comparison with symbols
24
+ def ==(other)
25
+ if other.is_a? Symbol
26
+ to_sym == other
27
+ else
28
+ super(other)
29
+ end
30
+ end
31
+
32
+ def in?(another_object)
33
+ super another_object.map(&:to_s)
34
+ end
35
+ end
36
+ end
data/lib/avo.rb CHANGED
@@ -11,37 +11,16 @@ loader.inflector.inflect(
11
11
  loader.ignore("#{__dir__}/generators")
12
12
  loader.setup
13
13
 
14
- # .//*,,.....,,*/(*
15
- # **,,..............,*#.
16
- # ,*,,..... .....*/#.
17
- # **,,.... ....,*/%%
18
- # ,**,,....... . ....*/#&%
19
- # **,,,...... . . ....*/#&&%
20
- # **,,........ . . ...,//#&&&.
21
- # */*,,..*//***,,,,*/(,.. .. .....*//%&%&*
22
- # ,/**,..**/******,,***/(###,...........,//(%&&%.
23
- # /**,,..((//*****////((##%%%%%*.........*//%%&&%
24
- # ****,...#/**,,,*,*/(#%##%%%%&&&(*,.....,*/(%&&&/
25
- # /**,....(/*,,,,,,,*(##%%%%%&&&&&(,.....,*(#&&&&.
26
- # ,//*,.....(/*,,**//(##%%%%&&&&@&&%/,....,*((&&&&*
27
- # .//*,,.....(((//(((##%%%&&&&&&&&@#/,....,*/#%&&&#
28
- # (/**,,......###%%%%%&&&&&&&&&&@#/,,...,,*/#&&&&&
29
- # (/**,,........%%%%%&&&&&&&&@%(*,...,,,*//(&&&&%.
30
- # ///*,,,.........,*#&&&&#(/,,.....,,,*//(%&&&&%*
31
- # (//**,,,.....................,,,,*//(%&&&&&&*
32
- # *(///**,,,,............,,,,,,**/((&&&&&&&%.
33
- # ((///*****,,,,,,,,,,,,***//((&&&&&%&%&#
34
- # .((((////********///(((%&%&&&&%%%%%
35
- # (############%%%%%%%%%%%%%%%*
36
- # ,(############%%%%%#*
37
-
38
14
  module Avo
15
+ extend ActiveSupport::LazyLoadHooks
16
+
39
17
  ROOT_PATH = Pathname.new(File.join(__dir__, ".."))
40
18
  IN_DEVELOPMENT = ENV["AVO_IN_DEVELOPMENT"] == "1"
41
19
  PACKED = !IN_DEVELOPMENT
42
20
  COOKIES_KEY = "avo"
43
21
  ENTITIES = {
44
22
  cards: ["app", "avo", "cards"],
23
+ scopes: ["app", "avo", "scopes"],
45
24
  fields: ["app", "avo", "fields"],
46
25
  filters: ["app", "avo", "filters"],
47
26
  actions: ["app", "avo", "actions"],
@@ -59,6 +38,112 @@ module Avo
59
38
  class NoPolicyError < StandardError; end
60
39
 
61
40
  class MissingGemError < StandardError; end
41
+
42
+ class DeprecatedAPIError < StandardError; end
43
+
44
+ class << self
45
+ attr_reader :logger
46
+ attr_reader :cache_store
47
+ attr_reader :field_manager
48
+
49
+ delegate :license, :app, :error_manager, :tool_manager, :resource_manager, to: Avo::Current
50
+
51
+ def boot
52
+ boot_logger
53
+ boot_fields
54
+ @cache_store = Avo.configuration.cache_store
55
+ plugin_manager.boot_plugins
56
+ Avo.run_load_hooks(:boot, self)
57
+ end
58
+
59
+ def init
60
+ Avo::Current.error_manager = Avo::ErrorManager.build
61
+ Avo::Current.resource_manager = Avo::Resources::ResourceManager.build
62
+ Avo::Current.tool_manager = Avo::Tools::ToolManager.build
63
+
64
+ Avo.run_load_hooks(:init, self)
65
+ end
66
+
67
+ # Generate a dynamic root path using the URIService
68
+ def root_path(paths: [], query: {}, **args)
69
+ Avo::Services::URIService.parse(Avo::Current.view_context.avo.root_url.to_s)
70
+ .append_paths(paths)
71
+ .append_query(query)
72
+ .to_s
73
+ end
74
+
75
+ def mount_path
76
+ Avo::Engine.routes.find_script_name({})
77
+ end
78
+
79
+ def main_menu
80
+ return unless Avo.plugin_manager.installed?("avo-menu")
81
+
82
+ # Return empty menu if the app doesn't have the profile menu configured
83
+ return Avo::Menu::Builder.new.build unless has_main_menu?
84
+
85
+ Avo::Menu::Builder.parse_menu(&Avo.configuration.main_menu)
86
+ end
87
+
88
+ def profile_menu
89
+ return unless Avo.plugin_manager.installed?("avo-menu")
90
+
91
+ # Return empty menu if the app doesn't have the profile menu configured
92
+ return Avo::Menu::Builder.new.build unless has_profile_menu?
93
+
94
+ Avo::Menu::Builder.parse_menu(&Avo.configuration.profile_menu)
95
+ end
96
+
97
+ def app_status
98
+ license.valid?
99
+ end
100
+
101
+ def avo_dynamic_filters_installed?
102
+ defined?(Avo::DynamicFilters).present?
103
+ end
104
+
105
+ def has_main_menu?
106
+ return false if Avo.license.lacks_with_trial(:menu_editor)
107
+ return false if Avo.configuration.main_menu.nil?
108
+
109
+ true
110
+ end
111
+
112
+ def has_profile_menu?
113
+ return false if Avo.license.lacks_with_trial(:menu_editor)
114
+ return false if Avo.configuration.profile_menu.nil?
115
+
116
+ true
117
+ end
118
+
119
+ # Mount all Avo engines
120
+ def mount_engines
121
+ -> {
122
+ mount Avo::DynamicFilters::Engine, at: "/avo-dynamic_filters" if defined?(Avo::DynamicFilters::Engine)
123
+ mount Avo::Dashboards::Engine, at: "/dashboards" if defined?(Avo::Dashboards::Engine)
124
+ mount Avo::Pro::Engine, at: "/avo-pro" if defined?(Avo::Pro::Engine)
125
+ }
126
+ end
127
+
128
+ private
129
+
130
+ def boot_logger
131
+ file_logger = ActiveSupport::Logger.new(Rails.root.join("log", "avo.log"))
132
+
133
+ file_logger.datetime_format = "%Y-%m-%d %H:%M:%S"
134
+ file_logger.formatter = proc do |severity, time, progname, msg|
135
+ "[Avo] #{time}: #{msg}\n".tap do |i|
136
+ puts i
137
+ end
138
+ end
139
+
140
+ @logger = file_logger
141
+ end
142
+
143
+ def boot_fields
144
+ @field_manager = Avo::Fields::FieldManager.build
145
+ end
146
+ end
62
147
  end
63
148
 
64
149
  loader.eager_load
@@ -5,20 +5,20 @@ module Generators
5
5
  class ActionGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
- class_option :standalone, type: :boolean
8
+ class_option :standalone, type: :boolean, default: false
9
+ class_option :name, type: :string
9
10
 
10
11
  namespace "avo:action"
11
12
 
12
13
  def create_resource_file
13
- type = "resource"
14
+ template "action.tt", "app/avo/actions/#{singular_name}.rb"
15
+ end
14
16
 
15
- type = "standalone" if options[:standalone]
17
+ def configuration_options
18
+ configuration = " self.name = \"#{options[:name] || name.titleize}\""
19
+ configuration += "\n self.standalone = true" if options[:standalone]
16
20
 
17
- if type == "standalone"
18
- template "standalone_action.tt", "app/avo/actions/#{singular_name}.rb"
19
- else
20
- template "action.tt", "app/avo/actions/#{singular_name}.rb"
21
- end
21
+ configuration
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,27 @@
1
+ require_relative "named_base_generator"
2
+
3
+ module Generators
4
+ module Avo
5
+ class Card < NamedBaseGenerator
6
+ namespace "avo:card"
7
+ source_root File.expand_path("templates", __dir__)
8
+ class_option :type, type: :string
9
+
10
+ def handle
11
+ raise "Invalid card type '#{options[:type]}'" unless card_types.include? options[:type]
12
+
13
+ template "cards/#{options[:type]}_card_sample.tt", "app/avo/cards/#{name.underscore}.rb"
14
+
15
+ if options[:type].to_sym == :partial
16
+ template "cards/partial_card_partial.tt", "app/views/avo/cards/_#{name.underscore}.html.erb"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def card_types
23
+ %w[metric chartkick partial]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module Generators
2
+ module Avo
3
+ module Concerns
4
+ module ParentController
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_option "parent-controller",
9
+ desc: "The name of the parent controller.",
10
+ type: :string,
11
+ required: false
12
+ end
13
+
14
+ def parent_controller
15
+ options["parent-controller"] || ::Avo.configuration.resource_parent_controller
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,8 +1,11 @@
1
1
  require_relative "named_base_generator"
2
+ require_relative "concerns/parent_controller"
2
3
 
3
4
  module Generators
4
5
  module Avo
5
6
  class ControllerGenerator < NamedBaseGenerator
7
+ include Generators::Avo::Concerns::ParentController
8
+
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  namespace "avo:controller"