avo 2.21.1.pre.issue1450 → 2.21.1.pre.pr1476
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/trix_field/edit_component.html.erb +2 -1
- data/app/components/avo/fields/trix_field/edit_component.rb +5 -1
- data/app/components/avo/index/resource_table_component.rb +3 -3
- data/app/components/avo/resource_component.rb +4 -2
- 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 +2 -2
- 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/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 +0 -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/locales/pagy/nn.yml +15 -0
- data/public/avo-assets/avo.base.js +2 -2
- data/public/avo-assets/avo.base.js.map +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f832c5802957b7d88c4271b886cfcb0a727ad98b1d200dc1f8e6d7a5a779067
|
4
|
+
data.tar.gz: bb639aec120f3881847aa5ce53bd4bc399da0ae3fde37d01aad77ef13c017cbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53180bdf4636c4dffd120fb8bb0f9ab0dacbbb9aad7e5ac3b906329144510b12b719591ebedb1dd2fb20d81a69d3a4932933d6500b4451e46947e9c3261885f0
|
7
|
+
data.tar.gz: 16f6f89ae35d3b8d1c491af4d3b35eee7148d56ee2dcfcdd7ec3a0b0bd16919a0f0424d93c6863f3a1d22acbb1d2be6cf02007122804fed43a11bd6229de491f
|
data/Gemfile.lock
CHANGED
@@ -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",
|
@@ -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
|
@@ -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
|
@@ -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,12 @@ 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
|
+
# Use the policy methods from the parent (Post)
|
71
72
|
service = reflection_resource.authorization
|
72
73
|
|
73
74
|
if service.has_method?(method_name, raise_exception: false)
|
74
|
-
|
75
|
+
# Override the record with the child record (Comment not Post)
|
76
|
+
policy_result = service.authorize_action(method_name, record: resource.model, raise_exception: false)
|
75
77
|
end
|
76
78
|
end
|
77
79
|
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: {
|
@@ -315,7 +315,7 @@ module Avo
|
|
315
315
|
filter[:class].new arguments: filter[:arguments]
|
316
316
|
end
|
317
317
|
.select do |filter|
|
318
|
-
filter.visible_in_view(resource: @resource,
|
318
|
+
filter.visible_in_view(resource: @resource, parent_resource: @parent_resource)
|
319
319
|
end
|
320
320
|
end
|
321
321
|
|
@@ -326,7 +326,7 @@ module Avo
|
|
326
326
|
action[:class].new(model: @model, resource: @resource, view: @view, arguments: action[:arguments])
|
327
327
|
end
|
328
328
|
.select do |action|
|
329
|
-
action.visible_in_view(
|
329
|
+
action.visible_in_view(parent_resource: @parent_resource)
|
330
330
|
end
|
331
331
|
end
|
332
332
|
|
@@ -44,27 +44,33 @@ module Avo
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def search_resource(resource)
|
47
|
-
query =
|
47
|
+
query = Avo::Hosts::SearchScopeHost.new(
|
48
48
|
block: resource.search_query,
|
49
49
|
params: params,
|
50
|
-
scope: resource.class.scope
|
50
|
+
scope: resource.class.scope
|
51
51
|
).handle
|
52
52
|
|
53
|
+
# Get the count
|
54
|
+
results_count = query.count
|
55
|
+
|
56
|
+
# Get the results
|
57
|
+
query = query.limit(8)
|
58
|
+
|
53
59
|
query = apply_scope(query) if should_apply_any_scope?
|
54
60
|
|
55
61
|
results = apply_search_metadata(query, resource)
|
56
62
|
|
57
63
|
header = resource.plural_name
|
58
64
|
|
59
|
-
if
|
60
|
-
header
|
65
|
+
if results_count > 0
|
66
|
+
header = "#{header} (#{results_count})"
|
61
67
|
end
|
62
68
|
|
63
69
|
result_object = {
|
64
70
|
header: header,
|
65
71
|
help: resource.class.search_query_help,
|
66
72
|
results: results,
|
67
|
-
count:
|
73
|
+
count: results_count
|
68
74
|
}
|
69
75
|
|
70
76
|
[resource.name.pluralize.downcase, result_object]
|
@@ -55,7 +55,7 @@ export default class extends Controller {
|
|
55
55
|
}
|
56
56
|
|
57
57
|
// Prevent file uploads for resources that haven't been saved yet.
|
58
|
-
if (this.resourceId
|
58
|
+
if (!this.resourceId) {
|
59
59
|
event.preventDefault()
|
60
60
|
alert("You can't upload files into the Trix editor until you save the resource.")
|
61
61
|
|
@@ -63,7 +63,7 @@ export default class extends Controller {
|
|
63
63
|
}
|
64
64
|
|
65
65
|
// Prevent file uploads for fields without an attachment key.
|
66
|
-
if (this.attachmentKey
|
66
|
+
if (!this.attachmentKey) {
|
67
67
|
event.preventDefault()
|
68
68
|
alert("You haven't set an `attachment_key` to this Trix field.")
|
69
69
|
}
|
@@ -93,7 +93,10 @@ export default class extends Controller {
|
|
93
93
|
|
94
94
|
xhr.open('POST', this.uploadUrl, true)
|
95
95
|
|
96
|
-
|
96
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content
|
97
|
+
if (csrfToken) {
|
98
|
+
xhr.setRequestHeader('X-CSRF-Token', csrfToken)
|
99
|
+
}
|
97
100
|
|
98
101
|
xhr.upload.addEventListener('progress', (event) => {
|
99
102
|
// eslint-disable-next-line no-mixed-operators
|
@@ -18,8 +18,7 @@ export default class extends Controller {
|
|
18
18
|
document.querySelectorAll(`[data-controller="item-selector"][data-resource-name="${this.resourceName}"] input[type=checkbox]`)
|
19
19
|
.forEach((checkbox) => checkbox.checked !== checked && checkbox.click())
|
20
20
|
|
21
|
-
|
22
|
-
if (this.pageCountValue > 1) {
|
21
|
+
if (this.selectAllEnabled()) {
|
23
22
|
this.selectAllOverlay(checked)
|
24
23
|
|
25
24
|
// When de-selecting everything, ensure the selectAll toggle is false and hide overlay.
|
@@ -35,8 +34,7 @@ export default class extends Controller {
|
|
35
34
|
this.itemCheckboxTargets.forEach((checkbox) => allSelected = allSelected && checkbox.checked)
|
36
35
|
this.checkboxTarget.checked = allSelected
|
37
36
|
|
38
|
-
|
39
|
-
if (this.pageCountValue > 1) {
|
37
|
+
if (this.selectAllEnabled()) {
|
40
38
|
this.selectAllOverlay(allSelected)
|
41
39
|
this.resetUnselected()
|
42
40
|
}
|
@@ -63,4 +61,9 @@ export default class extends Controller {
|
|
63
61
|
this.selectAllOverlayTarget.classList.add('hidden')
|
64
62
|
}
|
65
63
|
}
|
64
|
+
|
65
|
+
// True if there are more pages available and if query encryption run successfully
|
66
|
+
selectAllEnabled() {
|
67
|
+
return this.pageCountValue > 1 && this.selectedAllQueryValue !== 'select_all_disabled'
|
68
|
+
}
|
66
69
|
}
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<%= @action.action_name %>
|
19
19
|
<% end %>
|
20
20
|
<div class="flex-1 flex">
|
21
|
-
<%= @action.
|
21
|
+
<%= @action.get_message %>
|
22
22
|
</div>
|
23
23
|
<%= form.hidden_field :avo_resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
|
24
24
|
<%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
|
data/lib/avo/base_action.rb
CHANGED
@@ -72,6 +72,14 @@ module Avo
|
|
72
72
|
@response[:messages] = []
|
73
73
|
end
|
74
74
|
|
75
|
+
def get_message
|
76
|
+
if self.class.message.respond_to? :call
|
77
|
+
Avo::Hosts::ResourceRecordHost.new(block: self.class.message, record: self.class.model, resource: self.class.resource).handle
|
78
|
+
else
|
79
|
+
self.class.message
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
75
83
|
def get_attributes_for_action
|
76
84
|
get_fields.map do |field|
|
77
85
|
[field.id, field.value || field.default]
|
@@ -116,7 +124,7 @@ module Avo
|
|
116
124
|
self
|
117
125
|
end
|
118
126
|
|
119
|
-
def visible_in_view(
|
127
|
+
def visible_in_view(parent_resource: nil)
|
120
128
|
if visible.blank?
|
121
129
|
# Hide on the :new view by default
|
122
130
|
return false if view == :new
|
@@ -128,9 +136,7 @@ module Avo
|
|
128
136
|
# Run the visible block if available
|
129
137
|
Avo::Hosts::VisibilityHost.new(
|
130
138
|
block: visible,
|
131
|
-
model: self.class.model,
|
132
139
|
params: params,
|
133
|
-
parent_model: parent_model,
|
134
140
|
parent_resource: parent_resource,
|
135
141
|
resource: self.class.resource,
|
136
142
|
view: self.class.view,
|
data/lib/avo/base_card.rb
CHANGED
@@ -20,6 +20,10 @@ module Avo
|
|
20
20
|
attr_accessor :params
|
21
21
|
|
22
22
|
delegate :context, to: ::Avo::App
|
23
|
+
delegate :current_user, to: ::Avo::App
|
24
|
+
delegate :view_context, to: ::Avo::App
|
25
|
+
delegate :params, to: ::Avo::App
|
26
|
+
delegate :request, to: ::Avo::App
|
23
27
|
|
24
28
|
class << self
|
25
29
|
def query(&block)
|
@@ -106,9 +110,8 @@ module Avo
|
|
106
110
|
self
|
107
111
|
end
|
108
112
|
|
109
|
-
def hydrate(dashboard: nil
|
113
|
+
def hydrate(dashboard: nil)
|
110
114
|
@dashboard = dashboard if dashboard.present?
|
111
|
-
@params = params if params.present?
|
112
115
|
|
113
116
|
self
|
114
117
|
end
|
data/lib/avo/base_resource.rb
CHANGED
@@ -117,9 +117,10 @@ module Avo
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def valid_attachment_name(record, association_name)
|
120
|
-
get_record_associations(record).keys.
|
121
|
-
|
120
|
+
association_exists = get_record_associations(record).keys.any? do |name|
|
121
|
+
name == "#{association_name}_attachment" || name == "#{association_name}_attachments"
|
122
122
|
end
|
123
|
+
return association_name if association_exists
|
123
124
|
end
|
124
125
|
|
125
126
|
def get_available_models
|
@@ -12,7 +12,14 @@ module Avo
|
|
12
12
|
value = default
|
13
13
|
|
14
14
|
if type == :boolean
|
15
|
-
|
15
|
+
case args[name.to_sym]
|
16
|
+
when nil
|
17
|
+
value = default
|
18
|
+
when false
|
19
|
+
value = false
|
20
|
+
when true
|
21
|
+
value = true
|
22
|
+
end
|
16
23
|
else
|
17
24
|
value = args[name.to_sym] unless args.dig(name.to_sym).nil?
|
18
25
|
end
|
@@ -10,7 +10,6 @@ module Avo
|
|
10
10
|
include ActionView::Helpers::UrlHelper
|
11
11
|
include Avo::Fields::FieldExtensions::VisibleInDifferentViews
|
12
12
|
|
13
|
-
include Avo::Concerns::HandlesFieldArgs
|
14
13
|
include Avo::Concerns::HasHTMLAttributes
|
15
14
|
include Avo::Fields::Concerns::IsRequired
|
16
15
|
include Avo::Fields::Concerns::IsReadonly
|
@@ -60,14 +60,13 @@ module Avo
|
|
60
60
|
self.class.decode_filters params[PARAM_KEY]
|
61
61
|
end
|
62
62
|
|
63
|
-
def visible_in_view(resource: nil,
|
63
|
+
def visible_in_view(resource: nil, parent_resource: nil)
|
64
64
|
return true if visible.blank?
|
65
65
|
|
66
66
|
# Run the visible block if available
|
67
67
|
Avo::Hosts::VisibilityHost.new(
|
68
68
|
block: visible,
|
69
69
|
params: params,
|
70
|
-
parent_model: parent_model,
|
71
70
|
parent_resource: parent_resource,
|
72
71
|
resource: resource,
|
73
72
|
arguments: arguments
|
@@ -119,7 +119,7 @@ module Avo
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def authorize_action(action, **args)
|
122
|
-
self.class.authorize_action(user, record, action, policy_class: policy_class, **args)
|
122
|
+
self.class.authorize_action(user, args[:record] || record, action, policy_class: policy_class, **args)
|
123
123
|
end
|
124
124
|
|
125
125
|
def apply_policy(model)
|
@@ -131,7 +131,7 @@ module Avo
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def has_method?(method, **args)
|
134
|
-
defined_methods(record, **args).include? method.to_sym
|
134
|
+
defined_methods(args[:record] || record, **args).include? method.to_sym
|
135
135
|
end
|
136
136
|
end
|
137
137
|
end
|
data/lib/avo/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
nn:
|
2
|
+
pagy:
|
3
|
+
item_name:
|
4
|
+
one: "resultat"
|
5
|
+
other: "resultat"
|
6
|
+
nav:
|
7
|
+
prev: "‹ Førre"
|
8
|
+
next: "Neste ›"
|
9
|
+
gap: "…"
|
10
|
+
info:
|
11
|
+
no_items: "Ingen %{item_name} funne"
|
12
|
+
single_page: "Viser <b>%{count}</b> %{item_name}"
|
13
|
+
multiple_pages: "Viser %{item_name} <b>%{from}-%{to}</b> av totalt <b>%{count}</b>"
|
14
|
+
combo_nav_js: "<label>Side %{page_input} av %{pages}</label>"
|
15
|
+
items_selector_js: "<label>Vis %{items_input} %{item_name} per side</label>"
|