avo 2.11.0 → 2.11.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/Gemfile.lock +7 -6
  4. data/app/assets/stylesheets/avo.css +1 -4
  5. data/app/assets/stylesheets/css/sidebar.css +28 -0
  6. data/app/components/avo/fields/date_field/show_component.html.erb +4 -0
  7. data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -0
  8. data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -0
  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 +7 -6
  11. data/app/components/avo/fields/text_field/index_component.html.erb +2 -0
  12. data/app/components/avo/fields/text_field/show_component.html.erb +2 -0
  13. data/app/components/avo/index/field_wrapper_component.html.erb +4 -0
  14. data/app/components/avo/index/resource_controls_component.rb +7 -5
  15. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  16. data/app/components/avo/index/resource_table_component.rb +2 -1
  17. data/app/components/avo/index/table_row_component.html.erb +1 -1
  18. data/app/components/avo/index/table_row_component.rb +2 -1
  19. data/app/components/avo/item_switcher_component.rb +2 -0
  20. data/app/components/avo/panel_component.html.erb +2 -4
  21. data/app/components/avo/panel_component.rb +0 -4
  22. data/app/components/avo/resource_component.rb +14 -27
  23. data/app/components/avo/sidebar/link_component.rb +4 -1
  24. data/app/components/avo/sidebar_component.html.erb +2 -2
  25. data/app/components/avo/tab_group_component.html.erb +1 -2
  26. data/app/components/avo/tab_switcher_component.rb +4 -0
  27. data/app/components/avo/views/resource_edit_component.html.erb +30 -8
  28. data/app/components/avo/views/resource_edit_component.rb +4 -8
  29. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  30. data/app/components/avo/views/resource_index_component.rb +5 -3
  31. data/app/components/avo/views/resource_show_component.html.erb +14 -2
  32. data/app/components/avo/views/resource_show_component.rb +3 -3
  33. data/app/controllers/avo/application_controller.rb +24 -9
  34. data/app/controllers/avo/associations_controller.rb +38 -12
  35. data/app/controllers/avo/base_controller.rb +5 -3
  36. data/app/javascript/js/controllers/fields/date_field_controller.js +11 -1
  37. data/app/javascript/js/controllers/sidebar_controller.js +46 -0
  38. data/app/javascript/js/controllers.js +2 -2
  39. data/app/views/avo/base/edit.html.erb +0 -1
  40. data/app/views/avo/base/index.html.erb +1 -0
  41. data/app/views/avo/base/show.html.erb +7 -1
  42. data/app/views/avo/partials/_javascript.html.erb +1 -0
  43. data/app/views/avo/partials/_navbar.html.erb +5 -2
  44. data/app/views/layouts/avo/application.html.erb +3 -3
  45. data/avo.gemspec +1 -1
  46. data/lib/avo/base_action.rb +8 -6
  47. data/lib/avo/base_resource.rb +2 -5
  48. data/lib/avo/concerns/has_fields.rb +5 -0
  49. data/lib/avo/concerns/has_html_attributes.rb +1 -1
  50. data/lib/avo/fields/has_base_field.rb +11 -0
  51. data/lib/avo/fields/text_field.rb +4 -2
  52. data/lib/avo/services/authorization_service.rb +41 -37
  53. data/lib/avo/version.rb +1 -1
  54. data/lib/avo.rb +1 -0
  55. data/public/avo-assets/avo.css +51 -15
  56. data/public/avo-assets/avo.js +68 -67
  57. data/public/avo-assets/avo.js.map +3 -3
  58. metadata +10 -10
  59. data/app/javascript/js/controllers/mobile_controller.js +0 -9
  60. data/lib/avo/has_context.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebb9e406c79af9dcca77ccea6f411fa429550de8555f388b79d60af3b2ce7825
4
- data.tar.gz: 97aafbd2536588e5065b75674b18720f26ceb59dbdb0860c1fb5d5ea4a7aef24
3
+ metadata.gz: 794b7326ae2257afd693641ff51ba513d09d4729a77a671a96f1291f0b31b8e3
4
+ data.tar.gz: a3b8b5d2f19e9ac16164ae6cb634a0f53d92da7af1b4bc3c829704327f112c91
5
5
  SHA512:
6
- metadata.gz: a2d14c10d9e28687eca060949975278e020c63fb19935e5d05f4d4c6813bed779fc609bf0a72f831c784236b8122d545c04ce47d8b43463919f259b010201c6a
7
- data.tar.gz: 47d92e0cd4e94c2fffb1e0440f66deded02442f18c1eac9b7bfa22f403f11f9122d4353c1b882b7572b9fada13fd53ce193d66c923d12b034625c9c1a5b67e3f
6
+ metadata.gz: 15b95f8cef9a7ec9af6a272dd2abddbb7d8471f5edefb568b16e84f3b26165f7ac4f913974d70291463c8fcbc4427d7608a41a01c0167864d0368178ebf1e755
7
+ data.tar.gz: 7a7b600d0cc554e8aa30377199dad939e82c8165310b9f81cfe911c06a4d3cac3c72617fdad432475cd61bfcb60a1d00ee5ba4101a2d204940f48f6c6f03ba72
data/Gemfile CHANGED
@@ -121,8 +121,6 @@ gem "hotwire-rails"
121
121
 
122
122
  gem "active_link_to"
123
123
 
124
- gem "view_component"
125
-
126
124
  gem "addressable"
127
125
 
128
126
  gem "appraisal"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.11.0)
4
+ avo (2.11.1.pre.3)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
@@ -16,7 +16,7 @@ PATH
16
16
  pagy
17
17
  pundit
18
18
  rails (>= 6.0)
19
- view_component
19
+ view_component (= 2.60)
20
20
  zeitwerk
21
21
 
22
22
  GEM
@@ -201,7 +201,7 @@ GEM
201
201
  httparty (0.20.0)
202
202
  mime-types (~> 3.0)
203
203
  multi_xml (>= 0.5.2)
204
- i18n (1.11.0)
204
+ i18n (1.12.0)
205
205
  concurrent-ruby (~> 1.0)
206
206
  i18n_data (0.15.0)
207
207
  simple_po_parser (~> 1.1)
@@ -252,6 +252,8 @@ GEM
252
252
  nokogiri (1.13.7)
253
253
  mini_portile2 (~> 2.8.0)
254
254
  racc (~> 1.4)
255
+ nokogiri (1.13.7-x86_64-linux)
256
+ racc (~> 1.4)
255
257
  orm_adapter (0.5.0)
256
258
  pagy (5.10.1)
257
259
  activesupport
@@ -388,10 +390,10 @@ GEM
388
390
  turbo-rails (1.0.1)
389
391
  actionpack (>= 6.0.0)
390
392
  railties (>= 6.0.0)
391
- tzinfo (2.0.4)
393
+ tzinfo (2.0.5)
392
394
  concurrent-ruby (~> 1.0)
393
395
  unicode-display_width (2.1.0)
394
- view_component (2.57.1)
396
+ view_component (2.60.0)
395
397
  activesupport (>= 5.0.0, < 8.0)
396
398
  method_source (~> 1.0)
397
399
  warden (1.2.9)
@@ -481,7 +483,6 @@ DEPENDENCIES
481
483
  standard
482
484
  test-prof
483
485
  tzinfo-data
484
- view_component
485
486
  web-console (>= 3.3.0)
486
487
  webdrivers
487
488
  webmock
@@ -16,6 +16,7 @@
16
16
  @import './css/breadcrumbs.css';
17
17
  @import './css/search.css';
18
18
  @import './css/active-storage.css';
19
+ @import './css/sidebar.css';
19
20
  @import './css/spinner.css';
20
21
  @import './css/tags.css';
21
22
 
@@ -69,10 +70,6 @@ body {
69
70
  @apply opacity-0 translate-y-1;
70
71
  }
71
72
 
72
- .application-sidebar .active:hover,
73
- .application-sidebar .active {
74
- @apply bg-blue-100 text-blue-500;
75
- }
76
73
 
77
74
  .turbo-progress-bar {
78
75
  @apply bg-blue-400;
@@ -0,0 +1,28 @@
1
+ .application-sidebar .active:hover,
2
+ .application-sidebar .active {
3
+ @apply bg-blue-100 text-blue-500;
4
+ }
5
+
6
+ .content-area {
7
+ /* remove the left padding. */
8
+ .main-content-area {
9
+ @apply lg:pl-0;
10
+ }
11
+
12
+ /* Hide the sidebar by default. */
13
+ .avo-sidebar {
14
+ @apply lg:hidden;
15
+ }
16
+
17
+ &.sidebar-open {
18
+ /* Add padding to the main area to allow for the sidebar to expand. */
19
+ .main-content-area {
20
+ @apply lg:pl-64;
21
+ }
22
+
23
+ /* Show the sidebar. */
24
+ .avo-sidebar {
25
+ @apply lg:block;
26
+ }
27
+ }
28
+ }
@@ -5,5 +5,9 @@
5
5
  date_field_format_value: @field.format,
6
6
  } do %>
7
7
  <%= @field.formatted_value %>
8
+ <% if params[:avo_debug].present? %>
9
+ <!-- Raw value: -->
10
+ <!-- <%= @field.formatted_value.inspect %> -->
11
+ <% end %>
8
12
  <% end %>
9
13
  <% end %>
@@ -2,6 +2,7 @@
2
2
  <%= content_tag :div, data: {
3
3
  controller: "date-field",
4
4
  date_field_view_value: @view,
5
+ date_field_enable_time_value: true,
5
6
  date_field_format_value: @field.format,
6
7
  date_field_timezone_value: @field.timezone,
7
8
  date_field_picker_format_value: @field.picker_format,
@@ -2,6 +2,7 @@
2
2
  <%= content_tag :div, data: {
3
3
  controller: "date-field",
4
4
  date_field_view_value: @view,
5
+ date_field_enable_time_value: true,
5
6
  date_field_format_value: @field.format,
6
7
  date_field_timezone_value: @field.timezone,
7
8
  date_field_picker_format_value: @field.picker_format,
@@ -7,7 +7,7 @@
7
7
  <% c.tools do %>
8
8
  <% if !@field.readonly && can_attach? %>
9
9
  <%= a_link attach_path, icon: 'heroicons/outline/link', color: :primary, 'data-turbo-frame': 'attach_modal' do %>
10
- <%= t('avo.attach_item', item: @field.name) %>
10
+ <%= t('avo.attach_item', item: @field.name.downcase) %>
11
11
  <% end %>
12
12
  <% end %>
13
13
  <% end %>
@@ -4,19 +4,20 @@ class Avo::Fields::HasOneField::ShowComponent < Avo::Fields::ShowComponent
4
4
  include Avo::ApplicationHelper
5
5
 
6
6
  def can_attach?
7
- attach_policy = true
7
+ policy_result = true
8
+
8
9
  if @field.present?
9
10
  reflection_resource = @field.target_resource
10
11
  if reflection_resource.present? && @resource.present?
11
- method_name = ("attach_#{reflection_resource.model_key}?").to_sym
12
- defined_policy_methods = @resource.authorization.defined_methods(@resource.model_class, raise_exception: false)
12
+ method_name = "attach_#{@field.id}?".to_sym
13
13
 
14
- if defined_policy_methods.present? && defined_policy_methods.include?(method_name)
15
- attach_policy = @resource.authorization.authorize_action(method_name, raise_exception: false)
14
+ if @resource.authorization.has_method?(method_name, raise_exception: false)
15
+ policy_result = @resource.authorization.authorize_action(method_name, raise_exception: false)
16
16
  end
17
17
  end
18
18
  end
19
- attach_policy
19
+
20
+ policy_result
20
21
  end
21
22
 
22
23
  def attach_path
@@ -1,6 +1,8 @@
1
1
  <%= index_field_wrapper field: @field, resource: @resource do %>
2
2
  <% if @field.as_html %>
3
3
  <%== @field.value %>
4
+ <% elsif @field.protocol.present? %>
5
+ <%= link_to @field.value, "#{@field.protocol}:#{@field.value}" %>
4
6
  <% else %>
5
7
  <%= link_to_if @field.link_to_resource, @field.value, resource_path %>
6
8
  <% end %>
@@ -1,6 +1,8 @@
1
1
  <%= show_field_wrapper field: @field, resource: @resource, index: @index do %>
2
2
  <% if @field.as_html %>
3
3
  <%== @field.value %>
4
+ <% elsif @field.protocol.present? %>
5
+ <%= link_to @field.value, "#{@field.protocol}:#{@field.value}" %>
4
6
  <% else %>
5
7
  <%= @field.value %>
6
8
  <% end %>
@@ -17,4 +17,8 @@
17
17
  <%= content %>
18
18
  <% end %>
19
19
  <% end %>
20
+ <% if params[:avo_debug].present? %>
21
+ <!-- Raw value: -->
22
+ <!-- <%= @field.value.inspect %> -->
23
+ <% end %>
20
24
  <% end %>
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
4
- def initialize(resource: nil, reflection: nil, parent_model: nil, view_type: :table)
4
+ def initialize(resource: nil, reflection: nil, parent_model: nil, parent_resource: nil, view_type: :table)
5
5
  @resource = resource
6
6
  @reflection = reflection
7
7
  @parent_model = parent_model
8
+ @parent_resource = parent_resource
8
9
  @view_type = view_type
9
10
  end
10
11
 
@@ -12,7 +13,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
12
13
  @reflection.present? &&
13
14
  @resource.model.present? &&
14
15
  is_has_many_association &&
15
- authorize_association_for("detach")
16
+ authorize_association_for(:detach)
16
17
  end
17
18
 
18
19
  def can_edit?
@@ -22,8 +23,9 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
22
23
  end
23
24
 
24
25
  def can_view?
25
- return authorize_association_for(:view) if @reflection.present?
26
+ return authorize_association_for(:show) if @reflection.present?
26
27
 
28
+ # Even if there's a @reflection object present, for show we're going to fallback to the original policy.
27
29
  @resource.authorization.authorize_action(:show, raise_exception: false)
28
30
  end
29
31
 
@@ -42,7 +44,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
42
44
 
43
45
  def edit_path
44
46
  # Add the `view` param to let Avo know where to redirect back when the user clicks the `Cancel` button.
45
- args = {via_view: 'index'}
47
+ args = {via_view: "index"}
46
48
 
47
49
  if @parent_model.present?
48
50
  args = {
@@ -73,6 +75,6 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
73
75
  end
74
76
 
75
77
  def referrer_path
76
- Avo::App.root_path(paths: ['resources', params[:resource_name], params[:id], params[:related_name]], query: request.query_parameters.to_h)
78
+ Avo::App.root_path(paths: ["resources", params[:resource_name], params[:id], params[:related_name]], query: request.query_parameters.to_h)
77
79
  end
78
80
  end
@@ -4,7 +4,7 @@
4
4
  <tbody class="divide-y">
5
5
  <% @resources.each_with_index do |resource, index| %>
6
6
  <% cache_if Avo.configuration.cache_resources_on_index_view, resource.cache_hash(@parent_model), expires_in: 1.day do %>
7
- <%= render Avo::Index::TableRowComponent.new(resource: resource, reflection: @reflection, parent_model: @parent_model) %>
7
+ <%= render Avo::Index::TableRowComponent.new(resource: resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource) %>
8
8
  <% end %>
9
9
  <% end %>
10
10
  </tbody>
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Index::ResourceTableComponent < ViewComponent::Base
4
- def initialize(resources: nil, resource: nil, reflection: nil, parent_model: nil)
4
+ def initialize(resources: nil, resource: nil, reflection: nil, parent_model: nil, parent_resource: nil)
5
5
  @resources = resources
6
6
  @resource = resource
7
7
  @reflection = reflection
8
8
  @parent_model = parent_model
9
+ @parent_resource = parent_resource
9
10
  end
10
11
  end
@@ -14,7 +14,7 @@
14
14
  <% end %>
15
15
  <td class="text-right whitespace-nowrap px-2">
16
16
  <div class="flex items-center justify-end flex-grow-0 h-full w-full">
17
- <%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, view_type: :table)) %>
17
+ <%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, view_type: :table)) %>
18
18
  </div>
19
19
  </td>
20
20
  </tr>
@@ -3,9 +3,10 @@
3
3
  class Avo::Index::TableRowComponent < ViewComponent::Base
4
4
  include Avo::ResourcesHelper
5
5
 
6
- def initialize(resource: nil, reflection: nil, parent_model: nil)
6
+ def initialize(resource: nil, reflection: nil, parent_model: nil, parent_resource: nil)
7
7
  @resource = resource
8
8
  @reflection = reflection
9
9
  @parent_model = parent_model
10
+ @parent_resource = parent_resource
10
11
  end
11
12
  end
@@ -28,6 +28,8 @@ class Avo::ItemSwitcherComponent < Avo::BaseComponent
28
28
  return false if in_reflection? && item.hidden_in_reflection?
29
29
  end
30
30
 
31
+ return false if item.is_main_panel?
32
+
31
33
  true
32
34
  end
33
35
 
@@ -34,10 +34,8 @@
34
34
  </div>
35
35
  <% end %>
36
36
  <% if footer_tools? %>
37
- <div class="<%= white_panel_classes %> p-4 flex-1 flex flex-col xl:flex-row justify-between mt-6">
38
- <div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end space-y-2 sm:space-y-0 sm:space-x-2 mt-4 xl:mt-0">
39
- <%= footer_tools %>
40
- </div>
37
+ <div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end space-y-2 sm:space-y-0 sm:space-x-2 mt-4 xl:mt-0">
38
+ <%= footer_tools %>
41
39
  </div>
42
40
  <% end %>
43
41
  <% if footer? %>
@@ -47,8 +47,4 @@ class Avo::PanelComponent < ViewComponent::Base
47
47
  def render_header?
48
48
  @name.present? || description.present? || tools.present? || display_breadcrumbs?
49
49
  end
50
-
51
- def render_footer_tools?
52
- footer_tools.present?
53
- end
54
50
  end
@@ -39,52 +39,39 @@ class Avo::ResourceComponent < Avo::BaseComponent
39
39
  end
40
40
 
41
41
  def authorize_association_for(policy_method)
42
- association_policy = true
42
+ policy_result = true
43
43
 
44
44
  if @reflection.present?
45
+ # Fetch the appropiate resource
45
46
  reflection_resource = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name)
47
+ # Fetch the model
48
+ # Hydrate the resource with the model if we have one
46
49
  reflection_resource.hydrate(model: @parent_model) if @parent_model.present?
47
- association_name = params["related_name"]
50
+ # Use the related_name as the base of the association
51
+ association_name = @reflection.name
48
52
 
49
53
  if association_name.present?
50
54
  method_name = "#{policy_method}_#{association_name}?".to_sym
55
+ # Prepare the authorization service
56
+ service = reflection_resource.authorization
51
57
 
52
- if reflection_resource.authorization.has_method?(method_name, raise_exception: false)
53
- association_policy = reflection_resource.authorization.authorize_action(method_name, raise_exception: false)
58
+ if service.has_method?(method_name, raise_exception: false)
59
+ policy_result = service.authorize_action(method_name, raise_exception: false)
54
60
  end
55
61
  end
56
62
  end
57
63
 
58
- association_policy
64
+ policy_result
59
65
  end
60
66
 
61
- def split_panel_fields
62
- initialize_panels
63
- @resource.get_fields.each do |field|
64
- case field.class.to_s
65
- when "Avo::Fields::HasOneField"
66
- @has_one_panels << field
67
- when "Avo::Fields::HasManyField"
68
- @has_many_panels << field
69
- when "Avo::Fields::HasAndBelongsToManyField"
70
- @has_as_belongs_to_many_panels << field
71
- else
72
- @fields_by_panel[field.panel_name] ||= []
73
- @fields_by_panel[field.panel_name] << field
74
- end
67
+ def main_panel
68
+ @resource.get_items.find do |item|
69
+ item.is_main_panel?
75
70
  end
76
71
  end
77
72
 
78
73
  private
79
74
 
80
- def initialize_panels
81
- @fields_by_panel = {}
82
- @has_one_panels = []
83
- @has_many_panels = []
84
- @has_as_belongs_to_many_panels = []
85
- @resource_tools = @resource.tools
86
- end
87
-
88
75
  def via_resource?
89
76
  params[:via_resource_class].present? && params[:via_resource_id].present?
90
77
  end
@@ -14,7 +14,10 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
14
14
  end
15
15
 
16
16
  def is_external?
17
- URI(path).scheme.present?
17
+ # If the path contains the scheme, check if it includes the root path or not
18
+ return !path.include?(Avo::App.root_path) if URI(path).scheme.present?
19
+
20
+ false
18
21
  end
19
22
 
20
23
  # For external links active_link_to marks them all as active.
@@ -1,6 +1,6 @@
1
1
  <div
2
- class="fixed z-[60] t-0 application-sidebar w-64 hidden lg:flex flex-1 border-r lg:border-none bg-none h-[calc(100vh-4rem)] bg-gray-25 lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
3
- data-mobile-target="sidebar"
2
+ class="avo-sidebar fixed z-[60] t-0 application-sidebar w-64 hidden lg:flex flex-1 border-r lg:border-none bg-none h-[calc(100vh-4rem)] bg-gray-25 lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>";
3
+ data-sidebar-target="sidebar"
4
4
  >
5
5
  <div class="flex flex-col w-full h-full">
6
6
  <div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows">
@@ -5,8 +5,7 @@
5
5
  controller: "tabs",
6
6
  tabs_view_value: view,
7
7
  tabs_active_tab_value: active_tab_name
8
- },
9
- class: 'space-y-12' do %>
8
+ } do %>
10
9
  <% visible_tabs.each_with_index do |tab, index| %>
11
10
  <%
12
11
  args = {
@@ -80,6 +80,10 @@ class Avo::TabSwitcherComponent < Avo::BaseComponent
80
80
  visible = item.visible?
81
81
  end
82
82
 
83
+ if item.respond_to?(:authorized?)
84
+ visible = item.authorized?
85
+ end
86
+
83
87
  visible
84
88
  end
85
89
  end
@@ -33,20 +33,42 @@
33
33
  <% end %>
34
34
  <% end %>
35
35
  <% end %>
36
+ <%# Extract the main panel and display the fields here. %>
37
+ <%# This way we'll be able to render the footer buttons under the main fields. %>
38
+ <% if main_panel.present? %>
39
+ <% c.body do %>
40
+ <div class="divide-y">
41
+ <% main_panel.items.each_with_index do |field, index| %>
42
+ <%= render field.hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: view)
43
+ .component_for_view(view)
44
+ .new(field: field, resource: @resource, index: index, form: form)
45
+ %>
46
+ <% end %>
47
+ </div>
48
+ <% end %>
49
+ <% end %>
36
50
  <% if Avo.configuration.buttons_on_form_footers %>
37
51
  <% c.footer_tools do %>
38
- <%= a_link back_path, icon: 'arrow-left' do %>
39
- <%= t('avo.cancel').capitalize %>
40
- <% end %>
41
- <% if can_see_the_save_button? %>
42
- <%= a_button color: :green, loading: true, type: :submit, icon: 'save' do %>
43
- <%= t('avo.save').capitalize %>
52
+ <div class="mt-4">
53
+ <%= a_link back_path,
54
+ style: :text,
55
+ icon: 'arrow-left' do %>
56
+ <%= t('avo.cancel').capitalize %>
44
57
  <% end %>
45
- <% end %>
58
+ <% if can_see_the_save_button? %>
59
+ <%= a_button color: :primary,
60
+ style: :primary,
61
+ loading: true,
62
+ type: :submit,
63
+ icon: 'save' do %>
64
+ <%= t('avo.save').capitalize %>
65
+ <% end %>
66
+ <% end %>
67
+ </div>
46
68
  <% end %>
47
69
  <% end %>
48
70
  <% end %>
49
- <%= content_tag :div, class: 'space-y-12' do %>
71
+ <%= content_tag :div, class: 'space-y-12 mt-12' do %>
50
72
  <% @resource.get_items.each_with_index do |item, index| %>
51
73
  <% next if item.nil? %>
52
74
  <%= render Avo::ItemSwitcherComponent.new resource: @resource, item: item, index: index + 1, view: @view, form: form %>
@@ -11,8 +11,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
11
11
  @model = model
12
12
  @actions = actions
13
13
  @view = view
14
-
15
- split_panel_fields
16
14
  end
17
15
 
18
16
  def title
@@ -24,12 +22,10 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
24
22
  helpers.resource_path(model: params[:via_resource_class].safe_constantize, resource: relation_resource, resource_id: params[:via_resource_id])
25
23
  elsif via_index?
26
24
  helpers.resources_path(resource: @resource)
27
- else # via resource show page
28
- if is_edit?
29
- helpers.resource_path(model: @resource.model, resource: @resource)
30
- else
31
- helpers.resources_path(resource: @resource)
32
- end
25
+ elsif is_edit? # via resource show page
26
+ helpers.resource_path(model: @resource.model, resource: @resource)
27
+ else
28
+ helpers.resources_path(resource: @resource)
33
29
  end
34
30
  end
35
31
 
@@ -51,7 +51,7 @@
51
51
  <% if @resources.present? %>
52
52
  <div class="w-full overflow-auto flex flex-col mt-0">
53
53
  <div class="relative flex-1 flex">
54
- <%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model)) %>
54
+ <%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource)) %>
55
55
  </div>
56
56
  </div>
57
57
  <% else %>
@@ -15,6 +15,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
15
15
  reflection: nil,
16
16
  turbo_frame: "",
17
17
  parent_model: nil,
18
+ parent_resource: nil,
18
19
  applied_filters: []
19
20
  )
20
21
  @resource = resource
@@ -27,6 +28,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
27
28
  @reflection = reflection
28
29
  @turbo_frame = turbo_frame
29
30
  @parent_model = parent_model
31
+ @parent_resource = parent_resource
30
32
  @applied_filters = applied_filters
31
33
  @view = :index
32
34
  end
@@ -52,7 +54,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
52
54
  # The Create button is dependent on the new? policy method.
53
55
  # The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
54
56
  def can_see_the_create_button?
55
- return authorize_association_for("create") if @reflection.present?
57
+ return authorize_association_for(:create) if @reflection.present?
56
58
 
57
59
  @resource.authorization.authorize_action(:new, raise_exception: false) && !has_reflection_and_is_read_only
58
60
  end
@@ -60,7 +62,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
60
62
  def can_see_the_actions_button?
61
63
  return false if @actions.blank?
62
64
 
63
- return authorize_association_for("act_on") if @reflection.present?
65
+ return authorize_association_for(:act_on) if @reflection.present?
64
66
 
65
67
  @resource.authorization.authorize_action(:act_on, raise_exception: false) && !has_reflection_and_is_read_only
66
68
  end
@@ -69,7 +71,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
69
71
  klass = @reflection
70
72
  klass = @reflection.through_reflection if klass.is_a? ::ActiveRecord::Reflection::ThroughReflection
71
73
 
72
- @reflection.present? && klass.is_a?(::ActiveRecord::Reflection::HasManyReflection) && !has_reflection_and_is_read_only && authorize_association_for("attach")
74
+ @reflection.present? && klass.is_a?(::ActiveRecord::Reflection::HasManyReflection) && !has_reflection_and_is_read_only && authorize_association_for(:attach)
73
75
  end
74
76
 
75
77
  def has_reflection_and_is_read_only
@@ -19,8 +19,8 @@
19
19
  } do %>
20
20
  <%= t('avo.detach_item', item: title).capitalize %>
21
21
  <% end %>
22
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
23
22
  <% end %>
23
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
24
24
  <% if can_see_the_edit_button? %>
25
25
  <%= a_link edit_path,
26
26
  color: :primary,
@@ -64,8 +64,20 @@
64
64
  <% end %>
65
65
  <% end %>
66
66
  <% end %>
67
+ <% if main_panel.present? %>
68
+ <% c.body do %>
69
+ <div class="divide-y">
70
+ <% main_panel.items.each_with_index do |field, index| %>
71
+ <%= render field.hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: view)
72
+ .component_for_view(view)
73
+ .new(field: field, resource: @resource, index: index)
74
+ %>
75
+ <% end %>
76
+ </div>
77
+ <% end %>
78
+ <% end %>
67
79
  <% end %>
68
- <%= content_tag :div, class: 'space-y-12' do %>
80
+ <%= content_tag :div, class: 'space-y-12 mt-12' do %>
69
81
  <% @resource.get_items.each_with_index do |item, index| %>
70
82
  <% next if item.nil? %>
71
83
  <%= render Avo::ItemSwitcherComponent.new resource: @resource, reflection: @reflection, item: item, index: index + 1, view: @view %>
@@ -4,14 +4,14 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
4
4
  include Avo::ResourcesHelper
5
5
  include Avo::ApplicationHelper
6
6
 
7
- def initialize(resource: nil, reflection: nil, parent_model: nil, resource_panel: nil, actions: [])
7
+ def initialize(resource: nil, reflection: nil, parent_resource: nil, parent_model: nil, resource_panel: nil, actions: [])
8
8
  @resource = resource
9
9
  @reflection = reflection
10
10
  @resource_panel = resource_panel
11
11
  @actions = actions
12
+ @parent_model = parent_model
13
+ @parent_resource = parent_resource
12
14
  @view = :show
13
-
14
- split_panel_fields
15
15
  end
16
16
 
17
17
  def title