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
@@ -23,11 +23,8 @@ module Avo
23
23
  attr_accessor :authenticate
24
24
  attr_accessor :current_user
25
25
  attr_accessor :id_links_to_resource
26
- attr_accessor :full_width_container
27
- attr_accessor :full_width_index_view
28
26
  attr_accessor :cache_resources_on_index_view
29
27
  attr_accessor :context
30
- attr_accessor :display_breadcrumbs
31
28
  attr_accessor :hide_layout_when_printing
32
29
  attr_accessor :initial_breadcrumbs
33
30
  attr_accessor :home_path
@@ -36,7 +33,7 @@ module Avo
36
33
  attr_accessor :display_license_request_timeout_error
37
34
  attr_accessor :current_user_resource_name
38
35
  attr_accessor :raise_error_on_missing_policy
39
- attr_writer :disabled_features
36
+ attr_accessor :global_search
40
37
  attr_accessor :buttons_on_form_footers
41
38
  attr_accessor :main_menu
42
39
  attr_accessor :profile_menu
@@ -59,6 +56,63 @@ module Avo
59
56
  attr_accessor :column_names_mapping
60
57
  attr_accessor :column_types_mapping
61
58
  attr_accessor :model_generator_hook
59
+ attr_accessor :send_metadata
60
+ attr_accessor :use_stacked_fields
61
+ attr_accessor :default_editor_url
62
+ attr_writer :body_classes
63
+ attr_accessor :sidebar_toggle_visible
64
+
65
+ unless defined?(CONTAINER_WIDTH_DEFAULTS)
66
+ CONTAINER_WIDTH_DEFAULTS = {
67
+ index: :large,
68
+ show: :small,
69
+ new: :small,
70
+ edit: :small,
71
+ create: :small,
72
+ update: :small
73
+ }.freeze
74
+
75
+ VALID_CONTAINER_WIDTHS = %i[full large small].freeze
76
+
77
+ CONTAINER_WIDTH_GROUPS = {
78
+ forms: %i[new edit create update],
79
+ display: %i[index show],
80
+ single: %i[show new edit create update]
81
+ }.freeze
82
+ end
83
+
84
+ def container_width=(value)
85
+ case value
86
+ when NilClass
87
+ @container_width = nil
88
+ when Symbol
89
+ raise ArgumentError, "Invalid container width: #{value}. Must be one of #{VALID_CONTAINER_WIDTHS}" unless VALID_CONTAINER_WIDTHS.include?(value)
90
+ @container_width = CONTAINER_WIDTH_DEFAULTS.transform_values { value }
91
+ when Hash
92
+ valid_keys = CONTAINER_WIDTH_DEFAULTS.keys + CONTAINER_WIDTH_GROUPS.keys
93
+ invalid_keys = value.keys.reject { |k| valid_keys.include?(k) }
94
+ raise ArgumentError, "Invalid container width keys: #{invalid_keys}. Valid keys: #{valid_keys}" if invalid_keys.any?
95
+
96
+ invalid_values = value.values.reject { |v| VALID_CONTAINER_WIDTHS.include?(v) }
97
+ raise ArgumentError, "Invalid container widths: #{invalid_values}" if invalid_values.any?
98
+
99
+ # Expand group aliases first
100
+ expanded_aliases = value
101
+ .select { |k, _| CONTAINER_WIDTH_GROUPS.key?(k) }
102
+ .each_with_object({}) do |(alias_key, width), result|
103
+ CONTAINER_WIDTH_GROUPS[alias_key].each { |view| result[view] = width }
104
+ end
105
+
106
+ # Specific keys win over group aliases
107
+ specific_keys = value.reject { |k, _| CONTAINER_WIDTH_GROUPS.key?(k) }
108
+
109
+ @container_width = CONTAINER_WIDTH_DEFAULTS.merge(expanded_aliases).merge(specific_keys)
110
+ end
111
+ end
112
+
113
+ def container_width
114
+ @container_width || CONTAINER_WIDTH_DEFAULTS
115
+ end
62
116
 
63
117
  def initialize
64
118
  @root_path = "/avo"
@@ -84,17 +138,14 @@ module Avo
84
138
  destroy: "destroy?"
85
139
  }
86
140
  @id_links_to_resource = false
87
- @full_width_container = false
88
- @full_width_index_view = false
89
141
  @cache_resources_on_index_view = Avo::PACKED
90
142
  @persistence = {
91
143
  driver: nil
92
144
  }
93
145
  @context = proc {}
94
146
  @initial_breadcrumbs = proc {
95
- add_breadcrumb I18n.t("avo.home").humanize, avo.root_path
147
+ add_breadcrumb title: I18n.t("avo.home").humanize, path: avo.root_path, icon: "tabler/outline/home"
96
148
  }
97
- @display_breadcrumbs = true
98
149
  @hide_layout_when_printing = false
99
150
  @home_path = nil
100
151
  @search_debounce = 300
@@ -102,7 +153,6 @@ module Avo
102
153
  @display_license_request_timeout_error = true
103
154
  @current_user_resource_name = "user"
104
155
  @raise_error_on_missing_policy = false
105
- @disabled_features = []
106
156
  @buttons_on_form_footers = false
107
157
  @main_menu = nil
108
158
  @profile_menu = nil
@@ -117,7 +167,7 @@ module Avo
117
167
  @turbo = default_turbo
118
168
  @default_url_options = []
119
169
  @pagination = {}
120
- @click_row_to_view_record = false
170
+ @click_row_to_view_record = true
121
171
  @alert_dismiss_time = 5000
122
172
  @is_admin_method = :is_admin?
123
173
  @is_developer_method = :is_developer?
@@ -128,7 +178,16 @@ module Avo
128
178
  @column_names_mapping = {}
129
179
  @column_types_mapping = {}
130
180
  @resource_row_controls_config = {}
181
+ @global_search = {
182
+ enabled: true,
183
+ navigation_section: true
184
+ }
131
185
  @model_generator_hook = true
186
+ @send_metadata = true
187
+ @use_stacked_fields = false
188
+ @default_editor_url = "cursor://file/%{path}"
189
+ @sidebar_toggle_visible = true
190
+ @body_classes = []
132
191
  end
133
192
 
134
193
  unless defined?(RESOURCE_ROW_CONTROLS_CONFIG_DEFAULTS)
@@ -183,14 +242,6 @@ module Avo
183
242
  @root_path
184
243
  end
185
244
 
186
- def disabled_features
187
- Avo::ExecutionContext.new(target: @disabled_features).handle
188
- end
189
-
190
- def feature_enabled?(feature)
191
- !disabled_features.map(&:to_sym).include?(feature.to_sym)
192
- end
193
-
194
245
  def branding
195
246
  Avo::Configuration::Branding.new(**@branding || {})
196
247
  end
@@ -199,30 +250,6 @@ module Avo
199
250
  Avo::ExecutionContext.new(target: @app_name).handle
200
251
  end
201
252
 
202
- def license=(value)
203
- if Rails.env.development?
204
- puts "[Avo DEPRECATION WARNING]: The `config.license` configuration option is no longer supported and will be removed in future versions. Please discontinue its use and solely utilize the `license_key` instead."
205
- end
206
- end
207
-
208
- def clear_license_response_on_deploy=(value)
209
- if Rails.env.development?
210
- puts "[Avo DEPRECATION WARNING]: The `config.clear_license_response_on_deploy` configuration option is deprecated and will be removed in future versions. Please discontinue its use, no extra action is needed."
211
- end
212
- end
213
-
214
- def license
215
- gems = Gem::Specification.map {|gem| gem.name}
216
-
217
- @license ||= if gems.include?("avo-advanced")
218
- "advanced"
219
- elsif gems.include?("avo-pro")
220
- "pro"
221
- elsif gems.include?("avo")
222
- "community"
223
- end
224
- end
225
-
226
253
  def resource_default_view=(view)
227
254
  @resource_default_view = Avo::ViewInquirer.new(view.to_s)
228
255
  end
@@ -234,7 +261,7 @@ module Avo
234
261
  ).handle
235
262
  end
236
263
 
237
- # When not in production or test we'll just use the FileStore which is good enough.
264
+ # When not in production we'll just use the FileStore which is good enough.
238
265
  # When running in production we'll use Rails.cache if it's not ActiveSupport::Cache::MemoryStore or ActiveSupport::Cache::NullStore.
239
266
  # If it's one of rejected cache stores, we'll use the FileStore.
240
267
  # We decided against the MemoryStore in production because it will not be shared between multiple processes (when using Puma).
@@ -248,8 +275,6 @@ module Avo
248
275
  else
249
276
  Rails.cache
250
277
  end
251
- elsif Rails.env.test?
252
- Rails.cache
253
278
  else
254
279
  file_store_instance
255
280
  end
@@ -299,10 +324,32 @@ module Avo
299
324
  @locale || I18n.default_locale
300
325
  end
301
326
 
327
+ # Known RTL (Right-to-Left) locale codes
328
+ RTL_LOCALES = %w[ar he fa ur yi ps sd ku ckb ug dv].freeze unless defined?(RTL_LOCALES)
329
+
330
+ # Check if the given locale is RTL
331
+ def self.rtl_locale?(locale = I18n.locale)
332
+ RTL_LOCALES.include?(locale.to_s.split("-").first.downcase)
333
+ end
334
+
335
+ # Check if the current locale is RTL
336
+ def rtl?
337
+ self.class.rtl_locale?(I18n.locale)
338
+ end
339
+
340
+ # Returns "rtl" or "ltr" based on current locale
341
+ def text_direction
342
+ rtl? ? "rtl" : "ltr"
343
+ end
344
+
302
345
  def explicit_authorization
303
346
  Avo::ExecutionContext.new(target: @explicit_authorization).handle
304
347
  end
305
348
 
349
+ def body_classes
350
+ Avo::ExecutionContext.new(target: @body_classes).handle
351
+ end
352
+
306
353
  def persistence
307
354
  Avo::ExecutionContext.new(target: @persistence).handle
308
355
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Avo
4
- class CoverPhoto < PhotoObject
5
- def key = :cover_photo
4
+ class Cover < PhotoObject
5
+ def key = :cover
6
6
 
7
7
  def size
8
8
  options.fetch(:size, :md)
data/lib/avo/current.rb CHANGED
@@ -1,14 +1,3 @@
1
- begin
2
- require "active_support/isolated_execution_state"
3
- rescue LoadError
4
- # Older ActiveSupport versions may not expose this file directly.
5
- end
6
- require "active_support/current_attributes"
7
- begin
8
- require "active_support/code_generator"
9
- rescue LoadError
10
- # ActiveSupport 6.1 does not have this file.
11
- end
12
1
  class Avo::Current < ActiveSupport::CurrentAttributes
13
2
  attribute :app
14
3
  attribute :license
@@ -1,8 +1,7 @@
1
- require "prop_initializer"
2
- require "action_view/helpers"
3
1
  class Avo::DiscreetInformation
4
2
  extend PropInitializer::Properties
5
3
  include ActionView::Helpers::TagHelper
4
+ include ActionView::Helpers::DateHelper
6
5
 
7
6
  prop :resource, reader: :public
8
7
 
@@ -11,29 +10,31 @@ class Avo::DiscreetInformation
11
10
  def items
12
11
  Array.wrap(resource.class.discreet_information).map do |item|
13
12
  if item == :timestamps
14
- timestamp_item(item, as: :text)
15
- elsif item == :timestamps_badge
16
- timestamp_item(item, as: :badge)
13
+ timestamps_item(item)
14
+ elsif item == :created_at
15
+ timestamp_item(item, key: :created_at)
16
+ elsif item == :updated_at
17
+ timestamp_item(item, key: :updated_at)
17
18
  elsif item == :id
18
- id_item(item, as: :text)
19
- elsif item == :id_badge
20
- id_item(item, as: :badge)
19
+ id_item
21
20
  else
22
21
  parse_payload(item)
23
22
  end
24
- end
23
+ end.flatten.compact
25
24
  end
26
25
 
27
26
  private
28
27
 
29
- def id_item(item, as: :text)
30
- DiscreetInformationItem.new(
31
- label: "ID: #{record.id}",
32
- as:
33
- )
28
+ def id_item
29
+ {
30
+ value: record.id,
31
+ key: "ID",
32
+ as: :key_value
33
+ }
34
34
  end
35
35
 
36
- def timestamp_item(item, as: :text)
36
+ def timestamps_item(item)
37
+ as = :icon
37
38
  return if record.created_at.blank? && record.updated_at.blank?
38
39
 
39
40
  time_format = "%Y-%m-%d %H:%M:%S"
@@ -47,12 +48,31 @@ class Avo::DiscreetInformation
47
48
  updated_at_tag = if record.updated_at.present?
48
49
  I18n.t("avo.updated_at_timestamp", updated_at:)
49
50
  end
50
-
51
- DiscreetInformationItem.new(
52
- tooltip: tag.div([created_at_tag, updated_at_tag].compact.join(tag.br), style: "text-align: right;"),
53
- icon: "heroicons/outline/clock",
51
+ {
52
+ title: tag.div([created_at_tag, updated_at_tag].compact.join(tag.br), style: "text-align: right;"),
53
+ icon: "tabler/outline/calendar-time",
54
54
  as:
55
- )
55
+ }
56
+ end
57
+
58
+ def timestamp_item(item, key: nil)
59
+ return if record[key].blank?
60
+
61
+ time_format = "%Y-%m-%d %H:%M:%S"
62
+ timestamp = record[key].strftime(time_format)
63
+
64
+ # Older versions of rails don't have the relative_time_in_words helper
65
+ value = if defined?(relative_time_in_words)
66
+ relative_time_in_words(record[key])
67
+ else
68
+ timestamp
69
+ end
70
+
71
+ {
72
+ value:,
73
+ key: I18n.t("avo.#{key}"),
74
+ as: :key_value,
75
+ }
56
76
  end
57
77
 
58
78
  def parse_payload(item)
@@ -64,17 +84,20 @@ class Avo::DiscreetInformation
64
84
  view:
65
85
  }
66
86
 
67
- DiscreetInformationItem.new(
68
- tooltip: Avo::ExecutionContext.new(target: item[:tooltip], **args).handle,
87
+ visible = item[:visible].nil? || Avo::ExecutionContext.new(target: item[:visible], **args).handle
88
+
89
+ return unless visible
90
+
91
+ {
92
+ title: Avo::ExecutionContext.new(target: item[:title], **args).handle,
69
93
  icon: Avo::ExecutionContext.new(target: item[:icon], **args).handle,
70
94
  url: Avo::ExecutionContext.new(target: item[:url], **args).handle,
71
- url_target: Avo::ExecutionContext.new(target: item[:url_target], **args).handle,
95
+ target: Avo::ExecutionContext.new(target: item[:target], **args).handle,
72
96
  data: Avo::ExecutionContext.new(target: item[:data], **args).handle,
73
- label: Avo::ExecutionContext.new(target: item[:label], **args).handle,
74
- as: Avo::ExecutionContext.new(target: item[:as], **args).handle,
75
- visible: Avo::ExecutionContext.new(target: item[:visible], **args).handle
76
- )
97
+ text: Avo::ExecutionContext.new(target: item[:text], **args).handle,
98
+ key: Avo::ExecutionContext.new(target: item[:key], **args).handle,
99
+ value: Avo::ExecutionContext.new(target: item[:value], **args).handle,
100
+ as: Avo::ExecutionContext.new(target: item[:as], **args).handle
101
+ }
77
102
  end
78
-
79
- DiscreetInformationItem = Struct.new(:tooltip, :icon, :url, :url_target, :data, :label, :as, :visible, keyword_init: true) unless defined?(DiscreetInformationItem)
80
103
  end
@@ -76,7 +76,7 @@ module Avo
76
76
  field[:name].to_s == symbol.to_s
77
77
  end
78
78
 
79
- return matched_field[:class] if matched_field.present? && matched_field[:class].present?
79
+ matched_field[:class] if matched_field.present? && matched_field[:class].present?
80
80
  end
81
81
  end
82
82
  end
data/lib/avo/engine.rb CHANGED
@@ -18,10 +18,27 @@ Gem.loaded_specs["avo"].dependencies.each do |d|
18
18
  end
19
19
  end
20
20
 
21
+ # Check for avo-licensing as a transitive dependency
22
+ # This handles cases where avo-licensing is a dependency of other avo gems
23
+ if Gem.loaded_specs.key?("avo-licensing") && !defined?(Avo::Licensing)
24
+ require "avo/licensing"
25
+ end
26
+
21
27
  module Avo
22
28
  class Engine < ::Rails::Engine
23
29
  isolate_namespace Avo
24
30
 
31
+ rake_tasks do
32
+ # Ensure Avo tasks are loaded
33
+ load File.expand_path("../tasks/avo_tasks.rake", __dir__)
34
+
35
+ if ENV["BUILD_AVO_ASSETS"] == "true"
36
+ if Rake::Task.task_defined?("assets:precompile")
37
+ Rake::Task["assets:precompile"].enhance(["avo:build"])
38
+ end
39
+ end
40
+ end
41
+
25
42
  config.after_initialize do
26
43
  # Reset before reloads in development
27
44
  ::Avo.asset_manager.reset
@@ -40,7 +57,7 @@ module Avo
40
57
  # This undoes Rails' previous nested directories behavior in the `app` dir.
41
58
  # More on this: https://github.com/fxn/zeitwerk/issues/250
42
59
  avo_directory = Rails.root.join("app", "avo").to_s
43
- engine_avo_directory = Avo::Engine.root.join("app", "avo").to_s
60
+ engine_avo_directory = Engine.root.join("app", "avo").to_s
44
61
 
45
62
  [avo_directory, engine_avo_directory].each do |directory_path|
46
63
  ActiveSupport::Dependencies.autoload_paths.delete(directory_path)
@@ -81,7 +98,7 @@ module Avo
81
98
 
82
99
  initializer "avo.test_buddy" do |app|
83
100
  if Avo::IN_DEVELOPMENT
84
- Rails.autoloaders.main.push_dir Avo::Engine.root.join("spec", "testing_helpers")
101
+ Rails.autoloaders.main.push_dir Engine.root.join("spec", "testing_helpers")
85
102
  end
86
103
  end
87
104
 
@@ -89,11 +106,27 @@ module Avo
89
106
  app.config.debug_exception_response_format = :api
90
107
  end
91
108
 
92
- config.app_middleware.use(
93
- Rack::Static,
94
- urls: ["/avo-assets"],
95
- root: Avo::Engine.root.join("public")
96
- )
109
+ initializer "avo.assets-importmaps", before: "importmap" do |app|
110
+ if app.respond_to?(:importmap)
111
+ app.config.importmap.paths << Engine.root.join("config/importmap.rb")
112
+ end
113
+ end
114
+
115
+ initializer "avo.assets" do |app|
116
+ if app.config.respond_to?(:assets)
117
+ # Add Avo's assets to the asset pipeline
118
+ app.config.assets.paths << Engine.root.join("app", "assets", "builds").to_s
119
+ app.config.assets.paths << Engine.root.join("app", "assets", "images").to_s
120
+ app.config.assets.paths << Engine.root.join("app", "assets", "svgs").to_s
121
+ # Expose the fonts directory to sprockets
122
+ app.config.assets.paths << Engine.root.join("app", "assets", "images", "avo").to_s
123
+
124
+ if defined?(::Sprockets)
125
+ # Tell sprockets where your assets are located
126
+ app.config.assets.precompile += %w[avo_manifest.js]
127
+ end
128
+ end
129
+ end
97
130
 
98
131
  config.generators do |g|
99
132
  g.test_framework :rspec, view_specs: false
@@ -105,7 +138,7 @@ module Avo
105
138
  end
106
139
 
107
140
  initializer "avo.locales" do |app|
108
- I18n.load_path += Dir[Avo::Engine.root.join("lib", "generators", "avo", "templates", "locales", "*.{rb,yml}")]
141
+ I18n.load_path += Dir[Engine.root.join("lib", "generators", "avo", "templates", "locales", "*.{rb,yml}")]
109
142
  end
110
143
  end
111
144
  end
@@ -15,7 +15,7 @@ module Avo
15
15
  end
16
16
 
17
17
  def add(error)
18
- @errors << error
18
+ @errors << error unless @errors.include?(error)
19
19
  end
20
20
 
21
21
  def has_errors?
@@ -0,0 +1,19 @@
1
+ module Avo
2
+ module Fields
3
+ class AvatarField < BaseField
4
+ def initialize(id, **args, &block)
5
+ only_on :index
6
+
7
+ super
8
+ end
9
+
10
+ def table_header_label
11
+ @args[:name] || nil
12
+ end
13
+
14
+ def table_header_class
15
+ "w-16"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,17 +4,37 @@ module Avo
4
4
  attr_reader :options
5
5
 
6
6
  def initialize(id, **args, &block)
7
- super(id, **args, &block)
7
+ super
8
8
 
9
9
  hide_on [:edit, :new]
10
10
 
11
- default_options = {info: :info, success: :success, danger: :danger, warning: :warning, neutral: :neutral}
12
- @options = args[:options].present? ? default_options.merge(args[:options]) : default_options
11
+ @options = args[:options] || {}
12
+ @style = args[:style]
13
+ @icon = args[:icon]
13
14
  end
14
15
 
15
16
  def options_for_filter
16
17
  @options.values.flatten.uniq
17
18
  end
19
+
20
+ # Maps field value to a color based on @options configuration
21
+ # Example: "Done" -> "success" if options = { success: [:done, :complete] }
22
+ def color
23
+ return "neutral" if value.blank?
24
+
25
+ values = @options.find do |_, configured_values|
26
+ Array.wrap(configured_values).map { |v| v.to_s }.include?(value.to_s)
27
+ end
28
+ values&.first&.to_s || "neutral"
29
+ end
30
+
31
+ def style
32
+ execute_context(@style) || "subtle"
33
+ end
34
+
35
+ def icon
36
+ execute_context(@icon)
37
+ end
18
38
  end
19
39
  end
20
40
  end
@@ -16,6 +16,7 @@ module Avo
16
16
  include Avo::Fields::Concerns::IsDisabled
17
17
  include Avo::Fields::Concerns::IsRequired
18
18
  include Avo::Fields::Concerns::UseViewComponents
19
+ include Avo::Fields::Concerns::DomId
19
20
 
20
21
  include ActionView::Helpers::UrlHelper
21
22
 
@@ -44,8 +45,10 @@ module Avo
44
45
  attr_reader :format_form_using
45
46
  attr_reader :autocomplete
46
47
  attr_reader :help
48
+ attr_reader :label_help
47
49
  attr_reader :default
48
50
  attr_reader :stacked
51
+ attr_reader :size
49
52
  attr_reader :for_presentation_only
50
53
  attr_reader :for_attribute
51
54
 
@@ -60,6 +63,7 @@ module Avo
60
63
  attr_accessor :action
61
64
  attr_accessor :user
62
65
  attr_accessor :panel_name
66
+ attr_accessor :width
63
67
 
64
68
  class_attribute :field_name_attribute
65
69
 
@@ -94,12 +98,14 @@ module Avo
94
98
  @placeholder = args[:placeholder]
95
99
  @autocomplete = args[:autocomplete]
96
100
  @help = args[:help]
101
+ @label_help = args[:label_help]
97
102
  @default = args[:default]
98
103
  @visible = args[:visible]
99
104
  @html = args[:html]
100
105
  @view = Avo::ViewInquirer.new(args[:view])
101
106
  @value = args[:value]
102
107
  @stacked = args[:stacked]
108
+ @size = args[:size] || :md
103
109
  @for_presentation_only = args[:for_presentation_only] || false
104
110
  @resource = args[:resource]
105
111
  @action = args[:action]
@@ -107,6 +113,8 @@ module Avo
107
113
  @for_attribute = args[:for_attribute]
108
114
  @meta = args[:meta]
109
115
  @copyable = args[:copyable] || false
116
+ @react_on = Array.wrap(args[:react_on]).map(&:to_s)
117
+ @record = args[:record]
110
118
 
111
119
  @args = args
112
120
 
@@ -114,9 +122,19 @@ module Avo
114
122
  @computed = block.present?
115
123
  @computed_value = nil
116
124
 
125
+ @width = args[:width] || 100
126
+
127
+ if width_option.present? && width_option != 100
128
+ @stacked = true
129
+ end
130
+
117
131
  post_initialize if respond_to?(:post_initialize)
118
132
  end
119
133
 
134
+ def width_option
135
+ @width_option ||= execute_context(@width)
136
+ end
137
+
120
138
  def translation_key
121
139
  @translation_key || "avo.field_translations.#{@id}"
122
140
  end
@@ -129,6 +147,25 @@ module Avo
129
147
  t(translation_key, count: 2, default: default).humanize
130
148
  end
131
149
 
150
+ def width_class
151
+ case width_option
152
+ when 25
153
+ "w-1/4"
154
+ when 33
155
+ "w-1/3"
156
+ when 50
157
+ "w-1/2"
158
+ when 66
159
+ "w-2/3"
160
+ when 75
161
+ "w-3/4"
162
+ when 100
163
+ "w-full"
164
+ else
165
+ "w-full"
166
+ end
167
+ end
168
+
132
169
  # Getting the name of the resource (user/users, post/posts)
133
170
  # We'll first check to see if the user passed a name
134
171
  # Secondly we'll try to find a translation key
@@ -136,6 +173,8 @@ module Avo
136
173
  def name
137
174
  if custom_name?
138
175
  Avo::ExecutionContext.new(target: @name).handle
176
+ elsif name_override.present?
177
+ name_override
139
178
  elsif translation_key
140
179
  translated_name default: default_name
141
180
  else
@@ -143,6 +182,8 @@ module Avo
143
182
  end
144
183
  end
145
184
 
185
+ def name_override = nil
186
+
146
187
  def plural_name
147
188
  default = name.pluralize
148
189
 
@@ -157,6 +198,10 @@ module Avo
157
198
  @table_header_label ||= name
158
199
  end
159
200
 
201
+ def table_header_class
202
+ @table_header_class ||= ""
203
+ end
204
+
160
205
  def custom_name?
161
206
  !@name.nil?
162
207
  end
@@ -169,7 +214,7 @@ module Avo
169
214
  Avo::ExecutionContext.new(target: @placeholder || name, record: record, resource: @resource, view: @view).handle
170
215
  end
171
216
 
172
- def attribute_id = (@attribure_id ||= @for_attribute || @id)
217
+ def attribute_id = (@attribute_id ||= @for_attribute || @id)
173
218
 
174
219
  def value(property = nil)
175
220
  return @value if @value.present?
@@ -0,0 +1,17 @@
1
+ module Avo
2
+ module Fields
3
+ module Concerns
4
+ module DomId
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def param_key = to_s.underscore
9
+ end
10
+
11
+ def to_key = [@id]
12
+
13
+ def model_name = self.class
14
+ end
15
+ end
16
+ end
17
+ end