avo 2.30.2 → 2.32.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.

Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +10 -10
  4. data/app/assets/stylesheets/avo.base.css +0 -1
  5. data/app/assets/svgs/map-empty-state.svg +35 -0
  6. data/app/assets/svgs/map-view-type.svg +3 -0
  7. data/app/components/avo/actions_component.rb +1 -1
  8. data/app/components/avo/fields/area_field/edit_component.html.erb +7 -0
  9. data/app/components/avo/fields/area_field/edit_component.rb +4 -0
  10. data/app/components/avo/fields/area_field/show_component.html.erb +8 -0
  11. data/app/components/avo/fields/area_field/show_component.rb +4 -0
  12. data/app/components/avo/fields/country_field/edit_component.html.erb +2 -1
  13. data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
  14. data/app/components/avo/fields/has_one_field/show_component.html.erb +2 -2
  15. data/app/components/avo/fields/location_field/show_component.html.erb +1 -1
  16. data/app/components/avo/fields/number_field/edit_component.html.erb +2 -1
  17. data/app/components/avo/fields/password_field/edit_component.html.erb +2 -1
  18. data/app/components/avo/fields/select_field/edit_component.html.erb +2 -1
  19. data/app/components/avo/fields/text_field/edit_component.html.erb +2 -1
  20. data/app/components/avo/index/resource_map_component.html.erb +16 -0
  21. data/app/components/avo/index/resource_map_component.rb +109 -0
  22. data/app/components/avo/item_switcher_component.html.erb +1 -1
  23. data/app/components/avo/resource_component.rb +1 -1
  24. data/app/components/avo/views/resource_edit_component.html.erb +4 -4
  25. data/app/components/avo/views/resource_index_component.html.erb +12 -3
  26. data/app/components/avo/views/resource_show_component.html.erb +3 -3
  27. data/app/controllers/avo/application_controller.rb +4 -0
  28. data/app/views/avo/actions/show.html.erb +2 -2
  29. data/app/views/avo/associations/new.html.erb +2 -2
  30. data/app/views/avo/dashboards/show.html.erb +2 -2
  31. data/app/views/avo/debug/index.html.erb +2 -2
  32. data/app/views/avo/home/index.html.erb +1 -1
  33. data/app/views/avo/partials/_view_toggle_button.html.erb +5 -0
  34. data/app/views/avo/private/design.html.erb +2 -2
  35. data/avo.gemspec +1 -1
  36. data/db/factories.rb +1 -0
  37. data/lib/avo/app.rb +19 -4
  38. data/lib/avo/base_action.rb +4 -4
  39. data/lib/avo/base_resource.rb +2 -0
  40. data/lib/avo/concerns/fetches_things.rb +1 -3
  41. data/lib/avo/concerns/policy_helpers.rb +31 -0
  42. data/lib/avo/engine.rb +0 -5
  43. data/lib/avo/fields/area_field.rb +39 -0
  44. data/lib/avo/fields/base_field.rb +3 -2
  45. data/lib/avo/fields/location_field.rb +0 -1
  46. data/lib/avo/licensing/h_q.rb +1 -0
  47. data/lib/avo/version.rb +1 -1
  48. data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
  49. data/lib/generators/avo/templates/tool/view.tt +2 -2
  50. data/public/avo-assets/avo.base.css +24 -0
  51. metadata +14 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc6bc41d1c4845492b9ee785b1ccd4895d0369ec54d2b307c67835a112059923
4
- data.tar.gz: a04214b31f49e408ecf64166c126dd8a114543f4c3ad01383f33ba1d7216c88d
3
+ metadata.gz: 7bde773a8062f76d29ce0655fd0948bf963f1a0627b02d3d9df706225049fab6
4
+ data.tar.gz: 6503ea6bde6130648c2f2613e097ee9cc8db3e58d07702fea4d47a94b62a5118
5
5
  SHA512:
6
- metadata.gz: e36a294bc70cd7568ea15c7e5d4323b1d261bfeaf7295ae2439cf581bef67ea0efcebe9995d23bfb416904e89810342df73d20591aa6790d128593ffceca7a16
7
- data.tar.gz: d2eac35c9568ed230c05155823be7f52add0e4a86fa0f43ec85dbe2c69e84e5cb6188b7799714c739922269ba16b4919e3a0e7e7eb5f8d79cd4220669e0671ba
6
+ metadata.gz: c17065eb96f4b82a8f0d33f50627e635462e737c3fae582ab371c10a7976594df137fa8db3bb77252fcbc5d4c873ec4eb3db24c8ddedd201c6d830574be5687d
7
+ data.tar.gz: 762e69b4a753622e1a6ad3eef2038e27acf05b36356bbe31a1cb7798ba1491f65306fb867d4eea41f0ffe8870c959c66df8f5a55768620119d7158ef56a6e05a
data/Gemfile CHANGED
@@ -75,7 +75,7 @@ group :development do
75
75
 
76
76
  gem "htmlbeautifier"
77
77
 
78
- gem "hotwire-livereload", "~> 1.1"
78
+ gem "hotwire-livereload", "~> 1.2"
79
79
 
80
80
  gem "brakeman"
81
81
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.30.2)
4
+ avo (2.32.0)
5
5
  actionview (>= 6.0)
6
6
  active_link_to
7
7
  activerecord (>= 6.0)
@@ -13,7 +13,7 @@ PATH
13
13
  meta-tags
14
14
  pagy
15
15
  turbo-rails
16
- view_component
16
+ view_component (>= 2.54.0)
17
17
  zeitwerk (>= 2.6.2)
18
18
 
19
19
  GEM
@@ -196,7 +196,7 @@ GEM
196
196
  highline (2.1.0)
197
197
  hightop (0.3.0)
198
198
  activesupport (>= 5.2)
199
- hotwire-livereload (1.2.2)
199
+ hotwire-livereload (1.2.3)
200
200
  listen (>= 3.0.0)
201
201
  rails (>= 6.0.0)
202
202
  html_tokenizer (0.0.7)
@@ -233,10 +233,10 @@ GEM
233
233
  json (2.6.2)
234
234
  launchy (2.5.2)
235
235
  addressable (~> 2.8)
236
- listen (3.7.1)
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.19.1)
239
+ loofah (2.20.0)
240
240
  crass (~> 1.0.2)
241
241
  nokogiri (>= 1.5.9)
242
242
  mail (2.8.1)
@@ -268,14 +268,14 @@ GEM
268
268
  timeout
269
269
  net-smtp (0.3.3)
270
270
  net-protocol
271
- nio4r (2.5.8)
271
+ nio4r (2.5.9)
272
272
  nokogiri (1.14.3)
273
273
  mini_portile2 (~> 2.8.0)
274
274
  racc (~> 1.4)
275
275
  nokogiri (1.14.3-x86_64-linux)
276
276
  racc (~> 1.4)
277
277
  orm_adapter (0.5.0)
278
- pagy (6.0.3)
278
+ pagy (6.0.4)
279
279
  parallel (1.22.1)
280
280
  parser (3.2.0.0)
281
281
  ast (~> 2.4.1)
@@ -331,7 +331,7 @@ GEM
331
331
  activerecord (>= 6.0.4)
332
332
  activesupport (>= 6.0.4)
333
333
  i18n
334
- rb-fsevent (0.11.1)
334
+ rb-fsevent (0.11.2)
335
335
  rb-inotify (0.10.1)
336
336
  ffi (~> 1.0)
337
337
  redis (4.8.1)
@@ -421,7 +421,7 @@ GEM
421
421
  tzinfo (2.0.6)
422
422
  concurrent-ruby (~> 1.0)
423
423
  unicode-display_width (2.4.0)
424
- view_component (2.82.0)
424
+ view_component (3.0.0)
425
425
  activesupport (>= 5.2.0, < 8.0)
426
426
  concurrent-ruby (~> 1.0)
427
427
  method_source (~> 1.0)
@@ -483,7 +483,7 @@ DEPENDENCIES
483
483
  gem-release
484
484
  groupdate
485
485
  hightop
486
- hotwire-livereload (~> 1.1)
486
+ hotwire-livereload (~> 1.2)
487
487
  htmlbeautifier
488
488
  httparty
489
489
  i18n-tasks (~> 1.0.12)
@@ -71,7 +71,6 @@ body {
71
71
  @apply opacity-0 translate-y-1;
72
72
  }
73
73
 
74
-
75
74
  .turbo-progress-bar {
76
75
  @apply bg-primary-400;
77
76
  }
@@ -0,0 +1,35 @@
1
+ <svg width="248" height="287" viewBox="0 0 248 287" fill="none" xmlns="http://www.w3.org/2000/svg" data-target="grid-empty-state-svg">
2
+ <path d="M124 270.227C192.483 270.227 248 214.71 248 146.227C248 77.7433 192.483 22.2266 124 22.2266C55.5167 22.2266 0 77.7433 0 146.227C0 214.71 55.5167 270.227 124 270.227Z" fill="rgb(var(--color-primary-100))"/>
3
+ <g filter="rgb(var(--color-primary-100))">
4
+ <path d="M195.093 93.3198H52.9068C48.3412 93.3198 44.6401 97.0209 44.6401 101.586V275.186C44.6401 279.752 48.3412 283.453 52.9068 283.453H195.093C199.659 283.453 203.36 279.752 203.36 275.186V101.586C203.36 97.0209 199.659 93.3198 195.093 93.3198Z" fill="white"/>
5
+ </g>
6
+ <path d="M107.467 118.12H64.48C61.7407 118.12 59.52 120.34 59.52 123.08C59.52 125.819 61.7407 128.04 64.48 128.04H107.467C110.206 128.04 112.427 125.819 112.427 123.08C112.427 120.34 110.206 118.12 107.467 118.12Z" fill="rgb(var(--color-primary-100))"/>
7
+ <path d="M137.227 139.613H64.48C61.7407 139.613 59.52 141.834 59.52 144.573C59.52 147.312 61.7407 149.533 64.48 149.533H137.227C139.966 149.533 142.187 147.312 142.187 144.573C142.187 141.834 139.966 139.613 137.227 139.613Z" fill="rgb(var(--color-primary-100))" opacity="0.6"/>
8
+ <path d="M107.467 162.76H64.48C61.7407 162.76 59.52 164.981 59.52 167.72C59.52 170.459 61.7407 172.68 64.48 172.68H107.467C110.206 172.68 112.427 170.459 112.427 167.72C112.427 164.981 110.206 162.76 107.467 162.76Z" fill="rgb(var(--color-primary-100))"/>
9
+ <path d="M137.227 184.253H64.48C61.7407 184.253 59.52 186.474 59.52 189.213C59.52 191.953 61.7407 194.173 64.48 194.173H137.227C139.966 194.173 142.187 191.953 142.187 189.213C142.187 186.474 139.966 184.253 137.227 184.253Z" fill="rgb(var(--color-primary-100))" opacity="0.6"/>
10
+ <path d="M107.467 207.4H64.48C61.7407 207.4 59.52 209.621 59.52 212.36C59.52 215.099 61.7407 217.32 64.48 217.32H107.467C110.206 217.32 112.427 215.099 112.427 212.36C112.427 209.621 110.206 207.4 107.467 207.4Z" fill="rgb(var(--color-primary-100))"/>
11
+ <path d="M137.227 228.893H64.48C61.7407 228.893 59.52 231.114 59.52 233.853C59.52 236.592 61.7407 238.813 64.48 238.813H137.227C139.966 238.813 142.187 236.592 142.187 233.853C142.187 231.114 139.966 228.893 137.227 228.893Z" fill="rgb(var(--color-primary-100))" opacity="0.6"/>
12
+ <g filter="url(#filter1_d_577_1090)">
13
+ <path d="M195.093 9H52.9068C48.3412 9 44.6401 12.7011 44.6401 17.2667V66.8667C44.6401 71.4322 48.3412 75.1333 52.9068 75.1333H195.093C199.659 75.1333 203.36 71.4322 203.36 66.8667V17.2667C203.36 12.7011 199.659 9 195.093 9Z" fill="rgb(var(--color-primary-500))"/>
14
+ </g>
15
+ <path d="M107.467 27.1865H64.48C61.7407 27.1865 59.52 29.4072 59.52 32.1465C59.52 34.8859 61.7407 37.1065 64.48 37.1065H107.467C110.206 37.1065 112.427 34.8859 112.427 32.1465C112.427 29.4072 110.206 27.1865 107.467 27.1865Z" fill="rgb(var(--color-primary-100))"/>
16
+ <path d="M137.227 48.6799H64.48C61.7407 48.6799 59.52 50.9006 59.52 53.6399C59.52 56.3793 61.7407 58.5999 64.48 58.5999H137.227C139.966 58.5999 142.187 56.3793 142.187 53.6399C142.187 50.9006 139.966 48.6799 137.227 48.6799Z" fill="white"/>
17
+ <defs>
18
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
19
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
20
+ <feOffset dy="-3"/>
21
+ <feGaussianBlur stdDeviation="3"/>
22
+ <feColorMatrix type="matrix" values="0 0 0 0 0.788235 0 0 0 0 0.803922 0 0 0 0 0.85098 0 0 0 0.349 0"/>
23
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_577_1090"/>
24
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_577_1090" result="shape"/>
25
+ <filter id="filter1_d_577_1090" x="38.6401" y="0" width="170.72" height="78.1333" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
26
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
27
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
28
+ <feOffset dy="-3"/>
29
+ <feGaussianBlur stdDeviation="3"/>
30
+ <feColorMatrix type="matrix" values="0 0 0 0 0.788235 0 0 0 0 0.803922 0 0 0 0 0.85098 0 0 0 0.349 0"/>
31
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_577_1090"/>
32
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_577_1090" result="shape"/>
33
+ </filter>
34
+ </defs>
35
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
2
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 6.75V15m6-6v8.25m.503 3.498l4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 00-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0z"/>
3
+ </svg>
@@ -11,7 +11,7 @@ class Avo::ActionsComponent < ViewComponent::Base
11
11
  @exclude = exclude
12
12
  @color = color
13
13
  @style = style
14
- @label = label || t("avo.actions")
14
+ @label = label || I18n.t("avo.actions")
15
15
  end
16
16
 
17
17
  def render?
@@ -0,0 +1,7 @@
1
+ <%= field_wrapper **field_wrapper_args do %>
2
+ <%= @form.text_field @field.id,
3
+ class: classes("w-full"),
4
+ value: field.value.to_s,
5
+ placeholder: @field.placeholder,
6
+ disabled: disabled? %>
7
+ <% end %>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::AreaField::EditComponent < Avo::Fields::EditComponent
4
+ end
@@ -0,0 +1,8 @@
1
+ <%= field_wrapper **field_wrapper_args do %>
2
+ <% if field.value.present? %>
3
+ <%= area_map field.map_data, **field.mapkick_options %>
4
+ <% else %>
5
+
6
+ <% end %>
7
+ <% end %>
8
+
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::AreaField::ShowComponent < Avo::Fields::ShowComponent
4
+ end
@@ -10,6 +10,7 @@
10
10
  data: @field.get_html(:data, view: view, element: :input),
11
11
  disabled: disabled?,
12
12
  style: @field.get_html(:style, view: view, element: :input),
13
- placeholder: @field.include_blank.present? ? nil : @field.placeholder
13
+ placeholder: @field.include_blank.present? ? nil : @field.placeholder,
14
+ autocomplete: @field.autocomplete
14
15
  %>
15
16
  <% end %>
@@ -1,3 +1,3 @@
1
1
  <turbo-frame id="<%= @field.turbo_frame %>" src="<%= @field.frame_url %>" target="_top" class="block">
2
- <%= render(Avo::LoadingComponent.new(title: @field.name)) %>
2
+ <%= render(Avo::LoadingComponent.new(title: @field.plural_name)) %>
3
3
  </turbo-frame>
@@ -4,7 +4,7 @@
4
4
  </turbo-frame>
5
5
  <% else %>
6
6
  <%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
7
- <% c.tools do %>
7
+ <% c.with_tools do %>
8
8
  <% if !@field.is_readonly? && !@field.is_disabled? && can_attach? %>
9
9
  <%= a_link attach_path,
10
10
  icon: 'heroicons/outline/link',
@@ -25,7 +25,7 @@
25
25
  <% end %>
26
26
  <% end %>
27
27
 
28
- <% c.body do %>
28
+ <% c.with_body do %>
29
29
  <div class="py-8 flex justify-center items-center">
30
30
  <%= empty_state by_association: params[:related_name].present? %>
31
31
  </div>
@@ -1,6 +1,6 @@
1
1
  <%= field_wrapper **field_wrapper_args do %>
2
2
  <% if field.value_present? %>
3
- <%= js_map [{latitude: field.value[0], longitude: field.value[1]}] %>
3
+ <%= js_map [{latitude: field.value[0], longitude: field.value[1]}], id: "location-map" %>
4
4
  <% else %>
5
5
 
6
6
  <% end %>
@@ -7,6 +7,7 @@
7
7
  min: @field.min,
8
8
  placeholder: @field.placeholder,
9
9
  step: @field.step,
10
- style: @field.get_html(:style, view: view, element: :input)
10
+ style: @field.get_html(:style, view: view, element: :input),
11
+ autocomplete: @field.autocomplete
11
12
  %>
12
13
  <% end %>
@@ -4,6 +4,7 @@
4
4
  data: @field.get_html(:data, view: view, element: :input),
5
5
  disabled: disabled?,
6
6
  placeholder: @field.placeholder,
7
- style: @field.get_html(:style, view: view, element: :input)
7
+ style: @field.get_html(:style, view: view, element: :input),
8
+ autocomplete: @field.autocomplete
8
9
  %>
9
10
  <% end %>
@@ -10,6 +10,7 @@
10
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
- placeholder: @field.include_blank.present? ? nil : @field.placeholder
13
+ placeholder: @field.include_blank.present? ? nil : @field.placeholder,
14
+ autocomplete: @field.autocomplete
14
15
  %>
15
16
  <% end %>
@@ -6,6 +6,7 @@
6
6
  placeholder: @field.placeholder,
7
7
  style: @field.get_html(:style, view: view, element: :input),
8
8
  # value: @field.value,
9
- multiple: multiple
9
+ multiple: multiple,
10
+ autocomplete: @field.autocomplete
10
11
  %>
11
12
  <% end %>
@@ -0,0 +1,16 @@
1
+ <% if @resources.present? %>
2
+ <div class="map-view-container grid <%= grid_layout_classes %>">
3
+ <div class="map-component min-h-full <%= map_component_order_class %>">
4
+ <%= js_map(resource_location_markers, **resource_mapkick_options) %>
5
+ </div>
6
+ <% if render_table? %>
7
+ <div class="overflow-auto<%= table_component_order_class %>">
8
+ <%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
9
+ </div>
10
+ <% end %>
11
+ </div>
12
+ <% else %>
13
+ <div class="bg-white rounded shadow-panel">
14
+ <%= helpers.empty_state by_association: params[:related_name].present?, view_type: :map %>
15
+ </div>
16
+ <% end %>
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avo
4
+ module Index
5
+ # Render a map view for a list of resources, where each resource is
6
+ # expected to have an attribute/attribute set representing its location.
7
+ class ResourceMapComponent < ViewComponent::Base
8
+ attr_reader :resources
9
+
10
+ def initialize(resources: nil, resource: nil, reflection: nil, parent_model: nil, parent_resource: nil, pagy: nil, query: nil)
11
+ super
12
+ @resources = resources
13
+ @resource = resource
14
+ @reflection = reflection
15
+ @parent_model = parent_model
16
+ @parent_resource = parent_resource
17
+ @pagy = pagy
18
+ @query = query
19
+ end
20
+
21
+ def grid_layout_classes
22
+ return unless render_table?
23
+
24
+ if table_positioned_horizontally
25
+ "grid-flow-row sm:grid-flow-col grid-rows-1 auto-cols-fr"
26
+ elsif table_positioned_vertically
27
+ "grid-flow-row grid-cols-1"
28
+ end
29
+ end
30
+
31
+ def table_positioned_horizontally
32
+ %i[left right].include?(map_view_table_layout)
33
+ end
34
+
35
+ def table_positioned_vertically
36
+ %i[bottom top].include?(map_view_table_layout)
37
+ end
38
+
39
+ def map_component_order_class
40
+ if render_table? && table_positioned_at_the_start
41
+ "order-last"
42
+ else
43
+ "order-first"
44
+ end
45
+ end
46
+
47
+ def table_component_order_class
48
+ if table_positioned_at_the_start
49
+ "order-first"
50
+ else
51
+ "order-last"
52
+ end
53
+ end
54
+
55
+ def table_positioned_at_the_start
56
+ %i[left top].include?(map_view_table_layout)
57
+ end
58
+
59
+ def map_view_table_layout
60
+ map_options.dig(:table, :layout)
61
+ end
62
+
63
+ def resource_location_markers
64
+ # If we have no proc and no default location method, don't try to create markers
65
+ return [] unless resource_mappable?
66
+
67
+ resources
68
+ .map do |resource|
69
+ Avo::Hosts::ResourceRecordHost.new(block: marker_proc, resource: resource, record: resource.record).handle
70
+ end
71
+ .compact
72
+ .filter do |coordinates|
73
+ coordinates[:latitude].present? && coordinates[:longitude].present?
74
+ end
75
+ end
76
+
77
+ def resource_mapkick_options
78
+ map_options[:mapkick_options] || {}
79
+ end
80
+
81
+ def render_table?
82
+ map_options.dig(:table, :visible)
83
+ end
84
+
85
+ private
86
+
87
+ def default_record_marker_proc
88
+ lambda {
89
+ {
90
+ latitude: record.coordinates.first,
91
+ longitude: record.coordinates.last
92
+ }
93
+ }
94
+ end
95
+
96
+ def map_options
97
+ @resource.map_view || {}
98
+ end
99
+
100
+ def marker_proc
101
+ map_options[:record_marker] || default_record_marker_proc
102
+ end
103
+
104
+ def resource_mappable?
105
+ map_options[:record_marker].present? || @resources.first.record.respond_to?(:coordinates)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -4,7 +4,7 @@
4
4
  <% end %>
5
5
  <% elsif item.is_panel? %>
6
6
  <%= render Avo::PanelComponent.new(name: item.name, description: item.description, index: index) do |c| %>
7
- <% c.body do %>
7
+ <% c.with_body do %>
8
8
  <div class="divide-y">
9
9
  <% item.visible_items.each_with_index do |field, index| %>
10
10
  <%= render field
@@ -119,7 +119,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
119
119
  end
120
120
 
121
121
  if filtered_fields.present?
122
- filtered_fields.find { |f| f.id == @reflection.name }.readonly
122
+ filtered_fields.find { |f| f.id == @reflection.name }.is_readonly?
123
123
  else
124
124
  false
125
125
  end
@@ -19,7 +19,7 @@
19
19
  <%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
20
20
  <%= content_tag :div, class: 'space-y-12' do %>
21
21
  <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
22
- <% c.tools do %>
22
+ <% c.with_tools do %>
23
23
  <%= a_link back_path,
24
24
  style: :text,
25
25
  icon: 'arrow-left' do %>
@@ -56,7 +56,7 @@
56
56
  <%# Extract the main panel and display the fields here. %>
57
57
  <%# This way we'll be able to render the footer buttons under the main fields. %>
58
58
  <% if main_panel.present? %>
59
- <% c.body do %>
59
+ <% c.with_body do %>
60
60
  <div class="divide-y">
61
61
  <% main_panel.items.each_with_index do |field, index| %>
62
62
  <%= render field
@@ -69,12 +69,12 @@
69
69
  <% end %>
70
70
  <% end %>
71
71
  <% if sidebar.present? %>
72
- <% c.sidebar do %>
72
+ <% c.with_sidebar do %>
73
73
  <%= render sidebar_component form: form %>
74
74
  <% end %>
75
75
  <% end %>
76
76
  <% if Avo.configuration.buttons_on_form_footers %>
77
- <% c.footer_tools do %>
77
+ <% c.with_footer_tools do %>
78
78
  <div class="mt-4">
79
79
  <%= a_link back_path,
80
80
  style: :text,
@@ -5,7 +5,7 @@
5
5
  **@resource.stimulus_data_attributes
6
6
  } do %>
7
7
  <%= render Avo::PanelComponent.new(name: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
8
- <% c.tools do %>
8
+ <% c.with_tools do %>
9
9
  <% if can_attach? %>
10
10
  <%= a_link attach_path,
11
11
  icon: 'heroicons/outline/link',
@@ -29,7 +29,7 @@
29
29
  <% end %>
30
30
  <% end %>
31
31
  <% end %>
32
- <% c.body do %>
32
+ <% c.with_body do %>
33
33
  <div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= 'hidden' if @resource.search_query.nil? && @filters.empty? && available_view_types.count <= 1 %>">
34
34
  <% if show_search_input %>
35
35
  <div class="flex items-center px-4 w-64">
@@ -46,6 +46,15 @@
46
46
  </div>
47
47
  <% end %>
48
48
  </div>
49
+ <% if view_type.to_sym == :map %>
50
+ <% if @resources.present? %>
51
+ <div>
52
+ <%= render(Avo::Index::ResourceMapComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
53
+ </div>
54
+ <% else %>
55
+ <%= helpers.empty_state by_association: params[:related_name].present?, view_type: view_type, add_background: true %>
56
+ <% end %>
57
+ <% end %>
49
58
  <% if view_type.to_sym == :table %>
50
59
  <% if @resources.present? %>
51
60
  <div class="w-full relative flex-1 flex mt-0">
@@ -56,7 +65,7 @@
56
65
  <% end %>
57
66
  <% end %>
58
67
  <% end %>
59
- <% c.bare_content do %>
68
+ <% c.with_bare_content do %>
60
69
  <% if view_type.to_sym == :table %>
61
70
  <% if @models.present? %>
62
71
  <div class="mt-4">
@@ -8,7 +8,7 @@
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
10
  <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
11
- <% c.tools do %>
11
+ <% c.with_tools do %>
12
12
  <% if @resource.has_show_controls? %>
13
13
  <% @resource.render_show_controls.each do |control| %>
14
14
  <% if control.back_button? %>
@@ -155,7 +155,7 @@
155
155
  <% end %>
156
156
  <% end %>
157
157
  <% if main_panel.present? %>
158
- <% c.body do %>
158
+ <% c.with_body do %>
159
159
  <%# the overflow helps with long values %>
160
160
  <div class="divide-y overflow-auto">
161
161
  <% main_panel.items.each_with_index do |field, index| %>
@@ -169,7 +169,7 @@
169
169
  <% end %>
170
170
  <% end %>
171
171
  <% if sidebar.present? %>
172
- <% c.sidebar do %>
172
+ <% c.with_sidebar do %>
173
173
  <%= render sidebar_component %>
174
174
  <% end %>
175
175
  <% end %>
@@ -155,6 +155,10 @@ module Avo
155
155
  def set_model_to_fill
156
156
  @model_to_fill = @resource.model_class.new if @view == :create
157
157
  @model_to_fill = @model if @view == :update
158
+
159
+ # If resource.model is nil, most likely the user is creating a new record.
160
+ # In that case, to access resource.model in visible and readonly blocks we hydrate the resource with a new model.
161
+ @resource.hydrate(model: @model_to_fill) if @resource.model.nil?
158
162
  end
159
163
 
160
164
  def fill_model
@@ -14,7 +14,7 @@
14
14
  data: @action.class.form_data_attributes do |form|
15
15
  %>
16
16
  <%= render Avo::ModalComponent.new do |c| %>
17
- <% c.heading do %>
17
+ <% c.with_heading do %>
18
18
  <%= @action.action_name %>
19
19
  <% end %>
20
20
  <div class="flex-1 flex">
@@ -33,7 +33,7 @@
33
33
  <% end %>
34
34
  </div>
35
35
  <% end %>
36
- <% c.controls do %>
36
+ <% c.with_controls do %>
37
37
  <%= a_button type: :button,
38
38
  data: { action: 'click->modal#close' },
39
39
  size: :sm,
@@ -11,7 +11,7 @@
11
11
  'turbo-frame': '_top'
12
12
  } do |form| %>
13
13
  <%= render Avo::ModalComponent.new do |c| %>
14
- <% c.heading do %>
14
+ <% c.with_heading do %>
15
15
  <%= t 'avo.choose_item', item: @related_resource.name.downcase %>
16
16
  <% end %>
17
17
 
@@ -39,7 +39,7 @@
39
39
  <% end %>
40
40
  </div>
41
41
 
42
- <% c.controls do %>
42
+ <% c.with_controls do %>
43
43
  <%= a_button 'data-action': 'click->modal#close', size: :sm, style: :outline, color: :gray do %>
44
44
  <%= t('avo.cancel') %>
45
45
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%= render Avo::PanelComponent.new(name: @dashboard.name, description: @dashboard.description) do |c| %>
2
- <% c.bare_content do %>
2
+ <% c.with_bare_content do %>
3
3
  <% if @dashboard.items.present? %>
4
4
  <div class="min-h-24">
5
5
  <%= content_tag(:div, class: "grid gap-4 grid-cols-1 #{@dashboard.classes}") do %>
@@ -23,7 +23,7 @@
23
23
  <div class="w-full h-full">
24
24
  <% if Rails.env.development? %>
25
25
  <%= render Avo::PanelComponent.new do |c| %>
26
- <% c.body do %>
26
+ <% c.with_body do %>
27
27
  <div class="p-6">
28
28
  <%= t 'avo.empty_dashboard_message' %>. <%= link_to 'Docs', 'https://docs.avohq.io/2.0/dashboards.html', target: '_blank' %>
29
29
  </div>
@@ -15,9 +15,9 @@
15
15
  %>
16
16
  <div class="flex flex-col">
17
17
  <%= render Avo::PanelComponent.new(name: 'Debug Avo', description: 'Use this page to debug the Avo license.') do |c| %>
18
- <% c.tools do %>
18
+ <% c.with_tools do %>
19
19
  <% end %>
20
- <% c.bare_content do %>
20
+ <% c.with_bare_content do %>
21
21
  <div class="grid gap-4 sm:grid-cols-3">
22
22
  <div class="relative flex flex-col bg-white rounded shadow-panel p-4 space-y-4 h-full col-span-1">
23
23
  <div class="flex justify-between w-full">
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col">
2
2
  <%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
- <% c.body do %>
3
+ <% c.with_body do %>
4
4
  <div class="flex flex-col justify-between py-6 min-h-24">
5
5
  <div class="px-6 space-y-4">
6
6
  <h3>About</h3>
@@ -15,6 +15,11 @@
15
15
  new_view_type: 'list',
16
16
  new_icon: 'queue-list',
17
17
  },
18
+ map: {
19
+ new_view_type: 'map',
20
+ new_icon: 'map-view-type',
21
+ translation_key: 'avo.map_view',
22
+ },
18
23
  }
19
24
  %>
20
25
  <div class="flex">
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col">
2
2
  <%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
- <% c.tools do %>
3
+ <% c.with_tools do %>
4
4
  <%= a_link('/admin', icon: 'arrow-left', color: :green, style: :primary, is_link: true) do %>
5
5
  Primary
6
6
  <% end %>
@@ -18,7 +18,7 @@
18
18
  <% end %>
19
19
  <% end %>
20
20
 
21
- <% c.body do %>
21
+ <% c.with_body do %>
22
22
  <div class="flex flex-col justify-between py-6 min-h-24">
23
23
  <%= render 'links_and_buttons' %>
24
24
  </div>
data/avo.gemspec CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "zeitwerk", ">= 2.6.2"
39
39
  spec.add_dependency "httparty"
40
40
  spec.add_dependency "active_link_to"
41
- spec.add_dependency "view_component"
41
+ spec.add_dependency "view_component", ">= 2.54.0"
42
42
  spec.add_dependency "turbo-rails"
43
43
  spec.add_dependency "addressable"
44
44
  spec.add_dependency "meta-tags"
data/db/factories.rb CHANGED
@@ -112,6 +112,7 @@ FactoryBot.define do
112
112
  description { Faker::Address.community }
113
113
  status { ["open", "closed"].sample }
114
114
  tiny_description { Faker::Address.community }
115
+ city_center_area { [[[10.0, 11.2], [10.5, 11.9], [10.8, 12.0], [10.0, 11.2]]].to_json }
115
116
  end
116
117
 
117
118
  factory :product do
data/lib/avo/app.rb CHANGED
@@ -31,10 +31,25 @@ module Avo
31
31
  def boot
32
32
  init_fields
33
33
 
34
- if Rails.cache.instance_of?(ActiveSupport::Cache::NullStore)
35
- self.cache_store ||= ActiveSupport::Cache::MemoryStore.new
34
+ self.cache_store = get_cache_store
35
+ end
36
+
37
+ # When not in production we'll just use the MemoryStore which is good enough.
38
+ # Wehn running in production we'll try to use memcached or redis if available.
39
+ # If not, we'll use the FileStore.
40
+ # We decided against the MemoryStore in production because it will not be shared between multiple processes (when using Puma).
41
+ def get_cache_store
42
+ if Rails.env.production?
43
+ case Rails.cache.class
44
+ when ActiveSupport::Cache::MemCacheStore, ActiveSupport::Cache::RedisCacheStore
45
+ Rails.cache
46
+ else
47
+ ActiveSupport::Cache::FileStore.new
48
+ end
49
+ elsif Rails.env.test?
50
+ Rails.cache
36
51
  else
37
- self.cache_store = Rails.cache
52
+ ActiveSupport::Cache::MemoryStore.new
38
53
  end
39
54
  end
40
55
 
@@ -63,7 +78,7 @@ module Avo
63
78
  if Rails::VERSION::MAJOR === 6
64
79
  ActiveStorage::Current.host = request.base_url
65
80
  elsif Rails::VERSION::MAJOR === 7
66
- ActiveStorage::Current.url_options = request.base_url
81
+ ActiveStorage::Current.url_options = {protocol: request.protocol, host: request.host, port: request.port}
67
82
  end
68
83
  end
69
84
  rescue => exception
@@ -58,10 +58,10 @@ module Avo
58
58
  end
59
59
 
60
60
  def initialize(model: nil, resource: nil, user: nil, view: nil, arguments: {})
61
- self.class.model = model if model.present?
62
- self.class.resource = resource if resource.present?
63
- self.class.user = user if user.present?
64
- self.class.view = view if view.present?
61
+ self.class.model = model
62
+ self.class.resource = resource
63
+ self.class.user = user
64
+ self.class.view = view
65
65
  @arguments = arguments
66
66
 
67
67
  self.class.message ||= I18n.t("avo.are_you_sure_you_want_to_run_this_option")
@@ -55,6 +55,7 @@ module Avo
55
55
  class_attribute :keep_filters_panel_open, default: false
56
56
  class_attribute :extra_params
57
57
  class_attribute :link_to_child_resource, default: false
58
+ class_attribute :map_view
58
59
 
59
60
  class << self
60
61
  delegate :t, to: ::I18n
@@ -295,6 +296,7 @@ module Avo
295
296
  view_types = [:table]
296
297
 
297
298
  view_types << :grid if get_grid_fields.present?
299
+ view_types << :map if map_view.present?
298
300
 
299
301
  view_types
300
302
  end
@@ -24,9 +24,7 @@ module Avo
24
24
 
25
25
  # Filters out the resources that are missing the model_class
26
26
  def valid_resources
27
- resources.select do |resource|
28
- resource.model_class.present?
29
- end
27
+ resources.select { |resource| resource.model_class.present? }.sort_by(&:name)
30
28
  end
31
29
 
32
30
  # Returns the Avo resource by camelized name
@@ -0,0 +1,31 @@
1
+ module Avo
2
+ module Concerns
3
+ module PolicyHelpers
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def inherit_association_from_policy(association_name, policy_class)
8
+ [:create, :edit, :update, :destroy, :show, :reorder, :act_on].each do |method_action|
9
+ define_policy_method(method_action, association_name, policy_class)
10
+ end
11
+
12
+ define_policy_method("view", association_name, policy_class, "index")
13
+ end
14
+
15
+ private
16
+
17
+ # Define a method for the given action and association name.
18
+ # Call the policy class with the given action passing the user and record.
19
+ # Example:
20
+ # def create_team_members?
21
+ # TeamMemberPolicy.new(user, record).create?
22
+ # end
23
+ def define_policy_method(method_action, association_name, policy_class, policy_action = method_action)
24
+ define_method "#{method_action}_#{association_name}?" do
25
+ policy_class.new(user, record).send "#{policy_action}?"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/avo/engine.rb CHANGED
@@ -14,11 +14,6 @@ Gem.loaded_specs["avo"].dependencies.each do |d|
14
14
  end
15
15
  end
16
16
 
17
- # In development we should load the engine so we get the autoload for components
18
- if ENV["RAILS_ENV"] === "development"
19
- require "view_component/engine"
20
- end
21
-
22
17
  module Avo
23
18
  class Engine < ::Rails::Engine
24
19
  isolate_namespace Avo
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avo
4
+ module Fields
5
+ class AreaField < BaseField
6
+ attr_reader :mapkick_options
7
+ attr_reader :datapoint_options
8
+
9
+ def initialize(id, **args, &block)
10
+ hide_on :index
11
+
12
+ super(id, **args, &block)
13
+
14
+ @geometry = args[:geometry].presence || :polygon # Accepts: `:polygon` or `:multi_polygon`
15
+ @mapkick_options = args[:mapkick_options].presence || {}
16
+ @datapoint_options = args[:datapoint_options].presence || {}
17
+ end
18
+
19
+ def map_data
20
+ data_source = {
21
+ geometry: {
22
+ type: @geometry.to_s.classify,
23
+ coordinates: value
24
+ }
25
+ }
26
+
27
+ [data_source.merge(datapoint_options)]
28
+ end
29
+
30
+ def coordinates
31
+ value.present? ? JSON.parse(value) : []
32
+ end
33
+
34
+ def geometry
35
+ @geometry.to_s.classify
36
+ end
37
+ end
38
+ end
39
+ end
@@ -30,6 +30,7 @@ module Avo
30
30
  attr_reader :nullable
31
31
  attr_reader :null_values
32
32
  attr_reader :format_using
33
+ attr_reader :autocomplete
33
34
  attr_reader :help
34
35
  attr_reader :default
35
36
  attr_reader :visible
@@ -70,6 +71,7 @@ module Avo
70
71
  @null_values = args[:null_values] || [nil, ""]
71
72
  @format_using = args[:format_using] || nil
72
73
  @placeholder = args[:placeholder]
74
+ @autocomplete = args[:autocomplete] || nil
73
75
  @help = args[:help] || nil
74
76
  @default = args[:default] || nil
75
77
  @visible = args[:visible]
@@ -85,7 +87,6 @@ module Avo
85
87
 
86
88
  @args = args
87
89
 
88
- @updatable = !readonly
89
90
  @computable = true
90
91
  @computed = block.present?
91
92
  @computed_value = nil
@@ -257,7 +258,7 @@ module Avo
257
258
  end
258
259
 
259
260
  def updatable
260
- @updatable && visible?
261
+ !is_readonly? && visible?
261
262
  end
262
263
 
263
264
  private
@@ -7,7 +7,6 @@ module Avo
7
7
 
8
8
  def initialize(id, **args, &block)
9
9
  hide_on :index
10
-
11
10
  super(id, **args, &block)
12
11
 
13
12
  @stored_as = args[:stored_as].present? ? args[:stored_as] : nil # You can pass it an array of db columns [:latitude, :longitude]
@@ -106,6 +106,7 @@ module Avo
106
106
  **other_metadata(:filters),
107
107
  main_menu_present: Avo.configuration.main_menu.present?,
108
108
  profile_menu_present: Avo.configuration.profile_menu.present?,
109
+ cache_store: Avo::App.cache_store&.class&.to_s,
109
110
  **config_metadata
110
111
  }
111
112
  rescue
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.30.2" unless const_defined?(:VERSION)
2
+ VERSION = "2.32.0" unless const_defined?(:VERSION)
3
3
  end
@@ -1,12 +1,12 @@
1
1
  <div class="flex flex-col">
2
2
  <%%= render Avo::PanelComponent.new(name: "<%= human_name %>") do |c| %>
3
- <%% c.tools do %>
3
+ <%% c.with_tools do %>
4
4
  <%%= a_link('/avo', icon: 'heroicons/solid/academic-cap', color: :primary, style: :primary) do %>
5
5
  Dummy link
6
6
  <%% end %>
7
7
  <%% end %>
8
8
 
9
- <%% c.body do %>
9
+ <%% c.with_body do %>
10
10
  <div class="flex flex-col p-4 min-h-24">
11
11
  <div class="space-y-4">
12
12
  <h3>🪧 This partial is waiting to be updated</h3>
@@ -1,10 +1,10 @@
1
1
  <div class="flex flex-col">
2
2
  <%%= render Avo::PanelComponent.new(name: '<%= human_name %>', display_breadcrumbs: true) do |c| %>
3
- <%% c.tools do %>
3
+ <%% c.with_tools do %>
4
4
  <div class="text-sm italic">This is the panels tools section.</div>
5
5
  <%% end %>
6
6
 
7
- <%% c.body do %>
7
+ <%% c.with_body do %>
8
8
  <div class="flex flex-col justify-between py-6 min-h-24">
9
9
  <div class="px-6 space-y-4">
10
10
  <h3>What a nice new tool 👋</h3>
@@ -6374,6 +6374,14 @@ trix-toolbar .trix-button-group:not(:first-child){
6374
6374
  z-index:30
6375
6375
  }
6376
6376
 
6377
+ .order-last{
6378
+ order:9999
6379
+ }
6380
+
6381
+ .order-first{
6382
+ order:-9999
6383
+ }
6384
+
6377
6385
  .col-span-1{
6378
6386
  grid-column:span 1 / span 1
6379
6387
  }
@@ -6922,6 +6930,14 @@ trix-toolbar .trix-button-group:not(:first-child){
6922
6930
  appearance:none
6923
6931
  }
6924
6932
 
6933
+ .auto-cols-fr{
6934
+ grid-auto-columns:minmax(0, 1fr)
6935
+ }
6936
+
6937
+ .grid-flow-row{
6938
+ grid-auto-flow:row
6939
+ }
6940
+
6925
6941
  .grid-cols-1{
6926
6942
  grid-template-columns:repeat(1, minmax(0, 1fr))
6927
6943
  }
@@ -6930,6 +6946,10 @@ trix-toolbar .trix-button-group:not(:first-child){
6930
6946
  grid-template-columns:repeat(6, minmax(0, 1fr))
6931
6947
  }
6932
6948
 
6949
+ .grid-rows-1{
6950
+ grid-template-rows:repeat(1, minmax(0, 1fr))
6951
+ }
6952
+
6933
6953
  .flex-row{
6934
6954
  flex-direction:row
6935
6955
  }
@@ -9502,6 +9522,10 @@ trix-editor {
9502
9522
  max-width:42rem
9503
9523
  }
9504
9524
 
9525
+ .sm\:grid-flow-col{
9526
+ grid-auto-flow:column
9527
+ }
9528
+
9505
9529
  .sm\:grid-cols-3{
9506
9530
  grid-template-columns:repeat(3, minmax(0, 1fr))
9507
9531
  }
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.30.2
4
+ version: 2.32.0
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-04-18 00:00:00.000000000 Z
12
+ date: 2023-05-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -101,14 +101,14 @@ dependencies:
101
101
  requirements:
102
102
  - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: '0'
104
+ version: 2.54.0
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: '0'
111
+ version: 2.54.0
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: turbo-rails
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -1292,6 +1292,8 @@ files:
1292
1292
  - app/assets/svgs/information-circle.svg
1293
1293
  - app/assets/svgs/library.svg
1294
1294
  - app/assets/svgs/logout.svg
1295
+ - app/assets/svgs/map-empty-state.svg
1296
+ - app/assets/svgs/map-view-type.svg
1295
1297
  - app/assets/svgs/menu-back.svg
1296
1298
  - app/assets/svgs/menu.svg
1297
1299
  - app/assets/svgs/photograph.svg
@@ -1337,6 +1339,10 @@ files:
1337
1339
  - app/components/avo/empty_state_component.rb
1338
1340
  - app/components/avo/field_wrapper_component.html.erb
1339
1341
  - app/components/avo/field_wrapper_component.rb
1342
+ - app/components/avo/fields/area_field/edit_component.html.erb
1343
+ - app/components/avo/fields/area_field/edit_component.rb
1344
+ - app/components/avo/fields/area_field/show_component.html.erb
1345
+ - app/components/avo/fields/area_field/show_component.rb
1340
1346
  - app/components/avo/fields/badge_field/index_component.html.erb
1341
1347
  - app/components/avo/fields/badge_field/index_component.rb
1342
1348
  - app/components/avo/fields/badge_field/show_component.html.erb
@@ -1536,6 +1542,8 @@ files:
1536
1542
  - app/components/avo/index/resource_controls_component.rb
1537
1543
  - app/components/avo/index/resource_grid_component.html.erb
1538
1544
  - app/components/avo/index/resource_grid_component.rb
1545
+ - app/components/avo/index/resource_map_component.html.erb
1546
+ - app/components/avo/index/resource_map_component.rb
1539
1547
  - app/components/avo/index/resource_table_component.html.erb
1540
1548
  - app/components/avo/index/resource_table_component.rb
1541
1549
  - app/components/avo/index/table_row_component.html.erb
@@ -1726,6 +1734,7 @@ files:
1726
1734
  - lib/avo/concerns/has_stimulus_controllers.rb
1727
1735
  - lib/avo/concerns/is_resource_item.rb
1728
1736
  - lib/avo/concerns/model_class_constantized.rb
1737
+ - lib/avo/concerns/policy_helpers.rb
1729
1738
  - lib/avo/concerns/visible_in_dashboard.rb
1730
1739
  - lib/avo/concerns/visible_items.rb
1731
1740
  - lib/avo/configuration.rb
@@ -1740,6 +1749,7 @@ files:
1740
1749
  - lib/avo/dsl/field_parser.rb
1741
1750
  - lib/avo/dynamic_router.rb
1742
1751
  - lib/avo/engine.rb
1752
+ - lib/avo/fields/area_field.rb
1743
1753
  - lib/avo/fields/badge_field.rb
1744
1754
  - lib/avo/fields/base_field.rb
1745
1755
  - lib/avo/fields/belongs_to_field.rb