avo 2.16.0 → 2.16.1.pre.1.nativefields

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/Gemfile.lock +78 -86
  4. data/app/components/avo/base_component.rb +7 -1
  5. data/app/components/avo/field_wrapper_component.html.erb +40 -0
  6. data/app/components/avo/field_wrapper_component.rb +102 -0
  7. data/app/components/avo/fields/badge_field/show_component.html.erb +1 -1
  8. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +3 -3
  9. data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
  10. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  11. data/app/components/avo/fields/boolean_field/show_component.html.erb +1 -1
  12. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/fields/boolean_group_field/show_component.html.erb +1 -1
  14. data/app/components/avo/fields/code_field/edit_component.html.erb +2 -2
  15. data/app/components/avo/fields/code_field/show_component.html.erb +2 -2
  16. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -1
  17. data/app/components/avo/fields/country_field/show_component.html.erb +1 -1
  18. data/app/components/avo/fields/date_field/edit_component.html.erb +1 -1
  19. data/app/components/avo/fields/date_field/show_component.html.erb +1 -1
  20. data/app/components/avo/fields/date_time_field/edit_component.html.erb +1 -1
  21. data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -1
  22. data/app/components/avo/fields/edit_component.rb +22 -4
  23. data/app/components/avo/fields/external_image_field/edit_component.html.erb +1 -1
  24. data/app/components/avo/fields/external_image_field/show_component.html.erb +1 -1
  25. data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
  26. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  27. data/app/components/avo/fields/files_field/edit_component.html.erb +1 -1
  28. data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
  29. data/app/components/avo/fields/gravatar_field/show_component.html.erb +1 -1
  30. data/app/components/avo/fields/id_field/edit_component.html.erb +1 -1
  31. data/app/components/avo/fields/id_field/show_component.html.erb +1 -1
  32. data/app/components/avo/fields/key_value_field/edit_component.html.erb +2 -2
  33. data/app/components/avo/fields/key_value_field/show_component.html.erb +1 -1
  34. data/app/components/avo/fields/markdown_field/edit_component.html.erb +2 -2
  35. data/app/components/avo/fields/markdown_field/show_component.html.erb +1 -1
  36. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -1
  37. data/app/components/avo/fields/number_field/show_component.html.erb +1 -1
  38. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -1
  39. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -1
  40. data/app/components/avo/fields/progress_bar_field/show_component.html.erb +1 -1
  41. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -2
  42. data/app/components/avo/fields/select_field/show_component.html.erb +1 -1
  43. data/app/components/avo/fields/show_component.rb +36 -1
  44. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  45. data/app/components/avo/fields/status_field/show_component.html.erb +1 -1
  46. data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -5
  47. data/app/components/avo/fields/tags_field/show_component.html.erb +1 -1
  48. data/app/components/avo/fields/text_field/edit_component.html.erb +2 -2
  49. data/app/components/avo/fields/text_field/show_component.html.erb +1 -1
  50. data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -1
  51. data/app/components/avo/fields/textarea_field/show_component.html.erb +1 -1
  52. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
  53. data/app/components/avo/fields/trix_field/edit_component.rb +19 -1
  54. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  55. data/app/components/avo/index/resource_controls_component.rb +1 -0
  56. data/app/components/avo/views/resource_edit_component.html.erb +28 -26
  57. data/app/controllers/avo/application_controller.rb +8 -1
  58. data/app/controllers/avo/base_controller.rb +5 -5
  59. data/app/helpers/avo/application_helper.rb +31 -3
  60. data/app/helpers/avo/resources_helper.rb +4 -8
  61. data/app/javascript/js/controllers/action_controller.js +3 -1
  62. data/app/javascript/js/controllers/fields/date_field_controller.js +21 -1
  63. data/app/javascript/js/controllers/search_controller.js +122 -118
  64. data/avo.gemspec +1 -1
  65. data/config/master.key +1 -0
  66. data/lib/avo/base_resource.rb +5 -3
  67. data/lib/avo/concerns/fetches_things.rb +2 -0
  68. data/lib/avo/fields/base_field.rb +4 -0
  69. data/lib/avo/fields/select_field.rb +1 -0
  70. data/lib/avo/menu/menu.rb +2 -0
  71. data/lib/avo/services/authorization_service.rb +24 -20
  72. data/lib/avo/version.rb +1 -1
  73. data/lib/generators/avo/templates/field/components/edit_component.html.erb.tt +1 -1
  74. data/lib/generators/avo/templates/field/components/show_component.html.erb.tt +1 -1
  75. data/public/avo-assets/avo.base.css +26 -8
  76. data/public/avo-assets/avo.base.js +79 -79
  77. data/public/avo-assets/avo.base.js.map +3 -3
  78. metadata +8 -11
  79. data/app/components/avo/common_field_wrapper_component.html.erb +0 -26
  80. data/app/components/avo/common_field_wrapper_component.rb +0 -46
  81. data/app/components/avo/edit/field_wrapper_component.html.erb +0 -11
  82. data/app/components/avo/edit/field_wrapper_component.rb +0 -21
  83. data/app/components/avo/show/field_wrapper_component.html.erb +0 -9
  84. data/app/components/avo/show/field_wrapper_component.rb +0 -12
@@ -21,6 +21,10 @@ export default class extends Controller {
21
21
  disableMobile: Boolean,
22
22
  }
23
23
 
24
+ flatpickrInstance;
25
+
26
+ cachedInitialValue;
27
+
24
28
  get browserZone() {
25
29
  const time = DateTime.local()
26
30
 
@@ -59,6 +63,10 @@ export default class extends Controller {
59
63
  }
60
64
 
61
65
  connect() {
66
+ // Cache the initial value so we can fill it back on disconnection.
67
+ // We do that so the JS parser will continue to work when the user hits the back button to return on this page.
68
+ this.cacheInitialValue()
69
+
62
70
  if (this.isOnShow || this.isOnIndex) {
63
71
  this.initShow()
64
72
  } else if (this.isOnEdit) {
@@ -66,6 +74,18 @@ export default class extends Controller {
66
74
  }
67
75
  }
68
76
 
77
+ disconnect() {
78
+ if (this.isOnShow || this.isOnIndex) {
79
+ this.context.element.innerText = this.cachedInitialValue
80
+ } else if (this.isOnEdit) {
81
+ if (this.flatpickrInstance) this.flatpickrInstance.destroy()
82
+ }
83
+ }
84
+
85
+ cacheInitialValue() {
86
+ this.cachedInitialValue = this.initialValue
87
+ }
88
+
69
89
  // Turns the value in the controller wrapper into the timezone of the browser
70
90
  initShow() {
71
91
  let value = this.parsedValue
@@ -115,7 +135,7 @@ export default class extends Controller {
115
135
  options.defaultDate = universalTimestamp(this.initialValue)
116
136
  }
117
137
 
118
- flatpickr(this.fakeInputTarget, options)
138
+ this.flatpickrInstance = flatpickr(this.fakeInputTarget, options)
119
139
 
120
140
  if (this.enableTimeValue) {
121
141
  this.updateRealInput(this.parsedValue.setZone(this.displayTimezone).toISO())
@@ -25,6 +25,8 @@ export default class extends Controller {
25
25
 
26
26
  debouncedFetch = debouncePromise(fetch, this.searchDebounce);
27
27
 
28
+ destroyMethod;
29
+
28
30
  get dataset() {
29
31
  return this.autocompleteTarget.dataset
30
32
  }
@@ -56,97 +58,52 @@ export default class extends Controller {
56
58
  return this.dataset.searchResource === 'global'
57
59
  }
58
60
 
59
- searchUrl(query) {
60
- const url = URI()
61
-
62
- return url.segment(this.searchSegments()).search(this.searchParams(query)).toString()
63
- }
64
-
65
- searchSegments() {
66
- let segments = [
67
- window.Avo.configuration.root_path,
68
- 'avo_api',
69
- this.dataset.searchResource,
70
- 'search',
71
- ]
72
-
73
- if (this.isGlobalSearch) {
74
- segments = [window.Avo.configuration.root_path, 'avo_api', 'search']
75
- }
76
-
77
- return segments
78
- }
79
-
80
- searchParams(query) {
81
- let params = {
82
- q: query,
83
- global: false,
84
- }
85
-
86
- if (this.isGlobalSearch) {
87
- params.global = true
88
- }
61
+ connect() {
62
+ const that = this
89
63
 
90
- if (this.isBelongsToSearch || this.isHasManySearch) {
91
- params = this.addAssociationParams(params)
92
- params = this.addReflectionParams(params)
64
+ this.buttonTarget.onclick = () => this.showSearchPanel()
93
65
 
94
- if (this.isBelongsToSearch) {
95
- params = {
96
- ...params,
97
- // eslint-disable-next-line camelcase
98
- via_parent_resource_id: this.dataset.viaParentResourceId,
99
- // eslint-disable-next-line camelcase
100
- via_parent_resource_class: this.dataset.viaParentResourceClass,
101
- // eslint-disable-next-line camelcase
102
- via_relation: this.dataset.viaRelation,
103
- }
66
+ this.clearValueTargets.forEach((target) => {
67
+ if (target.getAttribute('value') && this.hasClearButtonTarget) {
68
+ this.clearButtonTarget.classList.remove('hidden')
104
69
  }
105
- }
106
-
107
- return params
108
- }
70
+ })
109
71
 
110
- addAssociationParams(params) {
111
- params = {
112
- ...params,
113
- // eslint-disable-next-line camelcase
114
- via_association: this.dataset.viaAssociation,
115
- // eslint-disable-next-line camelcase
116
- via_association_id: this.dataset.viaAssociationId,
72
+ if (this.isGlobalSearch) {
73
+ Mousetrap.bind(['command+k', 'ctrl+k'], () => this.showSearchPanel())
117
74
  }
118
75
 
119
- return params
120
- }
121
-
122
- addReflectionParams(params) {
123
- params = {
124
- ...params,
125
- // eslint-disable-next-line camelcase
126
- via_reflection_class: this.dataset.viaReflectionClass,
127
- // eslint-disable-next-line camelcase
128
- via_reflection_id: this.dataset.viaReflectionId,
129
- }
76
+ autocomplete({
77
+ container: this.autocompleteTarget,
78
+ placeholder: this.translationKeys.placeholder,
79
+ translations: {
80
+ detachedCancelButtonText: this.translationKeys.cancel_button,
81
+ },
82
+ autoFocus: true,
83
+ openOnFocus: true,
84
+ detachedMediaQuery: '',
85
+ getSources: ({ query }) => {
86
+ document.body.classList.add('search-loading')
87
+ const endpoint = that.searchUrl(query)
130
88
 
131
- return params
132
- }
89
+ return that
90
+ .debouncedFetch(endpoint)
91
+ .then((response) => {
92
+ document.body.classList.remove('search-loading')
133
93
 
134
- handleOnSelect({ item }) {
135
- if (this.isBelongsToSearch) {
136
- this.updateFieldAttribute(this.hiddenIdTarget, 'value', item._id)
137
- this.updateFieldAttribute(this.buttonTarget, 'value', item._label)
94
+ return response.json()
95
+ })
96
+ .then((data) => Object.keys(data).map((resourceName) => that.addSource(resourceName, data[resourceName])))
97
+ },
98
+ })
138
99
 
139
- document.querySelector('.aa-DetachedOverlay').remove()
100
+ // document.addEventListener('turbo:before-render', destroy)
101
+ // this.destroyMethod = destroy
140
102
 
141
- if (this.hasClearButtonTarget) {
142
- this.clearButtonTarget.classList.remove('hidden')
143
- }
144
- } else {
145
- Turbo.visit(item._url, { action: 'advance' })
103
+ // When using search for belongs-to
104
+ if (this.buttonTarget.dataset.shouldBeDisabled !== 'true') {
105
+ this.buttonTarget.removeAttribute('disabled')
146
106
  }
147
-
148
- // On searchable belongs to the class `aa-Detached` remains on the body making it unscrollable
149
- document.body.classList.remove('aa-Detached')
150
107
  }
151
108
 
152
109
  addSource(resourceName, data) {
@@ -221,59 +178,106 @@ export default class extends Controller {
221
178
  }
222
179
  }
223
180
 
224
- showSearchPanel() {
225
- this.autocompleteTarget.querySelector('button').click()
181
+ handleOnSelect({ item }) {
182
+ if (this.isBelongsToSearch) {
183
+ this.updateFieldAttribute(this.hiddenIdTarget, 'value', item._id)
184
+ this.updateFieldAttribute(this.buttonTarget, 'value', item._label)
185
+
186
+ document.querySelector('.aa-DetachedOverlay').remove()
187
+
188
+ if (this.hasClearButtonTarget) {
189
+ this.clearButtonTarget.classList.remove('hidden')
190
+ }
191
+ } else {
192
+ Turbo.visit(item._url, { action: 'advance' })
193
+ }
194
+
195
+ // On searchable belongs to the class `aa-Detached` remains on the body making it unscrollable
196
+ document.body.classList.remove('aa-Detached')
226
197
  }
227
198
 
228
- clearValue() {
229
- this.clearValueTargets.map((t) => this.updateFieldAttribute(t, 'value', ''))
230
- this.clearButtonTarget.classList.add('hidden')
199
+ searchUrl(query) {
200
+ const url = URI()
201
+
202
+ return url.segment(this.searchSegments()).search(this.searchParams(query)).toString()
231
203
  }
232
204
 
233
- connect() {
234
- const that = this
205
+ searchSegments() {
206
+ let segments = [
207
+ window.Avo.configuration.root_path,
208
+ 'avo_api',
209
+ this.dataset.searchResource,
210
+ 'search',
211
+ ]
235
212
 
236
- this.buttonTarget.onclick = () => this.showSearchPanel()
213
+ if (this.isGlobalSearch) {
214
+ segments = [window.Avo.configuration.root_path, 'avo_api', 'search']
215
+ }
237
216
 
238
- this.clearValueTargets.forEach((target) => {
239
- if (target.getAttribute('value') && this.hasClearButtonTarget) {
240
- this.clearButtonTarget.classList.remove('hidden')
241
- }
242
- })
217
+ return segments
218
+ }
219
+
220
+ searchParams(query) {
221
+ let params = {
222
+ q: query,
223
+ global: false,
224
+ }
243
225
 
244
226
  if (this.isGlobalSearch) {
245
- Mousetrap.bind(['command+k', 'ctrl+k'], () => this.showSearchPanel())
227
+ params.global = true
246
228
  }
247
229
 
248
- const { destroy } = autocomplete({
249
- container: this.autocompleteTarget,
250
- placeholder: this.translationKeys.placeholder,
251
- translations: {
252
- detachedCancelButtonText: this.translationKeys.cancel_button,
253
- },
254
- openOnFocus: true,
255
- detachedMediaQuery: '',
256
- getSources: ({ query }) => {
257
- document.body.classList.add('search-loading')
258
- const endpoint = that.searchUrl(query)
230
+ if (this.isBelongsToSearch || this.isHasManySearch) {
231
+ params = this.addAssociationParams(params)
232
+ params = this.addReflectionParams(params)
259
233
 
260
- return that
261
- .debouncedFetch(endpoint)
262
- .then((response) => {
263
- document.body.classList.remove('search-loading')
234
+ if (this.isBelongsToSearch) {
235
+ params = {
236
+ ...params,
237
+ // eslint-disable-next-line camelcase
238
+ via_parent_resource_id: this.dataset.viaParentResourceId,
239
+ // eslint-disable-next-line camelcase
240
+ via_parent_resource_class: this.dataset.viaParentResourceClass,
241
+ // eslint-disable-next-line camelcase
242
+ via_relation: this.dataset.viaRelation,
243
+ }
244
+ }
245
+ }
264
246
 
265
- return response.json()
266
- })
267
- .then((data) => Object.keys(data).map((resourceName) => that.addSource(resourceName, data[resourceName])))
268
- },
269
- })
247
+ return params
248
+ }
270
249
 
271
- document.addEventListener('turbo:before-render', destroy)
250
+ addAssociationParams(params) {
251
+ params = {
252
+ ...params,
253
+ // eslint-disable-next-line camelcase
254
+ via_association: this.dataset.viaAssociation,
255
+ // eslint-disable-next-line camelcase
256
+ via_association_id: this.dataset.viaAssociationId,
257
+ }
272
258
 
273
- // When using search for belongs-to
274
- if (this.buttonTarget.dataset.shouldBeDisabled !== 'true') {
275
- this.buttonTarget.removeAttribute('disabled')
259
+ return params
260
+ }
261
+
262
+ addReflectionParams(params) {
263
+ params = {
264
+ ...params,
265
+ // eslint-disable-next-line camelcase
266
+ via_reflection_class: this.dataset.viaReflectionClass,
267
+ // eslint-disable-next-line camelcase
268
+ via_reflection_id: this.dataset.viaReflectionId,
276
269
  }
270
+
271
+ return params
272
+ }
273
+
274
+ showSearchPanel() {
275
+ this.autocompleteTarget.querySelector('button').click()
276
+ }
277
+
278
+ clearValue() {
279
+ this.clearValueTargets.map((target) => this.updateFieldAttribute(target, 'value', ''))
280
+ this.clearButtonTarget.classList.add('hidden')
277
281
  }
278
282
 
279
283
  // Private
data/avo.gemspec CHANGED
@@ -41,7 +41,7 @@ Gem::Specification.new do |spec|
41
41
  spec.add_dependency "active_link_to"
42
42
  spec.add_dependency "image_processing"
43
43
  spec.add_dependency "view_component", "2.60"
44
- spec.add_dependency "hotwire-rails"
44
+ spec.add_dependency "turbo-rails"
45
45
  spec.add_dependency "addressable"
46
46
  spec.add_dependency "meta-tags"
47
47
  spec.add_dependency "breadcrumbs_on_rails"
data/config/master.key ADDED
@@ -0,0 +1 @@
1
+ 2aeb23d82b909d9c6b5abb62f7058c2a
@@ -30,6 +30,7 @@ module Avo
30
30
  class_attribute :search_query, default: nil
31
31
  class_attribute :search_query_help, default: ""
32
32
  class_attribute :includes, default: []
33
+ class_attribute :authorization_policy
33
34
  class_attribute :translation_key
34
35
  class_attribute :default_view_type, default: :table
35
36
  class_attribute :devise_password_optional, default: false
@@ -92,7 +93,7 @@ module Avo
92
93
  end
93
94
 
94
95
  def authorization
95
- Avo::Services::AuthorizationService.new Avo::App.current_user
96
+ Avo::Services::AuthorizationService.new Avo::App.current_user, model_class, policy_class: authorization_policy
96
97
  end
97
98
 
98
99
  def order_actions
@@ -285,8 +286,9 @@ module Avo
285
286
  model
286
287
  end
287
288
 
288
- def authorization
289
- Avo::Services::AuthorizationService.new(user, model || model_class)
289
+ def authorization(user: nil)
290
+ current_user = user || Avo::App.current_user
291
+ Avo::Services::AuthorizationService.new(current_user, model || model_class, policy_class: authorization_policy)
290
292
  end
291
293
 
292
294
  def file_hash
@@ -48,9 +48,11 @@ module Avo
48
48
  end
49
49
 
50
50
  # Returns the Avo resource by singular snake_cased name
51
+ # From all the resources that use the same model_class, it will fetch the first one in alphabetical order
51
52
  #
52
53
  # get_resource_by_name('User') => UserResource
53
54
  # get_resource_by_name(User) => UserResource
55
+
54
56
  def get_resource_by_model_name(klass)
55
57
  # Fetch the mappings imposed by the user.
56
58
  # If they are present, use those ones.
@@ -76,6 +76,8 @@ module Avo
76
76
  @as_description = args[:as_description] || false
77
77
  @index_text_align = args[:index_text_align] || :left
78
78
  @html = args[:html] || nil
79
+ @view = args[:view] || nil
80
+ @value = args[:value] || nil
79
81
 
80
82
  @args = args
81
83
 
@@ -155,6 +157,8 @@ module Avo
155
157
  end
156
158
 
157
159
  def value(property = nil)
160
+ return @value if @value.present?
161
+
158
162
  property ||= id
159
163
 
160
164
  # Get model value
@@ -30,6 +30,7 @@ module Avo
30
30
  if display_value
31
31
  options.invert
32
32
  else
33
+ # We need to use the label attribute as the option value because Rails casts it like that
33
34
  options.map { |label, value| [label, label] }.to_h
34
35
  end
35
36
  elsif display_value
data/lib/avo/menu/menu.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  class Avo::Menu::Menu < OpenStruct
2
+
3
+
2
4
  end
@@ -5,13 +5,14 @@ module Avo
5
5
  attr_accessor :record
6
6
 
7
7
  class << self
8
- def authorize(user, record, action, **args)
8
+ def authorize(user, record, action, policy_class: nil, **args)
9
9
  return true if skip_authorization
10
10
  return true if user.nil?
11
11
 
12
+ policy_class ||= Pundit.policy(user, record)&.class
12
13
  begin
13
- if Pundit.policy user, record
14
- Pundit.authorize user, record, action
14
+ if policy_class&.new(user, record)
15
+ Pundit.authorize user, record, action, policy_class: policy_class
15
16
  end
16
17
 
17
18
  true
@@ -28,7 +29,7 @@ module Avo
28
29
  end
29
30
  end
30
31
 
31
- def authorize_action(user, record, action, **args)
32
+ def authorize_action(user, record, action, policy_class: nil, **args)
32
33
  action = Avo.configuration.authorization_methods.stringify_keys[action.to_s] || action
33
34
 
34
35
  # If no action passed we should raise error if the user wants that.
@@ -41,16 +42,18 @@ module Avo
41
42
 
42
43
  # Add the question mark if it's missing
43
44
  action = "#{action}?" unless action.end_with? "?"
44
-
45
- authorize user, record, action, **args
45
+ authorize(user, record, action, policy_class: policy_class, **args)
46
46
  end
47
47
 
48
- def apply_policy(user, model)
49
- return model if skip_authorization
50
- return model if user.nil?
48
+ def apply_policy(user, model, policy_class: nil)
49
+ return model if skip_authorization || user.nil?
51
50
 
52
51
  begin
53
- Pundit.policy_scope! user, model
52
+ if policy_class
53
+ policy_class::Scope.new(user, model).resolve
54
+ else
55
+ Pundit.policy_scope! user, model
56
+ end
54
57
  rescue Pundit::NotDefinedError => e
55
58
  return model unless Avo.configuration.raise_error_on_missing_policy
56
59
 
@@ -68,12 +71,12 @@ module Avo
68
71
  end.to_h
69
72
  end
70
73
 
71
- def get_policy(user, record)
72
- Pundit.policy user, record
73
- end
74
+ def defined_methods(user, record, policy_class: nil, **args)
75
+ return Pundit.policy!(user, record).methods if policy_class.nil?
74
76
 
75
- def defined_methods(user, record, **args)
76
- Pundit.policy!(user, record).methods
77
+ # I'm aware this will not raise a Pundit error.
78
+ # Should the policy not exist, it will however raise an uninitialized constant error, which is probably what we want when specifying a custom policy
79
+ policy_class.new(user, record).methods
77
80
  rescue Pundit::NotDefinedError => e
78
81
  return [] unless Avo.configuration.raise_error_on_missing_policy
79
82
 
@@ -87,13 +90,14 @@ module Avo
87
90
  end
88
91
  end
89
92
 
90
- def initialize(user = nil, record = nil)
93
+ def initialize(user = nil, record = nil, policy_class: nil)
91
94
  @user = user
92
95
  @record = record
96
+ @policy_class = policy_class || Pundit.policy(user, record)&.class
93
97
  end
94
98
 
95
99
  def authorize(action, **args)
96
- self.class.authorize(user, record, action, **args)
100
+ self.class.authorize(user, record, action, policy_class: @policy_class, **args)
97
101
  end
98
102
 
99
103
  def set_record(record)
@@ -109,15 +113,15 @@ module Avo
109
113
  end
110
114
 
111
115
  def authorize_action(action, **args)
112
- self.class.authorize_action(user, record, action, **args)
116
+ self.class.authorize_action(user, record, action, policy_class: @policy_class, **args)
113
117
  end
114
118
 
115
119
  def apply_policy(model)
116
- self.class.apply_policy(user, model)
120
+ self.class.apply_policy(user, model, policy_class: @policy_class)
117
121
  end
118
122
 
119
123
  def defined_methods(model, **args)
120
- self.class.defined_methods(user, model, **args)
124
+ self.class.defined_methods(user, model, policy_class: @policy_class, **args)
121
125
  end
122
126
 
123
127
  def has_method?(method, **args)
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.16.0" unless const_defined?(:VERSION)
2
+ VERSION = "2.16.1.pre.1.nativefields" unless const_defined?(:VERSION)
3
3
  end
@@ -1,4 +1,4 @@
1
- <%%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
1
+ <%%= field_wrapper **field_wrapper_args do %>
2
2
  <%%= @form.text_field @field.id,
3
3
  class: classes("w-full"),
4
4
  placeholder: @field.placeholder,
@@ -1,3 +1,3 @@
1
- <%%= show_field_wrapper field: @field, resource: @resource, index: @index do %>
1
+ <%%= field_wrapper **field_wrapper_args do %>
2
2
  <%%= @field.value %>
3
3
  <%% end %>
@@ -6445,6 +6445,11 @@ trix-toolbar .trix-button-group:not(:first-child){
6445
6445
  margin-right:1.5rem
6446
6446
  }
6447
6447
 
6448
+ .-mx-4{
6449
+ margin-left:-1rem;
6450
+ margin-right:-1rem
6451
+ }
6452
+
6448
6453
  .mt-3{
6449
6454
  margin-top:0.75rem
6450
6455
  }
@@ -6573,10 +6578,6 @@ trix-toolbar .trix-button-group:not(:first-child){
6573
6578
  margin-left:auto
6574
6579
  }
6575
6580
 
6576
- .mt-12{
6577
- margin-top:3rem
6578
- }
6579
-
6580
6581
  .-mb-2{
6581
6582
  margin-bottom:-0.5rem
6582
6583
  }
@@ -6585,6 +6586,10 @@ trix-toolbar .trix-button-group:not(:first-child){
6585
6586
  margin-top:1.5rem
6586
6587
  }
6587
6588
 
6589
+ .mt-12{
6590
+ margin-top:3rem
6591
+ }
6592
+
6588
6593
  .mr-px{
6589
6594
  margin-right:1px
6590
6595
  }
@@ -6865,6 +6870,10 @@ trix-toolbar .trix-button-group:not(:first-child){
6865
6870
  flex-grow:0
6866
6871
  }
6867
6872
 
6873
+ .flex-grow{
6874
+ flex-grow:1
6875
+ }
6876
+
6868
6877
  .-translate-x-1\/2{
6869
6878
  --tw-translate-x:-50%;
6870
6879
  transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
@@ -8076,6 +8085,10 @@ trix-toolbar .trix-button-group:not(:first-child){
8076
8085
  opacity:1
8077
8086
  }
8078
8087
 
8088
+ .opacity-80{
8089
+ opacity:0.8
8090
+ }
8091
+
8079
8092
  .shadow-panel{
8080
8093
  --tw-shadow:0px 4px 8px rgba(0, 0, 0, 0.04), 0px 0px 2px rgba(0, 0, 0, 0.06), 0px 0px 1px rgba(0, 0, 0, 0.04);
8081
8094
  --tw-shadow-colored:0px 4px 8px var(--tw-shadow-color), 0px 0px 2px var(--tw-shadow-color), 0px 0px 1px var(--tw-shadow-color);
@@ -8120,6 +8133,11 @@ trix-toolbar .trix-button-group:not(:first-child){
8120
8133
  filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
8121
8134
  }
8122
8135
 
8136
+ .sepia{
8137
+ --tw-sepia:sepia(100%);
8138
+ filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
8139
+ }
8140
+
8123
8141
  .filter{
8124
8142
  filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
8125
8143
  }
@@ -9580,13 +9598,13 @@ trix-editor {
9580
9598
  padding-right:1.5rem
9581
9599
  }
9582
9600
 
9583
- .md\:pb-0{
9584
- padding-bottom:0px
9585
- }
9586
-
9587
9601
  .md\:pt-0{
9588
9602
  padding-top:0px
9589
9603
  }
9604
+
9605
+ .md\:pb-0{
9606
+ padding-bottom:0px
9607
+ }
9590
9608
  }
9591
9609
 
9592
9610
  @media (min-width: 1024px){