avo 2.20.0 → 2.21.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 +2 -2
- data/app/components/avo/empty_state_component.html.erb +1 -1
- data/app/components/avo/empty_state_component.rb +12 -10
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +1 -1
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/code_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/country_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/date_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/edit_component.rb +4 -0
- data/app/components/avo/fields/external_image_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -3
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/markdown_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/number_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/password_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/show_component.rb +4 -0
- data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/time_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/trix_field/edit_component.html.erb +3 -2
- data/app/components/avo/fields/trix_field/edit_component.rb +5 -1
- data/app/components/avo/index/resource_grid_component.html.erb +1 -1
- data/app/components/avo/index/resource_table_component.rb +3 -3
- data/app/components/avo/paginator_component.html.erb +1 -5
- data/app/components/avo/paginator_component.rb +8 -0
- data/app/components/avo/resource_component.rb +17 -2
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/controllers/avo/application_controller.rb +2 -2
- data/app/controllers/avo/associations_controller.rb +2 -1
- data/app/controllers/avo/attachments_controller.rb +4 -0
- data/app/controllers/avo/base_controller.rb +10 -4
- data/app/controllers/avo/dashboards/cards_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +11 -5
- data/app/javascript/js/controllers/fields/trix_field_controller.js +6 -3
- data/app/javascript/js/controllers/item_select_all_controller.js +7 -4
- data/app/views/avo/actions/show.html.erb +1 -1
- data/app/views/avo/base/_multiple_select_filter.html.erb +1 -1
- data/app/views/avo/partials/_resource_search.html.erb +1 -1
- data/config/i18n-tasks.yml +1 -1
- data/config/initializers/pagy.rb +16 -0
- data/lib/avo/base_action.rb +9 -3
- data/lib/avo/base_card.rb +5 -2
- data/lib/avo/base_resource.rb +3 -2
- data/lib/avo/concerns/handles_field_args.rb +8 -1
- data/lib/avo/fields/base_field.rb +2 -1
- data/lib/avo/fields/concerns/is_disabled.rb +19 -0
- data/lib/avo/fields/select_field.rb +1 -1
- data/lib/avo/filters/base_filter.rb +1 -2
- data/lib/avo/hosts/resource_record_host.rb +7 -0
- data/lib/avo/hosts/visibility_host.rb +0 -1
- data/lib/avo/services/authorization_service.rb +2 -2
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/field/components/edit_component.html.erb.tt +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +3 -2
- data/lib/generators/avo/templates/locales/avo.fr.yml +3 -2
- data/lib/generators/avo/templates/locales/avo.nb.yml +3 -2
- data/lib/generators/avo/templates/locales/avo.nn.yml +3 -2
- data/lib/generators/avo/templates/locales/avo.pt-BR.yml +3 -2
- data/lib/generators/avo/templates/locales/avo.pt.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.ro.yml +56 -55
- data/lib/generators/avo/templates/locales/avo.tr.yml +3 -2
- data/lib/generators/avo/templates/locales/pagy/nn.yml +15 -0
- data/lib/generators/avo/templates/locales/pagy/ro.yml +17 -0
- data/public/avo-assets/avo.base.js +2 -2
- data/public/avo-assets/avo.base.js.map +2 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 302280e8ea8c09012d0f68c72b017a8e903261346e02fdb8b4eaf2daa3160d39
|
4
|
+
data.tar.gz: eef2ab4ee6fd1576311d85ef6ae91add6f655f9762e3cc736f39bbb2f039c31e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdf810fecb08f2a6d8a157238b28df1141b396b1a62387a88bb6094d0ac4c39195d36c319751eb7dca1368ed6f5174a241a23279bf558ade568091ce201d65ae
|
7
|
+
data.tar.gz: 983acf054fc7a5c8fd4f1f32b9f1a6c45e187d9c87f70a223203e8445f3d0ecd1d05eb80ac0fc02ec497604636a37a20d8ab8365a21477dbd9decc60ad1760f5
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (2.
|
4
|
+
avo (2.21.0)
|
5
5
|
actionview (>= 6.0)
|
6
6
|
active_link_to
|
7
7
|
activerecord (>= 6.0)
|
@@ -409,7 +409,7 @@ GEM
|
|
409
409
|
tzinfo (2.0.5)
|
410
410
|
concurrent-ruby (~> 1.0)
|
411
411
|
unicode-display_width (2.2.0)
|
412
|
-
view_component (2.
|
412
|
+
view_component (2.78.0)
|
413
413
|
activesupport (>= 5.0.0, < 8.0)
|
414
414
|
concurrent-ruby (~> 1.0)
|
415
415
|
method_source (~> 1.0)
|
@@ -1,24 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::EmptyStateComponent < ViewComponent::Base
|
4
|
-
|
4
|
+
attr_reader :message, :view_type, :add_background, :by_association
|
5
|
+
|
6
|
+
def initialize(message: nil, view_type: :table, add_background: false, by_association: false)
|
5
7
|
@message = message
|
6
8
|
@view_type = view_type
|
7
|
-
@related_name = related_name
|
8
|
-
@resource_name = resource_name
|
9
9
|
@add_background = add_background
|
10
|
+
@by_association = by_association
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
translation_tag = @related_name.present? ? 'avo.no_related_item_found' : 'avo.no_item_found'
|
16
|
-
helpers.t translation_tag, item: @resource_name
|
13
|
+
def text
|
14
|
+
message || locale_message
|
17
15
|
end
|
18
16
|
|
19
17
|
def view_type_svg
|
20
|
-
|
18
|
+
"#{view_type}-empty-state"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
21
22
|
|
22
|
-
|
23
|
+
def locale_message
|
24
|
+
helpers.t by_association ? 'avo.no_related_item_found' : 'avo.no_item_found'
|
23
25
|
end
|
24
26
|
end
|
@@ -8,7 +8,7 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def disabled
|
11
|
-
return true if @field.is_readonly?
|
11
|
+
return true if @field.is_readonly? || @field.is_disabled?
|
12
12
|
|
13
13
|
# When visiting the record through it's association we keep the field disabled by default
|
14
14
|
# We make an exception when the user deliberately instructs Avo to allow detaching in this scenario
|
@@ -4,7 +4,7 @@
|
|
4
4
|
checked: @field.value,
|
5
5
|
class: "text-lg h-4 w-4 checked:bg-primary-400 focus:checked:!bg-primary-400 #{@field.get_html(:classes, view: view, element: :input)}",
|
6
6
|
data: @field.get_html(:data, view: view, element: :input),
|
7
|
-
disabled:
|
7
|
+
disabled: disabled?,
|
8
8
|
style: @field.get_html(:style, view: view, element: :input)
|
9
9
|
%>
|
10
10
|
</div>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
<%= check_box_tag "#{model_param_key}[#{@field.id}][]", id, checked, {
|
21
21
|
class: "w-4 h-4 #{@field.get_html(:classes, view: view, element: :input)}",
|
22
22
|
data: @field.get_html(:data, view: view, element: :input),
|
23
|
-
disabled:
|
23
|
+
disabled: disabled?,
|
24
24
|
id: "#{model_param_key}_#{@field.id}_#{id}",
|
25
25
|
style: @field.get_html(:style, view: view, element: :input)
|
26
26
|
} %> <%= label %>
|
@@ -8,12 +8,12 @@
|
|
8
8
|
language: @field.language,
|
9
9
|
theme: @field.theme,
|
10
10
|
'tab-size': @field.tab_size,
|
11
|
-
'read-only':
|
11
|
+
'read-only': disabled?,
|
12
12
|
'indent-with-tabs': @field.indent_with_tabs,
|
13
13
|
'line-wrapping': @field.line_wrapping,
|
14
14
|
**@field.get_html(:data, view: view, element: :input),
|
15
15
|
},
|
16
|
-
disabled:
|
16
|
+
disabled: disabled?,
|
17
17
|
placeholder: @field.placeholder,
|
18
18
|
style: @field.get_html(:style, view: view, element: :input)
|
19
19
|
%>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
},
|
9
9
|
class: classes("w-full"),
|
10
10
|
data: @field.get_html(:data, view: view, element: :input),
|
11
|
-
disabled:
|
11
|
+
disabled: disabled?,
|
12
12
|
style: @field.get_html(:style, view: view, element: :input),
|
13
13
|
placeholder: @field.include_blank.present? ? nil : @field.placeholder
|
14
14
|
%>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
placeholder: @field.placeholder,
|
19
19
|
**@field.get_html(:data, view: view, element: :input)
|
20
20
|
},
|
21
|
-
disabled:
|
21
|
+
disabled: disabled?,
|
22
22
|
placeholder: @field.placeholder,
|
23
23
|
style: @field.get_html(:style, view: view, element: :input)
|
24
24
|
%>
|
@@ -30,7 +30,7 @@
|
|
30
30
|
placeholder: @field.placeholder,
|
31
31
|
**@field.get_html(:data, view: view, element: :input)
|
32
32
|
},
|
33
|
-
disabled:
|
33
|
+
disabled: disabled?,
|
34
34
|
placeholder: @field.placeholder,
|
35
35
|
style: @field.get_html(:style, view: view, element: :input)
|
36
36
|
%>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
placeholder: @field.placeholder,
|
21
21
|
**@field.get_html(:data, view: view, element: :input)
|
22
22
|
},
|
23
|
-
disabled:
|
23
|
+
disabled: disabled?,
|
24
24
|
placeholder: @field.placeholder,
|
25
25
|
style: @field.get_html(:style, view: view, element: :input)
|
26
26
|
%>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
placeholder: @field.placeholder,
|
33
33
|
**@field.get_html(:data, view: view, element: :input)
|
34
34
|
},
|
35
|
-
disabled:
|
35
|
+
disabled: disabled?,
|
36
36
|
placeholder: @field.placeholder,
|
37
37
|
style: @field.get_html(:style, view: view, element: :input)
|
38
38
|
%>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= @form.text_field @field.id,
|
3
3
|
class: classes("w-full"),
|
4
4
|
data: @field.get_html(:data, view: view, element: :input),
|
5
|
-
disabled:
|
5
|
+
disabled: disabled?,
|
6
6
|
placeholder: @field.placeholder,
|
7
7
|
style: @field.get_html(:style, view: view, element: :input)
|
8
8
|
%>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
accept: @field.accept,
|
11
11
|
data: @field.get_html(:data, view: view, element: :input),
|
12
12
|
direct_upload: @field.direct_upload,
|
13
|
-
disabled:
|
13
|
+
disabled: disabled?,
|
14
14
|
style: @field.get_html(:style, view: view, element: :input),
|
15
15
|
class: "w-full"
|
16
16
|
%>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
accept: @field.accept,
|
8
8
|
data: @field.get_html(:data, view: view, element: :input),
|
9
9
|
direct_upload: @field.direct_upload,
|
10
|
-
disabled:
|
10
|
+
disabled: disabled?,
|
11
11
|
multiple: true,
|
12
12
|
style: @field.get_html(:style, view: view, element: :input),
|
13
13
|
class: "w-full"
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<% else %>
|
6
6
|
<%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
|
7
7
|
<% c.tools do %>
|
8
|
-
<% if !@field.is_readonly? && can_attach? %>
|
8
|
+
<% if !@field.is_readonly? && !@field.is_disabled? && can_attach? %>
|
9
9
|
<%= a_link attach_path,
|
10
10
|
icon: 'heroicons/outline/link',
|
11
11
|
color: :primary,
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<%= t('avo.attach_item', item: @field.name.downcase) %>
|
14
14
|
<% end %>
|
15
15
|
<% end %>
|
16
|
-
<% if !@field.is_readonly? && can_see_the_create_button? %>
|
16
|
+
<% if !@field.is_readonly? && !@field.is_disabled? && can_see_the_create_button? %>
|
17
17
|
<%= a_link create_path,
|
18
18
|
icon: 'heroicons/outline/plus',
|
19
19
|
'data-target': 'create',
|
@@ -27,7 +27,7 @@
|
|
27
27
|
|
28
28
|
<% c.body do %>
|
29
29
|
<div class="py-8 flex justify-center items-center">
|
30
|
-
<%= empty_state
|
30
|
+
<%= empty_state by_association: params[:related_name].present? %>
|
31
31
|
</div>
|
32
32
|
<% end %>
|
33
33
|
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<%= text_area_tag @field.id, @field.value,
|
4
4
|
class: helpers.input_classes('w-full js-has-simple-mde-editor'),
|
5
5
|
placeholder: @field.placeholder,
|
6
|
-
disabled:
|
6
|
+
disabled: disabled?,
|
7
7
|
'data-simple-mde-target': 'element',
|
8
8
|
'data-component-options': @field.options.to_json,
|
9
9
|
'data-view': :show %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= @form.password_field @field.id,
|
3
3
|
class: classes("w-full"),
|
4
4
|
data: @field.get_html(:data, view: view, element: :input),
|
5
|
-
disabled:
|
5
|
+
disabled: disabled?,
|
6
6
|
placeholder: @field.placeholder,
|
7
7
|
style: @field.get_html(:style, view: view, element: :input)
|
8
8
|
%>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<%= @form.range_field @field.id,
|
8
8
|
class: "w-full #{@field.get_html(:classes, view: view, element: :input)}",
|
9
9
|
data: @field.get_html(:data, view: view, element: :input),
|
10
|
-
disabled:
|
10
|
+
disabled: disabled?,
|
11
11
|
max: @field.max,
|
12
12
|
min: 0,
|
13
13
|
placeholder: @field.placeholder,
|
@@ -7,7 +7,7 @@
|
|
7
7
|
},
|
8
8
|
class: classes("w-full"),
|
9
9
|
data: @field.get_html(:data, view: view, element: :input),
|
10
|
-
disabled:
|
10
|
+
disabled: disabled?,
|
11
11
|
style: @field.get_html(:style, view: view, element: :input),
|
12
12
|
value: @field.model.present? ? @field.model[@field.id] : @field.value,
|
13
13
|
placeholder: @field.include_blank.present? ? nil : @field.placeholder
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= @form.text_field @field.id,
|
3
3
|
class: classes("w-full"),
|
4
4
|
data: @field.get_html(:data, view: view, element: :input),
|
5
|
-
disabled:
|
5
|
+
disabled: disabled?,
|
6
6
|
placeholder: @field.placeholder,
|
7
7
|
style: @field.get_html(:style, view: view, element: :input),
|
8
8
|
value: @resource.model.present? ? @resource.model[@field.id] : @field.value
|
@@ -6,7 +6,7 @@
|
|
6
6
|
data: {
|
7
7
|
'tags-field-target': 'fakeInput',
|
8
8
|
},
|
9
|
-
disabled:
|
9
|
+
disabled: disabled?,
|
10
10
|
placeholder: @field.placeholder,
|
11
11
|
style: @field.get_html(:style, view: view, element: :input),
|
12
12
|
value: ''
|
@@ -22,7 +22,7 @@
|
|
22
22
|
'delimiters': @field.delimiters,
|
23
23
|
'close-on-select': @field.close_on_select ? 1 : 0,
|
24
24
|
},
|
25
|
-
disabled:
|
25
|
+
disabled: disabled?,
|
26
26
|
placeholder: @field.placeholder,
|
27
27
|
style: @field.get_html(:style, view: view, element: :input),
|
28
28
|
value: @field.field_value.to_json
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= form.text_field @field.id,
|
3
3
|
class: classes("w-full"),
|
4
4
|
data: @field.get_html(:data, view: view, element: :input),
|
5
|
-
disabled:
|
5
|
+
disabled: disabled?,
|
6
6
|
placeholder: @field.placeholder,
|
7
7
|
style: @field.get_html(:style, view: view, element: :input),
|
8
8
|
# value: @field.value,
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= @form.text_area @field.id,
|
3
3
|
class: classes("w-full"),
|
4
4
|
data: @field.get_html(:data, view: view, element: :input),
|
5
|
-
disabled:
|
5
|
+
disabled: disabled?,
|
6
6
|
placeholder: @field.placeholder,
|
7
7
|
rows: @field.rows,
|
8
8
|
style: @field.get_html(:style, view: view, element: :input)
|
@@ -20,7 +20,7 @@
|
|
20
20
|
placeholder: @field.placeholder,
|
21
21
|
**@field.get_html(:data, view: view, element: :input)
|
22
22
|
},
|
23
|
-
disabled:
|
23
|
+
disabled: disabled?,
|
24
24
|
placeholder: @field.placeholder,
|
25
25
|
style: @field.get_html(:style, view: view, element: :input)
|
26
26
|
%>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
placeholder: @field.placeholder,
|
33
33
|
**@field.get_html(:data, view: view, element: :input)
|
34
34
|
},
|
35
|
-
disabled:
|
35
|
+
disabled: disabled?,
|
36
36
|
placeholder: @field.placeholder,
|
37
37
|
style: @field.get_html(:style, view: view, element: :input)
|
38
38
|
%>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<%= content_tag :div,
|
2
|
+
<%= content_tag :div,
|
3
|
+
class: "relative block overflow-x-auto max-w-full",
|
3
4
|
data: {
|
4
5
|
controller: "trix-field",
|
5
6
|
trix_field_target: "controller",
|
@@ -24,7 +25,7 @@
|
|
24
25
|
<%= @form.text_area @field.id,
|
25
26
|
class: classes("w-full hidden"),
|
26
27
|
data: @field.get_html(:data, view: view, element: :input),
|
27
|
-
disabled:
|
28
|
+
disabled: disabled?,
|
28
29
|
id: trix_id,
|
29
30
|
placeholder: @field.placeholder,
|
30
31
|
style: @field.get_html(:style, view: view, element: :input)
|
@@ -20,6 +20,10 @@ class Avo::Fields::TrixField::EditComponent < Avo::Fields::EditComponent
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def trix_id
|
23
|
-
|
23
|
+
if resource_name.present?
|
24
|
+
"trix_#{resource_name}_#{@field.id}"
|
25
|
+
elsif form.present?
|
26
|
+
"trix_#{form.index}_#{@field.id}"
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
@@ -9,6 +9,6 @@
|
|
9
9
|
</div>
|
10
10
|
<% else %>
|
11
11
|
<div class="bg-white rounded shadow-panel">
|
12
|
-
<%= helpers.empty_state
|
12
|
+
<%= helpers.empty_state by_association: params[:related_name].present?, view_type: :grid %>
|
13
13
|
</div>
|
14
14
|
<% end %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class Avo::Index::ResourceTableComponent < ViewComponent::Base
|
4
4
|
include Avo::ApplicationHelper
|
5
|
-
attr_reader :pagy
|
5
|
+
attr_reader :pagy, :query
|
6
6
|
|
7
7
|
def initialize(resources: nil, resource: nil, reflection: nil, parent_model: nil, parent_resource: nil, pagy: nil, query: nil)
|
8
8
|
@resources = resources
|
@@ -15,10 +15,10 @@ class Avo::Index::ResourceTableComponent < ViewComponent::Base
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def encrypted_query
|
18
|
-
return if
|
18
|
+
return :select_all_disabled if query.nil? || !query.respond_to?(:all) || !query.all.respond_to?(:to_sql)
|
19
19
|
|
20
20
|
Avo::Services::EncryptionService.encrypt(
|
21
|
-
message:
|
21
|
+
message: query.all.to_sql,
|
22
22
|
purpose: :select_all
|
23
23
|
)
|
24
24
|
end
|
@@ -25,11 +25,7 @@
|
|
25
25
|
%> <%= t('avo.per_page').downcase %>
|
26
26
|
</div>
|
27
27
|
<% per_page_options.each do |option| %>
|
28
|
-
|
29
|
-
<%= link_to "Change to #{option} items per page", helpers.related_resources_path(parent_model, parent_model, per_page: option, keep_query_params: true, page: 1), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
30
|
-
<% else %>
|
31
|
-
<%= link_to "Change to #{option} items per page", helpers.resources_path(resource: resource, per_page: option, keep_query_params: true, page: 1), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
32
|
-
<% end %>
|
28
|
+
<%= link_to "Change to #{option} items per page", change_items_per_page_url(option), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
33
29
|
<% end %>
|
34
30
|
</div>
|
35
31
|
</div>
|
@@ -16,4 +16,12 @@ class Avo::PaginatorComponent < ViewComponent::Base
|
|
16
16
|
@parent_model = parent_model
|
17
17
|
@discreet_pagination = discreet_pagination
|
18
18
|
end
|
19
|
+
|
20
|
+
def change_items_per_page_url(option)
|
21
|
+
if parent_model.present?
|
22
|
+
helpers.related_resources_path(parent_model, parent_model, per_page: option, keep_query_params: true, page: 1)
|
23
|
+
else
|
24
|
+
helpers.resources_path(resource: resource, per_page: option, keep_query_params: true, page: 1)
|
25
|
+
end
|
26
|
+
end
|
19
27
|
end
|
@@ -53,6 +53,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
# Ex: A Post has many Comments
|
56
57
|
def authorize_association_for(policy_method)
|
57
58
|
policy_result = true
|
58
59
|
|
@@ -67,11 +68,25 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
67
68
|
|
68
69
|
if association_name.present?
|
69
70
|
method_name = "#{policy_method}_#{association_name}?".to_sym
|
70
|
-
|
71
|
+
|
72
|
+
# Use the policy methods from the parent (Post)
|
71
73
|
service = reflection_resource.authorization
|
72
74
|
|
73
75
|
if service.has_method?(method_name, raise_exception: false)
|
74
|
-
|
76
|
+
# Some policy methods should get the parent record in order to have the necessarry information to do the authorization
|
77
|
+
# Example: Post->has_many->Comments
|
78
|
+
# When you want to authorize the creation/attaching of a Comment, you don't have the Comment instance.
|
79
|
+
# But you do have the Post instance and you can get that in your policy to authorize against.
|
80
|
+
parent_policy_methods = [:view, :create, :attach, :act_on]
|
81
|
+
|
82
|
+
record = if parent_policy_methods.include?(policy_method)
|
83
|
+
# Use the parent record (Post)
|
84
|
+
reflection_resource.model
|
85
|
+
else
|
86
|
+
# Override the record with the child record (Comment)
|
87
|
+
resource.model
|
88
|
+
end
|
89
|
+
policy_result = service.authorize_action(method_name, record: record, raise_exception: false)
|
75
90
|
end
|
76
91
|
end
|
77
92
|
end
|
@@ -52,7 +52,7 @@
|
|
52
52
|
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
|
53
53
|
</div>
|
54
54
|
<% else %>
|
55
|
-
<%= helpers.empty_state
|
55
|
+
<%= helpers.empty_state by_association: params[:related_name].present?, view_type: view_type, add_background: true %>
|
56
56
|
<% end %>
|
57
57
|
<% end %>
|
58
58
|
<% end %>
|
@@ -172,11 +172,11 @@ module Avo
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def hydrate_resource
|
175
|
-
@resource.hydrate(view: action_name.to_sym, user: _current_user)
|
175
|
+
@resource.hydrate(view: action_name.to_sym, user: _current_user, model: @model)
|
176
176
|
end
|
177
177
|
|
178
178
|
def hydrate_related_resource
|
179
|
-
@related_resource.hydrate(view: action_name.to_sym, user: _current_user, model: @
|
179
|
+
@related_resource.hydrate(view: action_name.to_sym, user: _current_user, model: @related_model)
|
180
180
|
end
|
181
181
|
|
182
182
|
def authorize_base_action
|
@@ -3,12 +3,13 @@ require_dependency "avo/base_controller"
|
|
3
3
|
module Avo
|
4
4
|
class AssociationsController < BaseController
|
5
5
|
before_action :set_model, only: [:show, :index, :new, :create, :destroy, :order]
|
6
|
+
before_action :hydrate_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
6
7
|
before_action :set_related_resource_name
|
7
8
|
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
8
9
|
before_action :set_related_authorization
|
9
10
|
before_action :set_reflection_field
|
10
|
-
before_action :hydrate_related_resource, only: [:show, :index, :create, :destroy, :order]
|
11
11
|
before_action :set_related_model, only: [:show, :order]
|
12
|
+
before_action :hydrate_related_resource, only: [:show, :index, :create, :destroy, :order]
|
12
13
|
before_action :set_reflection
|
13
14
|
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy, :order]
|
14
15
|
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
@@ -10,6 +10,10 @@ module Avo
|
|
10
10
|
blob = ActiveStorage::Blob.create_and_upload! io: params[:file], filename: params[:filename]
|
11
11
|
association_name = BaseResource.valid_attachment_name(@model, params[:attachment_key])
|
12
12
|
|
13
|
+
if association_name.blank?
|
14
|
+
raise ActionController::BadRequest.new("Could not find the attachment association for #{params[:attachment_key]} (check the `attachment_key` for this Trix field)")
|
15
|
+
end
|
16
|
+
|
13
17
|
@model.send(association_name).attach blob
|
14
18
|
|
15
19
|
render json: {
|
@@ -14,6 +14,7 @@ module Avo
|
|
14
14
|
before_action :fill_model, only: [:create, :update]
|
15
15
|
# Don't run base authorizations for associations
|
16
16
|
before_action :authorize_base_action, if: -> { controller_name != "associations" }
|
17
|
+
before_action :set_pagy_locale, only: :index
|
17
18
|
|
18
19
|
def index
|
19
20
|
@page_title = @resource.plural_name.humanize
|
@@ -223,11 +224,11 @@ module Avo
|
|
223
224
|
# In case there's an error somewhere else than the model
|
224
225
|
# Example: When you save a license that should create a user for it and creating that user throws and error.
|
225
226
|
# Example: When you Try to delete a record and has a foreign key constraint.
|
226
|
-
|
227
|
+
exception_message = exception.message
|
227
228
|
end
|
228
229
|
|
229
230
|
# Add the errors from the model
|
230
|
-
@errors =
|
231
|
+
@errors = @model.errors.full_messages.reject { |error| exception_message.include? error }.unshift exception_message
|
231
232
|
|
232
233
|
succeeded
|
233
234
|
end
|
@@ -315,7 +316,7 @@ module Avo
|
|
315
316
|
filter[:class].new arguments: filter[:arguments]
|
316
317
|
end
|
317
318
|
.select do |filter|
|
318
|
-
filter.visible_in_view(resource: @resource,
|
319
|
+
filter.visible_in_view(resource: @resource, parent_resource: @parent_resource)
|
319
320
|
end
|
320
321
|
end
|
321
322
|
|
@@ -326,7 +327,7 @@ module Avo
|
|
326
327
|
action[:class].new(model: @model, resource: @resource, view: @view, arguments: action[:arguments])
|
327
328
|
end
|
328
329
|
.select do |action|
|
329
|
-
action.visible_in_view(
|
330
|
+
action.visible_in_view(parent_resource: @parent_resource)
|
330
331
|
end
|
331
332
|
end
|
332
333
|
|
@@ -510,5 +511,10 @@ module Avo
|
|
510
511
|
def is_associated_record?
|
511
512
|
params[:via_relation_class].present? && params[:via_resource_id].present?
|
512
513
|
end
|
514
|
+
|
515
|
+
# Set pagy locale from params or from avo configuration, if both nil locale = "en"
|
516
|
+
def set_pagy_locale
|
517
|
+
@pagy_locale = locale.to_s || Avo.configuration.locale || "en"
|
518
|
+
end
|
513
519
|
end
|
514
520
|
end
|