avo 2.11.1 → 2.11.2.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/assets/stylesheets/avo.css +1 -4
- data/app/assets/stylesheets/css/sidebar.css +18 -0
- data/app/assets/svgs/failed_to_load.svg +15 -0
- data/app/components/avo/common_field_wrapper_component.html.erb +4 -0
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.rb +7 -6
- data/app/components/avo/fields/text_field/index_component.html.erb +2 -0
- data/app/components/avo/fields/text_field/show_component.html.erb +2 -0
- data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +4 -0
- data/app/components/avo/index/resource_controls_component.html.erb +3 -0
- data/app/components/avo/index/resource_controls_component.rb +7 -5
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/index/resource_table_component.rb +2 -1
- data/app/components/avo/index/table_row_component.html.erb +14 -5
- data/app/components/avo/index/table_row_component.rb +2 -1
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +11 -5
- data/app/components/avo/sidebar_component.html.erb +8 -2
- data/app/components/avo/sidebar_component.rb +9 -0
- data/app/components/avo/tab_switcher_component.rb +4 -0
- data/app/components/avo/views/resource_edit_component.rb +4 -6
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +5 -3
- data/app/components/avo/views/resource_show_component.html.erb +1 -1
- data/app/components/avo/views/resource_show_component.rb +3 -1
- data/app/controllers/avo/application_controller.rb +25 -10
- data/app/controllers/avo/associations_controller.rb +38 -12
- data/app/controllers/avo/base_controller.rb +7 -2
- data/app/javascript/js/controllers/fields/key_value_controller.js +3 -1
- data/app/javascript/js/controllers/sidebar_controller.js +49 -0
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/base/index.html.erb +1 -0
- data/app/views/avo/base/show.html.erb +7 -1
- data/app/views/avo/home/failed_to_load.html copy.erb +23 -0
- data/app/views/avo/home/failed_to_load.html.erb +9 -15
- data/app/views/avo/partials/_javascript.html.erb +1 -0
- data/app/views/avo/partials/_navbar.html.erb +5 -2
- data/app/views/avo/partials/_table_header.html.erb +12 -5
- data/app/views/layouts/avo/application.html.erb +9 -4
- data/bin/init +5 -0
- data/lib/avo/base_resource.rb +9 -1
- data/lib/avo/concerns/has_fields.rb +12 -3
- data/lib/avo/concerns/has_html_attributes.rb +1 -1
- data/lib/avo/concerns/model_class_constantized.rb +1 -1
- data/lib/avo/configuration/resource_configuration.rb +21 -0
- data/lib/avo/configuration.rb +2 -0
- data/lib/avo/fields/has_base_field.rb +11 -0
- data/lib/avo/fields/text_field.rb +4 -2
- data/lib/avo/items_holder.rb +6 -0
- data/lib/avo/panel_builder.rb +1 -0
- data/lib/avo/services/authorization_service.rb +41 -37
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +1 -0
- data/public/avo-assets/avo.css +78 -16
- data/public/avo-assets/avo.js +70 -69
- data/public/avo-assets/avo.js.map +3 -3
- metadata +9 -5
- data/app/javascript/js/controllers/mobile_controller.js +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d9e1f29fde441425a8bb70c8d3afc6f8acece76e6ac2a2dc2abc953567c6053
|
4
|
+
data.tar.gz: 8f9a42b1f4084a1846f8b1a279dd15119323cacad40054709677ac980cb7387d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07e9b92e4bfa7031cb8ef415c64d886f10c4e83c7b2974485f9f891f99d56bf1176ae3d576c7e2f68a4a8b202f829ca53e0978d06b2fbf0620deef581567c79c
|
7
|
+
data.tar.gz: 7700c610f99c0509b513a3180d420f28c82c403dfd4456867eb74e53178ac287d8c4d28a0c64c501b9923c0dbdc057d9940988fb222008024e836aabfb4c96ae
|
data/Gemfile.lock
CHANGED
@@ -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,18 @@
|
|
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
|
+
&.sidebar-open {
|
13
|
+
/* Add padding to the main area to allow for the sidebar to expand. */
|
14
|
+
.main-content-area {
|
15
|
+
@apply lg:pl-64;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<svg width="275" height="275" viewBox="0 0 275 275" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M137.714 274.227C213.377 274.227 274.714 212.89 274.714 137.227C274.714 61.5636 213.377 0.226593 137.714 0.226593C62.0512 0.226593 0.714233 61.5636 0.714233 137.227C0.714233 212.89 62.0512 274.227 137.714 274.227Z" fill="url(#paint0_linear_663_759)"/>
|
3
|
+
<rect x="55.5142" y="67.8133" width="164.4" height="32.88" fill="white"/>
|
4
|
+
<path d="M219.914 274.227H55.5142V97.0399C63.2629 97.0312 70.6918 93.9492 76.171 88.4701C81.6502 82.9909 84.7322 75.562 84.7409 67.8133H190.688C190.679 71.6518 191.432 75.4538 192.903 78.9994C194.374 82.5449 196.533 85.7636 199.256 88.4692C201.962 91.1929 205.181 93.353 208.727 94.8242C212.273 96.2953 216.075 97.0484 219.914 97.0399V274.227Z" fill="white"/>
|
5
|
+
<path d="M137.714 186.547C161.926 186.547 181.554 166.919 181.554 142.707C181.554 118.494 161.926 98.8666 137.714 98.8666C113.502 98.8666 93.8743 118.494 93.8743 142.707C93.8743 166.919 113.502 186.547 137.714 186.547Z" fill="#4285F4"/>
|
6
|
+
<path d="M153.214 163.373L137.714 147.874L122.214 163.373L117.048 158.207L132.548 142.707L117.048 127.207L122.214 122.041L137.714 137.54L153.214 122.041L158.381 127.207L142.881 142.707L158.381 158.207L153.214 163.373Z" fill="white"/>
|
7
|
+
<path d="M161.461 197.507H113.968C110.941 197.507 108.488 199.96 108.488 202.987C108.488 206.013 110.941 208.467 113.968 208.467H161.461C164.487 208.467 166.941 206.013 166.941 202.987C166.941 199.96 164.487 197.507 161.461 197.507Z" fill="#DFEAFB"/>
|
8
|
+
<path d="M177.901 219.427H97.5275C94.501 219.427 92.0475 221.88 92.0475 224.907C92.0475 227.933 94.501 230.387 97.5275 230.387H177.901C180.927 230.387 183.381 227.933 183.381 224.907C183.381 221.88 180.927 219.427 177.901 219.427Z" fill="#DFEAFB"/>
|
9
|
+
<defs>
|
10
|
+
<linearGradient id="paint0_linear_663_759" x1="137.714" y1="0.226593" x2="137.714" y2="274.227" gradientUnits="userSpaceOnUse">
|
11
|
+
<stop stop-color="#E3ECFA"/>
|
12
|
+
<stop offset="1" stop-color="#DAE7FF"/>
|
13
|
+
</linearGradient>
|
14
|
+
</defs>
|
15
|
+
</svg>
|
@@ -19,4 +19,8 @@
|
|
19
19
|
<div class="flex-1 flex flex-row md:min-h-inherit py-2 <% unless @displayed_in_modal %> px-6 <% end %>">
|
20
20
|
<%= content %>
|
21
21
|
</div>
|
22
|
+
<% if params[:avo_debug].present? %>
|
23
|
+
<!-- Raw value: -->
|
24
|
+
<!-- <%== @field.value.inspect %> -->
|
25
|
+
<% end %>
|
22
26
|
<% end %>
|
@@ -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
|
-
|
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 =
|
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
|
15
|
-
|
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
|
-
|
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 %>
|
@@ -5,6 +5,7 @@
|
|
5
5
|
<% if can_view? %>
|
6
6
|
<%= link_to helpers.svg('eye', class: button_classes),
|
7
7
|
show_path,
|
8
|
+
class: 'flex items-center',
|
8
9
|
title: t('avo.view_item', item: singular_resource_name).capitalize,
|
9
10
|
data: {
|
10
11
|
target: 'control:view',
|
@@ -17,6 +18,7 @@
|
|
17
18
|
<% if can_edit? %>
|
18
19
|
<%= link_to helpers.svg('edit', class: button_classes),
|
19
20
|
edit_path,
|
21
|
+
class: 'flex items-center',
|
20
22
|
title: t('avo.edit_item', item: singular_resource_name).capitalize,
|
21
23
|
data: {
|
22
24
|
target: 'control:edit',
|
@@ -31,6 +33,7 @@
|
|
31
33
|
<%= form_with url: helpers.resource_detach_path(params[:resource_name], params[:id], params[:related_name], @resource.model.id),
|
32
34
|
method: :delete,
|
33
35
|
local: true,
|
36
|
+
class: 'flex items-center',
|
34
37
|
html: {
|
35
38
|
'data-turbo-frame': params[:turbo_frame]
|
36
39
|
} do |form| %>
|
@@ -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(
|
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(:
|
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:
|
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: [
|
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
|
@@ -9,12 +9,21 @@
|
|
9
9
|
</div>
|
10
10
|
</td>
|
11
11
|
<% end %>
|
12
|
+
<% if Avo.configuration.resource_controls_on_the_left? %>
|
13
|
+
<td class="text-right whitespace-nowrap px-2" data-control="resource-controls">
|
14
|
+
<div class="flex items-center justify-end flex-grow-0 h-full w-full">
|
15
|
+
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, view_type: :table)) %>
|
16
|
+
</div>
|
17
|
+
</td>
|
18
|
+
<% end %>
|
12
19
|
<% @resource.get_fields(reflection: @reflection, only_root: true).each_with_index do |field, index| %>
|
13
20
|
<%= render field.component_for_view(:index).new(field: field, resource: @resource, index: index, parent_model: @parent_model) %>
|
14
21
|
<% end %>
|
15
|
-
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
<% if Avo.configuration.resource_controls_on_the_right? %>
|
23
|
+
<td class="text-right whitespace-nowrap px-2" data-control="resource-controls">
|
24
|
+
<div class="flex items-center justify-end flex-grow-0 h-full w-full">
|
25
|
+
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, view_type: :table)) %>
|
26
|
+
</div>
|
27
|
+
</td>
|
28
|
+
<% end %>
|
20
29
|
</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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% if item.is_tool? %>
|
2
2
|
<% if item&.partial.present? %>
|
3
|
-
<%= render item.partial, tool: item %>
|
3
|
+
<%= render item.partial, tool: item, form: @form %>
|
4
4
|
<% end %>
|
5
5
|
<% elsif item.is_panel? %>
|
6
6
|
<%= render Avo::PanelComponent.new(title: item.name, description: item.description, index: index, view: view) do |c| %>
|
@@ -39,23 +39,29 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def authorize_association_for(policy_method)
|
42
|
-
|
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
|
-
|
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
|
53
|
-
|
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
|
-
|
64
|
+
policy_result
|
59
65
|
end
|
60
66
|
|
61
67
|
def main_panel
|
@@ -1,6 +1,12 @@
|
|
1
1
|
<div
|
2
|
-
class="fixed z-[60] t-0 application-sidebar w-64
|
3
|
-
data-
|
2
|
+
class="avo-sidebar fixed z-[60] t-0 application-sidebar w-64 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 %> <%= @sidebar_open ? 'flex' : 'hidden' %>"
|
3
|
+
data-sidebar-target="<%= stimulus_target %>"
|
4
|
+
data-transition-enter="transition ease-out duration-100"
|
5
|
+
data-transition-enter-start="transform opacity-0 -translate-x-full"
|
6
|
+
data-transition-enter-end="transform opacity-100 translate-x-0"
|
7
|
+
data-transition-leave="transition ease-in duration-75"
|
8
|
+
data-transition-leave-start="transform opacity-100 translate-x-0"
|
9
|
+
data-transition-leave-end="transform opacity-0 -translate-x-full"
|
4
10
|
>
|
5
11
|
<div class="flex flex-col w-full h-full">
|
6
12
|
<div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows">
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::SidebarComponent < ViewComponent::Base
|
4
|
+
def initialize(sidebar_open: nil, for_mobile: false)
|
5
|
+
@sidebar_open = sidebar_open
|
6
|
+
@for_mobile = for_mobile
|
7
|
+
end
|
8
|
+
|
4
9
|
def dashboards
|
5
10
|
Avo::App.dashboards_for_navigation
|
6
11
|
end
|
@@ -12,4 +17,8 @@ class Avo::SidebarComponent < ViewComponent::Base
|
|
12
17
|
def tools
|
13
18
|
Avo::App.tools_for_navigation
|
14
19
|
end
|
20
|
+
|
21
|
+
def stimulus_target
|
22
|
+
@for_mobile ? "mobileSidebar" : "sidebar"
|
23
|
+
end
|
15
24
|
end
|
@@ -22,12 +22,10 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
22
22
|
helpers.resource_path(model: params[:via_resource_class].safe_constantize, resource: relation_resource, resource_id: params[:via_resource_id])
|
23
23
|
elsif via_index?
|
24
24
|
helpers.resources_path(resource: @resource)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
helpers.resources_path(resource: @resource)
|
30
|
-
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)
|
31
29
|
end
|
32
30
|
end
|
33
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(
|
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(
|
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(
|
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,
|
@@ -4,11 +4,13 @@ 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
15
|
end
|
14
16
|
|
@@ -21,6 +21,7 @@ module Avo
|
|
21
21
|
before_action :set_container_classes
|
22
22
|
before_action :add_initial_breadcrumbs
|
23
23
|
before_action :set_view
|
24
|
+
before_action :set_sidebar_open
|
24
25
|
|
25
26
|
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
26
27
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
@@ -129,7 +130,11 @@ module Avo
|
|
129
130
|
end
|
130
131
|
|
131
132
|
def set_related_model
|
132
|
-
@related_model =
|
133
|
+
@related_model = if @field.is_a? Avo::Fields::HasOneField
|
134
|
+
@model.send params[:related_name]
|
135
|
+
else
|
136
|
+
eager_load_files(@related_resource, @model.send(params[:related_name])).find params[:related_id]
|
137
|
+
end
|
133
138
|
end
|
134
139
|
|
135
140
|
def set_view
|
@@ -146,7 +151,7 @@ module Avo
|
|
146
151
|
is_attach_action = params[model_param_key].blank? && params[:related_name].present? && params[:fields].present?
|
147
152
|
|
148
153
|
unless is_attach_action
|
149
|
-
@model = @resource.fill_model(@model_to_fill, cast_nullable(model_params))
|
154
|
+
@model = @resource.fill_model(@model_to_fill, cast_nullable(model_params), extra_params: extra_params)
|
150
155
|
end
|
151
156
|
end
|
152
157
|
|
@@ -155,15 +160,20 @@ module Avo
|
|
155
160
|
end
|
156
161
|
|
157
162
|
def hydrate_related_resource
|
158
|
-
@related_resource.hydrate(view: action_name.to_sym, user: _current_user)
|
163
|
+
@related_resource.hydrate(view: action_name.to_sym, user: _current_user, model: @model)
|
159
164
|
end
|
160
165
|
|
161
|
-
def
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
166
|
+
def authorize_base_action
|
167
|
+
class_to_authorize = @model || @resource.model_class
|
168
|
+
|
169
|
+
authorize_action class_to_authorize
|
170
|
+
end
|
171
|
+
|
172
|
+
def authorize_action(class_to_authorize, action = nil)
|
173
|
+
# Use the provided action or figure it out from the request
|
174
|
+
action_to_authorize = action || action_name
|
175
|
+
|
176
|
+
@authorization.set_record(class_to_authorize).authorize_action action_to_authorize.to_sym
|
167
177
|
end
|
168
178
|
|
169
179
|
# Get the pluralized resource name for this request
|
@@ -310,10 +320,15 @@ module Avo
|
|
310
320
|
|
311
321
|
def default_url_options
|
312
322
|
if params[:force_locale].present?
|
313
|
-
{
|
323
|
+
{**super, force_locale: params[:force_locale]}
|
314
324
|
else
|
315
325
|
super
|
316
326
|
end
|
317
327
|
end
|
328
|
+
|
329
|
+
def set_sidebar_open
|
330
|
+
value = cookies["#{Avo::COOKIES_KEY}.sidebar.open"]
|
331
|
+
@sidebar_open = value.blank? || value == "1"
|
332
|
+
end
|
318
333
|
end
|
319
334
|
end
|