avo 2.49.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 (377) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +26 -25
  3. data/Gemfile.lock +179 -147
  4. data/README.md +1 -1
  5. data/app/assets/stylesheets/avo.base.css +0 -1
  6. data/app/assets/svgs/font.svg +1 -0
  7. data/app/assets/svgs/triangle-up.svg +1 -0
  8. data/app/components/avo/actions_component.html.erb +19 -5
  9. data/app/components/avo/actions_component.rb +37 -17
  10. data/app/components/avo/asset_manager/javascript_component.html.erb +3 -0
  11. data/app/components/avo/asset_manager/javascript_component.rb +13 -0
  12. data/app/components/avo/asset_manager/stylesheet_component.html.erb +3 -0
  13. data/app/components/avo/asset_manager/stylesheet_component.rb +13 -0
  14. data/app/components/avo/base_component.rb +15 -12
  15. data/app/components/avo/button_component.rb +20 -3
  16. data/app/components/avo/empty_state_component.rb +1 -1
  17. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  18. data/app/components/avo/field_wrapper_component.rb +15 -26
  19. data/app/components/avo/fields/area_field/edit_component.html.erb +2 -2
  20. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +96 -118
  21. data/app/components/avo/fields/belongs_to_field/edit_component.rb +6 -17
  22. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  23. data/app/components/avo/fields/belongs_to_field/show_component.rb +2 -2
  24. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  25. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +3 -3
  26. data/app/components/avo/fields/common/badge_viewer_component.html.erb +24 -1
  27. data/app/components/avo/fields/common/badge_viewer_component.rb +0 -24
  28. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  29. data/app/components/avo/fields/common/files/list_viewer_component.rb +3 -3
  30. data/app/components/avo/fields/common/files/view_type/{grid_item_component.html.erb → grid_component.html.erb} +2 -2
  31. data/app/components/avo/fields/common/files/view_type/{grid_item_component.rb → grid_component.rb} +4 -5
  32. data/app/components/avo/fields/common/files/view_type/{list_item_component.rb → list_component.rb} +1 -1
  33. data/app/components/avo/fields/edit_component.rb +1 -1
  34. data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
  35. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  36. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  37. data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -2
  38. data/app/components/avo/fields/has_one_field/show_component.rb +2 -2
  39. data/app/components/avo/fields/hidden_field/edit_component.html.erb +1 -2
  40. data/app/components/avo/fields/index_component.rb +5 -5
  41. data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
  42. data/app/components/avo/fields/preview_field/index_component.rb +4 -0
  43. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  44. data/app/components/avo/fields/show_component.rb +4 -1
  45. data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
  46. data/app/components/avo/filters_component.html.erb +9 -3
  47. data/app/components/avo/filters_component.rb +4 -4
  48. data/app/components/avo/index/field_wrapper_component.rb +0 -12
  49. data/app/components/avo/index/grid_item_component.html.erb +13 -36
  50. data/app/components/avo/index/grid_item_component.rb +43 -16
  51. data/app/components/avo/index/resource_controls_component.html.erb +3 -81
  52. data/app/components/avo/index/resource_controls_component.rb +124 -17
  53. data/app/components/avo/index/resource_grid_component.html.erb +5 -3
  54. data/app/components/avo/index/resource_grid_component.rb +5 -2
  55. data/app/components/avo/index/resource_map_component.html.erb +1 -1
  56. data/app/components/avo/index/resource_map_component.rb +3 -3
  57. data/app/components/avo/index/resource_table_component.html.erb +5 -4
  58. data/app/components/avo/index/resource_table_component.rb +14 -20
  59. data/app/components/avo/index/table_row_component.html.erb +8 -4
  60. data/app/components/avo/index/table_row_component.rb +3 -2
  61. data/app/components/avo/item_switcher_component.rb +2 -2
  62. data/app/components/avo/modal_component.html.erb +7 -12
  63. data/app/components/avo/modal_component.rb +0 -21
  64. data/app/components/avo/paginator_component.html.erb +40 -29
  65. data/app/components/avo/paginator_component.rb +5 -23
  66. data/app/components/avo/panel_component.html.erb +8 -6
  67. data/app/components/avo/referrer_params_component.html.erb +1 -2
  68. data/app/components/avo/resource_component.rb +189 -14
  69. data/app/components/avo/resource_sidebar_component.html.erb +6 -2
  70. data/app/components/avo/resource_sidebar_component.rb +1 -1
  71. data/app/components/avo/sidebar/link_component.rb +1 -1
  72. data/app/components/avo/sidebar_component.html.erb +10 -3
  73. data/app/components/avo/sidebar_component.rb +5 -3
  74. data/app/components/avo/sidebar_profile_component.html.erb +15 -8
  75. data/app/components/avo/tab_group_component.html.erb +13 -7
  76. data/app/components/avo/tab_group_component.rb +1 -6
  77. data/app/components/avo/tab_switcher_component.html.erb +17 -40
  78. data/app/components/avo/tab_switcher_component.rb +4 -39
  79. data/app/components/avo/views/resource_edit_component.html.erb +12 -48
  80. data/app/components/avo/views/resource_edit_component.rb +7 -18
  81. data/app/components/avo/views/resource_index_component.html.erb +41 -47
  82. data/app/components/avo/views/resource_index_component.rb +62 -12
  83. data/app/components/avo/views/resource_show_component.html.erb +6 -149
  84. data/app/components/avo/views/resource_show_component.rb +6 -11
  85. data/app/controllers/avo/actions_controller.rb +27 -24
  86. data/app/controllers/avo/application_controller.rb +105 -151
  87. data/app/controllers/avo/associations_controller.rb +34 -43
  88. data/app/controllers/avo/attachments_controller.rb +4 -4
  89. data/app/controllers/avo/base_controller.rb +102 -102
  90. data/app/controllers/avo/debug_controller.rb +17 -5
  91. data/app/controllers/avo/home_controller.rb +1 -1
  92. data/app/controllers/avo/search_controller.rb +30 -51
  93. data/app/controllers/avo/team_users_controller.rb +4 -0
  94. data/app/controllers/concerns/avo/initializes_avo.rb +21 -0
  95. data/app/helpers/avo/application_helper.rb +15 -9
  96. data/app/helpers/avo/resources_helper.rb +1 -1
  97. data/app/helpers/avo/url_helpers.rb +27 -11
  98. data/app/javascript/avo.base.js +1 -0
  99. data/app/javascript/js/application.js +0 -3
  100. data/app/javascript/js/controllers/action_controller.js +5 -3
  101. data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
  102. data/app/javascript/js/controllers/fields/date_field_controller.js +3 -7
  103. data/app/javascript/js/controllers/fields/key_value_controller.js +1 -2
  104. data/app/javascript/js/controllers/filter_controller.js +1 -1
  105. data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
  106. data/app/javascript/js/controllers/preview_controller.js +24 -0
  107. data/app/javascript/js/controllers/search_controller.js +2 -2
  108. data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
  109. data/app/javascript/js/controllers/toggle_controller.js +48 -0
  110. data/app/javascript/js/controllers.js +10 -6
  111. data/app/javascript/js/custom-stream-actions.js +15 -0
  112. data/app/views/avo/actions/keep_modal_open.turbo_stream.erb +5 -0
  113. data/app/views/avo/actions/show.html.erb +10 -7
  114. data/app/views/avo/associations/new.html.erb +2 -2
  115. data/app/views/avo/base/index.html.erb +3 -2
  116. data/app/views/avo/base/new.html.erb +2 -1
  117. data/app/views/avo/base/preview.html.erb +19 -0
  118. data/app/views/avo/base/show.html.erb +1 -1
  119. data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
  120. data/app/views/avo/debug/report.html.erb +32 -17
  121. data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
  122. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  123. data/app/views/avo/partials/_footer.html.erb +1 -1
  124. data/app/views/avo/partials/_javascript.html.erb +5 -0
  125. data/app/views/avo/partials/_logo.html.erb +1 -1
  126. data/app/views/avo/partials/_navbar.html.erb +3 -5
  127. data/app/views/avo/partials/_table_header.html.erb +5 -11
  128. data/app/views/layouts/avo/application.html.erb +4 -2
  129. data/avo.gemspec +11 -12
  130. data/bin/dev +1 -1
  131. data/bin/prod +0 -0
  132. data/config/i18n-tasks.yml +1 -1
  133. data/config/initializers/pagy.rb +0 -2
  134. data/config/master.key +1 -0
  135. data/config/routes.rb +6 -10
  136. data/db/factories.rb +7 -1
  137. data/lib/avo/action_model.rb +20 -0
  138. data/lib/avo/asset_manager.rb +30 -0
  139. data/lib/avo/base_action.rb +57 -42
  140. data/lib/avo/base_resource.rb +264 -227
  141. data/lib/avo/base_resource_tool.rb +9 -16
  142. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  143. data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
  144. data/lib/avo/concerns/filters_session_handler.rb +5 -3
  145. data/lib/avo/concerns/has_controls.rb +37 -0
  146. data/lib/avo/concerns/has_description.rb +23 -0
  147. data/lib/avo/concerns/has_item_type.rb +42 -0
  148. data/lib/avo/concerns/has_items.rb +325 -0
  149. data/lib/avo/concerns/{has_resource_stimulus_controllers.rb → has_stimulus_controllers.rb} +1 -1
  150. data/lib/avo/concerns/is_resource_item.rb +24 -36
  151. data/lib/avo/concerns/is_visible.rb +15 -0
  152. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  153. data/lib/avo/concerns/visible_in_different_views.rb +126 -0
  154. data/lib/avo/configuration/branding.rb +0 -12
  155. data/lib/avo/configuration.rb +1 -37
  156. data/lib/avo/current.rb +39 -0
  157. data/lib/avo/dsl/field_parser.rb +1 -1
  158. data/lib/avo/dynamic_router.rb +18 -3
  159. data/lib/avo/engine.rb +35 -30
  160. data/lib/avo/error_manager.rb +25 -0
  161. data/lib/avo/execution_context.rb +10 -14
  162. data/lib/avo/fields/badge_field.rb +1 -1
  163. data/lib/avo/fields/base_field.rb +91 -106
  164. data/lib/avo/fields/belongs_to_field.rb +18 -22
  165. data/lib/avo/fields/concerns/file_authorization.rb +2 -2
  166. data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
  167. data/lib/avo/fields/concerns/has_default.rb +1 -5
  168. data/lib/avo/fields/concerns/has_field_name.rb +22 -0
  169. data/lib/avo/fields/concerns/has_html_attributes.rb +110 -0
  170. data/lib/avo/fields/concerns/is_disabled.rb +1 -5
  171. data/lib/avo/fields/concerns/is_readonly.rb +1 -5
  172. data/lib/avo/fields/concerns/is_required.rb +5 -7
  173. data/lib/avo/fields/concerns/is_searchable.rb +13 -0
  174. data/lib/avo/fields/concerns/use_resource.rb +5 -1
  175. data/lib/avo/fields/country_field.rb +4 -0
  176. data/lib/avo/fields/date_time_field.rb +3 -14
  177. data/lib/avo/fields/field_manager.rb +55 -0
  178. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
  179. data/lib/avo/fields/has_base_field.rb +12 -15
  180. data/lib/avo/fields/has_many_field.rb +5 -2
  181. data/lib/avo/fields/has_one_field.rb +6 -10
  182. data/lib/avo/fields/heading_field.rb +4 -1
  183. data/lib/avo/fields/hidden_field.rb +1 -1
  184. data/lib/avo/fields/id_field.rb +1 -1
  185. data/lib/avo/fields/location_field.rb +8 -8
  186. data/lib/avo/fields/password_field.rb +1 -1
  187. data/lib/avo/fields/preview_field.rb +14 -0
  188. data/lib/avo/fields/select_field.rb +12 -8
  189. data/lib/avo/fields/status_field.rb +4 -0
  190. data/lib/avo/filters/base_filter.rb +8 -4
  191. data/lib/avo/html/builder.rb +7 -8
  192. data/lib/avo/item_grapher.rb +78 -0
  193. data/lib/avo/licensing/h_q.rb +8 -67
  194. data/lib/avo/licensing/license.rb +1 -1
  195. data/lib/avo/licensing/pro_license.rb +1 -7
  196. data/lib/avo/loaders/fields_loader.rb +7 -1
  197. data/lib/avo/plugin.rb +16 -0
  198. data/lib/avo/plugin_manager.rb +56 -0
  199. data/lib/avo/prefixed_test_helpers.rb +20 -0
  200. data/lib/avo/reloader.rb +3 -0
  201. data/lib/avo/resources/controls/actions_list.rb +7 -12
  202. data/lib/avo/resources/controls/attach_button.rb +15 -0
  203. data/lib/avo/resources/controls/back_button.rb +1 -1
  204. data/lib/avo/resources/controls/base_control.rb +15 -49
  205. data/lib/avo/resources/controls/create_button.rb +15 -0
  206. data/lib/avo/resources/controls/delete_button.rb +5 -1
  207. data/lib/avo/resources/controls/detach_button.rb +4 -1
  208. data/lib/avo/resources/controls/edit_button.rb +4 -1
  209. data/lib/avo/resources/controls/order_controls.rb +8 -0
  210. data/lib/avo/resources/controls/save_button.rb +13 -0
  211. data/lib/avo/resources/controls/show_button.rb +15 -0
  212. data/lib/avo/resources/items/holder.rb +84 -0
  213. data/lib/avo/resources/items/item_group.rb +49 -0
  214. data/lib/avo/resources/items/main_panel.rb +2 -0
  215. data/lib/avo/resources/items/panel.rb +2 -0
  216. data/lib/avo/resources/items/row.rb +54 -0
  217. data/lib/avo/resources/items/sidebar.rb +47 -0
  218. data/lib/avo/resources/items/tab.rb +60 -0
  219. data/lib/avo/resources/items/tab_group.rb +68 -0
  220. data/lib/avo/resources/resource_manager.rb +174 -0
  221. data/lib/avo/services/authorization_service.rb +11 -110
  222. data/lib/avo/services/debug_service.rb +93 -0
  223. data/lib/avo/services/encryption_service.rb +5 -1
  224. data/lib/avo/services/telemetry_service.rb +85 -0
  225. data/lib/avo/test_helpers.rb +362 -0
  226. data/lib/avo/tools/tool_manager.rb +30 -0
  227. data/lib/avo/version.rb +1 -1
  228. data/lib/avo.rb +115 -24
  229. data/lib/generators/avo/action_generator.rb +8 -8
  230. data/lib/generators/avo/card_generator.rb +27 -0
  231. data/lib/generators/avo/filter_generator.rb +8 -8
  232. data/lib/generators/avo/resource_generator.rb +4 -4
  233. data/lib/generators/avo/scope_generator.rb +15 -0
  234. data/lib/generators/avo/tailwindcss/install_generator.rb +1 -15
  235. data/lib/generators/avo/templates/action.tt +8 -6
  236. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  237. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  238. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  239. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  240. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  241. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  242. data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
  243. data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
  244. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  245. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
  246. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  247. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  248. data/lib/generators/avo/templates/initializer/avo.tt +1 -9
  249. data/lib/generators/avo/templates/locales/avo.ar.yml +6 -6
  250. data/lib/generators/avo/templates/locales/avo.en.yml +4 -5
  251. data/lib/generators/avo/templates/locales/avo.fr.yml +1 -2
  252. data/lib/generators/avo/templates/locales/avo.nb.yml +1 -2
  253. data/lib/generators/avo/templates/locales/avo.nn.yml +1 -2
  254. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -2
  255. data/lib/generators/avo/templates/locales/avo.pt.yml +1 -2
  256. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -7
  257. data/lib/generators/avo/templates/locales/avo.tr.yml +1 -2
  258. data/lib/generators/avo/templates/resource/resource.tt +7 -7
  259. data/lib/generators/avo/templates/resource_tools/partial.tt +4 -4
  260. data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
  261. data/lib/generators/avo/templates/scope.tt +6 -0
  262. data/lib/generators/avo/templates/tool/view.tt +2 -2
  263. data/lib/tasks/avo_tasks.rake +27 -0
  264. data/public/avo-assets/avo.base.css +1810 -1189
  265. data/public/avo-assets/avo.base.js +217 -307
  266. data/public/avo-assets/avo.base.js.map +3 -3
  267. data/public/avo-assets/avo.css +9744 -0
  268. data/public/avo-assets/avo.js +513 -0
  269. data/public/avo-assets/avo.js.map +7 -0
  270. metadata +102 -146
  271. data/app/assets/stylesheets/css/tags.css +0 -32
  272. data/app/components/avo/card_component.html.erb +0 -46
  273. data/app/components/avo/card_component.rb +0 -25
  274. data/app/components/avo/dashboards/divider_component.html.erb +0 -9
  275. data/app/components/avo/dashboards/divider_component.rb +0 -19
  276. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
  277. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
  278. data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
  279. data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
  280. data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
  281. data/app/components/avo/fields/tags_field/index_component.rb +0 -9
  282. data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
  283. data/app/components/avo/fields/tags_field/show_component.rb +0 -5
  284. data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
  285. data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
  286. data/app/components/avo/index/ordering/base_component.rb +0 -9
  287. data/app/components/avo/index/ordering/button_component.html.erb +0 -11
  288. data/app/components/avo/index/ordering/button_component.rb +0 -23
  289. data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
  290. data/app/components/avo/index/ordering/buttons_component.rb +0 -47
  291. data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
  292. data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
  293. data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
  294. data/app/controllers/avo/dashboards_controller.rb +0 -22
  295. data/app/controllers/avo/reorder_controller.rb +0 -25
  296. data/app/javascript/js/controllers/base_controller.js +0 -22
  297. data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +0 -51
  298. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
  299. data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
  300. data/app/views/avo/base/_new_via_belongs_to.html.erb +0 -12
  301. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +0 -8
  302. data/app/views/avo/base/create_fail_action.turbo_stream.erb +0 -13
  303. data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
  304. data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
  305. data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
  306. data/app/views/avo/dashboards/cards/show.html.erb +0 -3
  307. data/app/views/avo/dashboards/show.html.erb +0 -38
  308. data/app/views/avo/partials/_flash_alerts.turbo_stream.erb +0 -3
  309. data/app/views/avo/partials/_global_search.html.erb +0 -19
  310. data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
  311. data/lib/avo/app.rb +0 -237
  312. data/lib/avo/base_card.rb +0 -161
  313. data/lib/avo/concerns/fetches_things.rb +0 -150
  314. data/lib/avo/concerns/handles_field_args.rb +0 -47
  315. data/lib/avo/concerns/has_action_stimulus_controllers.rb +0 -15
  316. data/lib/avo/concerns/has_editable_controls.rb +0 -34
  317. data/lib/avo/concerns/has_fields.rb +0 -334
  318. data/lib/avo/concerns/has_html_attributes.rb +0 -123
  319. data/lib/avo/concerns/pagination.rb +0 -53
  320. data/lib/avo/concerns/policy_helpers.rb +0 -31
  321. data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
  322. data/lib/avo/concerns/visible_items.rb +0 -51
  323. data/lib/avo/dashboards/base_dashboard.rb +0 -89
  324. data/lib/avo/dashboards/base_divider.rb +0 -35
  325. data/lib/avo/dashboards/chartkick_card.rb +0 -77
  326. data/lib/avo/dashboards/dashboard_card.rb +0 -6
  327. data/lib/avo/dashboards/metric_card.rb +0 -9
  328. data/lib/avo/dashboards/partial_card.rb +0 -7
  329. data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
  330. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
  331. data/lib/avo/fields/tags_field.rb +0 -102
  332. data/lib/avo/grid_collector.rb +0 -42
  333. data/lib/avo/hosts/association_scope_host.rb +0 -8
  334. data/lib/avo/hosts/base_host.rb +0 -25
  335. data/lib/avo/hosts/card_visibility.rb +0 -20
  336. data/lib/avo/hosts/dashboard_card.rb +0 -22
  337. data/lib/avo/hosts/dashboard_visibility.rb +0 -19
  338. data/lib/avo/hosts/ordering.rb +0 -22
  339. data/lib/avo/hosts/record_host.rb +0 -7
  340. data/lib/avo/hosts/resource_record_host.rb +0 -7
  341. data/lib/avo/hosts/resource_view_record_host.rb +0 -7
  342. data/lib/avo/hosts/search_scope_host.rb +0 -7
  343. data/lib/avo/hosts/view_record_host.rb +0 -7
  344. data/lib/avo/hosts/visibility_host.rb +0 -12
  345. data/lib/avo/items_holder.rb +0 -96
  346. data/lib/avo/main_panel.rb +0 -3
  347. data/lib/avo/menu/base_item.rb +0 -25
  348. data/lib/avo/menu/builder.rb +0 -82
  349. data/lib/avo/menu/dashboard.rb +0 -22
  350. data/lib/avo/menu/group.rb +0 -2
  351. data/lib/avo/menu/link.rb +0 -6
  352. data/lib/avo/menu/menu.rb +0 -2
  353. data/lib/avo/menu/resource.rb +0 -22
  354. data/lib/avo/menu/section.rb +0 -2
  355. data/lib/avo/panel.rb +0 -24
  356. data/lib/avo/panel_builder.rb +0 -25
  357. data/lib/avo/resources/controls/action.rb +0 -38
  358. data/lib/avo/resources/controls/execution_context.rb +0 -58
  359. data/lib/avo/resources/controls/items_holder.rb +0 -19
  360. data/lib/avo/resources/controls/link_to.rb +0 -27
  361. data/lib/avo/row.rb +0 -26
  362. data/lib/avo/row_builder.rb +0 -24
  363. data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
  364. data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
  365. data/lib/avo/sidebar.rb +0 -30
  366. data/lib/avo/sidebar_builder.rb +0 -24
  367. data/lib/avo/tab.rb +0 -72
  368. data/lib/avo/tab_builder.rb +0 -25
  369. data/lib/avo/tab_group.rb +0 -42
  370. data/lib/avo/tab_group_builder.rb +0 -43
  371. data/lib/avo/tools_manager.rb +0 -11
  372. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  373. data/lib/generators/avo/card/metric_generator.rb +0 -18
  374. data/lib/generators/avo/card/partial_generator.rb +0 -19
  375. data/lib/generators/avo/templates/locales/avo.es.yml +0 -126
  376. data/lib/generators/avo/templates/standalone_action.tt +0 -8
  377. /data/app/components/avo/fields/common/files/view_type/{list_item_component.html.erb → list_component.html.erb} +0 -0
@@ -0,0 +1,85 @@
1
+ class Avo::Services::TelemetryService
2
+ class << self
3
+ def telemetry_info
4
+ {
5
+ # license: Avo.configuration.license,
6
+ # license_key: Avo.configuration.license_key,
7
+ avo_version: Avo::VERSION,
8
+ rails_version: Rails::VERSION::STRING,
9
+ ruby_version: RUBY_VERSION,
10
+ environment: Rails.env,
11
+ # ip: current_request&.ip,
12
+ # host: current_request&.host,
13
+ # port: current_request&.port,
14
+ app_name: app_name,
15
+ avo_metadata: avo_metadata,
16
+ }
17
+ end
18
+
19
+ def app_name
20
+ Rails.application.class.to_s.split("::").first
21
+ rescue
22
+ nil
23
+ end
24
+
25
+ def avo_metadata
26
+ resources = Avo.resource_manager.all
27
+ dashboards = Avo::Current.app.dashboard_manager.all
28
+ field_definitions = resources.map(&:get_field_definitions)
29
+ fields_count = field_definitions.map(&:count).sum
30
+ fields_per_resource = sprintf("%0.01f", fields_count / (resources.count + 0.0))
31
+
32
+ field_types = {}
33
+ custom_fields_count = 0
34
+ field_definitions.each do |fields|
35
+ fields.each do |field|
36
+ field_types[field.type] ||= 0
37
+ field_types[field.type] += 1
38
+
39
+ custom_fields_count += 1 if field.custom?
40
+ end
41
+ end
42
+
43
+ {
44
+ resources_count: resources.count,
45
+ dashboards_count: dashboards.count,
46
+ fields_count: fields_count,
47
+ fields_per_resource: fields_per_resource,
48
+ custom_fields_count: custom_fields_count,
49
+ field_types: field_types,
50
+ **other_metadata(:actions),
51
+ **other_metadata(:filters),
52
+ main_menu_present: Avo.configuration.main_menu.present?,
53
+ profile_menu_present: Avo.configuration.profile_menu.present?,
54
+ cache_store: Avo.cache_store&.class&.to_s,
55
+ **config_metadata
56
+ }
57
+ # rescue => error
58
+ # {
59
+ # error: error.message
60
+ # }
61
+ end
62
+
63
+ def other_metadata(type = :actions)
64
+ resources = Avo.resource_manager.all
65
+
66
+ types = resources.map(&:"get_#{type}")
67
+ type_count = types.flatten.uniq.count
68
+ type_per_resource = sprintf("%0.01f", types.map(&:count).sum / (resources.count + 0.0))
69
+
70
+ {
71
+ "#{type}_count": type_count,
72
+ "#{type}_per_resource": type_per_resource
73
+ }
74
+ end
75
+
76
+ def config_metadata
77
+ {
78
+ config: {
79
+ root_path: Avo.configuration.root_path,
80
+ app_name: Avo.configuration.app_name
81
+ }
82
+ }
83
+ end
84
+ end
85
+ end
@@ -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.49.0" unless const_defined?(:VERSION)
2
+ VERSION = "3.0.0.beta1" unless const_defined?(:VERSION)
3
3
  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,118 @@ 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 = get_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
+ # Renerate 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_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
+ private
120
+
121
+ def boot_logger
122
+ file_logger = ActiveSupport::Logger.new(Rails.root.join("log", "avo.log"))
123
+
124
+ file_logger.datetime_format = "%Y-%m-%d %H:%M:%S"
125
+ file_logger.formatter = proc do |severity, time, progname, msg|
126
+ "[Avo] #{time}: #{msg}\n".tap do |i|
127
+ puts i
128
+ end
129
+ end
130
+
131
+ @logger = file_logger
132
+ end
133
+
134
+ def boot_fields
135
+ @field_manager = Avo::Fields::FieldManager.build
136
+ end
137
+
138
+ def get_cache_store
139
+ if Rails.env.production?
140
+ case Rails.cache.class.to_s
141
+ when "ActiveSupport::Cache::MemCacheStore", "ActiveSupport::Cache::RedisCacheStore"
142
+ Rails.cache
143
+ else
144
+ ActiveSupport::Cache.lookup_store(:file_store, Rails.root.join("tmp", "cache"))
145
+ end
146
+ elsif Rails.env.test?
147
+ Rails.cache
148
+ else
149
+ ActiveSupport::Cache.lookup_store(:memory_store)
150
+ end
151
+ end
152
+ end
62
153
  end
63
154
 
64
155
  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