avo 3.30.4 → 4.0.0.beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +18 -1
  3. data/Gemfile.lock +257 -174
  4. data/README.md +1 -1
  5. data/app/assets/builds/avo/application.css +13979 -0
  6. data/app/assets/builds/avo/application.js +1160 -0
  7. data/app/assets/builds/avo/application.js.map +7 -0
  8. data/app/assets/builds/avo/late-registration.js +2 -0
  9. data/app/assets/builds/avo/late-registration.js.map +7 -0
  10. data/app/assets/config/avo_manifest.js +2 -1
  11. data/app/assets/images/avo/placeholder.svg +1 -0
  12. data/app/assets/stylesheets/application.css +250 -0
  13. data/app/assets/stylesheets/css/button-group.css +23 -0
  14. data/app/assets/stylesheets/css/components/avatar.css +128 -0
  15. data/app/assets/stylesheets/css/components/breadcrumbs.css +43 -0
  16. data/app/assets/stylesheets/css/components/button.css +343 -0
  17. data/app/assets/stylesheets/css/components/color_scheme_switcher.css +226 -0
  18. data/app/assets/stylesheets/css/components/discreet_information.css +49 -0
  19. data/app/assets/stylesheets/css/components/field-wrapper.css +107 -0
  20. data/app/assets/stylesheets/css/components/grid.css +120 -0
  21. data/app/assets/stylesheets/css/components/input.css +312 -0
  22. data/app/assets/stylesheets/css/components/modal.css +228 -0
  23. data/app/assets/stylesheets/css/components/tooltip.css +25 -0
  24. data/app/assets/stylesheets/css/components/ui/badge.css +143 -0
  25. data/app/assets/stylesheets/css/components/ui/card.css +95 -0
  26. data/app/assets/stylesheets/css/components/ui/checkbox.css +50 -0
  27. data/app/assets/stylesheets/css/components/ui/description_list.css +3 -0
  28. data/app/assets/stylesheets/css/components/ui/dropdown.css +68 -0
  29. data/app/assets/stylesheets/css/components/ui/file_upload_input.css +94 -0
  30. data/app/assets/stylesheets/css/components/ui/file_upload_item.css +78 -0
  31. data/app/assets/stylesheets/css/components/ui/panel.css +59 -0
  32. data/app/assets/stylesheets/css/components/ui/panel_header.css +48 -0
  33. data/app/assets/stylesheets/css/components/ui/radio.css +22 -0
  34. data/app/assets/stylesheets/css/components/ui/tabs.css +74 -0
  35. data/app/assets/stylesheets/css/css-animations.css +54 -0
  36. data/app/assets/stylesheets/css/fields/code.css +75 -9
  37. data/app/assets/stylesheets/css/fields/easy-mde.css +7 -0
  38. data/app/assets/stylesheets/css/fields/key_value.css +97 -0
  39. data/app/assets/stylesheets/css/fields/progress.css +4 -4
  40. data/app/assets/stylesheets/css/fields/status.css +7 -1
  41. data/app/assets/stylesheets/css/fields/tags.css +33 -16
  42. data/app/assets/stylesheets/css/fields/tiptap.css +17 -15
  43. data/app/assets/stylesheets/css/fields/trix.css +62 -2
  44. data/app/assets/stylesheets/css/fonts.css +24 -24
  45. data/app/assets/stylesheets/css/layout.css +135 -0
  46. data/app/assets/stylesheets/css/pagination.css +114 -78
  47. data/app/assets/stylesheets/css/resource-controls.css +13 -0
  48. data/app/assets/stylesheets/css/search.css +22 -12
  49. data/app/assets/stylesheets/css/sidebar.css +310 -24
  50. data/app/assets/stylesheets/css/table.css +60 -0
  51. data/app/assets/stylesheets/css/tooltips.css +1 -1
  52. data/app/assets/stylesheets/css/typography.css +10 -1
  53. data/app/assets/stylesheets/css/variables.css +318 -0
  54. data/app/assets/svgs/avo/moon-plus-plus.svg +1 -0
  55. data/app/components/avo/actions_component.html.erb +30 -36
  56. data/app/components/avo/actions_component.rb +8 -11
  57. data/app/components/avo/alert_component.html.erb +3 -3
  58. data/app/components/avo/alert_component.rb +1 -1
  59. data/app/components/avo/asset_manager/javascript_component.html.erb +1 -2
  60. data/app/components/avo/backtrace_alert_component.html.erb +4 -4
  61. data/app/components/avo/base_component.rb +3 -4
  62. data/app/components/avo/breadcrumb_element_component.html.erb +17 -0
  63. data/app/components/avo/breadcrumb_element_component.rb +21 -0
  64. data/app/components/avo/breadcrumbs_component.html.erb +19 -0
  65. data/app/components/avo/breadcrumbs_component.rb +5 -0
  66. data/app/components/avo/button_component.rb +20 -126
  67. data/app/components/avo/clipboard_component.html.erb +3 -2
  68. data/app/components/avo/clipboard_component.rb +1 -1
  69. data/app/components/avo/component_missing_component.rb +11 -0
  70. data/app/components/avo/cover_component.html.erb +3 -0
  71. data/app/components/avo/cover_component.rb +25 -0
  72. data/app/components/avo/debug/status_component.html.erb +59 -0
  73. data/app/components/avo/debug/status_component.rb +30 -0
  74. data/app/components/avo/description_list_component.rb +11 -0
  75. data/app/components/avo/discreet_information_component.html.erb +31 -6
  76. data/app/components/avo/discreet_information_component.rb +23 -32
  77. data/app/components/avo/divider_component.html.erb +2 -2
  78. data/app/components/avo/empty_state_component.html.erb +2 -9
  79. data/app/components/avo/empty_state_component.rb +0 -8
  80. data/app/components/avo/field_wrapper_component.html.erb +21 -22
  81. data/app/components/avo/field_wrapper_component.rb +9 -18
  82. data/app/components/avo/fields/avatar_field/index_component.html.erb +9 -0
  83. data/app/components/avo/fields/avatar_field/index_component.rb +4 -0
  84. data/app/components/avo/fields/badge_field/index_component.html.erb +7 -1
  85. data/app/components/avo/fields/badge_field/show_component.html.erb +6 -1
  86. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +16 -14
  87. data/app/components/avo/fields/belongs_to_field/edit_component.rb +13 -3
  88. data/app/components/avo/fields/boolean_field/edit_component.html.erb +2 -2
  89. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  90. data/app/components/avo/fields/boolean_group_field/edit_component.rb +2 -3
  91. data/app/components/avo/fields/code_field/show_component.html.erb +1 -1
  92. data/app/components/avo/fields/common/boolean_check_component.rb +3 -3
  93. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  94. data/app/components/avo/fields/common/files/controls_component.html.erb +30 -27
  95. data/app/components/avo/fields/common/files/controls_component.rb +0 -1
  96. data/app/components/avo/fields/common/files/list_viewer_component.html.erb +4 -5
  97. data/app/components/avo/fields/common/files/view_type/grid_item_component.html.erb +1 -1
  98. data/app/components/avo/fields/common/files/view_type/list_item_component.html.erb +7 -19
  99. data/app/components/avo/fields/common/heading_component.html.erb +2 -2
  100. data/app/components/avo/fields/common/heading_component.rb +1 -1
  101. data/app/components/avo/fields/common/key_value_component.html.erb +20 -24
  102. data/app/components/avo/fields/common/nested_field_component.html.erb +1 -1
  103. data/app/components/avo/fields/common/nested_field_component.rb +1 -1
  104. data/app/components/avo/fields/common/progress_bar_component.html.erb +2 -2
  105. data/app/components/avo/fields/common/stars_component.html.erb +1 -1
  106. data/app/components/avo/fields/common/status_viewer_component.html.erb +4 -10
  107. data/app/components/avo/fields/date_field/edit_component.html.erb +14 -1
  108. data/app/components/avo/fields/date_time_field/edit_component.html.erb +3 -3
  109. data/app/components/avo/fields/easy_mde_field/show_component.html.erb +1 -1
  110. data/app/components/avo/fields/edit_component.rb +9 -5
  111. data/app/components/avo/fields/file_field/edit_component.html.erb +14 -6
  112. data/app/components/avo/fields/files_field/edit_component.html.erb +11 -4
  113. data/app/components/avo/fields/has_one_field/show_component.html.erb +10 -9
  114. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  115. data/app/components/avo/fields/heading_field/show_component.html.erb +2 -2
  116. data/app/components/avo/fields/password_field/edit_component.html.erb +5 -7
  117. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -1
  118. data/app/components/avo/fields/radio_field/edit_component.html.erb +1 -1
  119. data/app/components/avo/fields/show_component.rb +4 -7
  120. data/app/components/avo/fields/stars_field/edit_component.html.erb +3 -4
  121. data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
  122. data/app/components/avo/fields/tags_field/tag_component.html.erb +7 -8
  123. data/app/components/avo/fields/time_field/edit_component.html.erb +3 -3
  124. data/app/components/avo/fields/tiptap_field/edit_component.html.erb +11 -11
  125. data/app/components/avo/fields/tiptap_field/show_component.html.erb +4 -4
  126. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
  127. data/app/components/avo/filters_component.html.erb +8 -16
  128. data/app/components/avo/index/field_wrapper_component.html.erb +9 -2
  129. data/app/components/avo/index/field_wrapper_component.rb +0 -16
  130. data/app/components/avo/index/grid_cover_empty_state_component.html.erb +16 -2
  131. data/app/components/avo/index/grid_cover_empty_state_component.rb +90 -0
  132. data/app/components/avo/index/grid_item_component.html.erb +29 -12
  133. data/app/components/avo/index/grid_item_component.rb +12 -10
  134. data/app/components/avo/index/resource_controls_component.html.erb +1 -1
  135. data/app/components/avo/index/resource_controls_component.rb +7 -17
  136. data/app/components/avo/index/resource_controls_dropdown_component.html.erb +3 -0
  137. data/app/components/avo/index/resource_controls_dropdown_component.rb +81 -0
  138. data/app/components/avo/index/table_row_component.html.erb +11 -11
  139. data/app/components/avo/items/panel_component.html.erb +8 -18
  140. data/app/components/avo/items/panel_component.rb +0 -20
  141. data/app/components/avo/items/switcher_component.html.erb +60 -1
  142. data/app/components/avo/items/switcher_component.rb +10 -5
  143. data/app/components/avo/items/visible_items_component.html.erb +2 -1
  144. data/app/components/avo/items/visible_items_component.rb +1 -0
  145. data/app/components/avo/media_library/item_details_component.html.erb +2 -2
  146. data/app/components/avo/media_library/list_component.html.erb +24 -19
  147. data/app/components/avo/media_library/list_component.rb +2 -2
  148. data/app/components/avo/media_library/list_item_component.html.erb +3 -3
  149. data/app/components/avo/modal_component.html.erb +52 -20
  150. data/app/components/avo/modal_component.rb +7 -12
  151. data/app/components/avo/paginator_component.html.erb +46 -33
  152. data/app/components/avo/paginator_component.rb +10 -5
  153. data/app/components/avo/panel_name_component.html.erb +1 -1
  154. data/app/components/avo/profile_item_component.html.erb +4 -4
  155. data/app/components/avo/profile_item_component.rb +2 -4
  156. data/app/components/avo/referrer_params_component.html.erb +1 -1
  157. data/app/components/avo/resource_component.rb +8 -19
  158. data/app/components/avo/resource_listing_component.html.erb +22 -0
  159. data/app/components/avo/resource_listing_component.rb +28 -0
  160. data/app/components/avo/resource_sidebar_component.html.erb +2 -2
  161. data/app/components/avo/resource_sidebar_component.rb +0 -4
  162. data/app/components/avo/row_component.html.erb +1 -1
  163. data/app/components/avo/row_selector_component.html.erb +2 -4
  164. data/app/components/avo/row_selector_component.rb +0 -1
  165. data/app/components/avo/search_overlay_component.html.erb +6 -0
  166. data/app/components/avo/search_overlay_component.rb +2 -0
  167. data/app/components/avo/sidebar/base_item_component.rb +9 -9
  168. data/app/components/avo/sidebar/group_component.html.erb +23 -27
  169. data/app/components/avo/sidebar/group_component.rb +4 -0
  170. data/app/components/avo/sidebar/link_component.html.erb +30 -7
  171. data/app/components/avo/sidebar/link_component.rb +30 -2
  172. data/app/components/avo/sidebar/section_component.html.erb +31 -11
  173. data/app/components/avo/sidebar/section_component.rb +1 -3
  174. data/app/components/avo/sidebar_component.html.erb +35 -36
  175. data/app/components/avo/sidebar_component.rb +16 -0
  176. data/app/components/avo/sidebar_profile_component.html.erb +27 -36
  177. data/app/components/avo/sidebar_profile_component.rb +14 -0
  178. data/app/components/avo/tab_group_component.html.erb +21 -9
  179. data/app/components/avo/tab_group_component.rb +54 -15
  180. data/app/components/avo/turbo_frame_wrapper_component.html.erb +4 -8
  181. data/app/components/avo/turbo_frame_wrapper_component.rb +9 -0
  182. data/app/components/avo/u_i/avatar_component.html.erb +11 -0
  183. data/app/components/avo/u_i/avatar_component.rb +61 -0
  184. data/app/components/avo/u_i/badge_component.html.erb +9 -0
  185. data/app/components/avo/u_i/badge_component.rb +35 -0
  186. data/app/components/avo/u_i/card_component.html.erb +29 -0
  187. data/app/components/avo/u_i/card_component.rb +65 -0
  188. data/app/components/avo/u_i/dropdown_component.html.erb +14 -0
  189. data/app/components/avo/u_i/dropdown_component.rb +26 -0
  190. data/app/components/avo/u_i/dropdown_menu_component.html.erb +16 -0
  191. data/app/components/avo/u_i/dropdown_menu_component.rb +8 -0
  192. data/app/components/avo/u_i/file_upload_input_component.html.erb +26 -0
  193. data/app/components/avo/u_i/file_upload_input_component.rb +15 -0
  194. data/app/components/avo/u_i/file_upload_item_component.html.erb +48 -0
  195. data/app/components/avo/u_i/file_upload_item_component.rb +17 -0
  196. data/app/components/avo/u_i/icon_button_component.html.erb +7 -0
  197. data/app/components/avo/u_i/icon_button_component.rb +22 -0
  198. data/app/components/avo/u_i/panel_component.html.erb +49 -0
  199. data/app/components/avo/u_i/panel_component.rb +29 -0
  200. data/app/components/avo/u_i/panel_header_component.html.erb +37 -0
  201. data/app/components/avo/u_i/panel_header_component.rb +24 -0
  202. data/app/components/avo/u_i/search_input_component.html.erb +28 -0
  203. data/app/components/avo/u_i/search_input_component.rb +12 -0
  204. data/app/components/avo/u_i/tabs/tab_component.html.erb +26 -0
  205. data/app/components/avo/u_i/tabs/tab_component.rb +25 -0
  206. data/app/components/avo/u_i/tabs/tabs_component.html.erb +7 -0
  207. data/app/components/avo/u_i/tabs/tabs_component.rb +13 -0
  208. data/app/components/avo/view_types/base_view_type_component.rb +26 -0
  209. data/app/components/avo/view_types/grid_component.html.erb +18 -0
  210. data/app/components/avo/view_types/grid_component.rb +4 -0
  211. data/app/components/avo/view_types/map_component.html.erb +17 -0
  212. data/app/components/avo/view_types/map_component.rb +110 -0
  213. data/app/components/avo/view_types/table_component.html.erb +63 -0
  214. data/app/components/avo/{index/resource_table_component.rb → view_types/table_component.rb} +1 -10
  215. data/app/components/avo/views/resource_edit_component.html.erb +12 -18
  216. data/app/components/avo/views/resource_edit_component.rb +1 -27
  217. data/app/components/avo/views/resource_index_component.html.erb +97 -74
  218. data/app/components/avo/views/resource_index_component.rb +23 -3
  219. data/app/components/avo/views/resource_show_component.html.erb +4 -2
  220. data/app/components/avo/views/resource_show_component.rb +1 -4
  221. data/app/controllers/avo/associations_controller.rb +1 -1
  222. data/app/controllers/avo/base_application_controller.rb +7 -5
  223. data/app/controllers/avo/base_controller.rb +139 -40
  224. data/app/controllers/avo/debug_controller.rb +0 -29
  225. data/app/controllers/avo/media_library_controller.rb +17 -1
  226. data/app/controllers/avo/search_controller.rb +5 -0
  227. data/app/controllers/concerns/avo/initializes_avo.rb +7 -8
  228. data/app/helpers/avo/application_helper.rb +60 -46
  229. data/app/helpers/avo/turbo_stream_actions_helper.rb +10 -1
  230. data/app/helpers/avo/url_helpers.rb +3 -2
  231. data/app/javascript/{avo.base.js → application.js} +9 -18
  232. data/app/javascript/js/application.js +40 -0
  233. data/app/javascript/js/controllers/action_controller.js +4 -4
  234. data/app/javascript/js/controllers/actions_overflow_controller.js +21 -6
  235. data/app/javascript/js/controllers/color_scheme_switcher_controller.js +226 -0
  236. data/app/javascript/js/controllers/dropdown_menu_controller.js +42 -0
  237. data/app/javascript/js/controllers/fields/code_field_controller.js +20 -3
  238. data/app/javascript/js/controllers/fields/easy_mde_controller.js +23 -1
  239. data/app/javascript/js/controllers/fields/key_value_controller.js +43 -39
  240. data/app/javascript/js/controllers/fields/panel_refresh_controller.js +4 -0
  241. data/app/javascript/js/controllers/fields/tags_field_controller.js +2 -2
  242. data/app/javascript/js/controllers/fields/tags_field_helpers.js +4 -6
  243. data/app/javascript/js/controllers/grid_cover_empty_state_controller.js +42 -0
  244. data/app/javascript/js/controllers/item_selector_controller.js +0 -2
  245. data/app/javascript/js/controllers/loading_button_controller.js +1 -5
  246. data/app/javascript/js/controllers/map_dark_mode_controller.js +131 -0
  247. data/app/javascript/js/controllers/menu_controller.js +38 -16
  248. data/app/javascript/js/controllers/modal_controller.js +16 -0
  249. data/app/javascript/js/controllers/modal_size_controller.js +83 -0
  250. data/app/javascript/js/controllers/nested_form_controller.js +2 -2
  251. data/app/javascript/js/controllers/password_visibility_controller.js +13 -0
  252. data/app/javascript/js/controllers/preview_controller.js +2 -2
  253. data/app/javascript/js/controllers/resource_search_controller.js +123 -0
  254. data/app/javascript/js/controllers/search_controller.js +10 -29
  255. data/app/javascript/js/controllers/sidebar_controller.js +29 -9
  256. data/app/javascript/js/controllers/table_row_controller.js +28 -0
  257. data/app/javascript/js/controllers/tippy_controller.js +1 -1
  258. data/app/javascript/js/controllers/toggle_controller.js +40 -5
  259. data/app/javascript/js/controllers.js +14 -2
  260. data/app/javascript/js/custom-stream-actions.js +10 -8
  261. data/app/views/avo/actions/show.html.erb +14 -10
  262. data/app/views/avo/base/_boolean_filter.html.erb +1 -1
  263. data/app/views/avo/base/_date_time_filter.html.erb +3 -3
  264. data/app/views/avo/base/_multiple_select_filter.html.erb +1 -1
  265. data/app/views/avo/base/_new_via_belongs_to.html.erb +2 -3
  266. data/app/views/avo/base/_text_filter.html.erb +1 -1
  267. data/app/views/avo/base/preview.html.erb +5 -4
  268. data/app/views/avo/debug/status.html.erb +5 -92
  269. data/app/views/avo/debug/status.text.erb +0 -2
  270. data/app/views/avo/home/_actions.html.erb +1 -1
  271. data/app/views/avo/home/_dashboards.html.erb +1 -1
  272. data/app/views/avo/home/_filters.html.erb +1 -1
  273. data/app/views/avo/home/_resources.html.erb +2 -2
  274. data/app/views/avo/home/failed_to_load.html.erb +2 -2
  275. data/app/views/avo/home/index.html.erb +25 -25
  276. data/app/views/avo/media_library/_form.html.erb +43 -28
  277. data/app/views/avo/media_library/show.html.erb +7 -3
  278. data/app/views/avo/modal/_size_selector.html.erb +46 -0
  279. data/app/views/avo/partials/_alerts.html.erb +1 -1
  280. data/app/views/avo/partials/_color_scheme_switcher.html.erb +106 -0
  281. data/app/views/avo/partials/_color_theme_override.html.erb +49 -0
  282. data/app/views/avo/partials/_confirm_dialog.html.erb +19 -17
  283. data/app/views/avo/partials/_custom_tools_alert.html.erb +6 -6
  284. data/app/views/avo/partials/_footer.html.erb +1 -1
  285. data/app/views/avo/partials/_header.html.erb +1 -1
  286. data/app/views/avo/partials/_javascript.html.erb +0 -2
  287. data/app/views/avo/partials/_navbar.html.erb +53 -8
  288. data/app/views/avo/partials/_sortable_component.html.erb +1 -1
  289. data/app/views/avo/partials/_table_header.html.erb +28 -19
  290. data/app/views/avo/partials/_view_toggle_button.html.erb +6 -29
  291. data/app/views/avo/partials/distribution_chart.html.erb +2 -2
  292. data/app/views/avo/private/_links_and_buttons.html.erb +12 -8
  293. data/app/views/avo/private/design.html.erb +8 -4
  294. data/app/views/avo/sidebar/_license_warning.html.erb +3 -3
  295. data/app/views/layouts/avo/application.html.erb +39 -17
  296. data/app/views/layouts/avo/modal.html.erb +7 -0
  297. data/avo.gemspec +3 -4
  298. data/config/i18n-tasks.yml +1 -1
  299. data/config/importmap.rb +1 -0
  300. data/config/initializers/pagy.rb +5 -25
  301. data/config/routes/dynamic_routes.rb +4 -0
  302. data/config/routes.rb +6 -7
  303. data/db/factories.rb +14 -0
  304. data/lib/avo/asset_manager.rb +2 -0
  305. data/lib/avo/avatar.rb +7 -0
  306. data/lib/avo/base_action.rb +16 -4
  307. data/lib/avo/concerns/breadcrumbs.rb +7 -66
  308. data/lib/avo/concerns/form_builder.rb +41 -0
  309. data/lib/avo/concerns/{has_profile_photo.rb → has_avatar.rb} +8 -4
  310. data/lib/avo/concerns/{has_cover_photo.rb → has_cover.rb} +4 -4
  311. data/lib/avo/concerns/has_description.rb +9 -0
  312. data/lib/avo/concerns/has_item_type.rb +6 -2
  313. data/lib/avo/concerns/has_items.rb +43 -58
  314. data/lib/avo/concerns/pagination.rb +29 -19
  315. data/lib/avo/concerns/row_controls_configuration.rb +22 -15
  316. data/lib/avo/configuration/branding.rb +7 -7
  317. data/lib/avo/configuration.rb +92 -45
  318. data/lib/avo/{cover_photo.rb → cover.rb} +2 -2
  319. data/lib/avo/current.rb +0 -11
  320. data/lib/avo/discreet_information.rb +52 -29
  321. data/lib/avo/dsl/field_parser.rb +1 -1
  322. data/lib/avo/engine.rb +41 -8
  323. data/lib/avo/error_manager.rb +1 -1
  324. data/lib/avo/fields/avatar_field.rb +19 -0
  325. data/lib/avo/fields/badge_field.rb +23 -3
  326. data/lib/avo/fields/base_field.rb +46 -1
  327. data/lib/avo/fields/concerns/dom_id.rb +17 -0
  328. data/lib/avo/fields/concerns/file_authorization.rb +4 -0
  329. data/lib/avo/fields/concerns/has_html_attributes.rb +1 -1
  330. data/lib/avo/fields/concerns/is_searchable.rb +2 -5
  331. data/lib/avo/fields/concerns/nested.rb +1 -1
  332. data/lib/avo/fields/files_field.rb +2 -2
  333. data/lib/avo/fields/frame_base_field.rb +2 -2
  334. data/lib/avo/fields/id_field.rb +5 -1
  335. data/lib/avo/fields/progress_bar_field.rb +1 -1
  336. data/lib/avo/fields/text_field.rb +1 -1
  337. data/lib/avo/photo_object.rb +12 -1
  338. data/lib/avo/plugin_manager.rb +4 -0
  339. data/lib/avo/resources/base.rb +33 -21
  340. data/lib/avo/resources/controls/actions_list.rb +3 -3
  341. data/lib/avo/resources/controls/base_control.rb +1 -1
  342. data/lib/avo/resources/items/card.rb +16 -0
  343. data/lib/avo/resources/items/header.rb +11 -0
  344. data/lib/avo/resources/items/holder.rb +18 -23
  345. data/lib/avo/resources/items/item_group.rb +5 -7
  346. data/lib/avo/resources/items/sidebar.rb +5 -9
  347. data/lib/avo/resources/items/tab.rb +8 -8
  348. data/lib/avo/resources/items/tab_group.rb +8 -10
  349. data/lib/avo/resources/resource_manager.rb +2 -1
  350. data/lib/avo/services/hq_reporter.rb +102 -0
  351. data/lib/avo/services/telemetry_service.rb +0 -1
  352. data/lib/avo/test_helpers.rb +36 -22
  353. data/lib/avo/u_i_instance.rb +60 -0
  354. data/lib/avo/version.rb +1 -1
  355. data/lib/avo/view_inquirer.rb +6 -1
  356. data/lib/avo/view_types/view_type_manager.rb +70 -0
  357. data/lib/avo.rb +30 -45
  358. data/lib/generators/avo/action_generator.rb +1 -1
  359. data/lib/generators/avo/resource_generator.rb +43 -0
  360. data/lib/generators/avo/resource_tool_generator.rb +1 -1
  361. data/lib/generators/avo/tailwindcss/install_generator.rb +0 -6
  362. data/lib/generators/avo/templates/cards/partial_card_partial.tt +1 -1
  363. data/lib/generators/avo/templates/initializer/avo.tt +7 -9
  364. data/lib/generators/avo/templates/locales/avo.ar.yml +25 -0
  365. data/lib/generators/avo/templates/locales/avo.de.yml +25 -0
  366. data/lib/generators/avo/templates/locales/avo.en.yml +25 -0
  367. data/lib/generators/avo/templates/locales/avo.es.yml +25 -0
  368. data/lib/generators/avo/templates/locales/avo.fr.yml +25 -0
  369. data/lib/generators/avo/templates/locales/avo.it.yml +25 -0
  370. data/lib/generators/avo/templates/locales/avo.ja.yml +25 -0
  371. data/lib/generators/avo/templates/locales/avo.nb.yml +25 -0
  372. data/lib/generators/avo/templates/locales/avo.nl.yml +25 -0
  373. data/lib/generators/avo/templates/locales/avo.nn.yml +25 -0
  374. data/lib/generators/avo/templates/locales/avo.pl.yml +25 -0
  375. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +25 -0
  376. data/lib/generators/avo/templates/locales/avo.pt.yml +25 -0
  377. data/lib/generators/avo/templates/locales/avo.ro.yml +25 -0
  378. data/lib/generators/avo/templates/locales/avo.ru.yml +25 -0
  379. data/lib/generators/avo/templates/locales/avo.tr.yml +25 -0
  380. data/lib/generators/avo/templates/locales/{avo.uk.yml → avo.ua.yml} +26 -1
  381. data/lib/generators/avo/templates/locales/avo.zh-TW.yml +25 -0
  382. data/lib/generators/avo/templates/locales/avo.zh.yml +25 -0
  383. data/lib/generators/avo/templates/resource/resource.tt +10 -1
  384. data/lib/generators/avo/templates/resource_tools/partial.tt +20 -22
  385. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +1 -3
  386. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +0 -7
  387. data/lib/generators/avo/templates/tool/view.tt +14 -16
  388. data/lib/generators/avo/tool_generator.rb +3 -3
  389. data/lib/generators/avo/version_generator.rb +1 -1
  390. data/lib/tasks/avo_tasks.rake +29 -25
  391. metadata +145 -97
  392. data/app/assets/stylesheets/avo.base.css +0 -130
  393. data/app/assets/stylesheets/css/breadcrumbs.css +0 -16
  394. data/app/assets/stylesheets/css/buttons.css +0 -19
  395. data/app/assets/stylesheets/css/tailwindcss/base.css +0 -1
  396. data/app/assets/stylesheets/css/tailwindcss/components.css +0 -1
  397. data/app/assets/stylesheets/css/tailwindcss/utilities.css +0 -1
  398. data/app/assets/svgs/avo/arrow-down.svg +0 -3
  399. data/app/assets/svgs/avo/arrow-up.svg +0 -3
  400. data/app/assets/svgs/avo/detach.svg +0 -8
  401. data/app/assets/svgs/avo/download-solid-reversed.svg +0 -3
  402. data/app/assets/svgs/avo/download-solid.svg +0 -3
  403. data/app/assets/svgs/avo/edit.svg +0 -5
  404. data/app/assets/svgs/avo/editor-bold.svg +0 -1
  405. data/app/assets/svgs/avo/editor-italic.svg +0 -1
  406. data/app/assets/svgs/avo/editor-link.svg +0 -1
  407. data/app/assets/svgs/avo/editor-list.svg +0 -1
  408. data/app/assets/svgs/avo/editor-strike.svg +0 -1
  409. data/app/assets/svgs/avo/editor-underline.svg +0 -1
  410. data/app/assets/svgs/avo/eye.svg +0 -1
  411. data/app/assets/svgs/avo/trash-sm.svg +0 -3
  412. data/app/assets/svgs/avo/trash.svg +0 -7
  413. data/app/components/avo/cover_photo_component.html.erb +0 -3
  414. data/app/components/avo/cover_photo_component.rb +0 -19
  415. data/app/components/avo/fields/common/badge_viewer_component.html.erb +0 -1
  416. data/app/components/avo/fields/common/badge_viewer_component.rb +0 -33
  417. data/app/components/avo/index/resource_grid_component.html.erb +0 -23
  418. data/app/components/avo/index/resource_grid_component.rb +0 -10
  419. data/app/components/avo/index/resource_map_component.html.erb +0 -16
  420. data/app/components/avo/index/resource_map_component.rb +0 -114
  421. data/app/components/avo/index/resource_table_component.html.erb +0 -52
  422. data/app/components/avo/panel_component.html.erb +0 -63
  423. data/app/components/avo/panel_component.rb +0 -43
  424. data/app/components/avo/panel_header_component.html.erb +0 -42
  425. data/app/components/avo/panel_header_component.rb +0 -31
  426. data/app/components/avo/profile_photo_component.html.erb +0 -6
  427. data/app/components/avo/profile_photo_component.rb +0 -9
  428. data/app/components/avo/sidebar/heading_component.html.erb +0 -21
  429. data/app/components/avo/sidebar/heading_component.rb +0 -9
  430. data/app/components/avo/tab_switcher_component.html.erb +0 -20
  431. data/app/components/avo/tab_switcher_component.rb +0 -45
  432. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +0 -8
  433. data/app/views/avo/debug/report.html.erb +0 -37
  434. data/app/views/avo/partials/_panel_breadcrumbs.html.erb +0 -3
  435. data/app/views/avo/partials/_resource_search.html.erb +0 -16
  436. data/lib/avo/licensing/community_license.rb +0 -6
  437. data/lib/avo/licensing/h_q.rb +0 -202
  438. data/lib/avo/licensing/license.rb +0 -76
  439. data/lib/avo/licensing/license_manager.rb +0 -24
  440. data/lib/avo/licensing/nil_license.rb +0 -14
  441. data/lib/avo/licensing/pro_license.rb +0 -20
  442. data/lib/avo/licensing/request.rb +0 -20
  443. data/lib/avo/profile_photo.rb +0 -7
  444. data/lib/avo/services/debug_service.rb +0 -107
  445. data/public/avo-assets/placeholder.svg +0 -1
  446. data/tailwind.preset.js +0 -171
  447. /data/{public/avo-assets → app/assets/images/avo}/favicon.ico +0 -0
  448. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.eot +0 -0
  449. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.svg +0 -0
  450. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.ttf +0 -0
  451. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.woff +0 -0
  452. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.woff2 +0 -0
  453. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.eot +0 -0
  454. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.svg +0 -0
  455. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.ttf +0 -0
  456. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.woff +0 -0
  457. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.woff2 +0 -0
  458. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.eot +0 -0
  459. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.svg +0 -0
  460. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.ttf +0 -0
  461. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.woff +0 -0
  462. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.woff2 +0 -0
  463. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.eot +0 -0
  464. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.svg +0 -0
  465. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.ttf +0 -0
  466. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.woff +0 -0
  467. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.woff2 +0 -0
  468. /data/{public/avo-assets → app/assets/images/avo}/logo-on-white.png +0 -0
  469. /data/{public/avo-assets → app/assets/images/avo}/logo.png +0 -0
  470. /data/{public/avo-assets → app/assets/images/avo}/logomark.png +0 -0
@@ -0,0 +1,17 @@
1
+ <% if @resources.present? %>
2
+ <div class="map-view-container grid <%= grid_layout_classes %> w-full gap-4">
3
+ <%= tag.div class: class_names("map-component rounded-2xl overflow-hidden", map_component_order_class), data: { controller: "map-dark-mode" } do %>
4
+ <%= js_map(resource_location_markers, **resource_mapkick_options) %>
5
+ <% end %>
6
+
7
+ <% if render_table? %>
8
+ <div class="overflow-auto <%= table_component_order_class %>">
9
+ <%= render(@resource.resolve_component(Avo::ViewTypes::TableComponent).new(resources: @resources, resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, pagy: @pagy, query: @query, actions: @actions, turbo_frame: @turbo_frame, index_params: @index_params)) %>
10
+ </div>
11
+ <% end %>
12
+ </div>
13
+ <% else %>
14
+ <div class="rounded-sm bg-white shadow-panel">
15
+ <%= helpers.empty_state by_association: params[:related_name].present? %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Render a map view for a list of resources, where each resource is
4
+ # expected to have an attribute/attribute set representing its location.
5
+ class Avo::ViewTypes::MapComponent < Avo::ViewTypes::BaseViewTypeComponent
6
+ attr_reader :resources
7
+
8
+ delegate :js_map, to: :helpers
9
+
10
+ def grid_layout_classes
11
+ return unless render_table?
12
+
13
+ if horizontal_layout?
14
+ "grid-flow-row sm:grid-flow-col grid-rows-1 auto-cols-fr"
15
+ elsif vertical_layout?
16
+ "grid-flow-row grid-cols-1"
17
+ end
18
+ end
19
+
20
+ def horizontal_layout?
21
+ %i[left right].include?(map_position)
22
+ end
23
+
24
+ def vertical_layout?
25
+ %i[bottom top].include?(map_position)
26
+ end
27
+
28
+ def map_component_order_class
29
+ if render_table? && table_positioned_at_the_start?
30
+ "order-last"
31
+ else
32
+ "order-first"
33
+ end
34
+ end
35
+
36
+ def table_component_order_class
37
+ if table_positioned_at_the_start?
38
+ "order-first"
39
+ else
40
+ "order-last"
41
+ end
42
+ end
43
+
44
+ def table_positioned_at_the_start?
45
+ %i[right bottom].include?(map_position)
46
+ end
47
+
48
+ def map_position
49
+ map_options.dig(:map, :position)
50
+ end
51
+
52
+ def resource_location_markers
53
+ # If we have no proc and no default location method, don't try to create markers
54
+ return [] unless resource_mappable?
55
+
56
+ records_markers = resources
57
+ .map do |resource|
58
+ Avo::ExecutionContext.new(target: marker_proc, record: resource.record).handle
59
+ end
60
+ .compact
61
+ .filter do |coordinates|
62
+ coordinates[:latitude].present? && coordinates[:longitude].present?
63
+ end
64
+
65
+ return records_markers if map_options[:extra_markers].nil?
66
+
67
+ records_markers + Avo::ExecutionContext.new(target: map_options[:extra_markers]).handle
68
+ end
69
+
70
+ def resource_mapkick_options
71
+ options = map_options[:mapkick_options] || {}
72
+
73
+ options[:height] = if horizontal_layout?
74
+ "100%"
75
+ else
76
+ "26rem"
77
+ end
78
+
79
+ options[:style] ||= "mapbox://styles/mapbox/light-v11"
80
+
81
+ options
82
+ end
83
+
84
+ def render_table?
85
+ map_options.dig(:table, :visible)
86
+ end
87
+
88
+ private
89
+
90
+ def default_record_marker_proc
91
+ lambda {
92
+ {
93
+ latitude: record.coordinates.first,
94
+ longitude: record.coordinates.last
95
+ }
96
+ }
97
+ end
98
+
99
+ def map_options
100
+ @resource.map_view || {}
101
+ end
102
+
103
+ def marker_proc
104
+ map_options[:record_marker] || default_record_marker_proc
105
+ end
106
+
107
+ def resource_mappable?
108
+ map_options[:record_marker].present? || map_options[:extra_markers].present? || @resources.first.record.respond_to?(:coordinates)
109
+ end
110
+ end
@@ -0,0 +1,63 @@
1
+ <turbo-frame id="<%= "#{@resource.model_key}_list" %>" target="_top" class="relative w-full">
2
+ <div
3
+ class="card relative w-full"
4
+ data-component-name="<%= self.class.to_s.underscore %>"
5
+ data-controller="item-select-all"
6
+ data-resource-name="<%= @resource.model_key %>"
7
+ data-item-select-all-selected-all-value="false"
8
+ data-item-select-all-selected-all-query-value="<%= encrypted_query %>"
9
+ data-item-select-all-page-count-value="<%= @pagy.pages %>"
10
+ data-selected-resources-name="<%= @resource.model_key %>"
11
+ data-selected-resources="[]"
12
+ >
13
+ <div class="card__wrapper mac-styled-scrollbar overflow-auto">
14
+ <% if @pagy.pages > 1 %>
15
+ <div
16
+ class="absolute z-30 ms-10 hidden w-[calc(100%-4rem)] mt-0.5 "
17
+ data-item-select-all-target="selectAllOverlay"
18
+ >
19
+ <div class="flex items-center ps-2 bg-secondary w-full">
20
+ <div data-item-select-all-target="unselectedMessage">
21
+ <%= selected_page_label %>
22
+
23
+ <%= a_link request.url,
24
+ size: :xs,
25
+ color: :primary,
26
+ class: "relative -top-[0.1rem] ms-2 cursor-pointer text-primary-500",
27
+ data: {action: "click->item-select-all#selectAll"} do %>
28
+ <%= t "avo.select_all_matching" %>
29
+ <% end %>
30
+ </div>
31
+
32
+ <div class="hidden w-full " data-item-select-all-target="selectedMessage">
33
+ <%= selected_all_label %>
34
+
35
+ <%= a_link request.url,
36
+ size: :xs,
37
+ color: :primary,
38
+ class: "relative -top-[0.1rem] ms-2 cursor-pointer text-primary-500",
39
+ data: {action: "click->item-select-all#selectAll"} do %>
40
+ <%= t("avo.undo").humanize %>
41
+ <% end %>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ <% end %>
46
+
47
+ <table class="w-full border-separate border-spacing-0">
48
+ <%= render partial: 'avo/partials/table_header', locals: {fields: @header_fields, resource: @resource} %>
49
+
50
+ <%= content_tag :tbody, class: "card__body table-row-group rounded-lg tr>td:first:rounded-t-lg tr>td:last:rounded-b-lg",
51
+ data: {
52
+ **(try(:drag_reorder_data_attributes) || {}),
53
+ } do %>
54
+ <% @table_row_components.each do |table_row_component| %>
55
+ <%= render table_row_component %>
56
+ <% end %>
57
+ <% end %>
58
+ </table>
59
+
60
+ </div>
61
+ <div class="card__footer"><%= render paginator_component %></div>
62
+ </div>
63
+ </turbo-frame>
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Avo::Index::ResourceTableComponent < Avo::BaseComponent
3
+ class Avo::ViewTypes::TableComponent < Avo::ViewTypes::BaseViewTypeComponent
4
4
  include Avo::ApplicationHelper
5
5
  attr_reader :pagy, :query
6
6
 
@@ -8,15 +8,6 @@ class Avo::Index::ResourceTableComponent < Avo::BaseComponent
8
8
  @header_fields, @table_row_components = cache_table_rows
9
9
  end
10
10
 
11
- prop :resources
12
- prop :resource
13
- prop :reflection
14
- prop :parent_record
15
- prop :parent_resource
16
- prop :pagy
17
- prop :query
18
- prop :actions
19
-
20
11
  def encrypted_query
21
12
  # TODO: move this to the resource where we can apply the adapter pattern
22
13
  if Module.const_defined?("Ransack::Search") && @query.instance_of?(Ransack::Search)
@@ -9,21 +9,11 @@
9
9
  **@resource.stimulus_data_attributes
10
10
  } do %>
11
11
  <%= render_cards_component %>
12
- <%= form_with model: @resource.record,
13
- scope: @resource.form_scope,
14
- url: form_url,
15
- method: form_method,
16
- local: true,
17
- html: {
18
- novalidate: true,
19
- data: {
20
- controller: "form",
21
- action: "keydown.ctrl+enter->form#submit keydown.meta+enter->form#submit"
22
- }
23
- },
24
- multipart: true do |form| %>
12
+
13
+ <%= build_form do |form| %>
25
14
  <%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
26
- <%= content_tag :div, class: "space-y-12" do %>
15
+
16
+ <%= content_tag :div, class: "panel-spacer" do %>
27
17
  <% @resource.get_items.each_with_index do |item, index| %>
28
18
  <%= render Avo::Items::SwitcherComponent.new(
29
19
  resource: @resource,
@@ -40,10 +30,14 @@
40
30
  <% end %>
41
31
 
42
32
  <% if Avo.configuration.buttons_on_form_footers %>
43
- <%= render Avo::PanelComponent.new do |c| %>
44
- <% c.with_footer_tools do %>
45
- <% @resource.render_edit_controls.each do |control| %>
46
- <%= render_control control %>
33
+ <%= render ui.panel do |panel| %>
34
+ <% panel.with_footer do %>
35
+ <%= render ui.panel_header do |header| %>
36
+ <% header.with_controls do %>
37
+ <% @resource.render_edit_controls.each do |control| %>
38
+ <%= render_control control %>
39
+ <% end %>
40
+ <% end %>
47
41
  <% end %>
48
42
  <% end %>
49
43
  <% end %>
@@ -2,16 +2,12 @@
2
2
 
3
3
  class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
4
4
  include Avo::ApplicationHelper
5
+ include Avo::Concerns::FormBuilder
5
6
 
6
7
  prop :resource
7
8
  prop :record
8
9
  prop :actions, default: [].freeze
9
10
  prop :view, default: Avo::ViewInquirer.new(:edit).freeze
10
- prop :display_breadcrumbs, default: true, reader: :public
11
-
12
- def after_initialize
13
- @display_breadcrumbs = @reflection.blank? && display_breadcrumbs
14
- end
15
11
 
16
12
  def title
17
13
  @resource.default_panel_name
@@ -64,26 +60,4 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
64
60
  def is_edit?
65
61
  @view.in?(%w[edit update])
66
62
  end
67
-
68
- def form_method
69
- return :put if is_edit?
70
-
71
- :post
72
- end
73
-
74
- def form_url
75
- if is_edit?
76
- helpers.resource_path(
77
- record: @resource.record,
78
- resource: @resource
79
- )
80
- else
81
- helpers.resources_path(
82
- resource: @resource,
83
- via_relation_class: params[:via_relation_class],
84
- via_relation: params[:via_relation],
85
- via_record_id: params[:via_record_id]
86
- )
87
- end
88
- end
89
63
  end
@@ -6,92 +6,115 @@
6
6
  resource_name: @resource.class.to_s,
7
7
  **@resource.stimulus_data_attributes
8
8
  } do %>
9
+
9
10
  <%= render_cards_component %>
10
- <%= render Avo::PanelComponent.new(
11
- description: description,
12
- cover_photo: resource.cover_photo,
13
- data: {component: "resources-index"},
14
- display_breadcrumbs: (@reflection.blank? && @parent_resource.blank?) || (@reflection.present? && !helpers.turbo_frame_request?)
15
- ) do |c| %>
16
- <% c.with_name_slot do %>
17
- <%= render Avo::PanelNameComponent.new name: title, url: (params[:turbo_frame].present? && linkable?) ? field.frame_url(add_turbo_frame: false) : nil, target: :_blank do |panel_name_component| %>
18
- <% panel_name_component.with_body do %>
19
- <% if reloadable %>
20
- <%= button_tag data: { controller: "panel-refresh", action: "click->panel-refresh#refresh" } do %>
21
- <%= helpers.svg "heroicons/outline/arrow-path", class: "ml-2 text-2xl h-6 " %>
22
- <% end %>
23
- <% end %>
11
+
12
+ <%= render ui.panel(
13
+ cover: resource.cover,
14
+ class: "w-full px-2",
15
+ data: {
16
+ component_name:,
17
+ controller: "resource-search",
18
+ "resource-search-debounce-value": "500",
19
+ "resource-search-url-value": request.fullpath
20
+ },
21
+ ) do |panel| %>
22
+ <% if @resource.cover.present? %>
23
+ <% panel.with_cover do %>
24
+ <%= render Avo::CoverComponent.new cover: @resource.cover %>
24
25
  <% end %>
25
26
  <% end %>
26
- <% end %>
27
- <% c.with_tools do %>
28
- <% @resource.render_index_controls(item: singular_resource_name.downcase).each do |control| %>
29
- <%= render_control control %>
30
- <% end %>
31
- <% end %>
32
- <% c.with_body do %>
33
- <div class="flex flex-col">
34
- <%= render scopes_list if can_render_scopes? %>
35
- <div class="flex flex-col">
36
- <div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= "hidden" unless header_visible? %>">
37
- <div class="flex items-center px-4 w-64">
38
- <% if show_search_input %>
39
- <%= render partial: "avo/partials/resource_search", locals: {resource: @resource.route_key, via_reflection: via_reflection} %>
40
- <% else %>
41
- <%# Offset for the space-y-2 property when the search is missing %>
42
- <div class="-mb-2"></div>
43
- <% end %>
44
- </div>
45
27
 
46
- <div class="justify-self-end flex justify-start xs:justify-end items-center px-4 space-x-3">
47
- <%= render_dynamic_filters_button %>
48
- <% unless field&.hide_filter_button %>
49
- <%= render Avo::FiltersComponent.new filters: @filters, resource: @resource, applied_filters: @applied_filters, parent_record: @parent_record %>
50
- <% end %>
28
+ <% panel.with_header do %>
29
+ <%= render ui.panel_header(
30
+ title:,
31
+ description:
32
+ ) do |header| %>
33
+ <% header.with_title_slot do %>
34
+ <% if reloadable? %>
35
+ <%= render Avo::DiscreetInformationComponent.new(
36
+ icon: "tabler/outline/refresh",
37
+ as: :icon,
38
+ title: t('avo.reload'),
39
+ classes: "cursor-pointer",
40
+ data: { controller: "panel-refresh", action: "click->panel-refresh#refresh" }
41
+ ) %>
42
+ <% end %>
51
43
 
52
- <%= render partial: "avo/partials/view_toggle_button", locals: { available_view_types: @resource.available_view_types, view_type: @resource.view_type, turbo_frame: @turbo_frame } %>
53
- </div>
54
- </div>
55
- <% if has_dynamic_filters? %>
56
- <%= render Avo::DynamicFilters::FiltersComponent.new resource: resource, turbo_frame: @turbo_frame, dynamic_filters_component_id: dynamic_filters_component_id, parent_record: @parent_record, parent_resource: @parent_resource %>
44
+ <% if linkable? %>
45
+ <%= render Avo::DiscreetInformationComponent.new(
46
+ icon: "tabler/outline/external-link",
47
+ as: :icon,
48
+ url: field.frame_url(add_turbo_frame: false),
49
+ target: :_blank,
50
+ title: t('avo.open_in_new_tab')
51
+ ) %>
52
+ <% end %>
53
+
54
+ <% if Rails.env.development? %>
55
+ <%= render Avo::DiscreetInformationComponent.new(
56
+ as: :icon,
57
+ title: t('avo.open_in_your_editor'),
58
+ url: helpers.editor_file_path(@resource),
59
+ icon: "tabler/outline/code"
60
+ ) %>
57
61
  <% end %>
58
- </div>
59
- </div>
60
- <% if @resource.view_type.to_sym == :table %>
61
- <% if @resources.present? %>
62
- <div class="w-full relative flex-1 flex mt-0">
63
- <%= render(@resource.resolve_component(Avo::Index::ResourceTableComponent).new(resources: @resources, resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, pagy: @pagy, query: @query, actions: @actions)) %>
64
- </div>
65
- <% else %>
66
- <%= helpers.empty_state by_association: params[:related_name].present?, view_type: @resource.view_type, add_background: true %>
67
62
  <% end %>
68
- <% end %>
69
- <% end %>
70
- <% c.with_bare_content do %>
71
- <% if @resource.view_type.to_sym == :map %>
72
- <% if @resources.present? %>
73
- <div>
74
- <%= render(@resource.resolve_component(Avo::Index::ResourceMapComponent).new(resources: @resources, resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
63
+
64
+ <% header.with_controls do %>
65
+ <div class="flex gap-3">
66
+ <% @resource.render_index_controls(item: singular_resource_name.downcase).each do |control| %>
67
+ <%= render_control control %>
68
+ <% end %>
75
69
  </div>
76
- <% else %>
77
- <%= helpers.empty_state by_association: params[:related_name].present?, view_type: @resource.view_type, add_background: true %>
78
70
  <% end %>
79
71
  <% end %>
80
- <% if @resource.view_type.to_sym == :table || @resource.view_type.to_sym == :map %>
81
- <% if @records.present? %>
82
- <div class="mt-4 w-full">
83
- <%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame, index_params: @index_params, resource: @resource, parent_record: @parent_record, parent_resource: @parent_resource, discreet_pagination: field&.discreet_pagination %>
72
+ <% end %>
73
+
74
+ <% panel.with_body do %>
75
+ <div class="relative flex flex-col gap-y-4">
76
+ <% if header_visible? %>
77
+ <div class="relative flex flex-col gap-y-4 z-20">
78
+ <div class="flex flex-col gap-y-4">
79
+ <%= render scopes_list if can_render_scopes? %>
80
+
81
+ <div class="flex flex-col xs:flex-row xs:justify-between">
82
+ <div class="flex w-64 items-center">
83
+ <% if show_search_input %>
84
+ <%= render ui.search_input(
85
+ name: "q",
86
+ value: params[:q],
87
+ id: nil,
88
+ placeholder: t('avo.search.placeholder'),
89
+ data: {
90
+ action: "input->resource-search#search",
91
+ "resource-search-target": "input"
92
+ }) %>
93
+ <% end %>
94
+ </div>
95
+
96
+ <div class="flex items-center justify-start space-x-3 rtl:space-x-reverse justify-self-end px-4 xs:justify-end">
97
+ <div class="index-missing-resources:hidden">
98
+ <%= render_dynamic_filters_button %>
99
+ </div>
100
+
101
+ <% unless field&.hide_filter_button %>
102
+ <%= render Avo::FiltersComponent.new filters: @filters, resource: @resource, applied_filters: @applied_filters, parent_record: @parent_record %>
103
+ <% end %>
104
+
105
+ <%= render partial: "avo/partials/view_toggle_button", locals: { available_view_types: @resource.available_view_types, view_type: @resource.view_type, turbo_frame: @turbo_frame } %>
106
+ </div>
107
+ </div>
108
+
109
+ <% if has_dynamic_filters? %>
110
+ <%= render Avo::DynamicFilters::FiltersComponent.new resource: resource, turbo_frame: @turbo_frame, dynamic_filters_component_id: dynamic_filters_component_id, parent_record: @parent_record, parent_resource: @parent_resource %>
111
+ <% end %>
112
+ </div>
84
113
  </div>
85
114
  <% end %>
86
- <% end %>
87
- <% if @resource.view_type.to_sym == :grid %>
88
- <div id="records_panel">
89
- <%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, actions: @actions) %>
90
- </div>
91
- <div class="mt-6">
92
- <%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame, index_params: @index_params, resource: @resource, parent_record: @parent_record, parent_resource: @parent_resource, discreet_pagination: field&.discreet_pagination %>
93
- </div>
94
- <% end %>
115
+
116
+ <%= render Avo::ResourceListingComponent.new(**resource_content_components_common_args) %>
117
+ </div>
95
118
  <% end %>
96
119
  <% end %>
97
120
  <% end %>
@@ -130,6 +130,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
130
130
  def render_dynamic_filters_button
131
131
  return unless Avo.avo_dynamic_filters_installed?
132
132
  return unless @resource.has_filters?
133
+ return unless has_resources?
133
134
  return if field&.hide_filter_button
134
135
  return if Avo::DynamicFilters.configuration.always_expanded
135
136
 
@@ -157,7 +158,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
157
158
  end
158
159
 
159
160
  def can_render_scopes?
160
- defined?(Avo::Advanced)
161
+ defined?(Avo::Advanced) && @scopes.present?
161
162
  end
162
163
 
163
164
  def back_path
@@ -194,7 +195,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
194
195
  end
195
196
 
196
197
  def header_visible?
197
- search_query_present? || filters_present? || has_many_view_types? || has_dynamic_filters?
198
+ search_query_present? || filters_present? || has_many_view_types? || has_dynamic_filters? || show_search_input || can_render_scopes?
198
199
  end
199
200
 
200
201
  def has_dynamic_filters?
@@ -219,11 +220,30 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
219
220
  @dynamic_filters_component_id ||= "dynamic_filters_component_id_#{SecureRandom.hex(3)}"
220
221
  end
221
222
 
222
- def reloadable
223
+ def reloadable?
223
224
  field&.reloadable?
224
225
  end
225
226
 
226
227
  def linkable?
227
228
  field&.linkable?
228
229
  end
230
+
231
+ def resource_content_components_common_args
232
+ @resource_content_components_common_args ||= {
233
+ resources: @resources,
234
+ resource: @resource,
235
+ reflection: @reflection,
236
+ parent_record: @parent_record,
237
+ parent_resource: @parent_resource,
238
+ pagy: @pagy,
239
+ query: @query,
240
+ actions: @actions,
241
+ turbo_frame: @turbo_frame,
242
+ index_params: @index_params
243
+ }
244
+ end
245
+
246
+ def has_resources?
247
+ @resources.present?
248
+ end
229
249
  end
@@ -7,8 +7,9 @@
7
7
  selected_resources: [@resource.record_param],
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
- <%= content_tag :div, class: 'space-y-12' do %>
10
+ <%= content_tag :div, class: "panel-spacer" do %>
11
11
  <%= render_cards_component %>
12
+
12
13
  <% @resource.get_items.each_with_index do |item, index| %>
13
14
  <%= render Avo::Items::SwitcherComponent.new(
14
15
  resource: @resource,
@@ -20,9 +21,10 @@
20
21
  parent_record: @parent_record,
21
22
  parent_component: self,
22
23
  actions: @actions
23
- )%>
24
+ ) %>
24
25
  <% end %>
25
26
  <% end %>
27
+
26
28
  <% if should_display_invalid_fields_errors? %>
27
29
  <turbo-stream action="append" target="alerts">
28
30
  <template>
@@ -3,8 +3,6 @@
3
3
  class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
4
4
  include Avo::ApplicationHelper
5
5
 
6
- attr_reader :display_breadcrumbs
7
-
8
6
  prop :resource
9
7
  prop :reflection
10
8
  prop :parent_resource
@@ -14,7 +12,6 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
14
12
 
15
13
  def after_initialize
16
14
  @view = Avo::ViewInquirer.new("show")
17
- @display_breadcrumbs = @reflection.blank?
18
15
  end
19
16
 
20
17
  def title
@@ -57,7 +54,7 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
57
54
  # When coming from a turbo frame, we don't want to return to that exact frame
58
55
  # for example when editing a has_one field we want to return to the parent frame
59
56
  # not the frame of the has_one field.
60
- args[:return_to] = e(request.fullpath) unless request.url.include?("turbo_frame=")
57
+ args[:return_to] = request.url unless request.url.include?("turbo_frame=")
61
58
 
62
59
  helpers.edit_resource_path(record: @resource.record, resource: @resource, **args)
63
60
  end
@@ -249,7 +249,7 @@ module Avo
249
249
  through_foreign_key => @record.id
250
250
  ),
251
251
  additional_params,
252
- fields: @attach_fields,
252
+ fields: @attach_fields
253
253
  )
254
254
  end
255
255
 
@@ -247,8 +247,9 @@ module Avo
247
247
  end
248
248
  end
249
249
 
250
- def mark_container_as_full_width
251
- @container_full_width = true
250
+ def mark_container_width(width)
251
+ raise ArgumentError, "Invalid container width: #{width}. Must be one of #{Avo::Configuration::VALID_CONTAINER_WIDTHS}" unless Avo::Configuration::VALID_CONTAINER_WIDTHS.include?(width.to_sym)
252
+ @container_size = width.to_s
252
253
  end
253
254
 
254
255
  def add_initial_breadcrumbs
@@ -295,13 +296,13 @@ module Avo
295
296
  end
296
297
 
297
298
  def set_stylesheet_assets_path
299
+ # TODO: handle this differently maybe?
300
+ # We'll definitely have to change it on TW4
298
301
  # Prefer the user's tailwind config if it exists, otherwise use the default one from Avo
299
302
  @stylesheet_assets_path = if Rails.root.join("config", "avo", "tailwind.config.js").exist?
300
303
  "avo.tailwind"
301
- elsif Avo::PACKED
302
- "/avo-assets/avo.base"
303
304
  else
304
- "avo.base"
305
+ "avo/application"
305
306
  end
306
307
  end
307
308
 
@@ -326,6 +327,7 @@ module Avo
326
327
 
327
328
  def decode_params
328
329
  if params[:return_to].present?
330
+ params[:raw_return_to] = params[:return_to]
329
331
  params[:return_to] = d(params[:return_to])
330
332
  end
331
333
  end