avo 2.35.0 → 2.36.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +72 -71
  3. data/app/components/avo/fields/area_field/edit_component.html.erb +1 -1
  4. data/app/components/avo/fields/belongs_to_field/edit_component.rb +2 -2
  5. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -0
  6. data/app/components/avo/fields/code_field/edit_component.html.erb +1 -0
  7. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -0
  8. data/app/components/avo/fields/markdown_field/edit_component.html.erb +1 -0
  9. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -0
  10. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -0
  11. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -0
  12. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
  14. data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -0
  15. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -0
  16. data/app/components/avo/sidebar/item_switcher_component.html.erb +3 -3
  17. data/app/components/avo/sidebar/link_component.html.erb +2 -0
  18. data/app/components/avo/sidebar/link_component.rb +4 -2
  19. data/app/components/avo/tab_switcher_component.rb +19 -22
  20. data/app/components/avo/views/resource_edit_component.html.erb +1 -1
  21. data/app/components/avo/views/resource_edit_component.rb +1 -1
  22. data/app/controllers/avo/base_controller.rb +11 -3
  23. data/app/controllers/avo/search_controller.rb +5 -0
  24. data/db/factories.rb +2 -1
  25. data/lib/avo/base_resource.rb +7 -4
  26. data/lib/avo/concerns/has_fields.rb +6 -16
  27. data/lib/avo/execution_context.rb +43 -0
  28. data/lib/avo/fields/base_field.rb +17 -5
  29. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +1 -1
  30. data/lib/avo/fields/location_field.rb +8 -0
  31. data/lib/avo/items_holder.rb +15 -1
  32. data/lib/avo/licensing/h_q.rb +5 -1
  33. data/lib/avo/licensing/license.rb +1 -1
  34. data/lib/avo/licensing/license_manager.rb +1 -1
  35. data/lib/avo/licensing/{null_license.rb → nil_license.rb} +1 -1
  36. data/lib/avo/tab.rb +4 -0
  37. data/lib/avo/version.rb +1 -1
  38. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5589a9a6b15cb0d2c1eb9371516e20cbbe381f2a200229ddbcaa5403bcae5df
4
- data.tar.gz: 9eea597e445b850adcbb069f36582550c8de44394d6cd203ad63fe95ac1bcf12
3
+ metadata.gz: 6cfa65ccbc3c3192f2daa5822ca180639c84bac36bbc8f4a05e608fb73525c20
4
+ data.tar.gz: 5a4846161d7aee464404f83e57da20c9efcc5624a54433fba1cf2031240d0355
5
5
  SHA512:
6
- metadata.gz: f958930dd25efc24c12b04aa9f7986418ea4c230e6e545adce927b664d5861ef97ee3f1cb20a703db0b6e4fa0497d4edd4407aade748b30c345df82f9d1f490e
7
- data.tar.gz: bb18b8e42aaac748f63da9a53ce2f7a42f65b4254aea02f7c56e9ad4ff5919c9a9340b9cadd798bd99d7f41c780cdf2c51d734b1e4f18109825d2314391fc9cc
6
+ metadata.gz: 82f1ef921487a6cfb94214ea861344dd85445dba19c5fa6cb63073da50fb547ef6aaae7db40ecb533972f6cd4bfa220ff54f2188e5b4ce39c7238a4e0ecaaf20
7
+ data.tar.gz: 031be9135507031c5d203dde3aa1429e27f7faf0e5b80f8fc201c3e4853ec758b705121c27756189a38b70cc0bed107023083de58c3a2fda2194e0f7d2ece363
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.35.0)
4
+ avo (2.36.1)
5
5
  actionview (>= 6.0)
6
6
  active_link_to
7
7
  activerecord (>= 6.0)
@@ -19,40 +19,40 @@ PATH
19
19
  GEM
20
20
  remote: https://rubygems.org/
21
21
  specs:
22
- actioncable (6.1.7.3)
23
- actionpack (= 6.1.7.3)
24
- activesupport (= 6.1.7.3)
22
+ actioncable (6.1.7.4)
23
+ actionpack (= 6.1.7.4)
24
+ activesupport (= 6.1.7.4)
25
25
  nio4r (~> 2.0)
26
26
  websocket-driver (>= 0.6.1)
27
- actionmailbox (6.1.7.3)
28
- actionpack (= 6.1.7.3)
29
- activejob (= 6.1.7.3)
30
- activerecord (= 6.1.7.3)
31
- activestorage (= 6.1.7.3)
32
- activesupport (= 6.1.7.3)
27
+ actionmailbox (6.1.7.4)
28
+ actionpack (= 6.1.7.4)
29
+ activejob (= 6.1.7.4)
30
+ activerecord (= 6.1.7.4)
31
+ activestorage (= 6.1.7.4)
32
+ activesupport (= 6.1.7.4)
33
33
  mail (>= 2.7.1)
34
- actionmailer (6.1.7.3)
35
- actionpack (= 6.1.7.3)
36
- actionview (= 6.1.7.3)
37
- activejob (= 6.1.7.3)
38
- activesupport (= 6.1.7.3)
34
+ actionmailer (6.1.7.4)
35
+ actionpack (= 6.1.7.4)
36
+ actionview (= 6.1.7.4)
37
+ activejob (= 6.1.7.4)
38
+ activesupport (= 6.1.7.4)
39
39
  mail (~> 2.5, >= 2.5.4)
40
40
  rails-dom-testing (~> 2.0)
41
- actionpack (6.1.7.3)
42
- actionview (= 6.1.7.3)
43
- activesupport (= 6.1.7.3)
41
+ actionpack (6.1.7.4)
42
+ actionview (= 6.1.7.4)
43
+ activesupport (= 6.1.7.4)
44
44
  rack (~> 2.0, >= 2.0.9)
45
45
  rack-test (>= 0.6.3)
46
46
  rails-dom-testing (~> 2.0)
47
47
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
48
- actiontext (6.1.7.3)
49
- actionpack (= 6.1.7.3)
50
- activerecord (= 6.1.7.3)
51
- activestorage (= 6.1.7.3)
52
- activesupport (= 6.1.7.3)
48
+ actiontext (6.1.7.4)
49
+ actionpack (= 6.1.7.4)
50
+ activerecord (= 6.1.7.4)
51
+ activestorage (= 6.1.7.4)
52
+ activesupport (= 6.1.7.4)
53
53
  nokogiri (>= 1.8.5)
54
- actionview (6.1.7.3)
55
- activesupport (= 6.1.7.3)
54
+ actionview (6.1.7.4)
55
+ activesupport (= 6.1.7.4)
56
56
  builder (~> 3.1)
57
57
  erubi (~> 1.4)
58
58
  rails-dom-testing (~> 2.0)
@@ -62,22 +62,22 @@ GEM
62
62
  addressable
63
63
  active_median (0.3.3)
64
64
  activesupport (>= 5.2)
65
- activejob (6.1.7.3)
66
- activesupport (= 6.1.7.3)
65
+ activejob (6.1.7.4)
66
+ activesupport (= 6.1.7.4)
67
67
  globalid (>= 0.3.6)
68
- activemodel (6.1.7.3)
69
- activesupport (= 6.1.7.3)
70
- activerecord (6.1.7.3)
71
- activemodel (= 6.1.7.3)
72
- activesupport (= 6.1.7.3)
73
- activestorage (6.1.7.3)
74
- actionpack (= 6.1.7.3)
75
- activejob (= 6.1.7.3)
76
- activerecord (= 6.1.7.3)
77
- activesupport (= 6.1.7.3)
68
+ activemodel (6.1.7.4)
69
+ activesupport (= 6.1.7.4)
70
+ activerecord (6.1.7.4)
71
+ activemodel (= 6.1.7.4)
72
+ activesupport (= 6.1.7.4)
73
+ activestorage (6.1.7.4)
74
+ actionpack (= 6.1.7.4)
75
+ activejob (= 6.1.7.4)
76
+ activerecord (= 6.1.7.4)
77
+ activesupport (= 6.1.7.4)
78
78
  marcel (~> 1.0)
79
79
  mini_mime (>= 1.1.0)
80
- activesupport (6.1.7.3)
80
+ activesupport (6.1.7.4)
81
81
  concurrent-ruby (~> 1.0, >= 1.0.2)
82
82
  i18n (>= 1.6, < 2)
83
83
  minitest (>= 5.1)
@@ -204,7 +204,7 @@ GEM
204
204
  httparty (0.21.0)
205
205
  mini_mime (>= 1.0.0)
206
206
  multi_xml (>= 0.5.2)
207
- i18n (1.12.0)
207
+ i18n (1.14.1)
208
208
  concurrent-ruby (~> 1.0)
209
209
  i18n-tasks (1.0.12)
210
210
  activesupport (>= 4.0.2)
@@ -236,9 +236,9 @@ GEM
236
236
  listen (3.8.0)
237
237
  rb-fsevent (~> 0.10, >= 0.10.3)
238
238
  rb-inotify (~> 0.9, >= 0.9.10)
239
- loofah (2.20.0)
239
+ loofah (2.21.3)
240
240
  crass (~> 1.0.2)
241
- nokogiri (>= 1.5.9)
241
+ nokogiri (>= 1.12.0)
242
242
  mail (2.8.1)
243
243
  mini_mime (>= 0.1.1)
244
244
  net-imap
@@ -255,11 +255,11 @@ GEM
255
255
  method_source (1.0.0)
256
256
  mini_magick (4.12.0)
257
257
  mini_mime (1.1.2)
258
- mini_portile2 (2.8.1)
259
- minitest (5.18.0)
258
+ mini_portile2 (2.8.2)
259
+ minitest (5.18.1)
260
260
  msgpack (1.5.6)
261
261
  multi_xml (0.6.0)
262
- net-imap (0.3.4)
262
+ net-imap (0.3.6)
263
263
  date
264
264
  net-protocol
265
265
  net-pop (0.1.2)
@@ -269,10 +269,10 @@ GEM
269
269
  net-smtp (0.3.3)
270
270
  net-protocol
271
271
  nio4r (2.5.9)
272
- nokogiri (1.14.3)
273
- mini_portile2 (~> 2.8.0)
272
+ nokogiri (1.15.2)
273
+ mini_portile2 (~> 2.8.2)
274
274
  racc (~> 1.4)
275
- nokogiri (1.14.3-x86_64-linux)
275
+ nokogiri (1.15.2-x86_64-linux)
276
276
  racc (~> 1.4)
277
277
  orm_adapter (0.5.0)
278
278
  pagy (6.0.4)
@@ -288,24 +288,24 @@ GEM
288
288
  nio4r (~> 2.0)
289
289
  pundit (2.2.0)
290
290
  activesupport (>= 3.0.0)
291
- racc (1.6.2)
292
- rack (2.2.6.4)
291
+ racc (1.7.1)
292
+ rack (2.2.7)
293
293
  rack-test (2.1.0)
294
294
  rack (>= 1.3)
295
- rails (6.1.7.3)
296
- actioncable (= 6.1.7.3)
297
- actionmailbox (= 6.1.7.3)
298
- actionmailer (= 6.1.7.3)
299
- actionpack (= 6.1.7.3)
300
- actiontext (= 6.1.7.3)
301
- actionview (= 6.1.7.3)
302
- activejob (= 6.1.7.3)
303
- activemodel (= 6.1.7.3)
304
- activerecord (= 6.1.7.3)
305
- activestorage (= 6.1.7.3)
306
- activesupport (= 6.1.7.3)
295
+ rails (6.1.7.4)
296
+ actioncable (= 6.1.7.4)
297
+ actionmailbox (= 6.1.7.4)
298
+ actionmailer (= 6.1.7.4)
299
+ actionpack (= 6.1.7.4)
300
+ actiontext (= 6.1.7.4)
301
+ actionview (= 6.1.7.4)
302
+ activejob (= 6.1.7.4)
303
+ activemodel (= 6.1.7.4)
304
+ activerecord (= 6.1.7.4)
305
+ activestorage (= 6.1.7.4)
306
+ activesupport (= 6.1.7.4)
307
307
  bundler (>= 1.15.0)
308
- railties (= 6.1.7.3)
308
+ railties (= 6.1.7.4)
309
309
  sprockets-rails (>= 2.0.0)
310
310
  rails-controller-testing (1.0.5)
311
311
  actionpack (>= 5.0.1.rc1)
@@ -314,14 +314,15 @@ GEM
314
314
  rails-dom-testing (2.0.3)
315
315
  activesupport (>= 4.2.0)
316
316
  nokogiri (>= 1.6)
317
- rails-html-sanitizer (1.5.0)
318
- loofah (~> 2.19, >= 2.19.1)
317
+ rails-html-sanitizer (1.6.0)
318
+ loofah (~> 2.21)
319
+ nokogiri (~> 1.14)
319
320
  rails-i18n (7.0.5)
320
321
  i18n (>= 0.7, < 2)
321
322
  railties (>= 6.0.0, < 8)
322
- railties (6.1.7.3)
323
- actionpack (= 6.1.7.3)
324
- activesupport (= 6.1.7.3)
323
+ railties (6.1.7.4)
324
+ actionpack (= 6.1.7.4)
325
+ activesupport (= 6.1.7.4)
325
326
  method_source
326
327
  rake (>= 12.2)
327
328
  thor (~> 1.0)
@@ -412,8 +413,8 @@ GEM
412
413
  terminal-table (3.0.2)
413
414
  unicode-display_width (>= 1.1.1, < 3)
414
415
  test-prof (1.0.10)
415
- thor (1.2.1)
416
- timeout (0.3.2)
416
+ thor (1.2.2)
417
+ timeout (0.4.0)
417
418
  turbo-rails (1.4.0)
418
419
  actionpack (>= 6.0.0)
419
420
  activejob (>= 6.0.0)
@@ -421,7 +422,7 @@ GEM
421
422
  tzinfo (2.0.6)
422
423
  concurrent-ruby (~> 1.0)
423
424
  unicode-display_width (2.4.0)
424
- view_component (3.2.0)
425
+ view_component (3.3.0)
425
426
  activesupport (>= 5.2.0, < 8.0)
426
427
  concurrent-ruby (~> 1.0)
427
428
  method_source (~> 1.0)
@@ -445,7 +446,7 @@ GEM
445
446
  websocket-extensions (0.1.5)
446
447
  xpath (3.2.0)
447
448
  nokogiri (~> 1.8)
448
- zeitwerk (2.6.7)
449
+ zeitwerk (2.6.8)
449
450
 
450
451
  PLATFORMS
451
452
  ruby
@@ -1,7 +1,7 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= @form.text_field @field.id,
3
- class: classes("w-full"),
4
3
  value: field.value.to_s,
4
+ class: classes("w-full"),
5
5
  placeholder: @field.placeholder,
6
6
  disabled: disabled? %>
7
7
  <% end %>
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
4
- def initialize(field: nil, resource: nil, index: 0, form: nil, compact: false)
5
- super field: field, resource: resource, index: index, form: form, compact: compact
4
+ def initialize(**args)
5
+ super(**args)
6
6
 
7
7
  @polymorphic_record = nil
8
8
  end
@@ -1,6 +1,7 @@
1
1
  <%= field_wrapper **field_wrapper_args, dash_if_blank: false do %>
2
2
  <div class="h-8 flex items-center">
3
3
  <%= @form.check_box @field.id,
4
+ value: @field.value,
4
5
  checked: @field.value,
5
6
  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
7
  data: @field.get_html(:data, view: view, element: :input),
@@ -1,6 +1,7 @@
1
1
  <%= field_wrapper **field_wrapper_args, full_width: true do %>
2
2
  <div data-controller="code-field">
3
3
  <%= @form.text_area @field.id,
4
+ value: @field.value,
4
5
  class: classes("w-full"),
5
6
  data: {
6
7
  'code-field-target': 'element',
@@ -1,5 +1,6 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= @form.select @field.id, @field.select_options, {
3
+ value: @field.value,
3
4
  selected: @field.value,
4
5
  include_blank: @field.include_blank
5
6
  },
@@ -1,6 +1,7 @@
1
1
  <%= field_wrapper **field_wrapper_args, full_width: true do %>
2
2
  <div data-controller="easy-mde">
3
3
  <%= @form.text_area @field.id,
4
+ value: @field.value,
4
5
  class: classes("w-full js-has-easy-mde-editor"),
5
6
  data: {
6
7
  view: view,
@@ -1,5 +1,6 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= @form.number_field @field.id,
3
+ value: @field.value,
3
4
  class: classes("w-full"),
4
5
  data: @field.get_html(:data, view: view, element: :input),
5
6
  disabled: disabled?,
@@ -1,5 +1,6 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= @form.password_field @field.id,
3
+ value: @field.value,
3
4
  class: classes("w-full"),
4
5
  data: @field.get_html(:data, view: view, element: :input),
5
6
  disabled: disabled?,
@@ -6,6 +6,7 @@
6
6
  </div>
7
7
  <% end %>
8
8
  <%= @form.range_field @field.id,
9
+ value: @field.value,
9
10
  class: "w-full #{@field.get_html(:classes, view: view, element: :input)}",
10
11
  data: {
11
12
  action: "input->progress-bar-field#update",
@@ -5,6 +5,6 @@
5
5
  disabled: disabled?,
6
6
  placeholder: @field.placeholder,
7
7
  style: @field.get_html(:style, view: view, element: :input),
8
- value: @resource.model.present? ? @resource.model[@field.id] : @field.value
8
+ value: @field.value
9
9
  %>
10
10
  <% end %>
@@ -1,11 +1,11 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= form.text_field @field.id,
3
+ value: @field.value,
3
4
  class: classes("w-full"),
4
5
  data: @field.get_html(:data, view: view, element: :input),
5
6
  disabled: disabled?,
6
7
  placeholder: @field.placeholder,
7
8
  style: @field.get_html(:style, view: view, element: :input),
8
- # value: @field.value,
9
9
  multiple: multiple,
10
10
  autocomplete: @field.autocomplete
11
11
  %>
@@ -1,5 +1,6 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <%= @form.text_area @field.id,
3
+ value: @field.value,
3
4
  class: classes("w-full"),
4
5
  data: @field.get_html(:data, view: view, element: :input),
5
6
  disabled: disabled?,
@@ -23,6 +23,7 @@
23
23
  <%= sanitize @field.value.to_s %>
24
24
  <% end %>
25
25
  <%= @form.text_area @field.id,
26
+ value: @field.value,
26
27
  class: classes("w-full hidden"),
27
28
  data: @field.get_html(:data, view: view, element: :input),
28
29
  disabled: disabled?,
@@ -1,11 +1,11 @@
1
1
  <% if item.is_a? Avo::Menu::Link %>
2
- <%= render Avo::Sidebar::LinkComponent.new label: item.name, path: item.path, target: item.target, data: item.data %>
2
+ <%= render Avo::Sidebar::LinkComponent.new label: item.name, path: item.path, target: item.target, data: item.data, icon: item.icon %>
3
3
  <% end %>
4
4
  <% if item.is_a? Avo::Menu::Resource %>
5
- <%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: helpers.resources_path(resource: resource), data: item.data %>
5
+ <%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: helpers.resources_path(resource: resource), data: item.data, icon: item.icon %>
6
6
  <% end %>
7
7
  <% if item.is_a? Avo::Menu::Dashboard %>
8
- <%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: dashboard.navigation_path, data: item.data %>
8
+ <%= render Avo::Sidebar::LinkComponent.new label: item.navigation_label, path: dashboard.navigation_path, data: item.data, icon: item.icon %>
9
9
  <% end %>
10
10
  <% if item.is_a? Avo::Menu::Section %>
11
11
  <%= render Avo::Sidebar::SectionComponent.new item: item %>
@@ -1,5 +1,6 @@
1
1
  <% if path.present? %>
2
2
  <%= send link_method, path, class: classes, active: active, target: target, data: data do %>
3
+ <%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
3
4
  <%= label %>
4
5
  <% if target == :_blank %>
5
6
  <%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
@@ -7,6 +8,7 @@
7
8
  <% end %>
8
9
  <% else %>
9
10
  <%= content_tag :div, class: classes, active: active, target: target, data: data do %>
11
+ <%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
10
12
  <%= label %>
11
13
  <% end %>
12
14
  <% end %>
@@ -6,13 +6,15 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
6
6
  attr_reader :label
7
7
  attr_reader :path
8
8
  attr_reader :data
9
+ attr_reader :icon
9
10
 
10
- def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {})
11
+ def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {}, icon: nil)
11
12
  @label = label
12
13
  @path = path
13
14
  @active = active
14
15
  @target = target
15
16
  @data = data
17
+ @icon = icon
16
18
  end
17
19
 
18
20
  def is_external?
@@ -28,6 +30,6 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
28
30
  end
29
31
 
30
32
  def classes
31
- "px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100"
33
+ "px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100 gap-1"
32
34
  end
33
35
  end
@@ -63,32 +63,29 @@ class Avo::TabSwitcherComponent < Avo::BaseComponent
63
63
  # Because the developer hasn't specified that it should be visible on edit views (with the show_on: :edit option),
64
64
  # the field should not be visible in the item switcher either.
65
65
  def visible_items
66
- tabs.select do |item|
67
- visible = true
68
-
69
- if item.items.blank?
70
- visible = false
71
- end
66
+ tabs.select do |tab|
67
+ next false if tab.items.blank?
68
+ next false if tab.is_field? && !tab.authorized?
69
+ next false if tab.has_a_single_item? && !single_item_visible?(tab.items.first)
70
+ next false if !tab.visible?
71
+ next false if !tab.visible_on?(view)
72
+
73
+ true
74
+ end
75
+ end
72
76
 
73
- first_item = item.items.first
74
- if item.items.count == 1 && first_item.is_field? && first_item.has_own_panel? && !first_item.visible_on?(view)
75
- # Return nil if tab contians a has_many type of fields and it's hidden in current view
76
- visible = false
77
- end
77
+ private
78
78
 
79
- if item.respond_to?(:visible_on?)
80
- visible = item.visible_on? view
81
- end
79
+ def single_item_visible?(item)
80
+ # Item is visible if is not a field or don't have its own panel
81
+ return true if !item.is_field?
82
+ return true if !item.has_own_panel?
82
83
 
83
- if item.respond_to?(:visible?)
84
- visible = item.visible?
85
- end
84
+ return false if !item.visible_on?(view)
86
85
 
87
- if item.respond_to?(:authorized?)
88
- visible = item.authorized?
89
- end
86
+ # If item is hydrated with the correct resource and is not authorized, it's not visible
87
+ return false if item.resource.present? && !item.authorized?
90
88
 
91
- visible
92
- end
89
+ true
93
90
  end
94
91
  end
@@ -7,7 +7,7 @@
7
7
  selected_resources: [@resource.model.id],
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
- <%= form_with model: @resource.model,
10
+ <%= form_with model: @resource.record,
11
11
  scope: @resource.form_scope,
12
12
  url: form_url,
13
13
  method: form_method,
@@ -80,6 +80,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
80
80
 
81
81
  # Render :show view for read only trix fields
82
82
  def view_for(field)
83
- (field.is_a? Avo::Fields::TrixField) && field.is_readonly? ? :show : view
83
+ (field.is_a?(Avo::Fields::TrixField) && field.is_readonly?) ? :show : view
84
84
  end
85
85
  end
@@ -215,16 +215,24 @@ module Avo
215
215
 
216
216
  def save_model
217
217
  perform_action_and_record_errors do
218
- @model.save!
218
+ save_model_action
219
219
  end
220
220
  end
221
221
 
222
+ def save_model_action
223
+ @model.save!
224
+ end
225
+
222
226
  def destroy_model
223
227
  perform_action_and_record_errors do
224
- @model.destroy!
228
+ destroy_model_action
225
229
  end
226
230
  end
227
231
 
232
+ def destroy_model_action
233
+ @model.destroy!
234
+ end
235
+
228
236
  def perform_action_and_record_errors(&block)
229
237
  begin
230
238
  succeeded = block.call
@@ -253,7 +261,7 @@ module Avo
253
261
  end
254
262
 
255
263
  def permitted_params
256
- @resource.get_field_definitions.select(&:updatable).map(&:to_permitted_param).concat extra_params
264
+ @resource.get_field_definitions.select(&:updatable).map(&:to_permitted_param).concat(extra_params).uniq
257
265
  end
258
266
 
259
267
  def extra_params
@@ -112,8 +112,13 @@ module Avo
112
112
  # This scope is applied if the search is being performed on a has_many association
113
113
  def apply_has_many_scope
114
114
  association_name = BaseResource.valid_association_name(parent, params[:via_association_id])
115
+
116
+ # Get association records
115
117
  scope = parent.send(association_name)
116
118
 
119
+ # Apply policy scope if authorization is present
120
+ scope = resource.authorization&.apply_policy scope
121
+
117
122
  Avo::Hosts::SearchScopeHost.new(block: @resource.search_query, params: params, scope: scope).handle
118
123
  end
119
124
 
data/db/factories.rb CHANGED
@@ -104,7 +104,8 @@ FactoryBot.define do
104
104
  factory :city do
105
105
  name { Faker::Address.city }
106
106
  population { rand(10000..999000) }
107
- coordinates { [Faker::Address.latitude, Faker::Address.longitude] }
107
+ latitude { Faker::Address.latitude }
108
+ longitude { Faker::Address.longitude }
108
109
  is_capital { [true, false].sample }
109
110
  features { Faker::Address.community }
110
111
  metadata { Faker::Address.community }
@@ -151,7 +151,8 @@ module Avo
151
151
  def record
152
152
  @model
153
153
  end
154
- alias :model :record
154
+ alias_method :model, :record
155
+
155
156
 
156
157
  def hydrate(model: nil, view: nil, user: nil, params: nil)
157
158
  @view = view if view.present?
@@ -307,9 +308,9 @@ module Avo
307
308
  end
308
309
  end
309
310
 
310
- def fill_model(model, params, extra_params: [])
311
- # Map the received params to their actual fields
312
- fields_by_database_id = get_field_definitions
311
+ # Map the received params to their actual fields.
312
+ def fields_by_database_id
313
+ get_field_definitions
313
314
  .reject do |field|
314
315
  field.computed
315
316
  end
@@ -317,7 +318,9 @@ module Avo
317
318
  [field.database_id.to_s, field]
318
319
  end
319
320
  .to_h
321
+ end
320
322
 
323
+ def fill_model(model, params, extra_params: [])
321
324
  # Write the field values
322
325
  params.each do |key, value|
323
326
  field = fields_by_database_id[key]
@@ -98,6 +98,10 @@ module Avo
98
98
  if item.is_field?
99
99
  fields << item
100
100
  end
101
+
102
+ if item.is_row?
103
+ fields << extract_fields_from_items(tab)
104
+ end
101
105
  end
102
106
 
103
107
  fields.flatten
@@ -117,7 +121,7 @@ module Avo
117
121
  thing.items.each do |item|
118
122
  if item.is_field?
119
123
  fields << item
120
- elsif item.is_panel?
124
+ elsif item.is_panel? || item.is_row?
121
125
  fields << extract_fields_from_items(item)
122
126
  end
123
127
  end
@@ -168,23 +172,9 @@ module Avo
168
172
 
169
173
  return [] if fields.blank?
170
174
 
171
- items = fields.map do |field|
175
+ fields.map do |field|
172
176
  field.hydrate(resource: self, user: user, view: view)
173
177
  end
174
-
175
- if Avo::App.license.lacks_with_trial(:custom_fields)
176
- items = items.reject do |field|
177
- field.custom?
178
- end
179
- end
180
-
181
- if Avo::App.license.lacks_with_trial(:advanced_fields)
182
- items = items.reject do |field|
183
- field.type == "tags"
184
- end
185
- end
186
-
187
- items
188
178
  end
189
179
 
190
180
  def get_fields(panel: nil, reflection: nil, only_root: false)
@@ -0,0 +1,43 @@
1
+ module Avo
2
+ class ExecutionContext
3
+ attr_accessor :target, :context, :params, :view_context, :current_user, :request, :include, :main_app, :avo
4
+
5
+ def initialize(**args)
6
+ # Extend the class with custom modules if required.
7
+ if args[:include].present?
8
+ args[:include].each do |mod|
9
+ self.class.send(:include, mod)
10
+ end
11
+ end
12
+
13
+ # If you want this block to behave like a view you can delegate the missing methods to the view_context
14
+ #
15
+ # Ex: Avo::ExecutionContext.new(target: ..., delegate_missing_to: :view_context).handle
16
+ if args[:delegate_missing_to].present?
17
+ self.class.send(:delegate_missing_to, args[:delegate_missing_to])
18
+ end
19
+
20
+ # If target doesn't respond to call, we don't need to initialize the others attr_accessors.
21
+ return unless (@target = args[:target]).respond_to? :call
22
+
23
+ args.except(:target).each do |key, value|
24
+ singleton_class.class_eval { attr_accessor key }
25
+ instance_variable_set("@#{key}", value)
26
+ end
27
+
28
+ # Set defaults on not initialized accessors
29
+ @context ||= Avo::App.context
30
+ @params ||= Avo::App.params
31
+ @view_context ||= Avo::App.view_context
32
+ @current_user ||= Avo::App.current_user
33
+ @request ||= view_context.request
34
+ @main_app ||= view_context.main_app
35
+ @avo ||= view_context.avo
36
+ end
37
+
38
+ # Return target if target is not callable, otherwise, execute target on this instance context
39
+ def handle
40
+ target.respond_to?(:call) ? instance_exec(&target) : target
41
+ end
42
+ end
43
+ end
@@ -70,6 +70,7 @@ module Avo
70
70
  @nullable = args[:nullable] || false
71
71
  @null_values = args[:null_values] || [nil, ""]
72
72
  @format_using = args[:format_using] || nil
73
+ @update_using = args[:update_using] || nil
73
74
  @placeholder = args[:placeholder]
74
75
  @autocomplete = args[:autocomplete] || nil
75
76
  @help = args[:help] || nil
@@ -183,20 +184,31 @@ module Avo
183
184
  final_value = instance_exec(@model, @resource, @view, self, &block)
184
185
  end
185
186
 
186
- # Run the value through resolver if present
187
- final_value = instance_exec(final_value, &@format_using) if @format_using.present?
188
-
189
- final_value
187
+ if @format_using.present?
188
+ # Apply the changes in the
189
+ Avo::ExecutionContext.new(target: @format_using, model: model, key: property, value: final_value, resource: resource, view: view, field: self, delegate_missing_to: :view_context).handle
190
+ else
191
+ final_value
192
+ end
190
193
  end
191
194
 
195
+ # Fills the model with the received value on create and update actions.
192
196
  def fill_field(model, key, value, params)
193
197
  return model unless model.methods.include? key.to_sym
194
198
 
195
- model.send("#{key}=", value)
199
+ if @update_using.present?
200
+ value = update_using(model, key, value, params)
201
+ end
202
+
203
+ model.public_send("#{key}=", value)
196
204
 
197
205
  model
198
206
  end
199
207
 
208
+ def update_using(model, key, value, params)
209
+ Avo::ExecutionContext.new(target: @update_using, model: model, key: key, value: value, resource: resource, field: self).handle
210
+ end
211
+
200
212
  # Try to see if the field has a different database ID than it's name
201
213
  def database_id
202
214
  foreign_key
@@ -18,7 +18,7 @@ module Avo
18
18
  def visible_on?(view)
19
19
  raise "No view specified on visibility check." if view.blank?
20
20
 
21
- send :"show_on_#{view.to_s}"
21
+ send :"show_on_#{view}"
22
22
  end
23
23
 
24
24
  def show_on(*where)
@@ -59,6 +59,14 @@ module Avo
59
59
  end
60
60
  end
61
61
 
62
+ def value
63
+ if value_as_array?
64
+ [@model.send(stored_as.first), @model.send(stored_as.last)]
65
+ else
66
+ super
67
+ end
68
+ end
69
+
62
70
  def value_present?
63
71
  return value.first.present? && value.second.present? if value.is_a?(Array) && value.count == 2
64
72
 
@@ -1,9 +1,23 @@
1
1
  module Avo
2
2
  class ItemsHolder
3
3
  attr_reader :tools
4
- attr_accessor :items
4
+ attr_writer :items
5
5
  attr_accessor :invalid_fields
6
6
 
7
+ def items
8
+ items = @items
9
+
10
+ if Avo::App.license.lacks_with_trial(:custom_fields)
11
+ items.reject! { |item| item.is_field? && item.custom? }
12
+ end
13
+
14
+ if Avo::App.license.lacks_with_trial(:advanced_fields)
15
+ items.reject! { |item| item.is_field? && item.type == "tags" }
16
+ end
17
+
18
+ items
19
+ end
20
+
7
21
  def initialize
8
22
  @items = []
9
23
  @items_index = 0
@@ -185,7 +185,11 @@ module Avo
185
185
  def perform_request
186
186
  ::Rails.logger.debug "[Avo] Performing request to avohq.io API to check license availability." if Rails.env.development?
187
187
 
188
- HTTParty.post ENDPOINT, body: payload.to_json, headers: {"Content-type": "application/json"}, timeout: REQUEST_TIMEOUT
188
+ if Rails.env.test?
189
+ OpenStruct.new({code: 200, parsed_response: {id: "pro", valid: true}})
190
+ else
191
+ HTTParty.post ENDPOINT, body: payload.to_json, headers: {"Content-type": "application/json"}, timeout: REQUEST_TIMEOUT
192
+ end
189
193
  end
190
194
 
191
195
  def app_name
@@ -6,7 +6,7 @@ module Avo
6
6
  attr_accessor :valid
7
7
  attr_accessor :payload
8
8
 
9
- def initialize(response)
9
+ def initialize(response = {})
10
10
  @response = response
11
11
  @id = response["id"]
12
12
  @valid = response["valid"]
@@ -12,7 +12,7 @@ module Avo
12
12
  when "pro"
13
13
  ProLicense.new @hq_response
14
14
  else
15
- NullLicense.new @hq_response
15
+ NilLicense.new @hq_response
16
16
  end
17
17
  end
18
18
 
@@ -1,6 +1,6 @@
1
1
  module Avo
2
2
  module Licensing
3
- class NullLicense < License
3
+ class NilLicense < License
4
4
  def initialize(response = nil)
5
5
  response ||= {
6
6
  id: "community",
data/lib/avo/tab.rb CHANGED
@@ -65,4 +65,8 @@ class Avo::Tab
65
65
  super(view)
66
66
  end
67
67
  end
68
+
69
+ def has_a_single_item?
70
+ items.count == 1
71
+ end
68
72
  end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.35.0" unless const_defined?(:VERSION)
2
+ VERSION = "2.36.1" unless const_defined?(:VERSION)
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.35.0
4
+ version: 2.36.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-06-20 00:00:00.000000000 Z
12
+ date: 2023-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -1752,6 +1752,7 @@ files:
1752
1752
  - lib/avo/dsl/field_parser.rb
1753
1753
  - lib/avo/dynamic_router.rb
1754
1754
  - lib/avo/engine.rb
1755
+ - lib/avo/execution_context.rb
1755
1756
  - lib/avo/fields/area_field.rb
1756
1757
  - lib/avo/fields/badge_field.rb
1757
1758
  - lib/avo/fields/base_field.rb
@@ -1823,7 +1824,7 @@ files:
1823
1824
  - lib/avo/licensing/h_q.rb
1824
1825
  - lib/avo/licensing/license.rb
1825
1826
  - lib/avo/licensing/license_manager.rb
1826
- - lib/avo/licensing/null_license.rb
1827
+ - lib/avo/licensing/nil_license.rb
1827
1828
  - lib/avo/licensing/pro_license.rb
1828
1829
  - lib/avo/loaders/actions_loader.rb
1829
1830
  - lib/avo/loaders/fields_loader.rb