avo 2.15.3 → 2.16.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/components/avo/fields/belongs_to_field/index_component.html.erb +2 -1
- data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/show_component.rb +8 -0
- data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
- data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +14 -1
- data/app/components/avo/fields/has_one_field/show_component.rb +21 -0
- data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/index_component.rb +9 -4
- data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +13 -13
- data/app/components/avo/index/grid_item_component.html.erb +6 -6
- data/app/components/avo/index/grid_item_component.rb +15 -0
- data/app/components/avo/index/resource_controls_component.rb +2 -0
- data/app/components/avo/index/resource_grid_component.rb +1 -1
- data/app/components/avo/resource_component.rb +5 -1
- data/app/components/avo/sidebar/item_switcher_component.html.erb +3 -3
- data/app/components/avo/sidebar/link_component.html.erb +2 -2
- data/app/components/avo/sidebar/link_component.rb +3 -1
- data/app/components/avo/views/resource_edit_component.html.erb +19 -2
- data/app/components/avo/views/resource_edit_component.rb +26 -9
- data/app/components/avo/views/resource_show_component.rb +0 -8
- data/app/controllers/avo/actions_controller.rb +7 -5
- data/app/controllers/avo/application_controller.rb +14 -2
- data/app/controllers/avo/associations_controller.rb +2 -2
- data/app/controllers/avo/base_controller.rb +19 -6
- data/app/helpers/avo/url_helpers.rb +8 -0
- data/app/views/avo/actions/show.html.erb +5 -1
- data/lib/avo/base_action.rb +25 -6
- data/lib/avo/base_resource.rb +1 -1
- data/lib/avo/base_resource_tool.rb +1 -1
- data/lib/avo/configuration.rb +2 -0
- data/lib/avo/fields/base_field.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +1 -1
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -1
- data/lib/avo/fields/has_base_field.rb +5 -1
- data/lib/avo/fields/has_many_field.rb +1 -1
- data/lib/avo/menu/base_item.rb +1 -0
- data/lib/avo/menu/builder.rb +4 -2
- data/lib/avo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ca4190d675e166dedf5f47c9c68f3b7fa57e29c9e7510262a4033f1c0cbb00d
|
4
|
+
data.tar.gz: 6f4f3c3f1a39fbb7b9d3566ff679cd3992b684576b1e4c1451b7d4fdd39c173f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2dfc8a393554111f16a4c95ed94ef1180e9b448327d182071ebef301773e37436db614411121744107bae9252e40a5432d828ebb2661abef2148883e0675c08
|
7
|
+
data.tar.gz: 3914b51410ba770dd7f8a396bddfb6bb1be58d694aebb159f23b3de1e3c841186fa85d62bf0d982ef475a5a07c80bd9f24a4cf41d0b22a874e4df073dc11da25
|
data/Gemfile.lock
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
<%= index_field_wrapper field: @field, resource: @resource do %>
|
2
|
-
<%= link_to @field.label, helpers.
|
2
|
+
<%= link_to @field.label, helpers.resource_view_path(model: @field.value, resource: @field.target_resource)
|
3
|
+
%>
|
3
4
|
<% end %>
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= show_field_wrapper field: @field, resource: @resource, index: @index do %>
|
2
|
-
<%= link_to @field.label,
|
2
|
+
<%= link_to @field.label, resource_view_path %>
|
3
3
|
<% end %>
|
@@ -1,4 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Fields::BelongsToField::ShowComponent < Avo::Fields::ShowComponent
|
4
|
+
def resource_view_path
|
5
|
+
helpers.resource_view_path(
|
6
|
+
model: @field.value,
|
7
|
+
resource: @field.target_resource,
|
8
|
+
via_resource_class: @resource.model_class,
|
9
|
+
via_resource_id: @resource.model.id
|
10
|
+
)
|
11
|
+
end
|
4
12
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<%= index_field_wrapper field: @field, resource: @resource, flush: flush? do %>
|
2
2
|
<% if @field.value.present? %>
|
3
3
|
<% if @field.value.attached? && @field.value.representable? && @field.is_image %>
|
4
|
-
<%= link_to_if @field.link_to_resource, image_tag(helpers.main_app.url_for(@field.value), class: 'h-10'),
|
4
|
+
<%= link_to_if @field.link_to_resource, image_tag(helpers.main_app.url_for(@field.value), class: 'h-10'), resource_view_path, class: 'block' %>
|
5
5
|
<% elsif @field.value.attached? && @field.is_audio %>
|
6
|
-
<%= link_to_if @field.link_to_resource, audio_tag(helpers.main_app.url_for(@field.value), controls: true, preload: false, class: 'max-h-full h-10'),
|
6
|
+
<%= link_to_if @field.link_to_resource, audio_tag(helpers.main_app.url_for(@field.value), controls: true, preload: false, class: 'max-h-full h-10'), resource_view_path, class: 'block h-8' %>
|
7
7
|
<% else %>
|
8
8
|
<%= @field.value.filename %>
|
9
9
|
<% end %>
|
@@ -6,10 +6,23 @@
|
|
6
6
|
<%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
|
7
7
|
<% c.tools do %>
|
8
8
|
<% if !@field.is_readonly? && can_attach? %>
|
9
|
-
<%= a_link attach_path,
|
9
|
+
<%= a_link attach_path,
|
10
|
+
icon: 'heroicons/outline/link',
|
11
|
+
color: :primary,
|
12
|
+
'data-turbo-frame': 'attach_modal' do %>
|
10
13
|
<%= t('avo.attach_item', item: @field.name.downcase) %>
|
11
14
|
<% end %>
|
12
15
|
<% end %>
|
16
|
+
<% if !@field.is_readonly? && can_see_the_create_button? %>
|
17
|
+
<%= a_link create_path,
|
18
|
+
icon: 'heroicons/outline/plus',
|
19
|
+
'data-target': 'create',
|
20
|
+
'data-turbo-frame': '_top',
|
21
|
+
style: :primary,
|
22
|
+
color: :primary do %>
|
23
|
+
<%= t('avo.create_new_item', item: @field.name.downcase ) %>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
13
26
|
<% end %>
|
14
27
|
|
15
28
|
<% c.body do %>
|
@@ -23,4 +23,25 @@ class Avo::Fields::HasOneField::ShowComponent < Avo::Fields::ShowComponent
|
|
23
23
|
def attach_path
|
24
24
|
helpers.avo.resources_associations_new_path(@resource.singular_model_key, @resource.model.id, @field.id)
|
25
25
|
end
|
26
|
+
|
27
|
+
def can_see_the_create_button?
|
28
|
+
create = "create_#{@field.id.to_s}?"
|
29
|
+
|
30
|
+
authorization_service = @resource.authorization
|
31
|
+
|
32
|
+
# By default return true if the create method is not defined for this field
|
33
|
+
return true unless authorization_service.has_method?(create, raise_exception: false)
|
34
|
+
|
35
|
+
authorization_service.authorize_action(create, raise_exception: false)
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_path
|
39
|
+
args = {
|
40
|
+
via_relation: @resource.singular_model_key,
|
41
|
+
via_relation_class: @resource.name,
|
42
|
+
via_resource_id: @resource.model.id
|
43
|
+
}
|
44
|
+
|
45
|
+
helpers.new_resource_path(resource: @field.target_resource, **args)
|
46
|
+
end
|
26
47
|
end
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= index_field_wrapper field: @field, resource: @resource, class: 'whitespace-no-wrap w-[1%]' do %>
|
2
|
-
<% link_to_if (@field.link_to_resource or Avo.configuration.id_links_to_resource), @field.value,
|
2
|
+
<% link_to_if (@field.link_to_resource or Avo.configuration.id_links_to_resource), @field.value, resource_view_path, title: t('avo.view_item', item: @resource.name).humanize %>
|
3
3
|
<% end %>
|
@@ -13,11 +13,16 @@ class Avo::Fields::IndexComponent < ViewComponent::Base
|
|
13
13
|
@view = :index
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def resource_view_path
|
17
|
+
args = {}
|
18
|
+
|
17
19
|
if @parent_model.present?
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
args = {
|
21
|
+
via_resource_class: @parent_model.class,
|
22
|
+
via_resource_id: @parent_model.id
|
23
|
+
}
|
21
24
|
end
|
25
|
+
|
26
|
+
helpers.resource_view_path(model: @resource.model, resource: @resource, **args)
|
22
27
|
end
|
23
28
|
end
|
@@ -4,6 +4,6 @@
|
|
4
4
|
<% elsif @field.protocol.present? %>
|
5
5
|
<%= link_to @field.value, "#{@field.protocol}:#{@field.value}" %>
|
6
6
|
<% else %>
|
7
|
-
<%= link_to_if @field.link_to_resource, @field.value,
|
7
|
+
<%= link_to_if @field.link_to_resource, @field.value, resource_view_path %>
|
8
8
|
<% end %>
|
9
9
|
<% end %>
|
@@ -1,16 +1,16 @@
|
|
1
1
|
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, full_width: true do %>
|
2
|
-
|
3
|
-
data
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
<%= content_tag :div, class: "relative block overflow-x-auto max-w-full",
|
3
|
+
data: {
|
4
|
+
controller: "trix-field",
|
5
|
+
trix_field_target: "controller",
|
6
|
+
resource_name: @resource.model_key,
|
7
|
+
resource_id: @resource.model.methods.include?(:id) ? @resource.model&.id : nil,
|
8
|
+
attachments_disabled: @field.attachments_disabled,
|
9
|
+
attachment_key: @field.attachment_key,
|
10
|
+
hide_attachment_filename: @field.hide_attachment_filename,
|
11
|
+
hide_attachment_filesize: @field.hide_attachment_filesize,
|
12
|
+
hide_attachment_url: @field.hide_attachment_url,
|
13
|
+
} do %>
|
14
14
|
<%= content_tag 'trix-editor',
|
15
15
|
class: 'trix-content',
|
16
16
|
data: {
|
@@ -29,5 +29,5 @@
|
|
29
29
|
placeholder: @field.placeholder,
|
30
30
|
style: @field.get_html(:style, view: view, element: :input)
|
31
31
|
%>
|
32
|
-
|
32
|
+
<% end %>
|
33
33
|
<% end %>
|
@@ -7,23 +7,23 @@
|
|
7
7
|
<%== item_selector_input floating: true, size: :lg %>
|
8
8
|
<% end %>
|
9
9
|
<% if cover.blank? %>
|
10
|
-
<%= link_to
|
10
|
+
<%= link_to resource_view_path do %>
|
11
11
|
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
12
12
|
<% end %>
|
13
13
|
<% elsif cover.respond_to?(:to_image) && cover.to_image.present? %>
|
14
|
-
<%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'),
|
14
|
+
<%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
15
15
|
<% elsif cover.type == 'file' %>
|
16
16
|
<% if cover.value.attached? && cover.value.representable? %>
|
17
|
-
<%= 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'),
|
17
|
+
<%= 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'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
18
18
|
<% else %>
|
19
|
-
<%= link_to
|
19
|
+
<%= link_to resource_view_path do %>
|
20
20
|
<div class="absolute bg-gray-100 w-full h-full">
|
21
21
|
<%= 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' %>
|
22
22
|
</div>
|
23
23
|
<% end %>
|
24
24
|
<% end %>
|
25
25
|
<% elsif cover.value.present? %>
|
26
|
-
<%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'),
|
26
|
+
<%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
27
27
|
<% else %>
|
28
28
|
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
29
29
|
<% end %>
|
@@ -31,7 +31,7 @@
|
|
31
31
|
<div class="grid grid-cols-1 place-content-between p-4 h-full">
|
32
32
|
<div class="mb-4 h-full flex flex-col space-between">
|
33
33
|
<div class="grid font-semibold leading-tight text-lg mb-2">
|
34
|
-
<%= link_to_if title.link_to_resource, title.value,
|
34
|
+
<%= link_to_if title.link_to_resource, title.value, resource_view_path if title.present? %>
|
35
35
|
</div>
|
36
36
|
<div class="text-sm break-words text-gray-500">
|
37
37
|
<%= body.value if body.present? %>
|
@@ -3,6 +3,8 @@
|
|
3
3
|
class Avo::Index::GridItemComponent < ViewComponent::Base
|
4
4
|
include Avo::ResourcesHelper
|
5
5
|
|
6
|
+
attr_reader :parent_resource
|
7
|
+
|
6
8
|
def initialize(resource: nil, reflection: nil, parent_model: nil, parent_resource: nil)
|
7
9
|
@resource = resource
|
8
10
|
@reflection = reflection
|
@@ -24,4 +26,17 @@ class Avo::Index::GridItemComponent < ViewComponent::Base
|
|
24
26
|
def body
|
25
27
|
@grid_fields.body_field
|
26
28
|
end
|
29
|
+
|
30
|
+
def resource_view_path
|
31
|
+
args = {}
|
32
|
+
|
33
|
+
if @parent_model.present?
|
34
|
+
args = {
|
35
|
+
via_resource_class: parent_resource.model_class,
|
36
|
+
via_resource_id: @parent_model.id
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
helpers.resource_view_path(model: @resource.model, resource: @resource, **args)
|
41
|
+
end
|
27
42
|
end
|
@@ -23,6 +23,8 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def can_view?
|
26
|
+
return false if Avo.configuration.resource_default_view == :edit
|
27
|
+
|
26
28
|
return authorize_association_for(:show) if @reflection.present?
|
27
29
|
|
28
30
|
# Even if there's a @reflection object present, for show we're going to fallback to the original policy.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Index::ResourceGridComponent < ViewComponent::Base
|
4
|
-
def initialize(resources: nil, resource: nil, reflection: nil, parent_model: nil, parent_resource:
|
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
|
@@ -46,7 +46,11 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def destroy_path
|
49
|
-
|
49
|
+
if params[:via_resource_class].present?
|
50
|
+
helpers.resource_path(model: @resource.model, resource: @resource, referrer: back_path)
|
51
|
+
else
|
52
|
+
helpers.resource_path(model: @resource.model, resource: @resource)
|
53
|
+
end
|
50
54
|
end
|
51
55
|
|
52
56
|
def authorize_association_for(policy_method)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<% if item.is_a? Avo::Menu::Link %>
|
2
|
-
<%= render Avo::Sidebar::LinkComponent.new label: item.name, path: item.path, target: item.target %>
|
2
|
+
<%= render Avo::Sidebar::LinkComponent.new label: item.name, path: item.path, target: item.target, data: item.data %>
|
3
3
|
<% end %>
|
4
4
|
<% if item.is_a? Avo::Menu::Resource %>
|
5
|
-
<%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: helpers.resources_path(resource: resource) %>
|
5
|
+
<%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: helpers.resources_path(resource: resource), data: item.data %>
|
6
6
|
<% end %>
|
7
7
|
<% if item.is_a? Avo::Menu::Dashboard %>
|
8
|
-
<%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: dashboard.navigation_path %>
|
8
|
+
<%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: dashboard.navigation_path, data: item.data %>
|
9
9
|
<% end %>
|
10
10
|
<% if item.is_a? Avo::Menu::Section %>
|
11
11
|
<%= render Avo::Sidebar::SectionComponent.new item: item %>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<% if path.present? %>
|
2
|
-
<%= send link_method, path, class: classes, active: active, target: target do %>
|
2
|
+
<%= send link_method, path, class: classes, active: active, target: target, data: data do %>
|
3
3
|
<%= label %>
|
4
4
|
<% if target == :_blank %>
|
5
5
|
<%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
8
8
|
<% else %>
|
9
|
-
<%= content_tag :div, class: classes, active: active, target: target do %>
|
9
|
+
<%= content_tag :div, class: classes, active: active, target: target, data: data do %>
|
10
10
|
<%= label %>
|
11
11
|
<% end %>
|
12
12
|
<% end %>
|
@@ -5,12 +5,14 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
|
|
5
5
|
attr_reader :target
|
6
6
|
attr_reader :label
|
7
7
|
attr_reader :path
|
8
|
+
attr_reader :data
|
8
9
|
|
9
|
-
def initialize(label: nil, path: nil, active: :inclusive, target: nil)
|
10
|
+
def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {})
|
10
11
|
@label = label
|
11
12
|
@path = path
|
12
13
|
@active = active
|
13
14
|
@target = target
|
15
|
+
@data = data
|
14
16
|
end
|
15
17
|
|
16
18
|
def is_external?
|
@@ -22,6 +22,23 @@
|
|
22
22
|
icon: 'arrow-left' do %>
|
23
23
|
<%= t('avo.cancel').capitalize %>
|
24
24
|
<% end %>
|
25
|
+
<% if can_see_the_destroy_button? %>
|
26
|
+
<%= a_link destroy_path,
|
27
|
+
method: :delete,
|
28
|
+
local: true,
|
29
|
+
style: :text,
|
30
|
+
loading: true,
|
31
|
+
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
32
|
+
color: :red,
|
33
|
+
icon: 'trash',
|
34
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
35
|
+
data: {
|
36
|
+
control: :destroy,
|
37
|
+
'resource-id': @resource.model.id,
|
38
|
+
} do %>
|
39
|
+
<%= t('avo.delete').capitalize %>
|
40
|
+
<% end %>
|
41
|
+
<% end %>
|
25
42
|
<% if can_see_the_actions_button? %>
|
26
43
|
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
27
44
|
<% end %>
|
@@ -41,8 +58,8 @@
|
|
41
58
|
<% c.body do %>
|
42
59
|
<div class="divide-y">
|
43
60
|
<% main_panel.items.each_with_index do |field, index| %>
|
44
|
-
<%= render field.hydrate(resource: @resource, model: @resource.model, user: @resource.user, view:
|
45
|
-
.component_for_view(
|
61
|
+
<%= render field.hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: view_for(field))
|
62
|
+
.component_for_view(view_for field)
|
46
63
|
.new(field: field, resource: @resource, index: index, form: form)
|
47
64
|
%>
|
48
65
|
<% end %>
|
@@ -16,16 +16,28 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def back_path
|
19
|
-
if via_resource?
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
helpers.
|
24
|
-
elsif is_edit? # via resource show page
|
25
|
-
helpers.resource_path(model: @resource.model, resource: @resource)
|
26
|
-
else
|
27
|
-
helpers.resources_path(resource: @resource)
|
19
|
+
return resource_view_path if via_resource?
|
20
|
+
return resources_path if via_index?
|
21
|
+
|
22
|
+
if is_edit? && Avo.configuration.resource_default_view == :show # via resource show or edit page
|
23
|
+
return helpers.resource_path(model: @resource.model, resource: @resource)
|
28
24
|
end
|
25
|
+
|
26
|
+
resources_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def resources_path
|
30
|
+
helpers.resources_path(resource: @resource)
|
31
|
+
end
|
32
|
+
|
33
|
+
def resource_view_path
|
34
|
+
helpers.resource_view_path(model: relation_resource.model, resource: relation_resource)
|
35
|
+
end
|
36
|
+
|
37
|
+
def can_see_the_destroy_button?
|
38
|
+
return super if is_edit? && Avo.configuration.resource_default_view == :edit
|
39
|
+
|
40
|
+
false
|
29
41
|
end
|
30
42
|
|
31
43
|
# The save button is dependent on the edit? policy method.
|
@@ -65,4 +77,9 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
65
77
|
)
|
66
78
|
end
|
67
79
|
end
|
80
|
+
|
81
|
+
# Render :show view for read only trix fields
|
82
|
+
def view_for(field)
|
83
|
+
(field.is_a? Avo::Fields::TrixField) && field.is_readonly? ? :show : view
|
84
|
+
end
|
68
85
|
end
|
@@ -45,14 +45,6 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
|
|
45
45
|
helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
|
46
46
|
end
|
47
47
|
|
48
|
-
def destroy_path
|
49
|
-
if params[:via_resource_class].present?
|
50
|
-
helpers.resource_path(model: @resource.model, resource: @resource, referrer: back_path)
|
51
|
-
else
|
52
|
-
helpers.resource_path(model: @resource.model, resource: @resource)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
48
|
private
|
57
49
|
|
58
50
|
# In development and test environments we shoudl show the invalid field errors
|
@@ -4,9 +4,15 @@ module Avo
|
|
4
4
|
class ActionsController < ApplicationController
|
5
5
|
before_action :set_resource_name
|
6
6
|
before_action :set_resource
|
7
|
+
before_action :set_model, only: :show, if: ->(request) do
|
8
|
+
# Try to se the model only if the user is on the record page.
|
9
|
+
# set_model will fail if it's tried to be used from the Index page.
|
10
|
+
request.params[:id].present?
|
11
|
+
end
|
7
12
|
before_action :set_action, only: [:show, :handle]
|
8
13
|
|
9
14
|
def show
|
15
|
+
@resource.hydrate(model: @model, view: :show, user: _current_user, params: params)
|
10
16
|
@model = ActionModel.new @action.get_attributes_for_action
|
11
17
|
end
|
12
18
|
|
@@ -44,11 +50,7 @@ module Avo
|
|
44
50
|
def set_action
|
45
51
|
action_class = params[:action_id].gsub("avo_actions_", "").camelize.safe_constantize
|
46
52
|
|
47
|
-
|
48
|
-
model = @resource.class.find_scope.find params[:id]
|
49
|
-
end
|
50
|
-
|
51
|
-
@action = action_class.new(model: model, resource: resource, user: _current_user, view: :edit)
|
53
|
+
@action = action_class.new(model: @model, resource: @resource, user: _current_user, view: :edit)
|
52
54
|
end
|
53
55
|
|
54
56
|
def respond(response)
|
@@ -26,7 +26,7 @@ module Avo
|
|
26
26
|
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
27
27
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
28
28
|
|
29
|
-
helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path, :turbo_frame_request
|
29
|
+
helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path, :turbo_frame_request?, :resource_view_path
|
30
30
|
add_flash_types :info, :warning, :success, :error
|
31
31
|
|
32
32
|
def init_app
|
@@ -126,7 +126,19 @@ module Avo
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def set_model
|
129
|
-
@model =
|
129
|
+
@model = model_find_scope.find record_id
|
130
|
+
end
|
131
|
+
|
132
|
+
def record_id
|
133
|
+
params.permit(:id).dig(:id)
|
134
|
+
end
|
135
|
+
|
136
|
+
def model_find_scope
|
137
|
+
eager_load_files(@resource, model_scope)
|
138
|
+
end
|
139
|
+
|
140
|
+
def model_scope
|
141
|
+
@resource.class.find_scope
|
130
142
|
end
|
131
143
|
|
132
144
|
def set_related_model
|
@@ -65,7 +65,7 @@ module Avo
|
|
65
65
|
|
66
66
|
respond_to do |format|
|
67
67
|
if @model.save
|
68
|
-
format.html { redirect_back fallback_location:
|
68
|
+
format.html { redirect_back fallback_location: resource_view_response_path, notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name) }
|
69
69
|
else
|
70
70
|
format.html { render :new }
|
71
71
|
end
|
@@ -80,7 +80,7 @@ module Avo
|
|
80
80
|
end
|
81
81
|
|
82
82
|
respond_to do |format|
|
83
|
-
format.html { redirect_to params[:referrer] ||
|
83
|
+
format.html { redirect_to params[:referrer] || resource_view_response_path, notice: t("avo.attachment_class_detached", attachment_class: @attachment_class) }
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -106,7 +106,7 @@ module Avo
|
|
106
106
|
|
107
107
|
@page_title = @resource.default_panel_name.to_s
|
108
108
|
|
109
|
-
if
|
109
|
+
if is_associated_record?
|
110
110
|
via_resource = Avo::App.get_resource_by_model_name params[:via_relation_class]
|
111
111
|
via_model = via_resource.class.find_scope.find params[:via_resource_id]
|
112
112
|
via_resource.hydrate model: via_model
|
@@ -412,13 +412,17 @@ module Avo
|
|
412
412
|
|
413
413
|
def after_create_path
|
414
414
|
# If this is an associated record return to the association show page
|
415
|
-
if
|
415
|
+
if is_associated_record?
|
416
416
|
parent_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class]
|
417
417
|
|
418
|
-
return
|
418
|
+
return resource_view_path(
|
419
|
+
model: @model.send(params[:via_relation]),
|
420
|
+
resource: parent_resource,
|
421
|
+
resource_id: params[:via_resource_id]
|
422
|
+
)
|
419
423
|
end
|
420
424
|
|
421
|
-
redirect_path_from_resource_option(:after_create_path) ||
|
425
|
+
redirect_path_from_resource_option(:after_create_path) || resource_view_response_path
|
422
426
|
end
|
423
427
|
|
424
428
|
def update_success_action
|
@@ -445,7 +449,12 @@ module Avo
|
|
445
449
|
def after_update_path
|
446
450
|
return params[:referrer] if params[:referrer].present?
|
447
451
|
|
448
|
-
redirect_path_from_resource_option(:after_update_path) ||
|
452
|
+
redirect_path_from_resource_option(:after_update_path) || resource_view_response_path
|
453
|
+
end
|
454
|
+
|
455
|
+
# Needs a different name, otwherwise, in some places, this can be called instead helpers.resource_view_path
|
456
|
+
def resource_view_response_path
|
457
|
+
helpers.resource_view_path(model: @model, resource: @resource)
|
449
458
|
end
|
450
459
|
|
451
460
|
def destroy_success_action
|
@@ -477,11 +486,15 @@ module Avo
|
|
477
486
|
|
478
487
|
if @resource.class.send(action) == :index
|
479
488
|
resources_path(resource: @resource)
|
480
|
-
elsif @resource.class.send(action) == :edit
|
489
|
+
elsif @resource.class.send(action) == :edit || Avo.configuration.resource_default_view == :edit
|
481
490
|
edit_resource_path(resource: @resource, model: @resource.model)
|
482
491
|
else
|
483
492
|
resource_path(model: @model, resource: @resource)
|
484
493
|
end
|
485
494
|
end
|
495
|
+
|
496
|
+
def is_associated_record?
|
497
|
+
params[:via_relation_class].present? && params[:via_resource_id].present?
|
498
|
+
end
|
486
499
|
end
|
487
500
|
end
|
@@ -76,5 +76,13 @@ module Avo
|
|
76
76
|
|
77
77
|
avo.resources_associations_index_path(parent_model.model_name.route_key, record.id, **existing_params, **args)
|
78
78
|
end
|
79
|
+
|
80
|
+
def resource_view_path(**args)
|
81
|
+
if Avo.configuration.resource_default_view == :edit
|
82
|
+
edit_resource_path(**args)
|
83
|
+
else
|
84
|
+
resource_path(**args)
|
85
|
+
end
|
86
|
+
end
|
79
87
|
end
|
80
88
|
end
|
@@ -25,7 +25,11 @@
|
|
25
25
|
<% if @action.get_fields.present? %>
|
26
26
|
<div class="mt-4">
|
27
27
|
<% @action.get_fields.each_with_index do |field, index| %>
|
28
|
-
<%= render field
|
28
|
+
<%= render field
|
29
|
+
.hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: @view)
|
30
|
+
.component_for_view(:edit)
|
31
|
+
.new(field: field, resource: @resource, index: index, form: form, displayed_in_modal: true)
|
32
|
+
%>
|
29
33
|
<% end %>
|
30
34
|
</div>
|
31
35
|
<% end %>
|
data/lib/avo/base_action.rb
CHANGED
@@ -73,26 +73,36 @@ module Avo
|
|
73
73
|
def get_attributes_for_action
|
74
74
|
get_fields.map do |field|
|
75
75
|
[field.id, field.value]
|
76
|
-
end
|
77
|
-
.to_h
|
76
|
+
end.to_h
|
78
77
|
end
|
79
78
|
|
80
79
|
def handle_action(**args)
|
81
80
|
models, fields, current_user, resource = args.values_at(:models, :fields, :current_user, :resource)
|
82
|
-
|
81
|
+
# Fetching the field definitions and not the actual fields (get_fields) because they will break if the user uses a `visible` block and adds a condition using the `params` variable. The params are different in the show method and the handle method.
|
82
|
+
action_fields = get_field_definitions.map { |field| [field.id, field] }.to_h
|
83
|
+
|
84
|
+
# For some fields, like belongs_to, the id and database_id differ (user vs user_id).
|
85
|
+
# That's why we need to fetch the database_id for when we process the action.
|
86
|
+
action_fields_by_database_id = action_fields.map do |id, value|
|
87
|
+
[value.database_id.to_sym, value]
|
88
|
+
end.to_h
|
83
89
|
|
84
90
|
if fields.present?
|
85
91
|
processed_fields = fields.to_unsafe_h.map do |name, value|
|
86
|
-
|
92
|
+
field = action_fields_by_database_id[name.to_sym]
|
93
|
+
|
94
|
+
next if field.blank?
|
95
|
+
|
96
|
+
[name, field.resolve_attribute(value)]
|
87
97
|
end
|
88
98
|
|
89
|
-
processed_fields = processed_fields.to_h
|
99
|
+
processed_fields = processed_fields.reject(&:blank?).to_h
|
90
100
|
else
|
91
101
|
processed_fields = {}
|
92
102
|
end
|
93
103
|
|
94
104
|
args = {
|
95
|
-
fields: processed_fields,
|
105
|
+
fields: processed_fields.with_indifferent_access,
|
96
106
|
current_user: current_user,
|
97
107
|
resource: resource
|
98
108
|
}
|
@@ -175,6 +185,15 @@ module Avo
|
|
175
185
|
self
|
176
186
|
end
|
177
187
|
|
188
|
+
# We're overriding this method to hydrate with the proper resource attribute.
|
189
|
+
def hydrate_fields(model: nil, view: nil)
|
190
|
+
fields.map do |field|
|
191
|
+
field.hydrate(model: @model, view: @view, resource: resource)
|
192
|
+
end
|
193
|
+
|
194
|
+
self
|
195
|
+
end
|
196
|
+
|
178
197
|
private
|
179
198
|
|
180
199
|
def add_message(body, type = :info)
|
data/lib/avo/base_resource.rb
CHANGED
data/lib/avo/configuration.rb
CHANGED
@@ -36,6 +36,7 @@ module Avo
|
|
36
36
|
attr_accessor :profile_menu
|
37
37
|
attr_accessor :model_resource_mapping
|
38
38
|
attr_accessor :tabs_style
|
39
|
+
attr_accessor :resource_default_view
|
39
40
|
attr_writer :branding
|
40
41
|
|
41
42
|
def initialize
|
@@ -83,6 +84,7 @@ module Avo
|
|
83
84
|
@profile_menu = nil
|
84
85
|
@model_resource_mapping = {}
|
85
86
|
@tabs_style = :tabs
|
87
|
+
@resource_default_view = :show
|
86
88
|
end
|
87
89
|
|
88
90
|
def current_user_method(&block)
|
@@ -210,7 +210,7 @@ module Avo
|
|
210
210
|
model
|
211
211
|
end
|
212
212
|
|
213
|
-
def database_id
|
213
|
+
def database_id
|
214
214
|
# If the field is a polymorphic value, return the polymorphic_type as key and pre-fill the _id in fill_field.
|
215
215
|
return "#{polymorphic_as}_type" if polymorphic_as.present?
|
216
216
|
|
@@ -30,7 +30,7 @@ module Avo
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def resource
|
33
|
-
Avo::App.get_resource_by_model_name
|
33
|
+
@resource || Avo::App.get_resource_by_model_name(@model.class)
|
34
34
|
end
|
35
35
|
|
36
36
|
def turbo_frame
|
@@ -108,6 +108,10 @@ module Avo
|
|
108
108
|
def frame_id
|
109
109
|
use_resource.present? ? use_resource.route_key.to_sym : @id
|
110
110
|
end
|
111
|
+
|
112
|
+
def default_view
|
113
|
+
Avo.configuration.skip_show_view ? :edit : :show
|
114
|
+
end
|
111
115
|
end
|
112
116
|
end
|
113
117
|
end
|
data/lib/avo/menu/base_item.rb
CHANGED
data/lib/avo/menu/builder.rb
CHANGED
@@ -22,9 +22,11 @@ class Avo::Menu::Builder
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Adds a link
|
25
|
-
def link(name, **args)
|
26
|
-
|
25
|
+
def link(name, path = nil, **args)
|
26
|
+
path ||= args[:path]
|
27
|
+
@menu.items << Avo::Menu::Link.new(name: name, path: path, **args)
|
27
28
|
end
|
29
|
+
alias_method :link_to, :link
|
28
30
|
|
29
31
|
# Validates and adds a resource
|
30
32
|
def resource(name, **args)
|
data/lib/avo/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrian Marin
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-09-
|
12
|
+
date: 2022-09-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|