avo 3.0.0.beta1 → 3.0.0.pre1

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

Potentially problematic release.


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

Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -5
  3. data/Gemfile.lock +81 -92
  4. data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +686 -728
  5. data/app/assets/builds/avo.base.js +93804 -0
  6. data/app/assets/builds/avo.base.js.map +7 -0
  7. data/app/assets/stylesheets/avo.base.css +2 -1
  8. data/app/assets/svgs/failed_to_load.svg +1 -0
  9. data/app/assets/svgs/grid-empty-state.svg +1 -0
  10. data/app/assets/svgs/table-empty-state.svg +1 -0
  11. data/app/assets/svgs/triangle-up.svg +1 -1
  12. data/app/components/avo/actions_component.html.erb +1 -1
  13. data/app/components/avo/actions_component.rb +16 -42
  14. data/app/components/avo/alert_component.html.erb +1 -1
  15. data/app/components/avo/base_component.rb +7 -7
  16. data/app/components/avo/field_wrapper_component.html.erb +4 -4
  17. data/app/components/avo/field_wrapper_component.rb +1 -1
  18. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
  19. data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -8
  20. data/app/components/avo/fields/boolean_field/edit_component.html.erb +0 -1
  21. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  22. data/app/components/avo/fields/code_field/edit_component.html.erb +0 -1
  23. data/app/components/avo/fields/common/files_list_viewer_component.html.erb +5 -0
  24. data/app/components/avo/fields/common/files_list_viewer_component.rb +8 -0
  25. data/app/components/avo/fields/common/heading_component.html.erb +1 -1
  26. data/app/components/avo/fields/common/single_file_viewer_component.html.erb +56 -0
  27. data/app/components/avo/fields/common/single_file_viewer_component.rb +55 -0
  28. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -3
  29. data/app/components/avo/fields/file_field/edit_component.html.erb +2 -4
  30. data/app/components/avo/fields/file_field/edit_component.rb +0 -1
  31. data/app/components/avo/fields/file_field/index_component.rb +2 -2
  32. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  33. data/app/components/avo/fields/files_field/edit_component.html.erb +2 -4
  34. data/app/components/avo/fields/files_field/edit_component.rb +0 -1
  35. data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
  36. data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
  37. data/app/components/avo/fields/has_one_field/show_component.html.erb +4 -5
  38. data/app/components/avo/fields/has_one_field/show_component.rb +2 -6
  39. data/app/components/avo/fields/index_component.rb +0 -1
  40. data/app/components/avo/fields/markdown_field/edit_component.html.erb +3 -4
  41. data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
  42. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -3
  43. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -3
  44. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +0 -1
  45. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -2
  46. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  47. data/app/components/avo/fields/text_field/edit_component.html.erb +2 -3
  48. data/app/components/avo/fields/textarea_field/edit_component.html.erb +0 -1
  49. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -2
  50. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  51. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  52. data/app/components/avo/index/field_wrapper_component.rb +12 -0
  53. data/app/components/avo/index/grid_item_component.html.erb +35 -9
  54. data/app/components/avo/index/grid_item_component.rb +10 -36
  55. data/app/components/avo/index/resource_controls_component.rb +11 -8
  56. data/app/components/avo/index/resource_table_component.rb +1 -1
  57. data/app/components/avo/item_switcher_component.html.erb +5 -10
  58. data/app/components/avo/item_switcher_component.rb +1 -2
  59. data/app/components/avo/modal_component.html.erb +1 -1
  60. data/app/components/avo/panel_component.html.erb +1 -6
  61. data/app/components/avo/panel_component.rb +0 -1
  62. data/app/components/avo/profile_item_component.html.erb +2 -17
  63. data/app/components/avo/profile_item_component.rb +1 -13
  64. data/app/components/avo/referrer_params_component.html.erb +0 -2
  65. data/app/components/avo/resource_component.rb +6 -69
  66. data/app/components/avo/resource_sidebar_component.rb +1 -1
  67. data/app/components/avo/sidebar/link_component.html.erb +0 -2
  68. data/app/components/avo/sidebar/link_component.rb +3 -5
  69. data/app/components/avo/sidebar_component.html.erb +3 -3
  70. data/app/components/avo/sidebar_component.rb +4 -4
  71. data/app/components/avo/sidebar_profile_component.html.erb +27 -27
  72. data/app/components/avo/views/resource_edit_component.html.erb +5 -5
  73. data/app/components/avo/views/resource_edit_component.rb +1 -1
  74. data/app/components/avo/views/resource_index_component.html.erb +10 -19
  75. data/app/components/avo/views/resource_index_component.rb +16 -22
  76. data/app/components/avo/views/resource_show_component.html.erb +4 -4
  77. data/app/controllers/avo/actions_controller.rb +20 -20
  78. data/app/controllers/avo/application_controller.rb +67 -90
  79. data/app/controllers/avo/associations_controller.rb +7 -5
  80. data/app/controllers/avo/attachments_controller.rb +7 -22
  81. data/app/controllers/avo/base_controller.rb +35 -47
  82. data/app/controllers/avo/home_controller.rb +1 -1
  83. data/app/controllers/avo/search_controller.rb +16 -20
  84. data/app/controllers/concerns/avo/initializes_avo.rb +8 -3
  85. data/app/helpers/avo/application_helper.rb +6 -13
  86. data/app/javascript/js/application.js +0 -2
  87. data/app/javascript/js/controllers/fields/{easy_mde_controller.js → simple_mde_controller.js} +3 -4
  88. data/app/javascript/js/controllers/search_controller.js +1 -3
  89. data/app/javascript/js/controllers.js +2 -2
  90. data/app/views/avo/actions/show.html.erb +3 -5
  91. data/app/views/avo/associations/new.html.erb +3 -3
  92. data/app/views/avo/debug/status.html.erb +5 -6
  93. data/app/views/avo/home/index.html.erb +1 -1
  94. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  95. data/app/views/avo/partials/_footer.html.erb +1 -1
  96. data/app/views/avo/partials/_javascript.html.erb +1 -1
  97. data/app/views/avo/partials/_navbar.html.erb +1 -1
  98. data/app/views/avo/partials/_table_header.html.erb +8 -0
  99. data/app/views/avo/partials/_view_toggle_button.html.erb +0 -9
  100. data/app/views/avo/private/design.html.erb +2 -2
  101. data/app/views/layouts/avo/application.html.erb +3 -2
  102. data/avo.gemspec +1 -2
  103. data/config/initializers/pagy.rb +10 -12
  104. data/config/routes.rb +5 -5
  105. data/db/factories.rb +0 -17
  106. data/lib/avo/app.rb +165 -0
  107. data/lib/avo/base_action.rb +18 -31
  108. data/lib/avo/base_resource.rb +213 -238
  109. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  110. data/lib/avo/concerns/can_replace_items.rb +7 -3
  111. data/lib/avo/concerns/filters_session_handler.rb +4 -5
  112. data/lib/avo/concerns/has_item_type.rb +0 -4
  113. data/lib/avo/concerns/has_items.rb +115 -93
  114. data/lib/avo/concerns/is_visible.rb +1 -1
  115. data/lib/avo/concerns/model_class_constantized.rb +2 -0
  116. data/lib/avo/configuration.rb +8 -9
  117. data/lib/avo/current.rb +1 -35
  118. data/lib/avo/dsl/field_parser.rb +1 -1
  119. data/lib/avo/dynamic_router.rb +2 -13
  120. data/lib/avo/engine.rb +13 -11
  121. data/lib/avo/execution_context.rb +2 -4
  122. data/lib/avo/fields/base_field.rb +14 -51
  123. data/lib/avo/fields/belongs_to_field.rb +13 -20
  124. data/lib/avo/fields/concerns/is_searchable.rb +1 -1
  125. data/lib/avo/fields/concerns/use_resource.rb +1 -1
  126. data/lib/avo/fields/date_field.rb +3 -16
  127. data/lib/avo/fields/field_manager.rb +3 -13
  128. data/lib/avo/fields/file_field.rb +0 -2
  129. data/lib/avo/fields/files_field.rb +0 -6
  130. data/lib/avo/fields/has_base_field.rb +5 -5
  131. data/lib/avo/fields/has_one_field.rb +1 -2
  132. data/lib/avo/fields/id_field.rb +1 -2
  133. data/lib/avo/filters/base_filter.rb +0 -9
  134. data/lib/avo/grid_collector.rb +40 -0
  135. data/lib/avo/html/builder.rb +1 -3
  136. data/lib/avo/licensing/h_q.rb +6 -11
  137. data/lib/avo/licensing/license.rb +1 -1
  138. data/lib/avo/licensing/license_manager.rb +1 -1
  139. data/lib/avo/licensing/{nil_license.rb → null_license.rb} +1 -1
  140. data/lib/avo/loaders/fields_loader.rb +1 -7
  141. data/lib/avo/plugin.rb +0 -10
  142. data/lib/avo/plugin_manager.rb +4 -2
  143. data/lib/avo/reloader.rb +1 -1
  144. data/lib/avo/resources/controls/actions_list.rb +1 -2
  145. data/lib/avo/resources/controls/create_button.rb +1 -1
  146. data/lib/avo/resources/controls/delete_button.rb +1 -1
  147. data/lib/avo/resources/controls/detach_button.rb +1 -1
  148. data/lib/avo/resources/controls/edit_button.rb +1 -1
  149. data/lib/avo/resources/controls/show_button.rb +1 -1
  150. data/lib/avo/resources/items/holder.rb +5 -13
  151. data/lib/avo/resources/items/item_group.rb +0 -1
  152. data/lib/avo/resources/resource_manager.rb +18 -11
  153. data/lib/avo/services/debug_service.rb +5 -6
  154. data/lib/avo/services/telemetry_service.rb +2 -3
  155. data/lib/avo/version.rb +1 -1
  156. data/lib/avo.rb +25 -109
  157. data/lib/generators/avo/action_generator.rb +8 -8
  158. data/lib/generators/avo/card/chartkick_generator.rb +18 -0
  159. data/lib/generators/avo/card/metric_generator.rb +18 -0
  160. data/lib/generators/avo/card/partial_generator.rb +19 -0
  161. data/lib/generators/avo/eject_generator.rb +0 -1
  162. data/lib/generators/avo/filter_generator.rb +8 -8
  163. data/lib/generators/avo/install_generator.rb +1 -11
  164. data/lib/generators/avo/resource_generator.rb +4 -22
  165. data/lib/generators/avo/tailwindcss/install_generator.rb +1 -4
  166. data/lib/generators/avo/templates/action.tt +5 -7
  167. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  168. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  169. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  170. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  171. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  172. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  173. data/lib/generators/avo/templates/dashboards/dashboard.tt +3 -5
  174. data/lib/generators/avo/templates/initializer/avo.tt +2 -4
  175. data/lib/generators/avo/templates/resource/resource.tt +6 -6
  176. data/lib/generators/avo/templates/scope.tt +1 -1
  177. data/lib/generators/avo/templates/standalone_action.tt +8 -0
  178. data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
  179. data/lib/tasks/avo_tasks.rake +0 -5
  180. metadata +19 -56
  181. data/app/assets/svgs/map-empty-state.svg +0 -35
  182. data/app/assets/svgs/map-view-type.svg +0 -3
  183. data/app/components/avo/fields/area_field/edit_component.html.erb +0 -7
  184. data/app/components/avo/fields/area_field/edit_component.rb +0 -4
  185. data/app/components/avo/fields/area_field/show_component.html.erb +0 -8
  186. data/app/components/avo/fields/area_field/show_component.rb +0 -4
  187. data/app/components/avo/fields/common/files/controls_component.html.erb +0 -29
  188. data/app/components/avo/fields/common/files/controls_component.rb +0 -19
  189. data/app/components/avo/fields/common/files/list_viewer_component.html.erb +0 -20
  190. data/app/components/avo/fields/common/files/list_viewer_component.rb +0 -41
  191. data/app/components/avo/fields/common/files/view_type/grid_component.html.erb +0 -27
  192. data/app/components/avo/fields/common/files/view_type/grid_component.rb +0 -51
  193. data/app/components/avo/fields/common/files/view_type/list_component.html.erb +0 -22
  194. data/app/components/avo/fields/common/files/view_type/list_component.rb +0 -15
  195. data/app/components/avo/fields/location_field/edit_component.html.erb +0 -22
  196. data/app/components/avo/fields/location_field/edit_component.rb +0 -4
  197. data/app/components/avo/fields/location_field/show_component.html.erb +0 -7
  198. data/app/components/avo/fields/location_field/show_component.rb +0 -4
  199. data/app/components/avo/index/resource_map_component.html.erb +0 -16
  200. data/app/components/avo/index/resource_map_component.rb +0 -109
  201. data/app/components/avo/row_component.html.erb +0 -3
  202. data/app/components/avo/row_component.rb +0 -12
  203. data/app/views/avo/attachments/destroy.turbo_stream.erb +0 -7
  204. data/app/views/avo/partials/_profile_menu_extra.html.erb +0 -2
  205. data/lib/avo/concerns/has_description.rb +0 -23
  206. data/lib/avo/fields/area_field.rb +0 -39
  207. data/lib/avo/fields/concerns/file_authorization.rb +0 -31
  208. data/lib/avo/fields/location_field.rb +0 -86
  209. data/lib/avo/resources/items/row.rb +0 -54
  210. data/lib/generators/avo/card_generator.rb +0 -27
  211. data/public/avo-assets/avo.base.css +0 -10542
  212. data/public/avo-assets/avo.base.js +0 -949
  213. data/public/avo-assets/avo.base.js.map +0 -7
  214. data/public/avo-assets/avo.js +0 -513
  215. data/public/avo-assets/avo.js.map +0 -7
@@ -20,14 +20,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
20
20
  end
21
21
 
22
22
  def can_detach?
23
- return false if @reflection.blank? || @resource.record.blank? || !authorize_association_for(:detach)
24
-
25
- # If the inverse_of is a belongs_to, we need to check if it's optional in order to know if we can detach it.
26
- if inverse_of.is_a?(ActiveRecord::Reflection::BelongsToReflection)
27
- inverse_of.options[:optional]
28
- else
29
- true
30
- end
23
+ authorize_association_for(:detach)
31
24
  end
32
25
 
33
26
  def detach_path
@@ -109,7 +102,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
109
102
  end
110
103
 
111
104
  def sidebar
112
- return if Avo.license.lacks_with_trial(:resource_sidebar)
105
+ return if Avo::App.license.lacks_with_trial(:resource_sidebar)
113
106
 
114
107
  @sidebar ||= search_for_sidebar
115
108
  end
@@ -120,15 +113,14 @@ class Avo::ResourceComponent < Avo::BaseComponent
120
113
 
121
114
  def has_reflection_and_is_read_only
122
115
  if @reflection.present? && @reflection.active_record.name && @reflection.name
123
- resource = Avo.resource_manager.get_resource_by_model_class(@reflection.active_record.name).new(params: helpers.params, view: view, user: helpers._current_user)
124
- fields = resource.get_field_definitions
116
+ fields = ::Avo::App.resources.get_resource_by_model_class(@reflection.active_record.name).get_field_definitions
125
117
  filtered_fields = fields.filter { |f| f.id == @reflection.name }
126
118
  else
127
119
  return false
128
120
  end
129
121
 
130
122
  if filtered_fields.present?
131
- filtered_fields.find { |f| f.id == @reflection.name }.is_disabled?
123
+ filtered_fields.find { |f| f.id == @reflection.name }.readonly
132
124
  else
133
125
  false
134
126
  end
@@ -173,7 +165,6 @@ class Avo::ResourceComponent < Avo::BaseComponent
173
165
  resource: @resource,
174
166
  view: @view,
175
167
  exclude: actions_list.exclude,
176
- include: actions_list.include,
177
168
  style: actions_list.style,
178
169
  color: actions_list.color,
179
170
  label: actions_list.label,
@@ -244,7 +235,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
244
235
  data: {
245
236
  confirm: "Are you sure you want to detach this #{title}."
246
237
  } do
247
- control.label || t("avo.detach_item", item: title).humanize
238
+ control.label || t("avo.detach_item", item: title).capitalize
248
239
  end
249
240
  end
250
241
 
@@ -254,6 +245,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
254
245
  a_link create_path,
255
246
  color: :primary,
256
247
  style: :primary,
248
+ target: "_top",
257
249
  icon: "heroicons/outline/plus",
258
250
  data: {
259
251
  target: :create
@@ -277,62 +269,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
277
269
  end
278
270
  end
279
271
 
280
- def render_link_to(link)
281
- a_link link.path,
282
- color: link.color,
283
- style: link.style,
284
- icon: link.icon,
285
- icon_class: link.icon_class,
286
- title: link.title, target: link.target,
287
- class: link.classes,
288
- size: link.size,
289
- data: {
290
- **link.data,
291
- tippy: link.title ? :tooltip : nil,
292
- } do
293
- link.label
294
- end
295
- end
296
-
297
- def render_action(action)
298
- return if !can_see_the_actions_button?
299
- return if !action.action.visible_in_view(parent_resource: @parent_resource)
300
-
301
- a_link action.path,
302
- color: action.color,
303
- style: action.style,
304
- icon: action.icon,
305
- icon_class: action.icon_class,
306
- title: action.title,
307
- size: action.size,
308
- data: {
309
- turbo_frame: "actions_show",
310
- action_name: action.action.action_name,
311
- tippy: action.title ? :tooltip : nil,
312
- action: "click->actions-picker#visitAction",
313
- } do
314
- action.label
315
- end
316
- end
317
-
318
272
  def is_a_related_resource?
319
273
  @reflection.present? && @resource.record.present?
320
274
  end
321
-
322
- def inverse_of
323
- current_reflection = @reflection.active_record.reflect_on_all_associations.find do |reflection|
324
- reflection.name == @reflection.name.to_sym
325
- end
326
-
327
- inverse_of = current_reflection.inverse_of
328
-
329
- if inverse_of.blank? && Rails.env.development?
330
- puts "WARNING! Avo uses the 'inverse_of' option to determine the inverse association and figure out if the association permit or not detaching."
331
- # Ex: Please configure the 'inverse_of' option for the ':users' association on the 'Project' model.
332
- puts "Please configure the 'inverse_of' option for the '#{current_reflection.macro} :#{current_reflection.name}' association on the '#{current_reflection.active_record.name}' model."
333
- puts "Otherwise the detach button will be visible by default.\n\n"
334
- end
335
-
336
- inverse_of
337
- end
338
275
  end
@@ -16,6 +16,6 @@ class Avo::ResourceSidebarComponent < ViewComponent::Base
16
16
  end
17
17
 
18
18
  def render?
19
- Avo.license.has_with_trial(:resource_sidebar)
19
+ Avo::App.license.has_with_trial(:resource_sidebar)
20
20
  end
21
21
  end
@@ -1,6 +1,5 @@
1
1
  <% if path.present? %>
2
2
  <%= send link_method, path, class: classes, active: active, target: target, data: data do %>
3
- <%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
4
3
  <%= label %>
5
4
  <% if target == :_blank %>
6
5
  <%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
@@ -8,7 +7,6 @@
8
7
  <% end %>
9
8
  <% else %>
10
9
  <%= content_tag :div, class: classes, active: active, target: target, data: data do %>
11
- <%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
12
10
  <%= label %>
13
11
  <% end %>
14
12
  <% end %>
@@ -6,20 +6,18 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
6
6
  attr_reader :label
7
7
  attr_reader :path
8
8
  attr_reader :data
9
- attr_reader :icon
10
9
 
11
- def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {}, icon: nil)
10
+ def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {})
12
11
  @label = label
13
12
  @path = path
14
13
  @active = active
15
14
  @target = target
16
15
  @data = data
17
- @icon = icon
18
16
  end
19
17
 
20
18
  def is_external?
21
19
  # If the path contains the scheme, check if it includes the root path or not
22
- return !path.include?(Avo.mount_path) if URI(path).scheme.present?
20
+ return !path.include?(Avo::App.mount_path) if URI(path).scheme.present?
23
21
 
24
22
  false
25
23
  end
@@ -30,6 +28,6 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
30
28
  end
31
29
 
32
30
  def classes
33
- "px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100 gap-1"
31
+ "px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100"
34
32
  end
35
33
  end
@@ -13,8 +13,8 @@
13
13
  <div class="space-y-6 mb-4">
14
14
  <%= render Avo::Sidebar::LinkComponent.new label: 'Get started', path: helpers.avo.root_path, active: :exclusive if Rails.env.development? && Avo.configuration.home_path.nil? %>
15
15
 
16
- <% if Avo.plugin_manager.installed?("avo-menu") && Avo.has_main_menu? %>
17
- <% Avo.main_menu.items.each do |item| %>
16
+ <% if Avo.plugin_manager.installed?(:avo_menu) && Avo::App.has_main_menu? %>
17
+ <% Avo::App.main_menu.items.each do |item| %>
18
18
  <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
19
19
  <% end %>
20
20
  <% else %>
@@ -60,7 +60,7 @@
60
60
  <% if Rails.env.development? %>
61
61
  <div class="p-4 border-t group">
62
62
  <%= link_to helpers.avo.avo_private_status_path, class: "block px-4 py-2 border rounded flex justify-between items-center w-full text-black text-sm" do %>
63
- <span>Avo Status</span> <span><div class="rounded-full w-4 h-4 <%= Avo.app_status ? "bg-green-400" : "bg-orange-400" %>"></div></span>
63
+ <span>Avo Status</span> <span><div class="rounded-full w-4 h-4 <%= Avo::App.instance.app_status ? "bg-green-400" : "bg-orange-400" %>"></div></span>
64
64
  <% end %>
65
65
  <div class="absolute text-xs text-gray-700 group-hover:block hidden text-center w-full -ml-4">👆Visible only in development👆</div>
66
66
  </div>
@@ -7,17 +7,17 @@ class Avo::SidebarComponent < ViewComponent::Base
7
7
  end
8
8
 
9
9
  def dashboards
10
- return [] unless Avo.plugin_manager.installed?("avo-dashboards")
10
+ return [] unless defined?(AvoDashboards)
11
11
 
12
- Avo::Dashboards.dashboard_manager.dashboards_for_navigation
12
+ AvoDashboards.dashboard_manager.dashboards_for_navigation
13
13
  end
14
14
 
15
15
  def resources
16
- Avo.resource_manager.resources_for_navigation helpers._current_user
16
+ Avo::Current.app.resource_manager.resources_for_navigation helpers._current_user
17
17
  end
18
18
 
19
19
  def tools
20
- Avo.tool_manager.tools_for_navigation
20
+ Avo::App.tools.tools_for_navigation
21
21
  end
22
22
 
23
23
  def stimulus_target
@@ -16,32 +16,32 @@
16
16
  <% end %>
17
17
  </div>
18
18
  </div>
19
- <div class="relative" data-controller="toggle">
20
- <a class="flex items-center h-full cursor-pointer" data-control="profile-dots" data-action="click->toggle#togglePanel">
21
- <%= helpers.svg 'three-dots', class: 'h-4' %>
22
- </a>
23
- <div
24
- class="hidden absolute flex flex-col inset-auto right-0 -mt-12 bg-white rounded min-w-[200px] shadow-context -translate-y-full z-40"
25
- data-toggle-target="panel"
26
- data-transition-enter="transition ease-out duration-100"
27
- data-transition-enter-start="transform opacity-0 translate-y-1"
28
- data-transition-enter-end="transform opacity-100 translate-y-0"
29
- data-transition-leave="transition ease-in duration-75"
30
- data-transition-leave-start="transform opacity-100 translate-y-0"
31
- data-transition-leave-end="transform opacity-0 translate-y-1"
32
- >
33
- <% if Avo.plugin_manager.installed?("avo-menu") && Avo.has_profile_menu? %>
34
- <div class="text-black space-y-4">
35
- <% Avo.profile_menu.items.each do |item| %>
36
- <% if item.is_a? Avo::Menu::Link %>
37
- <%= render Avo::ProfileItemComponent.new label: item.name, path: item.path, icon: item.icon, method: item.method, params: item.params %>
19
+ <% if can_destroy_user? %>
20
+ <div class="relative" data-controller="toggle">
21
+ <a class="flex items-center h-full cursor-pointer" data-control="profile-dots" data-action="click->toggle#togglePanel">
22
+ <%= helpers.svg 'three-dots', class: 'h-4' %>
23
+ </a>
24
+ <div
25
+ class="hidden absolute flex flex-col inset-auto right-0 -mt-12 bg-white rounded min-w-[200px] shadow-context -translate-y-full z-40"
26
+ data-toggle-target="panel"
27
+ data-transition-enter="transition ease-out duration-100"
28
+ data-transition-enter-start="transform opacity-0 translate-y-1"
29
+ data-transition-enter-end="transform opacity-100 translate-y-0"
30
+ data-transition-leave="transition ease-in duration-75"
31
+ data-transition-leave-start="transform opacity-100 translate-y-0"
32
+ data-transition-leave-end="transform opacity-0 translate-y-1"
33
+ >
34
+ <% if Avo.plugin_manager.installed?(:avo_menu) && Avo::App.has_profile_menu? %>
35
+ <div class="text-black space-y-4">
36
+ <% Avo::App.profile_menu.items.each do |item| %>
37
+ <% if item.is_a? AvoMenu::Link %>
38
+ <%= render Avo::ProfileItemComponent.new label: item.name, path: item.path, icon: item.icon %>
39
+ <% end %>
38
40
  <% end %>
39
- <% end %>
40
- </div>
41
- <% end %>
42
- <%# Example link below %>
43
- <%#= render Avo::ProfileItemComponent.new label: 'Profile', path: '/profile', icon: 'user-circle' %>
44
- <% if can_destroy_user? %>
41
+ </div>
42
+ <% end %>
43
+ <%# Example link below %>
44
+ <%#= render Avo::ProfileItemComponent.new label: 'Profile', path: '/profile', icon: 'user-circle' %>
45
45
  <%= button_to helpers.main_app.send(destroy_user_session_path),
46
46
  form: { "data-turbo" => "false" },
47
47
  method: :delete,
@@ -52,7 +52,7 @@
52
52
  form_class: 'flex-1' do %>
53
53
  <%= helpers.svg 'logout', class: 'h-4 mr-1' %> <%= t('avo.sign_out') %>
54
54
  <% end %>
55
- <% end %>
55
+ </div>
56
56
  </div>
57
- </div>
57
+ <% end %>
58
58
  </div>
@@ -18,8 +18,8 @@
18
18
  multipart: true do |form| %>
19
19
  <%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
20
20
  <%= content_tag :div, class: 'space-y-12' do %>
21
- <%= render Avo::PanelComponent.new(name: title, description: @resource.description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
22
- <% c.with_tools do %>
21
+ <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
22
+ <% c.tools do %>
23
23
  <% @resource.render_edit_controls.each do |control| %>
24
24
  <%= render_control control %>
25
25
  <% end %>
@@ -27,7 +27,7 @@
27
27
  <%# Extract the main panel and display the fields here. %>
28
28
  <%# This way we'll be able to render the footer buttons under the main fields. %>
29
29
  <% if main_panel.present? %>
30
- <% c.with_body do %>
30
+ <% c.body do %>
31
31
  <div class="divide-y">
32
32
  <% main_panel.items.each_with_index do |field, index| %>
33
33
  <%= render field
@@ -40,12 +40,12 @@
40
40
  <% end %>
41
41
  <% end %>
42
42
  <% if sidebar.present? %>
43
- <% c.with_sidebar do %>
43
+ <% c.sidebar do %>
44
44
  <%= render sidebar_component form: form %>
45
45
  <% end %>
46
46
  <% end %>
47
47
  <% if Avo.configuration.buttons_on_form_footers %>
48
- <% c.with_footer_tools do %>
48
+ <% c.footer_tools do %>
49
49
  <div class="mt-4">
50
50
  <%= a_link back_path,
51
51
  style: :text,
@@ -79,6 +79,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
79
79
 
80
80
  # Render :show view for read only trix fields
81
81
  def view_for(field)
82
- field.is_a?(Avo::Fields::TrixField) && field.is_disabled? ? :show : view
82
+ (field.is_a? Avo::Fields::TrixField) && field.is_readonly? ? :show : view
83
83
  end
84
84
  end
@@ -6,22 +6,22 @@
6
6
  **@resource.stimulus_data_attributes
7
7
  } do %>
8
8
  <%= render Avo::PanelComponent.new(name: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
9
- <% c.with_tools do %>
9
+ <% c.tools do %>
10
10
  <% @resource.render_index_controls(item: singular_resource_name.downcase).each do |control| %>
11
11
  <%= render_control control %>
12
12
  <% end %>
13
13
  <% end %>
14
- <% c.with_body do %>
14
+ <% c.body do %>
15
15
  <div class="flex flex-col">
16
16
  <%= render scopes_list if can_render_scopes? %>
17
- <div class="flex flex-col">
18
- <div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= 'hidden' unless header_visible? %>">
17
+ <div class="flex flex-col py-4 gap-4">
18
+ <div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 <%= 'hidden' unless header_visible? %>">
19
19
  <div class="flex items-center px-4 w-64">
20
- <% if show_search_input %>
21
- <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key, via_reflection: via_reflection} %>
22
- <% else %>
20
+ <% if hide_search_input %>
23
21
  <%# Offset for the space-y-2 property when the search is missing %>
24
22
  <div class="-mb-2"></div>
23
+ <% else %>
24
+ <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key, via_reflection: via_reflection} %>
25
25
  <% end %>
26
26
  </div>
27
27
 
@@ -34,7 +34,7 @@
34
34
  </div>
35
35
  </div>
36
36
  <% if Avo.avo_filters_installed? && resource.has_filters? %>
37
- <%= render Avo::DynamicFilters::FiltersComponent.new resource: resource, turbo_frame: turbo_frame %>
37
+ <%= render AvoFilters::FiltersComponent.new resource: resource %>
38
38
  <% end %>
39
39
  </div>
40
40
  </div>
@@ -48,17 +48,8 @@
48
48
  <% end %>
49
49
  <% end %>
50
50
  <% end %>
51
- <% c.with_bare_content do %>
52
- <% if view_type.to_sym == :map %>
53
- <% if @resources.present? %>
54
- <div>
55
- <%= render(Avo::Index::ResourceMapComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
56
- </div>
57
- <% else %>
58
- <%= helpers.empty_state by_association: params[:related_name].present?, view_type: view_type, add_background: true %>
59
- <% end %>
60
- <% end %>
61
- <% if view_type.to_sym == :table || view_type.to_sym == :map %>
51
+ <% c.bare_content do %>
52
+ <% if view_type.to_sym == :table %>
62
53
  <% if @records.present? %>
63
54
  <div class="mt-4">
64
55
  <%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_record: parent_record, discreet_pagination: field&.discreet_pagination %>
@@ -89,6 +89,10 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
89
89
  args[:via_relation] = @reflection.name
90
90
  end
91
91
 
92
+ if @reflection.parent_reflection.present? && @reflection.parent_reflection.inverse_of.present?
93
+ args[:via_relation] = @reflection.parent_reflection.inverse_of.name
94
+ end
95
+
92
96
  if @reflection.inverse_of.present?
93
97
  args[:via_relation] = @reflection.inverse_of.name
94
98
  end
@@ -100,7 +104,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
100
104
  def attach_path
101
105
  current_path = CGI.unescape(request.env["PATH_INFO"]).split("/").select(&:present?)
102
106
 
103
- Avo.root_path(paths: [*current_path, "new"])
107
+ Avo::App.root_path(paths: [*current_path, "new"])
104
108
  end
105
109
 
106
110
  def singular_resource_name
@@ -121,29 +125,19 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
121
125
  return
122
126
  end
123
127
 
124
- @resource.description
125
- end
126
-
127
- def show_search_input
128
- return false unless authorized_to_search?
129
- return false unless resource.class.search_query.present?
130
- return false if field&.hide_search_input
131
-
132
- true
128
+ @resource.resource_description
133
129
  end
134
130
 
135
- def authorized_to_search?
136
- # Hide the search if the authorization prevents it
137
- return true unless resource.authorization.respond_to?(:has_action_method?)
138
- return true unless resource.authorization.has_action_method?("search")
131
+ def hide_search_input
132
+ return true unless @resource.search_query.present?
139
133
 
140
- resource.authorization.authorize_action("search", raise_exception: false)
134
+ field&.hide_search_input || false
141
135
  end
142
136
 
143
137
  def render_dynamic_filters_button
144
138
  return unless Avo.avo_filters_installed?
145
139
  return unless resource.has_filters?
146
- return if Avo::DynamicFilters.configuration.always_expanded
140
+ return if AvoFilters.configuration.always_expanded
147
141
 
148
142
  a_button size: :sm,
149
143
  color: :primary,
@@ -152,21 +146,21 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
152
146
  controller: "avo-filters",
153
147
  action: "click->avo-filters#toggleFiltersArea",
154
148
  } do
155
- Avo::DynamicFilters.configuration.button_label
149
+ AvoFilters.configuration.button_label
156
150
  end
157
151
  end
158
152
 
159
153
  def scopes_list
160
- Avo::Pro::Scopes::ListComponent.new(
154
+ AvoPro::Scopes::ListComponent.new(
161
155
  scopes: scopes,
162
156
  resource: resource,
163
157
  turbo_frame: turbo_frame,
164
- parent_record: parent_record
158
+ parent_record: parent_record,
165
159
  )
166
160
  end
167
161
 
168
162
  def can_render_scopes?
169
- defined?(Avo::Pro)
163
+ defined?(AvoPro)
170
164
  end
171
165
 
172
166
  private
@@ -191,11 +185,11 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
191
185
  end
192
186
 
193
187
  def header_visible?
194
- search_query_present? || filters_present? || has_many_view_types? || (Avo.avo_filters_installed? && resource.has_filters? && Avo::DynamicFilters.configuration.always_expanded)
188
+ search_query_present? || filters_present? || has_many_view_types? || (Avo.avo_filters_installed? && resource.has_filters? && AvoFilters.configuration.always_expanded)
195
189
  end
196
190
 
197
191
  def search_query_present?
198
- @resource.class.search_query.present?
192
+ @resource.search_query.present?
199
193
  end
200
194
 
201
195
  def filters_present?
@@ -7,14 +7,14 @@
7
7
  selected_resources: [@resource.record.id],
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
- <%= render Avo::PanelComponent.new(name: title, description: @resource.description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
11
- <% c.with_tools do %>
10
+ <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
11
+ <% c.tools do %>
12
12
  <% @resource.render_show_controls.each do |control| %>
13
13
  <%= render_control control %>
14
14
  <% end %>
15
15
  <% end %>
16
16
  <% if main_panel.present? %>
17
- <% c.with_body do %>
17
+ <% c.body do %>
18
18
  <%# the overflow helps with long values %>
19
19
  <div class="divide-y overflow-auto">
20
20
  <% main_panel.items.each_with_index do |field, index| %>
@@ -28,7 +28,7 @@
28
28
  <% end %>
29
29
  <% end %>
30
30
  <% if sidebar.present? %>
31
- <% c.with_sidebar do %>
31
+ <% c.sidebar do %>
32
32
  <%= render sidebar_component %>
33
33
  <% end %>
34
34
  <% end %>
@@ -31,10 +31,12 @@ module Avo
31
31
  resource: resource
32
32
  }
33
33
 
34
- args[:records] = if @selected_query.present?
35
- @resource.model_class.find_by_sql decrypted_query
36
- else
37
- @resource.find_record resource_ids, params: params
34
+ unless @action.standalone
35
+ args[:models] = if @selected_query.present?
36
+ @resource.model_class.find_by_sql decrypted_query
37
+ else
38
+ @resource.find_record resource_ids, params: params
39
+ end
38
40
  end
39
41
 
40
42
  performed_action = @action.handle_action(**args)
@@ -45,7 +47,7 @@ module Avo
45
47
  private
46
48
 
47
49
  def action_params
48
- params.permit(:authenticity_token, :resource_name, :action_id, :button, fields: {})
50
+ params.permit(:authenticity_token, :resource_name, :action_id, fields: {})
49
51
  end
50
52
 
51
53
  def set_action
@@ -53,14 +55,17 @@ module Avo
53
55
  record: @record,
54
56
  resource: @resource,
55
57
  user: _current_user,
56
- view: :new, # force the action view to in order to render new-related fields (hidden field)
57
- arguments: decrypted_arguments || {}
58
+ view: @view,
59
+ arguments: @resource.get_action_arguments(action_class)
58
60
  )
59
61
  end
60
62
 
61
63
  def action_class
64
+ klass_name = params[:action_id].gsub("avo_actions_", "").camelize
65
+ klass_name = "Avo::Actions::#{klass_name}"
66
+
62
67
  Avo::BaseAction.descendants.find do |action|
63
- action.to_s == params[:action_id]
68
+ action.to_s == klass_name
64
69
  end
65
70
  end
66
71
 
@@ -80,8 +85,13 @@ module Avo
80
85
  flash_messages messages
81
86
 
82
87
  if response[:type] == :redirect
83
- redirect_to Avo::ExecutionContext.new(target: response[:path]).handle,
84
- **{allow_other_host: response[:allow_other_host], status: response[:status]}.compact
88
+ path = response[:path]
89
+
90
+ if path.respond_to? :call
91
+ path = instance_eval(&path)
92
+ end
93
+
94
+ redirect_to path
85
95
  elsif response[:type] == :reload
86
96
  redirect_back fallback_location: resources_path(resource: @resource)
87
97
  end
@@ -112,16 +122,6 @@ module Avo
112
122
  )
113
123
  end
114
124
 
115
- def decrypted_arguments
116
- arguments = params[:arguments] || params.dig(:fields, :arguments)
117
- return if arguments.blank?
118
-
119
- Avo::Services::EncryptionService.decrypt(
120
- message: Base64.decode64(arguments),
121
- purpose: :action_arguments
122
- )
123
- end
124
-
125
125
  def flash_messages(messages)
126
126
  messages.each do |message|
127
127
  flash[message[:type]] = message[:body]