avo 1.18.2 → 1.19.1.pre.3

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +10 -7
  4. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  5. data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
  6. data/app/components/avo/fields/common/multiple_file_viewer_component.html.erb +1 -1
  7. data/app/components/avo/fields/common/single_file_viewer_component.html.erb +1 -2
  8. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  9. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
  10. data/app/components/avo/fields/has_one_field/show_component.rb +6 -1
  11. data/app/components/avo/fields/index_component.rb +2 -2
  12. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/index/grid_item_component.html.erb +4 -4
  14. data/app/components/avo/index/resource_controls_component.html.erb +1 -1
  15. data/app/components/avo/index/resource_controls_component.rb +22 -6
  16. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  17. data/app/components/avo/panel_component.rb +3 -4
  18. data/app/components/avo/resource_component.rb +5 -1
  19. data/app/components/avo/views/resource_edit_component.html.erb +3 -3
  20. data/app/components/avo/views/resource_edit_component.rb +9 -3
  21. data/app/components/avo/views/resource_index_component.html.erb +3 -9
  22. data/app/components/avo/views/resource_index_component.rb +11 -17
  23. data/app/components/avo/views/resource_new_component.html.erb +6 -4
  24. data/app/components/avo/views/resource_new_component.rb +12 -2
  25. data/app/components/avo/views/resource_show_component.html.erb +7 -6
  26. data/app/components/avo/views/resource_show_component.rb +20 -7
  27. data/app/controllers/avo/actions_controller.rb +1 -1
  28. data/app/controllers/avo/application_controller.rb +17 -61
  29. data/app/controllers/avo/attachments_controller.rb +3 -2
  30. data/app/controllers/avo/base_controller.rb +30 -25
  31. data/app/controllers/avo/home_controller.rb +5 -1
  32. data/app/controllers/avo/relations_controller.rb +3 -3
  33. data/app/controllers/avo/search_controller.rb +1 -1
  34. data/app/helpers/avo/application_helper.rb +5 -11
  35. data/app/helpers/avo/resources_helper.rb +1 -1
  36. data/app/helpers/avo/url_helpers.rb +77 -0
  37. data/app/packs/entrypoints/application.css +1 -0
  38. data/app/packs/entrypoints/application.js +7 -0
  39. data/app/packs/js/controllers/loading_button_controller.js +22 -0
  40. data/app/packs/stylesheets/components/status.css +22 -15
  41. data/app/packs/stylesheets/spinner.css +49 -0
  42. data/app/views/avo/actions/show.html.erb +2 -2
  43. data/app/views/avo/base/_actions.html.erb +3 -3
  44. data/app/views/avo/base/_filters.html.erb +1 -1
  45. data/app/views/avo/home/failed_to_load.html.erb +3 -0
  46. data/app/views/avo/partials/_failed_state.html.erb +16 -0
  47. data/app/views/avo/partials/_paginator.html.erb +2 -2
  48. data/app/views/avo/relations/new.html.erb +0 -2
  49. data/app/views/avo/sidebar/_sidebar.html.erb +1 -1
  50. data/app/views/kaminari/_page.html.erb +1 -1
  51. data/config/routes.rb +7 -5
  52. data/lib/avo/app.rb +4 -8
  53. data/lib/avo/base_action.rb +9 -1
  54. data/lib/avo/base_resource.rb +33 -7
  55. data/lib/avo/configuration.rb +2 -0
  56. data/lib/avo/fields/base_field.rb +15 -4
  57. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -19
  58. data/lib/avo/fields/has_base_field.rb +35 -0
  59. data/lib/avo/fields/has_many_field.rb +1 -19
  60. data/lib/avo/fields/has_one_field.rb +3 -19
  61. data/lib/avo/fields/key_value_field.rb +4 -4
  62. data/lib/avo/services/authorization_service.rb +8 -4
  63. data/lib/avo/version.rb +1 -1
  64. data/lib/generators/avo/templates/locales/avo.en.yml +12 -3
  65. data/lib/generators/avo/templates/locales/avo.ro.yml +7 -0
  66. data/public/avo-packs/css/{application-f9191617.css → application-c3b50b28.css} +54 -12
  67. data/public/avo-packs/css/application-c3b50b28.css.br +0 -0
  68. data/public/avo-packs/css/{application-f9191617.css.gz → application-c3b50b28.css.gz} +0 -0
  69. data/public/avo-packs/css/application-c3b50b28.css.map +1 -0
  70. data/public/avo-packs/css/application-c3b50b28.css.map.br +0 -0
  71. data/public/avo-packs/css/application-c3b50b28.css.map.gz +0 -0
  72. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js +2 -0
  73. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.br +0 -0
  74. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.gz +0 -0
  75. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map +1 -0
  76. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.br +0 -0
  77. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.gz +0 -0
  78. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js +26 -0
  79. data/public/avo-packs/js/{application-cc89f096028eb1d4d971.js.LICENSE.txt → application-6fc968cfa52976c4582b.js.LICENSE.txt} +0 -0
  80. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.br +0 -0
  81. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.gz +0 -0
  82. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map +1 -0
  83. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.br +0 -0
  84. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.gz +0 -0
  85. data/public/avo-packs/manifest.json +21 -21
  86. metadata +29 -23
  87. data/public/avo-packs/css/application-f9191617.css.br +0 -0
  88. data/public/avo-packs/css/application-f9191617.css.map +0 -1
  89. data/public/avo-packs/css/application-f9191617.css.map.br +0 -0
  90. data/public/avo-packs/css/application-f9191617.css.map.gz +0 -0
  91. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js +0 -2
  92. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.br +0 -0
  93. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.gz +0 -0
  94. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map +0 -1
  95. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.br +0 -0
  96. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.gz +0 -0
  97. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js +0 -26
  98. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.br +0 -0
  99. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.gz +0 -0
  100. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map +0 -1
  101. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.br +0 -0
  102. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a9e6624587295b46f8f052da4cb2b6ffb8faff958d1de9ab0fe2eb98a58c05c
4
- data.tar.gz: 1010b48e463a388d0b20e3348de1c49f8468d63c2a14d78fe9ca4a9ad5c87e3e
3
+ metadata.gz: f172a929188a46646390efd7beef272e1f791b99c48a095f1fdb9bc8d3e3ec3d
4
+ data.tar.gz: 701fde39cac34c8ba48fd3403631c22f4f9ff9f90d4d2ad15ceb648f1819b887
5
5
  SHA512:
6
- metadata.gz: d18de447e0138f28d1ceb806bf16968b88dc81c0f1b097fee892bda8b19259a8df939c3fe3060e963a0f1f04e2696f3706b1f68a42b92c2e1f53a48e09788518
7
- data.tar.gz: 91d9ec101ce25c6dba5300a054476ef8fef432cfe18d6140b0f6ff92a73be95fca213a549af6c38bfd7e3f392822ad6feaeea2fff77f208395137f063e3b7594
6
+ metadata.gz: 9c4a9071eeb4fd9034e3d3326e109432cb4efa949d78a77a7fb6eddf99c008225732a20f0ba1da98f2061f3affdddea52e199cb173180df7f675b365aadd26ea
7
+ data.tar.gz: 9a706c402ce0b27429c60b909af0db4ad143819f371112ad0cbb0b198912a626645ee758da5bf9d2d9615e12c2622e04296c818d703f84b942ffaa52b06c9981
data/Gemfile CHANGED
@@ -15,7 +15,7 @@ gemspec
15
15
  # gem 'byebug', group: [:development, :test]
16
16
 
17
17
  # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
18
- gem "webpacker", "6.0.0.rc.6"
18
+ gem "webpacker", "6.0.0.rc.2"
19
19
 
20
20
  gem "countries"
21
21
 
@@ -91,7 +91,7 @@ group :test do
91
91
  gem "rspec-rails", "~> 4.0.0"
92
92
  gem "rails-controller-testing"
93
93
  # Adds support for Capybara system testing and selenium driver
94
- gem "capybara", ">= 2.15"
94
+ gem "capybara", "3.36"
95
95
  gem "selenium-webdriver"
96
96
  # Easy installation and use of web drivers to run system tests with browsers
97
97
  gem "webdrivers"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (1.18.2)
4
+ avo (1.19.1.pre.3)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
@@ -224,11 +224,14 @@ GEM
224
224
  net-protocol
225
225
  timeout
226
226
  nio4r (2.5.8)
227
- nokogiri (1.13.0)
227
+ nokogiri (1.13.1)
228
228
  mini_portile2 (~> 2.7.0)
229
229
  racc (~> 1.4)
230
+ nokogiri (1.13.1-x86_64-linux)
231
+ racc (~> 1.4)
230
232
  orm_adapter (0.5.0)
231
- pagy (5.7.3)
233
+ pagy (5.9.3)
234
+ activesupport
232
235
  parallel (1.21.0)
233
236
  parser (3.1.0.0)
234
237
  ast (~> 2.4.1)
@@ -394,7 +397,7 @@ GEM
394
397
  addressable (>= 2.8.0)
395
398
  crack (>= 0.3.2)
396
399
  hashdiff (>= 0.4.0, < 2.0.0)
397
- webpacker (6.0.0.rc.6)
400
+ webpacker (6.0.0.rc.2)
398
401
  activesupport (>= 5.2)
399
402
  rack-proxy (>= 0.6.1)
400
403
  railties (>= 5.2)
@@ -420,7 +423,7 @@ DEPENDENCIES
420
423
  breadcrumbs_on_rails
421
424
  bump
422
425
  byebug
423
- capybara (>= 2.15)
426
+ capybara (= 3.36)
424
427
  countries
425
428
  database_cleaner
426
429
  devise
@@ -461,8 +464,8 @@ DEPENDENCIES
461
464
  web-console (>= 3.3.0)
462
465
  webdrivers
463
466
  webmock
464
- webpacker (= 6.0.0.rc.6)
467
+ webpacker (= 6.0.0.rc.2)
465
468
  zeitwerk (~> 2.3)
466
469
 
467
470
  BUNDLED WITH
468
- 2.2.32
471
+ 2.3.5
@@ -1,3 +1,3 @@
1
1
  <%= index_field_wrapper field: @field do %>
2
- <%= link_to @field.label, helpers.resource_path(@field.value) %>
2
+ <%= link_to @field.label, helpers.resource_path(model: @field.value, resource: @field.target_resource) %>
3
3
  <% end %>
@@ -1,3 +1,3 @@
1
1
  <%= show_field_wrapper field: @field, index: @index do %>
2
- <%= link_to @field.label, helpers.resource_path(@field.value, via_resource_class: @resource.model_class, via_resource_id: @resource.model.id) %>
2
+ <%= link_to @field.label, helpers.resource_path(model: @field.value, resource: @field.target_resource, via_resource_class: @resource.model_class, via_resource_id: @resource.model.id) %>
3
3
  <% end %>
@@ -23,7 +23,7 @@
23
23
  </div>
24
24
  <div>
25
25
  <% if @resource.authorization.authorize_action(:delete_attachments?, raise_exception: false) %>
26
- <%= a_link "#{Avo::App.root_path}/resources/#{@resource.model.model_name.route_key}/#{@resource.model.id}/active_storage_attachments/#{@id}/#{@file.id}", color: :red, variant: :outlined, size: :xs, class: 'text-center', 'data-turbo-frame': 'destroy_attachment_form', data: { confirm: t('avo.are_you_sure')} do %>
26
+ <%= a_link "#{@resource.record_path}/active_storage_attachments/#{@id}/#{@file.id}", color: :red, variant: :outlined, size: :xs, class: 'text-center', 'data-turbo-frame': 'destroy_attachment_form', data: { confirm: t('avo.are_you_sure')} do %>
27
27
  <%= helpers.svg 'trash' %> <span class="hidden lg:block lg:flex-1"><%= t 'avo.delete_file', item: @file.filename %></span>
28
28
  <% end %>
29
29
  <% end %>
@@ -23,8 +23,7 @@
23
23
  </div>
24
24
  <div>
25
25
  <% if @resource.authorization.authorize_action(:delete_attachments?, raise_exception: false) %>
26
- <%= a_link "#{Avo::App.root_path}/resources/#{@resource.model.model_name.route_key}/#{@resource.model.id
27
- }/active_storage_attachments/#{@id}/#{@file.blob_id}", color: :red, variant: :outlined, size: :md, class: '', 'data-turbo-frame': 'destroy_attachment_form', data: { confirm: t('avo.are_you_sure')} do %>
26
+ <%= a_link "#{@resource.record_path}/active_storage_attachments/#{@id}/#{@file.blob_id}", color: :red, variant: :outlined, size: :md, class: '', 'data-turbo-frame': 'destroy_attachment_form', data: { confirm: t('avo.are_you_sure')} do %>
28
27
  <%= helpers.svg 'trash' %> <%= t 'avo.delete_file', item: @file.filename %>
29
28
  <% end %>
30
29
  <% end %>
@@ -1,3 +1,3 @@
1
1
  <%= index_field_wrapper field: @field do %>
2
- <%= link_to @field.label, helpers.resource_path(@field.value) %>
2
+ <%= link_to @field.label, helpers.resource_path(model: @field.value, resource: @field.target_resource) %>
3
3
  <% end %>
@@ -6,7 +6,7 @@
6
6
  <%= render Avo::PanelComponent.new(title: @field.id.capitalize) do |c| %>
7
7
  <% c.tools do %>
8
8
  <% if !@field.readonly && can_attach? %>
9
- <%= a_link helpers.resource_attach_path(@resource.model.model_name.route_key, @resource.model.id, @field.id), color: 'indigo', 'data-turbo-frame': 'attach_modal' do %>
9
+ <%= a_link attach_path, color: 'indigo', 'data-turbo-frame': 'attach_modal' do %>
10
10
  <%= svg 'view-grid-add' %> <%= t('avo.attach_item', item: @field.id).capitalize %>
11
11
  <% end %>
12
12
  <% end %>
@@ -8,8 +8,9 @@ class Avo::Fields::HasOneField::ShowComponent < Avo::Fields::ShowComponent
8
8
  if @field.present?
9
9
  reflection_resource = @field.target_resource
10
10
  if reflection_resource.present? && @resource.present?
11
- method_name = ('attach_' + reflection_resource.model_class.model_name.singular_route_key.underscore + '?').to_sym
11
+ method_name = ("attach_#{reflection_resource.model_key}?").to_sym
12
12
  defined_policy_methods = @resource.authorization.defined_methods(@resource.model_class, raise_exception: false)
13
+
13
14
  if defined_policy_methods.present? && defined_policy_methods.include?(method_name)
14
15
  attach_policy = @resource.authorization.authorize_action(method_name, raise_exception: false)
15
16
  end
@@ -17,4 +18,8 @@ class Avo::Fields::HasOneField::ShowComponent < Avo::Fields::ShowComponent
17
18
  end
18
19
  attach_policy
19
20
  end
21
+
22
+ def attach_path
23
+ helpers.avo.resources_associations_new_path(@resource.singular_model_key, @resource.model.id, @field.id)
24
+ end
20
25
  end
@@ -12,9 +12,9 @@ class Avo::Fields::IndexComponent < ViewComponent::Base
12
12
 
13
13
  def resource_path
14
14
  if @parent_model.present?
15
- helpers.resource_path(@resource.model, via_resource_class: @parent_model.class, via_resource_id: @parent_model.id)
15
+ helpers.resource_path(model: @resource.model, resource: @resource, via_resource_class: @parent_model.class, via_resource_id: @parent_model.id)
16
16
  else
17
- helpers.resource_path(@resource.model)
17
+ helpers.resource_path(model: @resource.model, resource: @resource)
18
18
  end
19
19
  end
20
20
  end
@@ -2,7 +2,7 @@
2
2
  <div
3
3
  data-controller="trix-field"
4
4
  data-trix-field-target="controller"
5
- data-resource-name="<%= @resource.model_class.model_name.route_key %>"
5
+ data-resource-name="<%= @resource.model_key %>"
6
6
  data-resource-id="<%= @resource.model.id %>"
7
7
  data-attachments-disabled="<%= @field.attachments_disabled %>"
8
8
  data-attachment-key="<%= @field.attachment_key %>"
@@ -7,17 +7,17 @@
7
7
  <% if cover.blank? %>
8
8
  <%= render Avo::Index::GridCoverEmptyStateComponent.new %>
9
9
  <% elsif cover.respond_to?(:to_image) && cover.to_image.present? %>
10
- <%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'), helpers.resource_path(@resource.model), class: 'absolute h-full w-full object-cover', title: title.value %>
10
+ <%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'), helpers.resource_path(model: @resource.model, resource: @resource), class: 'absolute h-full w-full object-cover', title: title.value %>
11
11
  <% elsif cover.type == 'file' %>
12
12
  <% if cover.value.attached? && cover.value.representable? %>
13
- <%= link_to_if cover.link_to_resource, image_tag(helpers.main_app.url_for(cover.value.variant(resize_to_limit: [480, 480])), class: 'absolute h-full w-full object-cover'), helpers.resource_path(@resource.model), class: 'absolute h-full w-full object-cover', title: title.value %>
13
+ <%= link_to_if cover.link_to_resource, image_tag(helpers.main_app.url_for(cover.value.variant(resize_to_limit: [480, 480])), class: 'absolute h-full w-full object-cover'), helpers.resource_path(model: @resource.model, resource: @resource), class: 'absolute h-full w-full object-cover', title: title.value %>
14
14
  <% else %>
15
15
  <div class="absolute bg-gray-100 w-full h-full">
16
16
  <%= helpers.svg 'avocado', class: 'relative transform -translate-x-1/2 -translate-y-1/2 h-20 text-gray-400 inset-auto top-1/2 left-1/2' %>
17
17
  </div>
18
18
  <% end %>
19
19
  <% elsif cover.value.present? %>
20
- <%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'), helpers.resource_path(@resource.model), class: 'absolute h-full w-full object-cover', title: title.value %>
20
+ <%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'), helpers.resource_path(model: @resource.model, resource: @resource), class: 'absolute h-full w-full object-cover', title: title.value %>
21
21
  <% else %>
22
22
  <%= render Avo::Index::GridCoverEmptyStateComponent.new %>
23
23
  <% end %>
@@ -25,7 +25,7 @@
25
25
  <div class="grid grid-cols-1 place-content-between p-4 h-full">
26
26
  <div class="mb-4">
27
27
  <div class="grid font-semibold leading-tight text-lg mb-2">
28
- <%= link_to_if title.link_to_resource, title.value, helpers.resource_path(@resource.model) if title.present? %>
28
+ <%= link_to_if title.link_to_resource, title.value, helpers.resource_path(model: @resource.model, resource: @resource) if title.present? %>
29
29
  </div>
30
30
  <div class="text-sm break-words">
31
31
  <%= body.value if body.present? %>
@@ -42,7 +42,7 @@
42
42
  <% end %>
43
43
 
44
44
  <% if can_delete? %>
45
- <%= form_with url: helpers.resource_path(@resource.model), method: :delete, html: {
45
+ <%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource), method: :delete, html: {
46
46
  'data-turbo-frame': params[:turbo_frame]
47
47
  } do |form| %>
48
48
  <%= form.button helpers.svg('trash', class: 'text-gray-400 h-6 hover:text-gray-600'),
@@ -23,19 +23,29 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
23
23
  end
24
24
 
25
25
  def show_path
26
+ args = {}
27
+
26
28
  if @parent_model.present?
27
- helpers.resource_path(@resource.model, via_resource_class: @parent_model.class.base_class, via_resource_id: @parent_model.id)
28
- else
29
- helpers.resource_path(@resource.model)
29
+ args = {
30
+ via_resource_class: parent_resource.model_class,
31
+ via_resource_id: @parent_model.id
32
+ }
30
33
  end
34
+
35
+ helpers.resource_path(model: @resource.model, resource: @resource, **args)
31
36
  end
32
37
 
33
38
  def edit_path
39
+ args = {}
40
+
34
41
  if @parent_model.present?
35
- helpers.edit_resource_path(@resource.model, via_resource_class: @parent_model.class.base_class, via_resource_id: @parent_model.id)
36
- else
37
- helpers.edit_resource_path(@resource.model)
42
+ args = {
43
+ via_resource_class: parent_resource.model_class,
44
+ via_resource_id: @parent_model.id
45
+ }
38
46
  end
47
+
48
+ helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
39
49
  end
40
50
 
41
51
  def singular_resource_name
@@ -45,4 +55,10 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
45
55
  @resource.singular_name.present? ? @resource.singular_name : @resource.model_class.model_name.name.downcase
46
56
  end
47
57
  end
58
+
59
+ def parent_resource
60
+ return nil if @parent_model.blank?
61
+
62
+ ::Avo::App.get_resource_by_model_name @parent_model.class
63
+ end
48
64
  end
@@ -1,6 +1,6 @@
1
1
  <div class="w-full">
2
2
  <% if @resources.present?%>
3
- <table class="w-full px-4 overflow-hidden" data-resource-name='<%= @resource.model_class.model_name.route_key %>' data-controller='item-select-all'>
3
+ <table class="w-full px-4 overflow-hidden" data-resource-name='<%= @resource.model_key %>' data-controller='item-select-all'>
4
4
  <%= render partial: 'avo/partials/table_header', locals: {fields: @resource.get_fields(reflection: @reflection)} %>
5
5
  <tbody>
6
6
  <% @resources.each_with_index do |resource, index| %>
@@ -6,19 +6,18 @@ class Avo::PanelComponent < ViewComponent::Base
6
6
  renders_one :bare_content
7
7
  renders_one :footer
8
8
 
9
- def initialize(title: nil, body_classes: nil, data: {}, display_breadcrumbs: false)
9
+ def initialize(title: nil, body_classes: nil, data: {}, display_breadcrumbs: false, index: nil)
10
10
  @title = title
11
11
  @body_classes = body_classes
12
12
  @data = data
13
13
  @display_breadcrumbs = display_breadcrumbs
14
+ @index = index
14
15
  end
15
16
 
16
17
  private
17
18
 
18
19
  def data_attributes
19
- return if @data.blank?
20
-
21
- @data.map do |key, value|
20
+ @data.merge({'panel-index': @index}).map do |key, value|
22
21
  " data-#{key}=\"#{value}\""
23
22
  end.join
24
23
  end
@@ -12,7 +12,7 @@ class Avo::ResourceComponent < ViewComponent::Base
12
12
  if @reflection.present?
13
13
  reflection_resource = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name)
14
14
  if reflection_resource.present?
15
- method_name = ("#{policy_method}_#{@reflection.name.to_s.underscore}?").to_sym
15
+ method_name = "#{policy_method}_#{@reflection.name.to_s.underscore}?".to_sym
16
16
  defined_policy_methods = reflection_resource.authorization.defined_methods(reflection_resource.model_class, raise_exception: false)
17
17
  if defined_policy_methods.present? && defined_policy_methods.include?(method_name)
18
18
  association_policy = reflection_resource.authorization.authorize_action(method_name, raise_exception: false)
@@ -28,4 +28,8 @@ class Avo::ResourceComponent < ViewComponent::Base
28
28
  def simple_relation?
29
29
  @reflection.is_a? ::ActiveRecord::Reflection::HasManyReflection
30
30
  end
31
+
32
+ def relation_resource
33
+ ::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
34
+ end
31
35
  end
@@ -1,6 +1,6 @@
1
1
  <div data-model-id="<%= @resource.model.id %>">
2
2
  <% @resource.panels.each do |resource_panel| %>
3
- <%= form_with model: @resource.model, scope: @resource.form_scope, url: helpers.resource_path(@resource.model), method: :put, multipart: true do |form| %>
3
+ <%= form_with model: @resource.model, scope: @resource.form_scope, url: helpers.resource_path(model: @resource.model, resource: @resource), method: :put, multipart: true do |form| %>
4
4
  <%= hidden_field_tag :referrer, back_path if params[:via_resource_class] %>
5
5
 
6
6
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], display_breadcrumbs: true) do |c| %>
@@ -10,8 +10,8 @@
10
10
  <%= helpers.svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
11
11
  <% end %>
12
12
 
13
- <% if @resource.authorization.authorize_action :update, raise_exception: false %>
14
- <%= a_button color: 'green', variant: 'outlined', type: :submit do %>
13
+ <% if can_see_the_save_button? %>
14
+ <%= a_button color: 'green', variant: 'outlined', spinner: true, type: :submit do %>
15
15
  <%= helpers.svg 'save' %> <%= t('avo.save').capitalize %>
16
16
  <% end %>
17
17
  <% end %>
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Avo::Views::ResourceEditComponent < ViewComponent::Base
3
+ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
4
4
  include Avo::ResourcesHelper
5
5
  include Avo::ApplicationHelper
6
6
 
@@ -10,12 +10,18 @@ class Avo::Views::ResourceEditComponent < ViewComponent::Base
10
10
 
11
11
  def back_path
12
12
  if via_resource?
13
- helpers.resource_path(params[:via_resource_class].safe_constantize, resource_id: params[:via_resource_id])
13
+ helpers.resource_path(model: params[:via_resource_class].safe_constantize, resource: relation_resource, resource_id: params[:via_resource_id])
14
14
  else
15
- helpers.resource_path(@resource.model)
15
+ helpers.resource_path(model: @resource.model, resource: @resource)
16
16
  end
17
17
  end
18
18
 
19
+ # The save button is dependent on the edit? policy method.
20
+ # The update? method should be called only when the user clicks the Save button so the developer gets access to the params from the form.
21
+ def can_see_the_save_button?
22
+ @resource.authorization.authorize_action :edit, raise_exception: false
23
+ end
24
+
19
25
  private
20
26
 
21
27
  def via_resource?
@@ -3,18 +3,12 @@
3
3
  <% c.tools do %>
4
4
  <%= render 'actions' if @actions.present? %>
5
5
 
6
- <% if can_create? %>
6
+ <% if can_see_the_create_button? %>
7
7
  <%= a_link create_path do %>
8
8
  <%= svg 'plus' %> <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
9
9
  <% end %>
10
10
  <% end %>
11
11
 
12
- <% if can_detach? %>
13
- <%= a_link detach_path, color: 'indigo', method: :delete, data: { confirm: "Are you sure you want to detach this #{@resource.singular_name}." } do %>
14
- <%= svg 'trash' %> <%= t('avo.detach_item', item: singular_resource_name).capitalize %>
15
- <% end %>
16
- <% end %>
17
-
18
12
  <% if can_attach? %>
19
13
  <%= a_link attach_path, color: 'indigo', 'data-turbo-frame': 'attach_modal' do %>
20
14
  <%= svg 'view-grid-add' %> <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
@@ -24,11 +18,11 @@
24
18
 
25
19
  <% c.body do %>
26
20
  <div class="flex justify-between pt-2 pb-2 min-h-16"
27
- data-selected-resources-name="<%= @resource.model_class.model_name.route_key %>"
21
+ data-selected-resources-name="<%= @resource.model_key %>"
28
22
  data-selected-resources="[]"
29
23
  >
30
24
  <div class="flex items-center px-6 w-64">
31
- <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key} if @resource.search_query.present? %>
25
+ <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.model_class.model_name.plural} if @resource.search_query.present? %>
32
26
  </div>
33
27
  <div class="flex justify-end items-center px-6 space-x-3">
34
28
  <%= render partial: 'avo/partials/view_toggle_button', locals: { available_view_types: available_view_types, view_type: view_type, turbo_frame: @turbo_frame } if @models.present? %>
@@ -44,8 +44,10 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
44
44
  @index_params[:available_view_types]
45
45
  end
46
46
 
47
- def can_create?
48
- @resource.authorization.authorize_action(:create, raise_exception: false) && simple_relation? && !has_reflection_and_is_read_only
47
+ # The Create button is dependent on the new? policy method.
48
+ # The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
49
+ def can_see_the_create_button?
50
+ @resource.authorization.authorize_action(:new, raise_exception: false) && simple_relation? && !has_reflection_and_is_read_only
49
51
  end
50
52
 
51
53
  def can_attach?
@@ -55,10 +57,6 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
55
57
  @reflection.present? && klass.is_a?(::ActiveRecord::Reflection::HasManyReflection) && !has_reflection_and_is_read_only && authorize_association_for("attach")
56
58
  end
57
59
 
58
- def can_detach?
59
- @reflection.present? && @reflection.is_a?(::ActiveRecord::Reflection::HasOneReflection) && @models.present? && !has_reflection_and_is_read_only && authorize_association_for("detach")
60
- end
61
-
62
60
  def has_reflection_and_is_read_only
63
61
  if @reflection.present? && @reflection.active_record.name && @reflection.name
64
62
  fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
@@ -75,35 +73,31 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
75
73
  end
76
74
 
77
75
  def create_path
76
+ args = {}
77
+
78
78
  if @reflection.present?
79
- path_args = {
79
+ args = {
80
80
  via_relation_class: @parent_model.model_name,
81
81
  via_resource_id: @parent_model.id
82
82
  }
83
83
 
84
84
  if @reflection.inverse_of.present?
85
- path_args[:via_relation] = @reflection.inverse_of.name
85
+ args[:via_relation] = @reflection.inverse_of.name
86
86
  end
87
-
88
- helpers.new_resource_path(@resource.model_class, **path_args)
89
- else
90
- helpers.new_resource_path(@resource.model_class)
91
87
  end
88
+
89
+ helpers.new_resource_path(model: @resource.model_class, resource: @resource, **args)
92
90
  end
93
91
 
94
92
  def attach_path
95
93
  "#{Avo::App.root_path}#{request.env["PATH_INFO"]}/new"
96
94
  end
97
95
 
98
- def detach_path
99
- helpers.resource_detach_path(via_resource_name, via_resource_id, via_relation_param, @models.first.id)
100
- end
101
-
102
96
  def singular_resource_name
103
97
  if @reflection.present?
104
98
  ::Avo::App.get_resource_by_model_name(@reflection.class_name).name
105
99
  else
106
- @resource.singular_name.present? ? @resource.singular_name : @resource.model_class.model_name.name.downcase
100
+ @resource.singular_name || @resource.model_class.model_name.name.downcase
107
101
  end
108
102
  end
109
103
 
@@ -1,6 +1,6 @@
1
1
  <div>
2
2
  <% @resource.panels.each do |resource_panel| %>
3
- <%= form_with model: @resource.model, url: helpers.resources_path(@resource.model, via_relation_class: params[:via_relation_class], via_resource_id: params[:via_resource_id]), local: true, multipart: true do |form| %>
3
+ <%= form_with model: @resource.model, url: helpers.resources_path(resource: @resource, via_relation_class: params[:via_relation_class], via_resource_id: params[:via_resource_id]), local: true, multipart: true do |form| %>
4
4
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], display_breadcrumbs: true) do |c| %>
5
5
  <% c.tools do %>
6
6
  <div class="flex justify-end space-x-2">
@@ -8,9 +8,11 @@
8
8
  <%= svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
9
9
  <% end %>
10
10
 
11
- <%= a_button color: 'green', type: :submit do %>
12
- <%= svg 'save' %> <%= t('avo.save').capitalize %>
13
- <% end if @resource.authorization.authorize_action :create, raise_exception: false %>
11
+ <% if can_see_the_save_button? %>
12
+ <%= a_button color: 'green', spinner: true, type: :submit do %>
13
+ <%= svg 'save' %> <%= t('avo.save').capitalize %>
14
+ <% end %>
15
+ <% end %>
14
16
  </div>
15
17
  <% end %>
16
18
 
@@ -14,15 +14,25 @@ class Avo::Views::ResourceNewComponent < ViewComponent::Base
14
14
 
15
15
  def back_path
16
16
  if via_resource?
17
- helpers.resource_path(params[:via_relation_class].safe_constantize, resource_id: params[:via_resource_id])
17
+ helpers.resource_path(model: params[:via_relation_class].safe_constantize, resource: relation_resource, resource_id: params[:via_resource_id])
18
18
  else
19
- helpers.resources_path(@resource.model)
19
+ helpers.resources_path(resource: @resource)
20
20
  end
21
21
  end
22
22
 
23
+ # The create button is dependent on the new? policy method.
24
+ # The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
25
+ def can_see_the_save_button?
26
+ @resource.authorization.authorize_action :new, raise_exception: false
27
+ end
28
+
23
29
  private
24
30
 
25
31
  def via_resource?
26
32
  params[:via_relation_class].present? && params[:via_resource_id].present?
27
33
  end
34
+
35
+ def relation_resource
36
+ ::Avo::App.get_resource_by_model_name params[:via_relation_class].safe_constantize
37
+ end
28
38
  end
@@ -1,9 +1,9 @@
1
1
  <div data-model-id="<%= @resource.model.id %>"
2
- data-selected-resources-name="<%= @resource.model.model_name.route_key %>"
2
+ data-selected-resources-name="<%= @resource.model_key %>"
3
3
  data-selected-resources='["<%= @resource.model.id %>"]'
4
4
  >
5
- <% @resource.panels.each do |resource_panel| %>
6
- <%= render Avo::PanelComponent.new(title: resource_panel[:name], display_breadcrumbs: @reflection.blank?) do |c| %>
5
+ <% @resource.panels.each_with_index do |resource_panel, index| %>
6
+ <%= render Avo::PanelComponent.new(title: resource_panel[:name], display_breadcrumbs: @reflection.blank?, index: index) do |c| %>
7
7
  <% c.tools do %>
8
8
  <% if resource_panel[:name] == @resource.default_panel_name %>
9
9
  <%= render 'actions' %>
@@ -14,7 +14,7 @@
14
14
  <%= svg 'trash' %> <%= t('avo.detach_item', item: @reflection.name.to_s).capitalize %>
15
15
  <% end %>
16
16
  <% end %>
17
- <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
17
+ <% if can_see_the_edit_button? %>
18
18
  <%= a_link edit_path, color: 'indigo' do %>
19
19
  <%= svg 'edit' %> <%= t('avo.edit').capitalize %>
20
20
  <% end %>
@@ -24,9 +24,10 @@
24
24
  <%= svg 'arrow-left' %> <%= t('avo.go_back') %>
25
25
  <% end %>
26
26
 
27
- <% if @resource.authorization.authorize_action(:destroy, raise_exception: false) %>
28
- <%= form_with url: helpers.resource_path(@resource.model), method: :delete, html: { 'data-turbo-frame': params[:turbo_frame] } do |form| %>
27
+ <% if can_see_the_destroy_button? %>
28
+ <%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource), method: :delete, html: { 'data-turbo-frame': params[:turbo_frame] } do |form| %>
29
29
  <%= a_button title: t('avo.delete_item', item: @resource.model.model_name.name.downcase).capitalize,
30
+ spinner: true,
30
31
  color: 'red',
31
32
  variant: 'outlined',
32
33
  type: :submit,
@@ -15,18 +15,23 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
15
15
 
16
16
  def back_path
17
17
  if via_resource?
18
- helpers.resource_path(params[:via_resource_class].safe_constantize, resource_id: params[:via_resource_id])
18
+ helpers.resource_path(model: params[:via_resource_class].safe_constantize, resource: relation_resource, resource_id: params[:via_resource_id])
19
19
  else
20
- helpers.resources_path(@resource.model)
20
+ helpers.resources_path(resource: @resource)
21
21
  end
22
22
  end
23
23
 
24
24
  def edit_path
25
+ args = {}
26
+
25
27
  if via_resource?
26
- helpers.edit_resource_path(@resource.model, via_resource_class: params[:via_resource_class], via_resource_id: params[:via_resource_id])
27
- else
28
- helpers.edit_resource_path(@resource.model)
28
+ args = {
29
+ via_resource_class: params[:via_resource_class],
30
+ via_resource_id: params[:via_resource_id]
31
+ }
29
32
  end
33
+
34
+ helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
30
35
  end
31
36
 
32
37
  def detach_path
@@ -34,11 +39,19 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
34
39
  end
35
40
 
36
41
  def destroy_path
37
- helpers.resource_path(@resource.model)
42
+ helpers.resource_path(model: @resource.model, resource: @resource)
38
43
  end
39
44
 
40
45
  def can_detach?
41
- authorize_association_for('detach')
46
+ authorize_association_for("detach")
47
+ end
48
+
49
+ def can_see_the_edit_button?
50
+ @resource.authorization.authorize_action(:edit, raise_exception: false)
51
+ end
52
+
53
+ def can_see_the_destroy_button?
54
+ @resource.authorization.authorize_action(:destroy, raise_exception: false)
42
55
  end
43
56
 
44
57
  private
@@ -67,7 +67,7 @@ module Avo
67
67
 
68
68
  redirect_to path, "#{response[:message_type]}": response[:message]
69
69
  elsif response[:type] == :reload
70
- redirect_back fallback_location: resources_path(@resource.model_class), "#{response[:message_type]}": response[:message]
70
+ redirect_back fallback_location: resources_path(resource: @resource), "#{response[:message_type]}": response[:message]
71
71
  end
72
72
  end
73
73
  end